Skip to content

Conversation

@AvhiMaz
Copy link

@AvhiMaz AvhiMaz commented Nov 3, 2025

Remove slow cargo-expand dependency and replace with faster syn-based
approach for testing Mergeable derive macro. Uses trait bounds to verify
actual Merge implementation instead of macro expansion output.

Fixes #504

Summary by CodeRabbit

  • Tests

    • Replaced fixture-based macro tests with a deterministic, self-contained code-generation test suite and removed several obsolete positive and negative fixtures.
  • Chores

    • Removed unused workspace/dev dev-dependencies and a CI install step, and added a dev-dependency to support deterministic test output formatting.

  Remove slow cargo-expand dependency and replace with faster syn-based
  approach for testing Mergeable derive macro. Uses trait bounds to verify
  actual Merge implementation instead of macro expansion output.

  Fixes magicblock-labs#504

Signed-off-by: AvhiMaz <avhimazumder5@outlook.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 3, 2025

Walkthrough

Removed workspace test tooling (cargo-expand, macrotest, trybuild) and CI install; replaced fixture/expand-based macro tests with in-repo codegen tests using proc_macro2/quote/syn and added prettyplease. Deleted multiple expand/fixture files and updated macro crate dev-dependencies.

Changes

Cohort / File(s) Summary
Workspace dependency removal
Cargo.toml
Removed cargo-expand = "1" and macrotest = "1" from [workspace.dependencies].
Macro crate dev-deps update
magicblock-config-macro/Cargo.toml
Removed dev-dependencies trybuild = { workspace = true } and macrotest = { workspace = true }; added prettyplease = "0.2" to dev-dependencies.
Test implementation refactor
magicblock-config-macro/tests/test_merger.rs
Replaced expand/trybuild/macrotest fixture-based tests with direct codegen tests using proc_macro2, quote, and syn; added helpers (merge_impl, pretty_print, assert_merge_impl_fn) and multiple positive/negative test cases validating generated Merge impl TokenStreams.
Removed fixture-based tests
magicblock-config-macro/tests/fixtures/*
magicblock-config-macro/tests/fixtures/fail_merge_enum.rs, .../fail_merge_enum.stderr, .../fail_merge_union.rs, .../fail_merge_union.stderr, .../fail_merge_unnamed.rs, .../fail_merge_unnamed.stderr, .../pass_merge.rs, .../pass_merge.expanded.rs
Deleted fixture source and expected output files formerly used for expand/trybuild-based tests.
CI workflow change
.github/workflows/ci-test-unit.yml
Removed the step that installed cargo-expand (cargo install cargo-expand).

Sequence Diagram(s)

sequenceDiagram
    participant T as tests/test_merger.rs
    participant G as merge_impl (codegen)
    participant S as syn/quote/proc_macro2
    participant P as pretty_print / prettyplease
    participant A as assertions

    Note over T,G: In-repo codegen replaces external cargo-expand fixtures
    T->>G: provide input struct TokenStream
    G->>S: parse & inspect input
    S-->>G: produced impl TokenStream
    G->>P: normalize generated impl
    P-->>G: normalized tokens
    G->>T: return normalized generated impl
    T->>P: normalize expected impl
    P-->>T: normalized expected tokens
    T->>A: compare normalized tokens / assert results
    A-->>T: pass / fail
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay extra attention to:
    • correctness and edge-case handling in merge_impl (struct-shape validation and error messages),
    • determinism and coverage of pretty_print normalization,
    • that removed negative fixture cases are represented by new tests,
    • CI removal of cargo-expand installation step.

Suggested reviewers

  • thlorenz

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main objective: replacing cargo-expand with syn-based verification for testing the Mergeable derive macro.
Linked Issues check ✅ Passed The PR successfully eliminates cargo-expand dependency and implements syn-based verification as required by #504, maintaining test coverage while improving CI performance.
Out of Scope Changes check ✅ Passed All changes are directly related to replacing cargo-expand with syn-based verification; no unrelated modifications are present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 57e61a2 and 9652919.

📒 Files selected for processing (1)
  • magicblock-config-macro/tests/test_merger.rs (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-14T09:56:14.047Z
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 564
File: test-integration/programs/flexi-counter/src/processor/call_handler.rs:122-125
Timestamp: 2025-10-14T09:56:14.047Z
Learning: The file test-integration/programs/flexi-counter/src/processor/call_handler.rs contains a test smart contract used for integration testing, not production code.

Applied to files:

  • magicblock-config-macro/tests/test_merger.rs
🧬 Code graph analysis (1)
magicblock-config-macro/tests/test_merger.rs (1)
magicblock-config-helpers/src/lib.rs (1)
  • merge (2-2)

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
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: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1faae18 and 399edb2.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • Cargo.toml (0 hunks)
  • magicblock-config-macro/Cargo.toml (1 hunks)
  • magicblock-config-macro/tests/test_merger.rs (2 hunks)
💤 Files with no reviewable changes (1)
  • Cargo.toml
🔇 Additional comments (2)
magicblock-config-macro/tests/test_merger.rs (2)

3-4: LGTM!

The new imports are necessary for the syn-based verification approach and are used appropriately in the new test.


89-136: Verification acceptable—fixture files exist and test coverage is adequate.

All four referenced fixture files exist:

  • pass_merge.rs
  • fail_merge_enum.rs
  • fail_merge_union.rs
  • fail_merge_unnamed.rs

The test provides sufficient coverage across three verification layers:

  1. Compile-time verification (lines 132-135): trybuild ensures pass/fail fixtures behave as expected
  2. Trait implementation verification (line 86): assert_merge::<TestConfig>() confirms the Merge trait is implemented
  3. Behavioral verification (lines 22-72): Two behavioral tests execute actual merge operations with concrete assertions, catching any issues in the generated implementation logic

While the syn-based approach (lines 89-136) doesn't expose full macro expansion details like cargo-expand would, the behavioral tests verify the generated code's correctness at runtime. If the implementation structure was incorrect, the behavioral tests would fail. This trade-off between test speed and verification depth is acceptable for the stated performance goal.

Comment on lines 100 to 114
let has_mergeable_derive = file.items.iter().any(|item| {
if let Item::Struct(item_struct) = item {
item_struct
.attrs
.iter()
.any(|attr| attr.path().is_ident("derive"))
} else {
false
}
});

assert!(
has_mergeable_derive,
"Expected struct with #[derive(Mergeable)]"
);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Strengthen the derive attribute verification.

The current check only verifies that some struct has any derive attribute, not specifically #[derive(Mergeable)]. This check would pass for #[derive(Debug)] or any other derive macro, making it a very weak verification.

Consider parsing the derive attribute's tokens to verify Mergeable is actually present:

     // Verify the file contains the Mergeable derive
     let has_mergeable_derive = file.items.iter().any(|item| {
         if let Item::Struct(item_struct) = item {
             item_struct
                 .attrs
                 .iter()
-                .any(|attr| attr.path().is_ident("derive"))
+                .any(|attr| {
+                    attr.path().is_ident("derive") && {
+                        attr.parse_args::<syn::Path>()
+                            .map(|path| path.is_ident("Mergeable"))
+                            .unwrap_or(false)
+                    }
+                })
         } else {
             false
         }
     });

Note: This simplified example assumes a single derive argument. For multiple derives like #[derive(Debug, Mergeable)], you'll need to parse syn::punctuated::Punctuated<syn::Path, syn::Token![,]> instead.

Committable suggestion skipped: line range outside the PR's diff.

@AvhiMaz
Copy link
Author

AvhiMaz commented Nov 4, 2025

hi @Dodecahedr0x, could you please review this?

@Dodecahedr0x Dodecahedr0x self-requested a review November 4, 2025 09:22
Copy link
Contributor

@Dodecahedr0x Dodecahedr0x left a comment

Choose a reason for hiding this comment

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

Hey, thanks for the PR!

We're expecting something along the line of what is done here: remove rust files containing the code and embed them directly in the test, parse them with syn and check that it matches what we expect.

Also, the github workflow for unit test installs cargo-expand, which should be removed.

Finally, please address code rabbit's comments

AvhiMaz and others added 2 commits November 4, 2025 16:09
  Remove cargo-expand dependency and replace trybuild fixture-based testing with
  embedded code verification using syn and token stream comparison

Signed-off-by: AvhiMaz <avhimazumder5@outlook.com>
Copy link
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: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 399edb2 and eaa388c.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • .github/workflows/ci-test-unit.yml (0 hunks)
  • magicblock-config-macro/Cargo.toml (0 hunks)
  • magicblock-config-macro/tests/fixtures/fail_merge_enum.rs (0 hunks)
  • magicblock-config-macro/tests/fixtures/fail_merge_enum.stderr (0 hunks)
  • magicblock-config-macro/tests/fixtures/fail_merge_union.rs (0 hunks)
  • magicblock-config-macro/tests/fixtures/fail_merge_union.stderr (0 hunks)
  • magicblock-config-macro/tests/fixtures/fail_merge_unnamed.rs (0 hunks)
  • magicblock-config-macro/tests/fixtures/fail_merge_unnamed.stderr (0 hunks)
  • magicblock-config-macro/tests/fixtures/pass_merge.expanded.rs (0 hunks)
  • magicblock-config-macro/tests/fixtures/pass_merge.rs (0 hunks)
  • magicblock-config-macro/tests/test_merger.rs (2 hunks)
💤 Files with no reviewable changes (10)
  • magicblock-config-macro/tests/fixtures/fail_merge_unnamed.rs
  • magicblock-config-macro/Cargo.toml
  • magicblock-config-macro/tests/fixtures/pass_merge.rs
  • magicblock-config-macro/tests/fixtures/pass_merge.expanded.rs
  • magicblock-config-macro/tests/fixtures/fail_merge_union.rs
  • .github/workflows/ci-test-unit.yml
  • magicblock-config-macro/tests/fixtures/fail_merge_enum.rs
  • magicblock-config-macro/tests/fixtures/fail_merge_unnamed.stderr
  • magicblock-config-macro/tests/fixtures/fail_merge_enum.stderr
  • magicblock-config-macro/tests/fixtures/fail_merge_union.stderr
🧰 Additional context used
🧬 Code graph analysis (1)
magicblock-config-macro/tests/test_merger.rs (2)
magicblock-config-macro/src/merger.rs (1)
  • type_has_merge_method (8-23)
magicblock-config-helpers/src/lib.rs (1)
  • merge (2-2)
🔇 Additional comments (2)
magicblock-config-macro/tests/test_merger.rs (2)

3-5: LGTM: Imports support the syn-based approach.

The new imports (proc_macro2, quote, syn) are necessary for implementing the syn-based macro verification that replaces cargo-expand. All imports are utilized in the test helper functions below.


75-85: LGTM: Compile-time trait verification is effective.

The trait bound check approach (assert_merge<T: Merge>()) elegantly verifies at compile time that the Mergeable macro generates valid Merge implementations. This is complemented by the AST-based verification in test_merge_macro_codegen_verification which validates correctness.

Signed-off-by: AvhiMaz <avhimazumder5@outlook.com>
Copy link
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 details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eaa388c and fd572ee.

📒 Files selected for processing (1)
  • magicblock-config-macro/tests/test_merger.rs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
magicblock-config-macro/tests/test_merger.rs (3)
magicblock-config-macro/src/merger.rs (1)
  • type_has_merge_method (8-23)
magicblock-config-helpers/src/lib.rs (1)
  • merge (2-2)
magicblock-config/src/rpc.rs (1)
  • merge (29-36)
🔇 Additional comments (4)
magicblock-config-macro/tests/test_merger.rs (4)

1-5: LGTM! Appropriate dependencies for syn-based verification.

The imports correctly bring in the necessary tools for the new token-stream-based macro testing approach, replacing the cargo-expand dependency.


22-73: LGTM! Comprehensive runtime behavior verification.

The tests effectively verify both default-value replacement and non-default value preservation, ensuring the macro generates correct merge behavior.


75-85: LGTM! Effective compile-time trait verification.

The trait bound check ensures the macro generates valid Merge implementations. Combined with the runtime behavior tests, this provides comprehensive coverage.


87-168: The helper functions enable effective codegen verification.

The merge_impl, pretty_print, and assert_merge_impl_fn helpers provide a solid foundation for comparing expected vs. generated implementations without cargo-expand. The approach is sound for testing proc macro output.

Note: The type_has_merge_method duplication is already covered by past review comments.

@AvhiMaz
Copy link
Author

AvhiMaz commented Nov 4, 2025

hi @Dodecahedr0x, could you please check if my implementation is correct? also, should i add more test cases as codehabbit suggested?

@Dodecahedr0x
Copy link
Contributor

Yes, good job! Please handle all code rabbit's comments and we're good to merge

Signed-off-by: AvhiMaz <avhimazumder5@outlook.com>
Copy link
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: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd572ee and 49bb91e.

📒 Files selected for processing (1)
  • magicblock-config-macro/tests/test_merger.rs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
magicblock-config-macro/tests/test_merger.rs (2)
magicblock-config-macro/src/merger.rs (1)
  • type_has_merge_method (8-23)
magicblock-config-helpers/src/lib.rs (1)
  • merge (2-2)
🔇 Additional comments (4)
magicblock-config-macro/tests/test_merger.rs (4)

3-5: LGTM! Imports support the new syn-based testing approach.

The addition of proc_macro2, quote, and syn imports enables direct code generation and comparison without external fixture dependencies.


22-73: LGTM! Runtime tests provide solid coverage of merge behavior.

These tests verify both the default-value-based merging for primitives and the nested merge delegation for Config types, covering the two main code paths in the generated implementation.


75-85: LGTM! Elegant compile-time verification approach.

Using trait bounds to verify the Merge implementation is an excellent replacement for cargo-expand. This catches compilation issues and ensures the trait is properly implemented without the overhead of external tooling.


297-334: Negative tests verify reference implementation panics, not macro compilation errors.

These tests verify that merge_impl panics with expected messages for invalid inputs (enum, tuple struct, unit struct). However, they don't verify the actual Mergeable macro produces compilation errors with helpful messages.

Limitation:

  • The real macro's error messages are controlled by panic! calls in the macro implementation (likely in src/lib.rs)
  • If the macro's error messages change or differ from merge_impl, these tests won't catch it
  • Testing proc_macro error messages directly is challenging without tools like trybuild

Current coverage is acceptable:

  • These tests document expected error behavior
  • If the macro accepts invalid input that should be rejected, the user will discover it at compile time
  • Runtime and compile-time tests provide the primary verification

This limitation is a trade-off of removing trybuild, but acceptable given the test suite provides strong coverage overall.

@AvhiMaz
Copy link
Author

AvhiMaz commented Nov 4, 2025

Hey @Dodecahedr0x, Rust's proc-macro architecture doesn't allow us to directly inspect generated code at runtime, so we can't verify the actual macro output matches our reference implementation. We're using runtime tests to verify the macro works correctly and codegen tests to verify the logic is sound, but we can't guarantee 100% parity. This is a known limitation of proc-macro testing in Rust, the current approach catches regressions and verifies functionality, which is the best we can do with the architectural constraints.

AvhiMaz and others added 2 commits November 4, 2025 21:55
Copy link
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: 6

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 49bb91e and b5547e5.

📒 Files selected for processing (1)
  • magicblock-config-macro/tests/test_merger.rs (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
magicblock-config-macro/tests/test_merger.rs (3)
magicblock-config-macro/src/merger.rs (1)
  • type_has_merge_method (8-23)
magicblock-config-helpers/src/lib.rs (1)
  • merge (2-2)
magicblock-config/src/rpc.rs (1)
  • merge (29-36)
🔇 Additional comments (2)
magicblock-config-macro/tests/test_merger.rs (2)

3-5: LGTM: Appropriate imports for syn-based verification.

The added imports support the new test infrastructure correctly.


75-85: LGTM: Strong compile-time verification.

This trait bound check directly verifies the actual Mergeable macro generates valid code. Combined with the runtime tests, this provides robust verification of macro correctness.

Comment on lines +167 to +176
/// Helper function that compares generated merge impl with expected output
fn assert_merge_impl_fn(code: TokenStream2, expected: TokenStream2) {
let generated = merge_impl(code);

assert_eq!(
pretty_print(generated),
pretty_print(expected),
"Generated merge implementation does not match expected output"
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Helper tests reference implementation, not actual macro.

While this function is correctly implemented, it compares merge_impl output against expectations. It doesn't verify what the actual Mergeable derive macro generates, creating a verification gap.

If you remove the codegen tests (recommended in comment on lines 87-154), delete this helper as well.

🤖 Prompt for AI Agents
In magicblock-config-macro/tests/test_merger.rs around lines 167-176, the helper
assert_merge_impl_fn compares the hand-called merge_impl function instead of the
actual Mergeable derive macro output, leaving a verification gap; if you are
removing the codegen tests as suggested, delete this helper entirely and any
callers, otherwise change the helper to expand the real derive macro (e.g.,
invoke the proc-macro expansion/path used by your test harness or use trybuild
to compile a test crate and capture the expanded impl) and compare that
expansion to the expected TokenStream rather than calling merge_impl directly.

@AvhiMaz
Copy link
Author

AvhiMaz commented Nov 4, 2025

hi @Dodecahedr0x , there was a lint issue, I’ve pushed a fix. also noticed a deployment issue, but it seems to be an authorization problem since I don’t have permission to trigger it.

@github-actions
Copy link

github-actions bot commented Nov 6, 2025

❌ Failed to trigger deploy for branch ``. Make sure you have permission or use the manual deploy link in the PR comment.

@AvhiMaz
Copy link
Author

AvhiMaz commented Nov 6, 2025

hi @Dodecahedr0x, can you please trigger the deployment? I don’t have permission to do it. all test cases have passed.

Signed-off-by: AvhiMaz <avhimazumder5@outlook.com>
@Dodecahedr0x
Copy link
Contributor

I think the test should use the actual Merger struct from the magicblock-config-macro crate to test, instead of the merge_impl, as suggested by Code Rabbit. Tagging @thlorenz for more feedbacks

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.

Remove cargo-expand dependency

2 participants