lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README | LICENSE

commit 97d6dcb9233db7dd088e78f14bbab6f50505bf59
parent e5ee69f011f4626e5351b1d6c04734363af3ec7e
Author: triesap <tyson@radroots.org>
Date:   Sat, 21 Feb 2026 18:33:22 +0000

types: add exhaustive tests for exported wrapper type paths


- add wrapper constructors and helper methods for error result list and pass types
- add branch-covering status and list emptiness paths required for strict coverage
- add serde shape tests for exported wrapper contracts
- run cargo check -q -p `radroots-types` cargo test -q -p `radroots-types` and strict types gate

Diffstat:
Mcrates/types/src/types.rs | 44++++++++++++++++++++++++++++++++++++++++----
Acrates/types/tests/types.rs | 49+++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 89 insertions(+), 4 deletions(-)

diff --git a/crates/types/src/types.rs b/crates/types/src/types.rs @@ -4,28 +4,28 @@ use ts_rs::TS; #[cfg_attr(feature = "ts-rs", derive(TS))] #[cfg_attr(feature = "ts-rs", ts(export, export_to = "types.ts"))] -#[derive(Serialize)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] pub struct IError<T> { pub err: T, } #[cfg_attr(feature = "ts-rs", derive(TS))] #[cfg_attr(feature = "ts-rs", ts(export, export_to = "types.ts"))] -#[derive(Serialize)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] pub struct IResult<T> { pub result: T, } #[cfg_attr(feature = "ts-rs", derive(TS))] #[cfg_attr(feature = "ts-rs", ts(export, export_to = "types.ts"))] -#[derive(Serialize)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] pub struct IResultList<T> { pub results: Vec<T>, } #[cfg_attr(feature = "ts-rs", derive(TS))] #[cfg_attr(feature = "ts-rs", ts(export, export_to = "types.ts"))] -#[derive(Serialize)] +#[derive(Clone, Debug, PartialEq, Eq, Serialize)] pub struct IResultPass { pub pass: bool, } @@ -35,3 +35,39 @@ impl<T> From<T> for IError<T> { Self { err } } } + +impl<T> IError<T> { + pub fn new(err: T) -> Self { + Self { err } + } +} + +impl<T> IResult<T> { + pub fn new(result: T) -> Self { + Self { result } + } +} + +impl<T> IResultList<T> { + pub fn new(results: Vec<T>) -> Self { + Self { results } + } + + pub fn is_empty(&self) -> bool { + self.results.is_empty() + } +} + +impl IResultPass { + pub fn new(pass: bool) -> Self { + Self { pass } + } + + pub fn status_label(&self) -> &'static str { + if self.pass { + "pass" + } else { + "fail" + } + } +} diff --git a/crates/types/tests/types.rs b/crates/types/tests/types.rs @@ -0,0 +1,49 @@ +use radroots_types::types::{IError, IResult, IResultList, IResultPass}; + +#[test] +fn error_wrapper_from_and_new_paths_are_exercised() { + let from_impl: IError<&str> = IError::from("boom"); + assert_eq!(from_impl.err, "boom"); + + let via_new = IError::new("bad"); + assert_eq!(via_new.err, "bad"); +} + +#[test] +fn result_wrapper_new_path_is_exercised() { + let out = IResult::new(42u32); + assert_eq!(out.result, 42); +} + +#[test] +fn result_list_helpers_cover_empty_and_non_empty_branches() { + let empty = IResultList::<u32>::new(Vec::new()); + assert!(empty.is_empty()); + + let non_empty = IResultList::new(vec![1u32, 2u32]); + assert!(!non_empty.is_empty()); + assert_eq!(non_empty.results, vec![1u32, 2u32]); +} + +#[test] +fn result_pass_status_label_covers_both_branches() { + let pass = IResultPass::new(true); + let fail = IResultPass::new(false); + assert_eq!(pass.status_label(), "pass"); + assert_eq!(fail.status_label(), "fail"); +} + +#[test] +fn serde_shapes_for_types_are_stable() { + let err = serde_json::to_value(IError::new("boom")).unwrap(); + assert_eq!(err, serde_json::json!({ "err": "boom" })); + + let out = serde_json::to_value(IResult::new(7u32)).unwrap(); + assert_eq!(out, serde_json::json!({ "result": 7 })); + + let list = serde_json::to_value(IResultList::new(vec!["a", "b"])).unwrap(); + assert_eq!(list, serde_json::json!({ "results": ["a", "b"] })); + + let pass = serde_json::to_value(IResultPass::new(true)).unwrap(); + assert_eq!(pass, serde_json::json!({ "pass": true })); +}