-
Notifications
You must be signed in to change notification settings - Fork 90
fix(clp-s::log_converter): Update timezone regex to only accept spaces when followed by an actual timezone (fixes #2187). #2192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4263f24
32e4101
180ee22
a04da68
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,81 @@ | ||||||||||||||||||
| """ | ||||||||||||||||||
| Integration tests verifying that CLP core compression binaries perform lossless round-trip | ||||||||||||||||||
| compression and decompression. | ||||||||||||||||||
| """ | ||||||||||||||||||
|
Comment on lines
+1
to
+4
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Module docstring overstates what this test verifies. The test does not validate decompression; it validates log conversion, Proposed fix-Integration tests verifying that CLP core compression binaries perform lossless round-trip
-compression and decompression.
+Integration tests verifying log-converter output can be compressed by clp-s and searched
+with expected event counts.📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| import pytest | ||||||||||||||||||
|
|
||||||||||||||||||
| from tests.utils.config import ( | ||||||||||||||||||
| ClpCorePathConfig, | ||||||||||||||||||
| ConversionTestPathConfig, | ||||||||||||||||||
| IntegrationTestLogs, | ||||||||||||||||||
| IntegrationTestPathConfig, | ||||||||||||||||||
| ) | ||||||||||||||||||
| from tests.utils.subprocess_utils import run_and_log_subprocess | ||||||||||||||||||
|
|
||||||||||||||||||
| pytestmark = pytest.mark.core | ||||||||||||||||||
|
|
||||||||||||||||||
| text_datasets = pytest.mark.parametrize( | ||||||||||||||||||
| "test_logs_fixture", | ||||||||||||||||||
| [ | ||||||||||||||||||
| "simple_unstructured", | ||||||||||||||||||
| ], | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| @pytest.mark.clp_s | ||||||||||||||||||
| @text_datasets | ||||||||||||||||||
| def test_log_converter_transform( | ||||||||||||||||||
| request: pytest.FixtureRequest, | ||||||||||||||||||
| clp_core_path_config: ClpCorePathConfig, | ||||||||||||||||||
| integration_test_path_config: IntegrationTestPathConfig, | ||||||||||||||||||
| test_logs_fixture: str, | ||||||||||||||||||
| ) -> None: | ||||||||||||||||||
| """ | ||||||||||||||||||
| Validate that converted logs from the core binary `log-converter` can be ingested successfully | ||||||||||||||||||
| by `clp-s`. | ||||||||||||||||||
|
|
||||||||||||||||||
| :param request: | ||||||||||||||||||
| :param clp_core_path_config: | ||||||||||||||||||
| :param integration_test_path_config: | ||||||||||||||||||
| :param test_logs_fixture: | ||||||||||||||||||
| """ | ||||||||||||||||||
| integration_test_logs: IntegrationTestLogs = request.getfixturevalue(test_logs_fixture) | ||||||||||||||||||
| test_logs_name = integration_test_logs.name | ||||||||||||||||||
|
|
||||||||||||||||||
| test_paths = ConversionTestPathConfig( | ||||||||||||||||||
| test_name=f"clp-s-{test_logs_name}", | ||||||||||||||||||
| logs_source_dir=integration_test_logs.extraction_dir, | ||||||||||||||||||
| num_log_events=integration_test_logs.num_log_events, | ||||||||||||||||||
| integration_test_path_config=integration_test_path_config, | ||||||||||||||||||
| ) | ||||||||||||||||||
| _convert_and_compress(clp_core_path_config, test_paths) | ||||||||||||||||||
|
|
||||||||||||||||||
| test_paths.clear_test_outputs() | ||||||||||||||||||
|
|
||||||||||||||||||
|
Comment on lines
+52
to
+55
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Ensure cleanup always runs on failure. If Proposed fix- _convert_and_compress(clp_core_path_config, test_paths)
-
- test_paths.clear_test_outputs()
+ try:
+ _convert_and_compress(clp_core_path_config, test_paths)
+ finally:
+ test_paths.clear_test_outputs()🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| def _convert_and_compress( | ||||||||||||||||||
| clp_core_path_config: ClpCorePathConfig, | ||||||||||||||||||
| test_paths: ConversionTestPathConfig, | ||||||||||||||||||
| ) -> None: | ||||||||||||||||||
| test_paths.clear_test_outputs() | ||||||||||||||||||
| log_converter_bin_path = str(clp_core_path_config.log_converter_binary_path) | ||||||||||||||||||
| clp_s_bin_path = str(clp_core_path_config.clp_s_binary_path) | ||||||||||||||||||
| src_path = str(test_paths.logs_source_dir) | ||||||||||||||||||
| conversion_path = str(test_paths.conversion_dir) | ||||||||||||||||||
| compression_path = str(test_paths.compression_dir) | ||||||||||||||||||
| run_and_log_subprocess([log_converter_bin_path, src_path, "--output-dir", conversion_path]) | ||||||||||||||||||
| run_and_log_subprocess( | ||||||||||||||||||
| [clp_s_bin_path, "c", compression_path, conversion_path, "--timestamp-key", "timestamp"] | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
||||||||||||||||||
| if test_paths.num_log_events is None: | ||||||||||||||||||
| return | ||||||||||||||||||
|
|
||||||||||||||||||
| output = run_and_log_subprocess([clp_s_bin_path, "s", compression_path, "timestamp > 0"]) | ||||||||||||||||||
| num_events = 0 if output.stdout is None else len(output.stdout.splitlines()) | ||||||||||||||||||
| if num_events != test_paths.num_log_events: | ||||||||||||||||||
gibber9809 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
| pytest.fail( | ||||||||||||||||||
| f"Expected {test_paths.num_log_events} log events after conversion, " | ||||||||||||||||||
| f"but found {num_events}." | ||||||||||||||||||
| ) | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -61,6 +61,11 @@ def clp_s_binary_path(self) -> Path: | |
| """:return: The absolute path to the core binary `clp-s`.""" | ||
| return self.clp_core_bins_dir / "clp-s" | ||
|
|
||
| @property | ||
| def log_converter_binary_path(self) -> Path: | ||
| """:return: The absolute path to the core binary `log-converter`.""" | ||
| return self.clp_core_bins_dir / "log-converter" | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class PackagePathConfig: | ||
|
|
@@ -310,6 +315,8 @@ class IntegrationTestLogs: | |
| tarball_path: Path = field(init=False, repr=True) | ||
| #: | ||
| extraction_dir: Path = field(init=False, repr=True) | ||
| #: Optional number of log events in the downloaded logs. | ||
| num_log_events: int | None = None | ||
|
Comment on lines
+318
to
+319
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validate
Proposed fix def __post_init__(self, integration_test_path_config: IntegrationTestPathConfig) -> None:
"""Initialize and set tarball and extraction paths for integration test logs."""
+ if self.num_log_events is not None and self.num_log_events < 0:
+ err_msg = "`num_log_events` cannot be negative."
+ raise ValueError(err_msg)
+
name = self.name.strip()
if 0 == len(name):
err_msg = "`name` cannot be empty."
raise ValueError(err_msg)🤖 Prompt for AI Agents |
||
|
|
||
| def __post_init__(self, integration_test_path_config: IntegrationTestPathConfig) -> None: | ||
| """Initialize and set tarball and extraction paths for integration test logs.""" | ||
|
|
@@ -358,3 +365,38 @@ def clear_test_outputs(self) -> None: | |
| """Remove any existing output directories created by this compression test.""" | ||
| remove_path(self.compression_dir) | ||
| remove_path(self.decompression_dir) | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class ConversionTestPathConfig: | ||
| """Per-test path configuration for conversion workflow artifacts.""" | ||
|
|
||
| #: | ||
| test_name: str | ||
| #: Directory containing the original (uncompressed) log files used by this test. | ||
| logs_source_dir: Path | ||
| integration_test_path_config: InitVar[IntegrationTestPathConfig] | ||
| #: Path to store converted kv-ir files generated by the test. | ||
| conversion_dir: Path = field(init=False, repr=True) | ||
| #: Path to store compressed archives generated by the test. | ||
| compression_dir: Path = field(init=False, repr=True) | ||
| #: Optional number of log events in the converted logs. | ||
| num_log_events: int | None = None | ||
|
|
||
| def __post_init__(self, integration_test_path_config: IntegrationTestPathConfig) -> None: | ||
| """Initialize and set required directory paths for conversion tests.""" | ||
| test_name = self.test_name.strip() | ||
| if 0 == len(test_name): | ||
| err_msg = "`test_name` cannot be empty." | ||
| raise ValueError(err_msg) | ||
| test_root_dir = integration_test_path_config.test_root_dir | ||
| validate_dir_exists(test_root_dir) | ||
|
|
||
| object.__setattr__(self, "test_name", test_name) | ||
| object.__setattr__(self, "conversion_dir", test_root_dir / f"{test_name}-converted") | ||
| object.__setattr__(self, "compression_dir", test_root_dir / f"{test_name}-archives") | ||
|
|
||
|
Comment on lines
+386
to
+398
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add existence validation for
Proposed fix def __post_init__(self, integration_test_path_config: IntegrationTestPathConfig) -> None:
"""Initialize and set required directory paths for conversion tests."""
test_name = self.test_name.strip()
if 0 == len(test_name):
err_msg = "`test_name` cannot be empty."
raise ValueError(err_msg)
+ validate_dir_exists(self.logs_source_dir)
test_root_dir = integration_test_path_config.test_root_dir
validate_dir_exists(test_root_dir)🤖 Prompt for AI Agents |
||
| def clear_test_outputs(self) -> None: | ||
| """Remove any existing output directories created by this conversion test.""" | ||
| remove_path(self.conversion_dir) | ||
| remove_path(self.compression_dir) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Add regression tests for the exact timezone edge cases fixed here.
Please add automated coverage for at least: no timezone, lone space,
" Z"," UTC"," +05:30", and"UTC+05:30"so this parser/serializer boundary doesn’t regress again.🤖 Prompt for AI Agents