Skip to content

feat(xtest): add audit cancel event tests#411

Draft
dmihalcik-virtru wants to merge 3 commits intoopentdf:mainfrom
dmihalcik-virtru:feat/xtest-audit-cancel
Draft

feat(xtest): add audit cancel event tests#411
dmihalcik-virtru wants to merge 3 commits intoopentdf:mainfrom
dmihalcik-virtru:feat/xtest-audit-cancel

Conversation

@dmihalcik-virtru
Copy link
Member

Summary

  • Add test_audit_cancel.py with 340 lines of test coverage for deferred/cancel audit event guarantees

Parent PRs

Test plan

  • cd xtest && uv run ruff check . && uv run pyright
  • With platform: uv run pytest test_audit_cancel.py --sdks go -v

🤖 Generated with Claude Code

Part of stacked PR series decomposing chore/the-claudiest-day-tmux

dmihalcik-virtru and others added 3 commits February 12, 2026 20:12
Bump pyright from 1.1.380 to 1.1.408 and alphabetize dev
dependency ordering in pyproject.toml.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: David Mihalcik <dmihalcik@virtru.com>
Replace busy-wait polling with condition-based wakeup using
threading.Condition. Improve clock skew handling with explicit
timezone support. Add frozenset constants for audit types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: David Mihalcik <dmihalcik@virtru.com>
Add test coverage for deferred/cancel audit event guarantees
with 340-line test file covering cancel audit event scenarios.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: David Mihalcik <dmihalcik@virtru.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @dmihalcik-virtru, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the robustness and reliability of audit log testing by introducing new integration tests for deferred audit event guarantees, particularly focusing on scenarios involving client disconnections. It refines the underlying audit log collection mechanism for improved efficiency and clarity, ensuring that audit events are consistently captured and accurately reflect various operation outcomes. Additionally, it updates related test fixtures and dependencies to support these new testing capabilities.

Highlights

  • New Audit Cancel Event Tests: Added test_audit_cancel.py with 340 lines of integration tests to verify deferred/cancel audit event guarantees, ensuring events are logged even during client disconnections.
  • Improved Audit Log Collection Efficiency: The AuditLogCollector now uses threading.Condition instead of time.sleep() for more efficient waiting and notification of new log data, leading to more responsive log assertions.
  • Refactored Audit Event Constants: Audit event constants (ObjectType, ActionType, ActionResult, AuditVerb) in audit_logs.py were converted from Literal types to frozensets and individual string constants for better maintainability and static analysis.
  • New Attribute Fixture for RSA Wrapping: Introduced attribute_default_rsa fixture in xtest/fixtures/attributes.py to provide an attribute with explicit RSA key mapping, ensuring consistent test behavior regardless of platform base_key configuration.
  • Updated pyright Dependency: The pyright development dependency has been updated to version 1.1.408 in pyproject.toml and uv.lock.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • xtest/audit_logs.py
    • Improved timezone handling for collection_time in record_sample and observed_skew.
    • Refactored audit event constants from Literal types to frozensets and string constants.
    • Added threading.Condition to AuditLogCollector for efficient new data notification.
    • Modified AuditLogCollector.start to handle log files that don't exist yet more gracefully.
    • Modified AuditLogCollector.stop to notify waiting threads upon shutdown.
    • Introduced AuditLogCollector.wait_for_new_data for blocking until new log data arrives.
    • Updated _tail_file to batch-read lines and notify _new_data condition.
    • Added is_enabled property to AuditLogAsserter.
    • Replaced time.sleep(0.1) with self._collector.wait_for_new_data in various assertion methods for improved responsiveness.
    • Updated parse_audit_log to use new verb constants.
  • xtest/fixtures/attributes.py
    • Added attribute_default_rsa fixture to provide an attribute with RSA key mapping for tests requiring explicit RSA wrapping.
  • xtest/pyproject.toml
    • Updated pyright dependency version.
  • xtest/test_audit_cancel.py
    • Added new test file with integration tests for deferred/cancel audit event guarantees.
    • Implemented _build_decrypt_command, _launch_and_kill_staggered, and _collect_rewrap_events helper functions.
    • Included tests for rewrap audit on success, client disconnect, and metadata presence on cancel.
  • xtest/test_audit_logs.py
    • Imported new audit constants.
    • Added TestAuditConstants class to verify the new frozenset and string constants.
    • Removed pytest.approx from ClockSkewEstimate and AuditLogAsserter skew assertions for exact float comparisons.
  • xtest/test_audit_logs_integration.py
    • Added skip_if_audit_disabled fixture to skip tests if audit log collection is not enabled.
    • Updated test_rewrap_success_fields, test_rewrap_failure_access_denied, test_audit_logs_on_tampered_file, and test_audit_under_sequential_load to use the new attribute_default_rsa fixture.
    • Modified test_rewrap_failure_access_denied description and logic to reflect access denied scenario.
    • Updated test_attribute_crud_audit to reflect that attribute values are embedded in the attribute definition event.
    • Made decision log assertion optional in test_decision_on_successful_access.
    • Removed unused base64 import.
  • xtest/uv.lock
    • Updated pyright dependency version.
Activity
  • A new test file, test_audit_cancel.py, was added, contributing 340 lines of new test coverage.
  • The pull request builds upon a parent PR, #408 (fix/xtest-audit-framework).
  • The author provided a detailed test plan, including commands for ruff check, pyright, and pytest execution.
  • The PR description indicates that it was generated using Claude Code and is part of a larger stacked PR series.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a comprehensive test suite for deferred audit event guarantees, particularly focusing on client cancellation scenarios. The changes in audit_logs.py to use threading.Condition for more efficient log waiting are a significant improvement. The new tests in test_audit_cancel.py are well-structured and provide good coverage for this critical feature.

My review includes a few suggestions to improve code quality and test clarity:

  • Simplifying some redundant conditional logic in audit_logs.py.
  • Aligning test names and docstrings with their implementations in test_audit_logs_integration.py to avoid confusion.
  • Adhering to PEP 8 for import statements.

Overall, this is a solid contribution that enhances the robustness of the audit logging tests.

Comment on lines +198 to +202
if collection_time.tzinfo is None:
# Assume local time, convert to UTC
collection_utc = collection_time.astimezone(UTC)
else:
collection_utc = collection_time.astimezone(UTC)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This if/else block is redundant as both branches execute the same code: collection_utc = collection_time.astimezone(UTC). The astimezone() method correctly handles both naive and timezone-aware datetime objects. You can simplify this by reverting to the single line of code that was here previously.

        collection_utc = collection_time.astimezone(UTC)

Comment on lines +365 to +368
if collection_t.tzinfo is None:
collection_utc = collection_t.astimezone(UTC)
else:
collection_utc = collection_t.astimezone(UTC)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to a previous change, this if/else block is redundant. Both branches contain the same code, and astimezone() can handle both naive and aware datetime objects correctly. This can be simplified to a single line.

        collection_utc = collection_t.astimezone(UTC)

Comment on lines +200 to +203
def test_namespace_crud_audit(
self, otdfctl: OpentdfCommandLineTool, audit_logs: AuditLogAsserter
):
"""Test namespace creation audit trail."""
"""Test namespace create/update/delete audit trail."""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test is named test_namespace_crud_audit and the docstring mentions testing the 'create/update/delete audit trail', but the implementation only tests the 'create' part. This is misleading. To improve clarity, please either expand the test to cover update and delete operations, or rename it to test_namespace_create_audit to accurately reflect its scope.

Comment on lines +217 to 220
def test_attribute_crud_audit(
self, otdfctl: OpentdfCommandLineTool, audit_logs: AuditLogAsserter
):
"""Test attribute and value creation audit trail."""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test is named test_attribute_crud_audit, which implies it tests create, read, update, and delete operations for attributes. However, the implementation only covers the creation of an attribute and its values. Please consider expanding the test to cover other CRUD operations or rename it to test_attribute_create_audit for clarity.

Comment on lines +385 to +391
import base64

h = pb.hash
altered = base64.b64encode(b"tampered" + base64.b64decode(h)[:8])
pb.hash = str(altered)
else:
import base64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The import base64 statements are placed inside the tamper_policy_binding function. According to PEP 8, imports should be at the top of the file. Please move these imports to the top of the file to adhere to Python's standard style guide. It seems import base64 was removed from the top of the file in this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant