Skip to content

chore(minikupo): Add comprehensive tests#939

Open
gonzalezzfelipe wants to merge 2 commits intomainfrom
chore/minikupo-tests
Open

chore(minikupo): Add comprehensive tests#939
gonzalezzfelipe wants to merge 2 commits intomainfrom
chore/minikupo-tests

Conversation

@gonzalezzfelipe
Copy link
Contributor

@gonzalezzfelipe gonzalezzfelipe commented Mar 10, 2026

  • Includes testing of minibf scripts endpoints

Summary by CodeRabbit

  • Tests

    • Added comprehensive test suites for API endpoints covering success paths, error handling, and edge cases.
    • Introduced test infrastructure and helpers to standardize testing across modules.
  • Chores

    • Added development dependencies to support testing infrastructure.

@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

This PR adds comprehensive test coverage and test infrastructure across minibf and minikupo crates. It introduces TestDomainBuilder and TestApp utilities for HTTP testing, adds test modules for multiple route handlers (scripts, datums, health, matches, metadata), and extends synthetic fixture generation to include datum and script data with CBOR encodings.

Changes

Cohort / File(s) Summary
Test Infrastructure
crates/minikupo/Cargo.toml, crates/minikupo/src/lib.rs, crates/minikupo/src/test_support.rs
Adds dev-dependencies (dolos-testing, tower, http-body-util) and introduces TestDomainBuilder and TestApp for constructing synthetic test environments with HTTP request capabilities and fault injection support.
Synthetic Fixtures Extension
crates/testing/src/synthetic.rs
Extends SyntheticVectors with new metadata fields (policy_id, asset_name_hex, datum_hash, datum_cbor_hex, script_hash, script_cbor_hex); refactors transaction assembly to use SyntheticTxSpec carrying both body and witness sets with embedded datum/script fixture data.
minibf Route Tests
crates/minibf/src/routes/scripts.rs
Adds test module covering by_hash, by_hash_json, by_hash_cbor, by_datum_hash, and by_datum_hash_cbor endpoints with happy path, not found, and internal error scenarios.
minikupo Route Tests
crates/minikupo/src/routes/datums.rs, crates/minikupo/src/routes/health.rs, crates/minikupo/src/routes/matches.rs, crates/minikupo/src/routes/metadata.rs, crates/minikupo/src/routes/scripts.rs
Adds comprehensive test suites for all route endpoints covering happy paths, error conditions, filtering/ordering behavior, and validation error scenarios with assertions on status codes, response payloads, and headers.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • scarmuega

Poem

🐰 Hops with glee through test-filled days,
Scripts and datums now have ways,
TestApp builders, fixtures bright,
Code is covered—what delight!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'chore(minikupo): Add comprehensive tests' is partially related to the changeset but overly broad; it doesn't specify which components are being tested. Consider a more specific title that highlights the main testing additions, such as 'chore(minikupo, minibf): Add comprehensive endpoint tests' to better reflect the scope of added test coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/minikupo-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

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

🧹 Nitpick comments (3)
crates/minibf/src/routes/scripts.rs (2)

172-182: Add a same-length non-hex case for the parser decode branch.

invalid_script_hash() and invalid_datum_hash() are only invalid because of length, so the new *_invalid_hash tests never exercise the hex::decode failure path in parse_script_hash / parse_datum_hash. Please add a 56/64-character non-hex case as well, otherwise a regression there can slip through while these tests still pass.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/minibf/src/routes/scripts.rs` around lines 172 - 182, Tests only cover
length-invalid hashes; add same-length non-hex variants so the hex::decode
failure path in parse_script_hash and parse_datum_hash is exercised: add
functions (e.g. invalid_script_hash_nonhex returning a 56-char non-hex string
like repeated 'g' and invalid_datum_hash_nonhex returning a 64-char non-hex
string) and update the *_invalid_hash tests to include/replace a case using
these new functions so parse_script_hash and parse_datum_hash hit the hex decode
error branch.

198-286: Plutus script responses are still untested.

Line 214 locks the shared fixture to ScriptType::Timelock, so the happy-path coverage here only exercises the native-script branch. That leaves the materially different Plutus behavior unverified for /scripts/{hash}, /scripts/{hash}/json, and /scripts/{hash}/cbor (serialised_size = Some(_), json = None, cbor = Some(_)). Adding one Plutus fixture would close that gap.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/minibf/src/routes/scripts.rs` around lines 198 - 286, Add a new test
that mirrors scripts_by_hash_happy_path / scripts_by_hash_json_happy_path /
scripts_by_hash_cbor_happy_path but uses a Plutus-backed fixture (e.g.
fixture_app_plutus() or create a TestApp whose vectors contain a Plutus script)
and assert the Plutus-specific expectations: for scripts_by_hash assert
item.r#type == ScriptType::Plutus and item.serialised_size.is_some(); for /json
assert ScriptJson.json.is_none(); for /cbor assert ScriptCbor.cbor.is_some();
reuse the same path formatting and serde parsing as the existing tests (Script,
ScriptJson, ScriptCbor) so the Plutus branch is covered.
crates/testing/src/toy_domain.rs (1)

266-271: Consider preserving the original CardanoConfig during reinitialization.

When reinitializing CardanoLogic, CardanoConfig::default() is used instead of the config that was originally passed to ToyDomain::new_with_genesis_and_config. If tests use non-default configurations, this could lead to subtle inconsistencies.

♻️ Suggested fix to preserve config

You could store the CardanoConfig in ToyDomain and use it here:

 let new_chain = dolos_cardano::CardanoLogic::initialize::<ToyDomain>(
-    CardanoConfig::default(),
+    domain.cardano_config().clone(),
     domain.state(),
     domain.genesis.as_ref(),
 )

This would require adding a cardano_config field and accessor to ToyDomain.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/testing/src/toy_domain.rs` around lines 266 - 271, The
reinitialization call uses CardanoConfig::default() which discards any
non-default config passed to ToyDomain::new_with_genesis_and_config; update
ToyDomain to store the original CardanoConfig (add a cardano_config field and a
getter, e.g., cardano_config()) and change the CardanoLogic::initialize call to
pass domain.cardano_config() (or the accessor) instead of
CardanoConfig::default() so the original configuration is preserved during
reinitialization.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/minibf/src/routes/scripts.rs`:
- Around line 172-182: Tests only cover length-invalid hashes; add same-length
non-hex variants so the hex::decode failure path in parse_script_hash and
parse_datum_hash is exercised: add functions (e.g. invalid_script_hash_nonhex
returning a 56-char non-hex string like repeated 'g' and
invalid_datum_hash_nonhex returning a 64-char non-hex string) and update the
*_invalid_hash tests to include/replace a case using these new functions so
parse_script_hash and parse_datum_hash hit the hex decode error branch.
- Around line 198-286: Add a new test that mirrors scripts_by_hash_happy_path /
scripts_by_hash_json_happy_path / scripts_by_hash_cbor_happy_path but uses a
Plutus-backed fixture (e.g. fixture_app_plutus() or create a TestApp whose
vectors contain a Plutus script) and assert the Plutus-specific expectations:
for scripts_by_hash assert item.r#type == ScriptType::Plutus and
item.serialised_size.is_some(); for /json assert ScriptJson.json.is_none(); for
/cbor assert ScriptCbor.cbor.is_some(); reuse the same path formatting and serde
parsing as the existing tests (Script, ScriptJson, ScriptCbor) so the Plutus
branch is covered.

In `@crates/testing/src/toy_domain.rs`:
- Around line 266-271: The reinitialization call uses CardanoConfig::default()
which discards any non-default config passed to
ToyDomain::new_with_genesis_and_config; update ToyDomain to store the original
CardanoConfig (add a cardano_config field and a getter, e.g., cardano_config())
and change the CardanoLogic::initialize call to pass domain.cardano_config() (or
the accessor) instead of CardanoConfig::default() so the original configuration
is preserved during reinitialization.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f91bc41-ce3d-4ac0-8006-176692eb71a0

📥 Commits

Reviewing files that changed from the base of the PR and between dd9aebd and 3a076ea.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • crates/minibf/src/routes/scripts.rs
  • crates/minibf/src/test_support.rs
  • crates/minikupo/Cargo.toml
  • crates/minikupo/src/lib.rs
  • crates/minikupo/src/routes/datums.rs
  • crates/minikupo/src/routes/health.rs
  • crates/minikupo/src/routes/matches.rs
  • crates/minikupo/src/routes/metadata.rs
  • crates/minikupo/src/routes/scripts.rs
  • crates/minikupo/src/test_support.rs
  • crates/testing/src/synthetic.rs
  • crates/testing/src/toy_domain.rs

Copy link

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

🧹 Nitpick comments (1)
crates/minikupo/src/test_support.rs (1)

126-144: Consider simplifying the fault handling logic.

The match statement can be simplified since both branches construct FaultyToyDomain::new with different fault values. Using unwrap_or_default() leverages the #[default] derive on TestFault::None.

♻️ Suggested simplification
     pub fn new_with_cfg_and_fault(cfg: SyntheticBlockConfig, fault: Option<TestFault>) -> Self {
         let (domain, vectors) = TestDomainBuilder::new_with_synthetic(cfg).finish();
 
-        let domain = match fault {
-            Some(fault) => dolos_testing::faults::FaultyToyDomain::new(domain, fault),
-            None => dolos_testing::faults::FaultyToyDomain::new(domain, TestFault::None),
-        };
+        let domain = dolos_testing::faults::FaultyToyDomain::new(
+            domain,
+            fault.unwrap_or_default(),
+        );
 
         let router = build_router_with_facade(Facade {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/minikupo/src/test_support.rs` around lines 126 - 144, The match in
new_with_cfg_and_fault can be simplified: replace the explicit match on fault
with using fault.unwrap_or_default() (leveraging TestFault's Default/#[default]
None) and pass that to dolos_testing::faults::FaultyToyDomain::new(domain, ...);
update references in that function (new_with_cfg_and_fault, TestFault, and
FaultyToyDomain::new) accordingly so there is a single call to
FaultyToyDomain::new with the unwrapped/defaulted TestFault.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/minikupo/src/test_support.rs`:
- Around line 126-144: The match in new_with_cfg_and_fault can be simplified:
replace the explicit match on fault with using fault.unwrap_or_default()
(leveraging TestFault's Default/#[default] None) and pass that to
dolos_testing::faults::FaultyToyDomain::new(domain, ...); update references in
that function (new_with_cfg_and_fault, TestFault, and FaultyToyDomain::new)
accordingly so there is a single call to FaultyToyDomain::new with the
unwrapped/defaulted TestFault.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 98d74874-2268-487b-8433-011eff5299c5

📥 Commits

Reviewing files that changed from the base of the PR and between 3a076ea and 9dca1da.

📒 Files selected for processing (1)
  • crates/minikupo/src/test_support.rs

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