Skip to content

Conversation

@kami922
Copy link
Contributor

@kami922 kami922 commented Jan 21, 2026

Summary

Implements dynamic file discovery for test fixtures, addressing issue #1743.

This is a cleaned-up resubmission of #2802, incorporating maintainer feedback.

Background

Issue #1743 requested adding get_sample_short_name_by_md5() as the inverse of the existing get_sample_md5_by_name() function. The previous PR #2802 was closed with feedback to follow the original issue's vision of using dynamic discovery instead of maintaining hardcoded lists.

Problem

The codebase maintains hardcoded lists of file names and MD5 hashes in get_sample_md5_by_name(), requiring manual updates whenever test samples are added. This creates maintenance burden and potential for errors.

Solution

This PR implements dynamic sample discovery as requested by @williballenthin in #1743:

  • _build_sample_cache() - Walks tests/data/ directory once at module import time
  • Auto-indexing - Samples indexed by MD5, SHA256, filename, and stem
  • get_sample_short_name_by_md5() - Reverse MD5→name lookup using the dynamic cache
  • Comprehensive tests - Parametrized tests for forward/reverse lookups and roundtrips

Benefits

  • Zero maintenance: New test files are automatically discovered
  • No manual hashing: Eliminates typo errors in 32-char MD5 strings
  • Scalable: Code size stays constant regardless of sample count
  • Fast: O(1) lookup performance via dictionary cache
  • Foundation for future work: Enables generic lookup functions as discussed in fixtures: add function to resolve sample shortened name by MD5 #1743

Implementation Details

Follows the approach suggested by @williballenthin in #1743:

"we should tear a lot of that down and provide some generic routines that use os.walk to find the requested file"

Implementation is similar to collect_samples() in scripts/lint.py, as referenced in the issue discussion.

Changes

  • tests/fixtures.py: Add cache building and reverse lookup function (+90 lines)
  • tests/test_fixtures.py: Add parametrized tests for lookups and roundtrips (+126 lines)

Testing

pytest [test_fixtures.py](http://_vscodecontentref_/0) -v

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @kami922, 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 introduces a significant improvement to how test fixtures are managed by transitioning from a brittle, manually updated system to a dynamic, automated discovery and indexing mechanism. By building a comprehensive cache of test samples at module import, it enables efficient lookups by various identifiers, including a new reverse MD5-to-name lookup. This enhancement not only streamlines the process of adding new test data but also boosts the reliability and scalability of the testing infrastructure.

Highlights

  • Dynamic Sample Discovery: Implemented _build_sample_cache() to automatically discover test fixtures by walking the tests/data/ directory at module import time, replacing manual updates.
  • Automated Indexing: Samples are now indexed by MD5, SHA256, filename, and filename stem, providing flexible lookup capabilities.
  • Reverse MD5 Lookup: A new function, get_sample_short_name_by_md5(), has been added to perform reverse lookups from an MD5 hash to the sample's short name.
  • Comprehensive Testing: A new test file, tests/test_fixtures.py, introduces parametrized tests for both forward and reverse lookups, including roundtrip validation, ensuring the robustness of the new system.
  • Reduced Maintenance: This change eliminates the need for hardcoded lists of file names and MD5 hashes, significantly reducing maintenance burden and potential for errors.

🧠 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.

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.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Please add bug fixes, new features, breaking changes and anything else you think is worthwhile mentioning to the master (unreleased) section of CHANGELOG.md. If no CHANGELOG update is needed add the following to the PR description: [x] No CHANGELOG update needed

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 dynamic sample discovery and a reverse MD5 lookup function, significantly improving the maintainability and scalability of test fixtures. The new _build_sample_cache function efficiently indexes samples by various attributes, and get_sample_short_name_by_md5 provides a convenient way to retrieve sample names from their MD5 hashes. Comprehensive tests have been added to validate the new functionality, including forward, reverse, and round-trip lookups. Overall, this is a well-implemented solution that addresses the maintenance burden of hardcoded lists.

cache[md5.upper()] = path

# Index by filename
cache[path.name] = path
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 cache uses path.name as a key for indexing by filename. If there are multiple files with the same name but in different subdirectories (e.g., data/subdir1/file.txt and data/subdir2/file.txt), only the last encountered file will be stored in the cache for that path.name. This could lead to unexpected behavior if a specific file is expected when looking up by filename. Consider if path.name is guaranteed to be unique across all samples, or if a more robust key (e.g., relative path) is needed for filename lookups to prevent collisions.

raise ValueError(f"unexpected sample fixture: {name}")


def get_sample_short_name_by_md5(md5):
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Please add a type hint for the md5 parameter to improve code readability and enable static analysis. Based on the docstring, str would be appropriate.

Suggested change
def get_sample_short_name_by_md5(md5):
def get_sample_short_name_by_md5(md5: str):

"""Test reverse MD5 lookup returns correct sample name."""
result = get_sample_short_name_by_md5(md5)
# The result should match the expected name (or be a prefix for hash-named files)
assert name in result or result in name
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

For SIMPLE_SAMPLES, the get_sample_short_name_by_md5 function should return the exact name (e.g., "mimikatz"). The current assertion assert name in result or result in name is too broad and might pass even if the stem extraction is not perfectly accurate (e.g., if it returns "mimikatz.exe"). Please change this to an exact equality check.

Suggested change
assert name in result or result in name
assert result == name

md5 = get_sample_md5_by_name(name)
result_name = get_sample_short_name_by_md5(md5)
# For simple names, result should contain the original name
assert name in result_name or result_name in name
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 test_reverse_lookup, for SIMPLE_SAMPLES, the round-trip lookup should result in an exact match for the name. The current assertion assert name in result_name or result_name in name is too lenient. Please update it to assert result_name == name for precise validation.

Suggested change
assert name in result_name or result_name in name
assert result_name == name

@github-actions github-actions bot dismissed their stale review January 21, 2026 21:20

CHANGELOG updated or no update needed, thanks! 😄

@kami922
Copy link
Contributor Author

kami922 commented Jan 21, 2026

@mike-hunhoff @mr-tz Hello I am working on CI failed tests meanwhile can you please tell me is running CI tests locally Via "act" a good approach? so I can see failed tests and fix them before committing and pushing. currently I am not following this approach if yes could you also tell me few guidelines and best practices related to this project.

@williballenthin
Copy link
Collaborator

using "act" is fine. sometimes i do this to avoid waiting for the round trip of committing, pushing, and waiting for GH Actions to spawn and complete.

i'm not quite sure what hints would help. i'd suggest running the linters, formatters, and tests before submitting a PR. what else?

@kami922
Copy link
Contributor Author

kami922 commented Jan 21, 2026

using "act" is fine. sometimes i do this to avoid waiting for the round trip of committing, pushing, and waiting for GH Actions to spawn and complete.

i'm not quite sure what hints would help. i'd suggest running the linters, formatters, and tests before submitting a PR. what else?

ok alot of tests are failing currently I will fix them. but one confusion I am having currently regarding running act locally is that I think act might take a lot of disk space of my laptop even tho docker image is pulled and current failing tests might according to my comprehension are related to OS. anyways I will experiment with it then fix it and commit again

Walk the tests/data directory at module import time to build a cache
indexed by MD5, SHA256, filename, and stem. Add get_sample_short_name_by_md5()
for reverse lookups, eliminating the need for hardcoded hash mappings.

Closes mandiant#1743
@kami922 kami922 force-pushed the fix-1743-dynamic-sample-discovery branch from d9b662c to 98227bf Compare January 26, 2026 14:24
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.

2 participants