Skip to content

feat: add basic fuzz testing#1896

Merged
exploreriii merged 14 commits intohiero-ledger:mainfrom
AntonioCeppellini:1872-implement-fuzzing
Mar 26, 2026
Merged

feat: add basic fuzz testing#1896
exploreriii merged 14 commits intohiero-ledger:mainfrom
AntonioCeppellini:1872-implement-fuzzing

Conversation

@AntonioCeppellini
Copy link
Copy Markdown
Member

@AntonioCeppellini AntonioCeppellini commented Mar 1, 2026

Description:
This PR adds:

Related issue(s):
Fixes #1872

Important notes for reviewer:

  1. First time doing fuzz testing ULTRA open to any kind of suggestion.

  2. Two fuzz tests are failing here:

========================================================================================== FAILURES ==========================================================================================
_________________________________________________________________________ test_hbar_from_string_accepts_valid_inputs _________________________________________________________________________

    @given(case=get_strategy("hbar_valid_string"))
>   def test_hbar_from_string_accepts_valid_inputs(case: HbarStringCase) -> None:
                   ^^^

tests/fuzz/test_hbar_fuzz.py:22: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/fuzz/test_hbar_fuzz.py:25: in test_hbar_from_string_accepts_valid_inputs
    _assert_hbar_invariants(parsed, case.tinybars)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

value = Hbar(90071992.54740994), expected_tinybars = 9007199254740993

    def _assert_hbar_invariants(value: Hbar, expected_tinybars: int) -> None:
>       assert value.to_tinybars() == expected_tinybars
E       assert 9007199254740992 == 9007199254740993
E        +  where 9007199254740992 = to_tinybars()
E        +    where to_tinybars = Hbar(90071992.54740994).to_tinybars
E       Falsifying example: test_hbar_from_string_accepts_valid_inputs(
E           case=(lambda tinybars: _hbar_string_case(HbarUnit.HBAR, tinybars))(
E               9_007_199_254_740_993,
E           ),
E       )

tests/fuzz/test_hbar_fuzz.py:14: AssertionError
________________________________________________________________________ test_hbar_constructor_preserves_exact_value _________________________________________________________________________

    @given(case=get_strategy("hbar_valid_constructor"))
>   def test_hbar_constructor_preserves_exact_value(case: HbarConstructorCase) -> None:
                   ^^^

tests/fuzz/test_hbar_fuzz.py:36: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/fuzz/test_hbar_fuzz.py:39: in test_hbar_constructor_preserves_exact_value
    _assert_hbar_invariants(parsed, case.tinybars)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

value = Hbar(90071992.54740994), expected_tinybars = 9007199254740993

    def _assert_hbar_invariants(value: Hbar, expected_tinybars: int) -> None:
>       assert value.to_tinybars() == expected_tinybars
E       assert 9007199254740992 == 9007199254740993
E        +  where 9007199254740992 = to_tinybars()
E        +    where to_tinybars = Hbar(90071992.54740994).to_tinybars
E       Falsifying example: test_hbar_constructor_preserves_exact_value(
E           case=(lambda tinybars: _hbar_constructor_case(HbarUnit.TINYBAR, tinybars))(
E               9_007_199_254_740_993,
E           ),
E       )

tests/fuzz/test_hbar_fuzz.py:14: AssertionError
================================================================================== short test summary info ===================================================================================
FAILED tests/fuzz/test_hbar_fuzz.py::test_hbar_from_string_accepts_valid_inputs - assert 9007199254740992 == 9007199254740993
FAILED tests/fuzz/test_hbar_fuzz.py::test_hbar_constructor_preserves_exact_value - assert 9007199254740992 == 9007199254740993
=============================================================================== 2 failed, 35 passed in 27.87s ================================================================================

and this could be good because it could be a bug and we found it or, maybe I could make a softer check because i'm checking quite extreme values.
BUT we are a losing right now SMAAAAAAAAAAAAAALLLLLLLLLLLLLLLLL values and it could be a HUUUUUGE problem because we are talking about money.

To resolve the failing tests i applied a small change in hbar file

FINAL CONSIDERATION
The two failing tests could be my errors :D

Checklist

  • Documented (Code comments)
  • Documented (README, ecc)
  • Tested (unit, fuzz)

Signed-off-by: Antonio Ceppellini <antonio.ceppellini@gmail.com>
Signed-off-by: Antonio Ceppellini <antonio.ceppellini@gmail.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 1, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1896      +/-   ##
==========================================
+ Coverage   93.66%   93.68%   +0.02%     
==========================================
  Files         144      144              
  Lines        9348     9348              
==========================================
+ Hits         8756     8758       +2     
+ Misses        592      590       -2     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 1, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds Hypothesis-based fuzz testing: dev dependency and pytest marker, .hypothesis ignored, a fuzz test package with a comprehensive conftest.py providing dataclasses and strategies, and multiple new property-based test modules for IDs, Hbar, keys, contract params, and Transaction.from_bytes.

Changes

Cohort / File(s) Summary
Build & Config
​.gitignore, CHANGELOG.md, pyproject.toml, pytest.ini
Added .hypothesis/ to ignore, documented fuzz tests in CHANGELOG.md, added hypothesis>=6.0 to dev dependencies, and defined a fuzz pytest marker.
Fuzz package & registry
tests/fuzz/__init__.py, tests/fuzz/conftest.py
New fuzz test package initializer and a large conftest.py that defines dataclasses, Hypothesis profiles, many strategies for SDK types, helpers to build valid/invalid payloads/transactions, FUZZ_STRATEGIES registry, get_strategy() accessor, and pytest fixtures.
Contract parameters tests
tests/fuzz/test_contract_function_parameters_fuzz.py
Property-based tests for ContractFunctionParameters covering valid encodings, invalid-value rejection with specific exception types, and deterministic encoding assertions.
Entity ID tests
tests/fuzz/test_entity_id_fuzz.py
Fuzz tests for AccountId, TokenId, and ContractId parsing, canonicalization, alias/EVM forms, checksum handling, and invalid-input rejection.
Hbar tests & runtime tweak
tests/fuzz/test_hbar_fuzz.py, src/hiero_sdk_python/hbar.py, tests/unit/hbar_test.py
Added Hbar fuzz tests and unit tests for large values and non-finite Decimals; minor Hbar changes: Decimal finiteness check, fractional tinybar validation tweak, and to_tinybars() returning internal tinybar value.
Key handling tests
tests/fuzz/test_keys_fuzz.py
Fuzz tests for PrivateKey/PublicKey roundtrips from strings/bytes, canonical encodings, invalid-input expectations, and is_ed25519 consistency.
Transaction.from_bytes tests
tests/fuzz/test_transaction_from_bytes_fuzz.py
Fuzz tests validating Transaction.from_bytes round-trip for valid payloads and rejection of empty, truncated, corrupted, or random payloads.

Sequence Diagram(s)

(Skipped — changes add test infra and tests; no new multi-component sequential runtime flow requiring visualization.)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 76.81% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: add basic fuzz testing' clearly and concisely summarizes the main change, which is the introduction of basic fuzz testing functionality to the SDK.
Description check ✅ Passed The description provides relevant context about adding the Hypothesis package, creating a tests/fuzz/ folder with multiple test files, and acknowledges failing tests and precision issues discovered during fuzzing.
Linked Issues check ✅ Passed The PR addresses the core objectives of #1872: researching fuzzing (Hypothesis selected), implementing a basic fuzz suite with five test modules covering entity IDs, Hbar, keys, contract parameters, and transactions, validating SDK types, and including a changelog entry. Tests are included but documentation updates are incomplete.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing basic fuzz testing as specified in #1872. The only non-fuzz changes (Hbar modifications for finiteness validation and precision handling) are necessary to resolve issues discovered by the fuzz tests themselves.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📋 Issue Planner

Built with CodeRabbit's Coding Plans for faster development and fewer bugs.

View plan used: #1872

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 12


ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3bad42a and 6879f4c.

📒 Files selected for processing (11)
  • .gitignore
  • CHANGELOG.md
  • pyproject.toml
  • pytest.ini
  • tests/fuzz/__init__.py
  • tests/fuzz/conftest.py
  • tests/fuzz/test_contract_function_parameters_fuzz.py
  • tests/fuzz/test_entity_id_fuzz.py
  • tests/fuzz/test_hbar_fuzz.py
  • tests/fuzz/test_keys_fuzz.py
  • tests/fuzz/test_transaction_from_bytes_fuzz.py

Comment thread .gitignore Outdated
Comment thread pyproject.toml Outdated
Comment thread tests/fuzz/__init__.py
Comment thread tests/fuzz/conftest.py Outdated
Comment thread tests/fuzz/conftest.py Outdated
Comment thread tests/fuzz/test_contract_function_parameters_fuzz.py
Comment thread tests/fuzz/test_entity_id_fuzz.py
Comment thread tests/fuzz/test_hbar_fuzz.py
Comment thread tests/fuzz/test_hbar_fuzz.py
Comment thread tests/fuzz/test_keys_fuzz.py
@exploreriii exploreriii added status: needs triage review reviewer: maintainer PR needs a review from the maintainer team labels Mar 1, 2026
@mizoz
Copy link
Copy Markdown
Contributor

mizoz commented Mar 4, 2026

Great work introducing fuzz testing to the Python SDK, @AntonioCeppellini! This is a valuable addition that will help catch edge cases we might miss with traditional unit tests.

A few thoughts on the failing Hbar tests:

On the failing tests (test_hbar_from_string_accepts_valid_inputs and test_hbar_constructor_preserves_exact_value):

The assertion failure at 9007199254740993 → 9007199254740992 suggests floating-point precision loss when dealing with extreme values near Number.MAX_SAFE_INTEGER (2⁵³ - 1 = 9,007,199,254,740,991).

Options to consider:

  1. Document the limitation: If this is expected behavior due to float64 precision, add a note in the Hbar class docs about the safe range for string parsing, and adjust the fuzz test strategy to exclude values beyond MAX_SAFE_INTEGER.

  2. Use Decimal for precision: If Hbar needs to handle values beyond float64 precision accurately, consider using decimal.Decimal internally for the conversion logic (though this may have performance implications).

  3. Soak the assertion: For fuzz testing purposes, you could add a tolerance check for extreme values while keeping exact assertions for the normal range:

    if abs(expected_tinybars) < 2**53:
        assert value.to_tinybars() == expected_tinybars
    else:
        # Allow for float64 precision loss at extreme ranges
        assert abs(value.to_tinybars() - expected_tinybars) <= 1

Given this is testing money-related values, I'd lean toward option 1 (document and constrain the input range) unless there's a specific requirement to handle values beyond float64 precision.

Minor suggestions:

  • Consider adding a README.md in tests/fuzz/ explaining how to run fuzz tests and interpret failures
  • The hypothesis deadline might need adjustment for complex strategies (you can use @settings(deadline=...) if needed)

Excellent initiative on bringing property-based testing to the SDK! This will definitely improve our confidence in edge case handling. 🎯

Signed-off-by: Antonio Ceppellini <antonio.ceppellini@gmail.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
.gitignore (1)

34-35: ⚠️ Potential issue | 🟡 Minor

Fix the Hypothesis cache directory typo.

.hypotesis/ is misspelled and will not ignore Hypothesis state artifacts. Use .hypothesis/ instead.

Suggested patch
 # Hypothesis state
-.hypotesis/
+.hypothesis/

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8becebd3-8304-4040-90be-e0631e79e5ca

📥 Commits

Reviewing files that changed from the base of the PR and between 6879f4c and 5fbfede.

📒 Files selected for processing (1)
  • .gitignore

Signed-off-by: Antonio Ceppellini <antonio.ceppellini@gmail.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 5, 2026

Hi, this is WorkflowBot.
Your pull request cannot be merged as it is not passing all our workflow checks.
Please click on each check to review the logs and resolve issues so all checks pass.
To help you:

Copy link
Copy Markdown
Contributor

@MonaaEid MonaaEid left a comment

Choose a reason for hiding this comment

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

I think the tests are very good ..for the errors I believe that we should ban floats from internal representation and return decimal instead of float in conversions, we should implement this change to ensure the tests pass, and possibly open a new issue for it.

@github-actions
Copy link
Copy Markdown

Hello, this is the OfficeHourBot.

This is a reminder that the Hiero Python SDK Office Hours are scheduled in approximately 4 hours (14:00 UTC).

This session provides an opportunity to ask questions regarding this Pull Request.

Details:

Disclaimer: This is an automated reminder. Please verify the schedule here for any changes.

From,
The Python SDK Team

…id float precision loss

Signed-off-by: Antonio Ceppellini <antonio.ceppellini@gmail.com>
Signed-off-by: Antonio Ceppellini <antonio.ceppellini@gmail.com>
Signed-off-by: Antonio Ceppellini <antonio.ceppellini@gmail.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 04368ca4-1e51-490e-ae22-d3c718f4fc55

📥 Commits

Reviewing files that changed from the base of the PR and between ae840aa and 4f9018f.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • tests/unit/hbar_test.py

Comment thread tests/unit/hbar_test.py
@AntonioCeppellini
Copy link
Copy Markdown
Member Author

@MonaaEid @exploreriii i have made a small change in file hbar.py and added unit tests to cover it, i'm not sure why the changelog check is failing and why my asserts are also causing warnings...
i'm pretty srure to have written the entry in changelog file under unreleased section but my head is quite fried right now so i can be wrong, please help me check it 🤣

@MonaaEid
Copy link
Copy Markdown
Contributor

@MonaaEid @exploreriii i have made a small change in file hbar.py and added unit tests to cover it, i'm not sure why the changelog check is failing and why my asserts are also causing warnings...
i'm pretty srure to have written the entry in changelog file under unreleased section but my head is quite fried right now so i can be wrong, please help me check it 🤣

The changelog is not updated this is the old version.. the assert warning I think we should ignore the B101 it in the pyprojet.toml

Comment thread tests/fuzz/conftest.py Outdated
Comment thread tests/fuzz/conftest.py Outdated
Copy link
Copy Markdown
Contributor

@exploreriii exploreriii left a comment

Choose a reason for hiding this comment

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

Hi @AntonioCeppellini
Well done with this
Problem this is so difficult to review, for many reasons
Could we settle on a middle ground where the conftest in particular is made a bit more user friendly, which will help us expand this in the future as we add more tests?

Comment thread tests/fuzz/conftest.py Outdated
Comment thread tests/fuzz/conftest.py Outdated
Comment thread tests/fuzz/conftest.py Outdated
Comment thread tests/fuzz/conftest.py Outdated
@exploreriii
Copy link
Copy Markdown
Contributor

Ok so i know this is basic fuzz testing - but we will need it to be solid enough for others to build from

maybe something like this can be more maintaiable:
strategies/
entity_ids.py
keys.py
hbar.py
transactions.py
contracts.py

test_entity_ids.py
test_keys.py
test_hbar.py
test_transactions.py
test_contract_parameters.py

and maybe eg
infra/
profiles.py
registry.py
helpers.py
classes.py
etc

Later we could try:

  • several parameters
  • increase size random payloads
  • cross encoding stability
  • move assertions out of helpers, so they return instead
  • add random mutations
    but we need to make sure current tests are organised enough to remember where to proceed next

@exploreriii exploreriii marked this pull request as draft March 14, 2026 23:20
AntonioCeppellini and others added 3 commits March 19, 2026 14:28
Signed-off-by: Antonio Ceppellini <antonio.ceppellini@gmail.com>
Signed-off-by: Antonio Ceppellini <antonio.ceppellini@gmail.com>
@AntonioCeppellini AntonioCeppellini marked this pull request as ready for review March 19, 2026 13:38
@exploreriii
Copy link
Copy Markdown
Contributor

Hi @AntonioCeppellini could you please rebase, there was a tck issue on accounts that got merged which may have touched similar areas to you

Copy link
Copy Markdown
Contributor

@exploreriii exploreriii left a comment

Choose a reason for hiding this comment

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

Love it! So much easier to maintain and understand
Just final tidy please

Comment thread tests/fuzz/support/registry.py
AntonioCeppellini and others added 4 commits March 25, 2026 16:40
Signed-off-by: Antonio Ceppellini <antonio.ceppellini@gmail.com>
Signed-off-by: Antonio Ceppellini <antonio.ceppellini@gmail.com>
Signed-off-by: Antonio Ceppellini <antonio.ceppellini@gmail.com>
@AntonioCeppellini AntonioCeppellini marked this pull request as ready for review March 25, 2026 16:15
@exploreriii exploreriii requested a review from MonaaEid March 25, 2026 23:17
Copy link
Copy Markdown
Contributor

@exploreriii exploreriii left a comment

Choose a reason for hiding this comment

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

Really nice work

@exploreriii exploreriii merged commit 0a71cd3 into hiero-ledger:main Mar 26, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

reviewer: maintainer PR needs a review from the maintainer team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Advanced]: Implement (basic) fuzzing

4 participants