Date: 2025-07-25 Status: Accepted
- Testing requires reusable utilities that may need to be shared across crates
- Test utilities should be isolated from production code while remaining accessible to child crates
- We need to minimize feature flags to optimize Rust compiler artifact reuse and reduce build times
Test utilities must follow this organizational structure:
Core Rules:
- All test utilities belong in a dedicated
testmodule within each crate - Utilities become public only when used by child crates or integration tests
- Public test utilities must not introduce additional dependencies
- Private test utilities are gated behind
cfg(test) - Import paths must explicitly include
testmodules to prevent accidental production usage - Feature flags are prohibited for test utility isolation
Module Organization:
- Test doubles (mocks, fakes, stubs):
test::doublemodule - Test data builders:
test::buildermodule - Test-only type extensions: Extension traits in
testmodule- Trait names end with
TestExtension - Implementations follow trait definitions, except when accessing private fields
- Trait names end with
- Consistent codebase organization across all crates
- Clear separation between production and test code
- Improved discoverability and maintainability of test utilities
- Reduced build times through minimal feature flag usage
- Enhanced reusability of test utilities across child crates
Date: 2025-07-22 Status: Accepted
The use of dummy() functions for creating test doubles is widespread across the codebase. However, inconsistencies
in their placement and visibility have led to maintenance challenges and reduced code clarity.
A Dummy trait will be introduced, functioning similarly to Rust's Default trait.
The following guidelines will be adopted for implementing the Dummy trait:
- Most implementations should reside in a
test::double::dummiesmodule within the crate where the type is defined. - For types with non-public fields, the
Dummytrait should be implemented directly below the type's definition.
- Enhanced consistency in code organization.
- Improved discoverability of test doubles.
- Clearer distinction between production and test code.
- Simplified maintenance of test implementations.
date: 2025-02-26 status: Accepted
After the update to rust 1.85 on 2025-02-21, we noticed that mithril-client-wasm was failing to compile with the error:
[INFO]: ⬇️ Installing wasm-bindgen...
thread 'main' panicked at crates/wasm-interpreter/src/lib.rs:245:21:
mithril_common::signable_builder::interface::_::__ctor::h4977fb9f7c35308c: Read a negative address value from the stack. Did we run out of memory?
Investigating the problem, we found that the use of typetag::serde attribute was causing the issue, as removing them
allowed the project to compile successfully.
Furthermore, we found that this is a known issue with typetag and WebAssembly, as documented in the typetag repository
issue #54.
Why this issue wasn't happening before the update to rust 1.85 is still unknown, as this incompatibility predates the update.
We use the typetag::serde attribute to serialize and deserialize Artifacts which are implementing a common trait.
As of today, this serialization is only used by mithril-aggregator to store the Artifacts in the database.
We will remove the typetag::serde attribute from the Artifacts when compiling to WebAssembly.
Web Assembly will not be able to serialize and deserialize Artifacts using the generic Artifact trait.
This will not affect mithril-aggregator as it is not compiled to WebAssembly.
In the future, if we need to serialize and deserialize Artifacts in WebAssembly, we will need to find an alternative solution.
date: 2025-02-26 status: Accepted
We already have a few ADRs in the docs/website/adr directory which document project-wide architectural decisions.
But we also want to document the rationale behind smaller decisions, so they are not lost in the shuffle, avoiding
the need to rehash the same discussions in the future.
We will use Architecture Decision Records, as described by Michael Nygard in this article: http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions
To keep things simple, we will store these ADRs in a single file, and use a simple format to keep them readable.
See Michael Nygard's article, linked above.