Skip to content

Commit c37622f

Browse files
committed
test(dpp): co-locate validation_result aggregator tests with their version modules
The previous commit landed v0/v1-specific tests in `validation_result/mod.rs::tests` alongside facade dispatch tests, which duplicated coverage (the facade tests already exercise v0/v1 behavior through dispatch). Move per-version behavior tests into their own modules: flatten/v0/mod.rs::tests — 3 tests for legacy Some(empty_vec) flatten/v1/mod.rs::tests — 5 tests for canonical None-on-empty merge_many/v0/mod.rs::tests — 3 tests for legacy Some(empty_vec) merge_many/v1/mod.rs::tests — 4 tests for canonical None-on-empty mod.rs::tests — facade dispatch tests + struct/method tests Same 61 tests, same coverage, no duplication.
1 parent 9a7d350 commit c37622f

5 files changed

Lines changed: 181 additions & 173 deletions

File tree

packages/rs-dpp/src/validation/validation_result/flatten/v0/mod.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,42 @@ where
3434
});
3535
ValidationResult::new_with_data_and_errors(aggregate_data, aggregate_errors)
3636
}
37+
38+
#[cfg(test)]
39+
mod tests {
40+
use super::*;
41+
42+
#[test]
43+
fn merges_data_and_errors() {
44+
let r1: ValidationResult<Vec<i32>, String> = ValidationResult::new_with_data(vec![1, 2]);
45+
let r2: ValidationResult<Vec<i32>, String> =
46+
ValidationResult::new_with_data_and_errors(vec![3], vec!["e".to_string()]);
47+
let r3: ValidationResult<Vec<i32>, String> =
48+
ValidationResult::new_with_error("e2".to_string());
49+
50+
let flat = flatten_v0(vec![r1, r2, r3]);
51+
assert_eq!(flat.data, Some(vec![1, 2, 3]));
52+
assert_eq!(flat.errors, vec!["e".to_string(), "e2".to_string()]);
53+
}
54+
55+
#[test]
56+
fn empty_input_returns_some_empty() {
57+
// Legacy v11 behavior: Some(empty_vec), not None.
58+
let flat: ValidationResult<Vec<i32>, String> =
59+
flatten_v0(std::iter::empty::<ValidationResult<Vec<i32>, String>>());
60+
assert_eq!(flat.data, Some(vec![]));
61+
assert!(flat.errors.is_empty());
62+
}
63+
64+
#[test]
65+
fn all_inputs_no_data_returns_some_empty() {
66+
let r1: ValidationResult<Vec<i32>, String> =
67+
ValidationResult::new_with_error("e1".to_string());
68+
let r2: ValidationResult<Vec<i32>, String> =
69+
ValidationResult::new_with_error("e2".to_string());
70+
71+
let flat = flatten_v0(vec![r1, r2]);
72+
assert_eq!(flat.data, Some(vec![]));
73+
assert_eq!(flat.errors, vec!["e1".to_string(), "e2".to_string()]);
74+
}
75+
}

packages/rs-dpp/src/validation/validation_result/flatten/v1/mod.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,64 @@ where
3939
ValidationResult::new_with_data_and_errors(aggregate_data, aggregate_errors)
4040
}
4141
}
42+
43+
#[cfg(test)]
44+
mod tests {
45+
use super::*;
46+
47+
#[test]
48+
fn merges_non_empty_data() {
49+
let r1: ValidationResult<Vec<i32>, String> = ValidationResult::new_with_data(vec![1, 2]);
50+
let r2: ValidationResult<Vec<i32>, String> =
51+
ValidationResult::new_with_data_and_errors(vec![3], vec!["e".to_string()]);
52+
let r3: ValidationResult<Vec<i32>, String> =
53+
ValidationResult::new_with_error("e2".to_string());
54+
55+
let flat = flatten_v1(vec![r1, r2, r3]);
56+
assert_eq!(flat.data, Some(vec![1, 2, 3]));
57+
assert_eq!(flat.errors, vec!["e".to_string(), "e2".to_string()]);
58+
}
59+
60+
#[test]
61+
fn empty_input_returns_none() {
62+
let flat: ValidationResult<Vec<i32>, String> =
63+
flatten_v1(std::iter::empty::<ValidationResult<Vec<i32>, String>>());
64+
assert_eq!(flat.data, None);
65+
assert!(flat.errors.is_empty());
66+
}
67+
68+
#[test]
69+
fn all_inputs_no_data_returns_none() {
70+
// Downstream code (process_validation_result_v0:241) keys on
71+
// data.is_none() to route to UnpaidConsensusError.
72+
let r1: ValidationResult<Vec<i32>, String> =
73+
ValidationResult::new_with_error("e1".to_string());
74+
let r2: ValidationResult<Vec<i32>, String> =
75+
ValidationResult::new_with_error("e2".to_string());
76+
77+
let flat = flatten_v1(vec![r1, r2]);
78+
assert!(flat.data.is_none());
79+
assert_eq!(flat.errors, vec!["e1".to_string(), "e2".to_string()]);
80+
}
81+
82+
#[test]
83+
fn some_empty_some_non_empty_returns_some() {
84+
let r1: ValidationResult<Vec<i32>, String> = ValidationResult::new_with_data(vec![]);
85+
let r2: ValidationResult<Vec<i32>, String> = ValidationResult::new_with_data(vec![42]);
86+
87+
let flat = flatten_v1(vec![r1, r2]);
88+
assert_eq!(flat.data, Some(vec![42]));
89+
assert!(flat.errors.is_empty());
90+
}
91+
92+
#[test]
93+
fn all_some_empty_returns_none() {
94+
// All inputs had data:Some(empty_vec). The aggregate Vec is empty → data:None.
95+
let r1: ValidationResult<Vec<i32>, String> = ValidationResult::new_with_data(vec![]);
96+
let r2: ValidationResult<Vec<i32>, String> = ValidationResult::new_with_data(vec![]);
97+
98+
let flat = flatten_v1(vec![r1, r2]);
99+
assert!(flat.data.is_none());
100+
assert!(flat.errors.is_empty());
101+
}
102+
}

packages/rs-dpp/src/validation/validation_result/merge_many/v0/mod.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,38 @@ where
3434
});
3535
ValidationResult::new_with_data_and_errors(aggregate_data, aggregate_errors)
3636
}
37+
38+
#[cfg(test)]
39+
mod tests {
40+
use super::*;
41+
42+
#[test]
43+
fn collects_data_into_vec() {
44+
let r1: ValidationResult<i32, String> = ValidationResult::new_with_data(1);
45+
let r2: ValidationResult<i32, String> = ValidationResult::new_with_data(2);
46+
let r3: ValidationResult<i32, String> = ValidationResult::new_with_error("e".to_string());
47+
48+
let merged = merge_many_v0(vec![r1, r2, r3]);
49+
assert_eq!(merged.data, Some(vec![1, 2]));
50+
assert_eq!(merged.errors, vec!["e".to_string()]);
51+
}
52+
53+
#[test]
54+
fn empty_input_returns_some_empty() {
55+
// Legacy v11 behavior: Some(empty_vec), not None.
56+
let merged: ValidationResult<Vec<i32>, String> =
57+
merge_many_v0(std::iter::empty::<ValidationResult<i32, String>>());
58+
assert_eq!(merged.data, Some(vec![]));
59+
assert!(merged.errors.is_empty());
60+
}
61+
62+
#[test]
63+
fn all_inputs_no_data_returns_some_empty() {
64+
let r1: ValidationResult<i32, String> = ValidationResult::new_with_error("e1".to_string());
65+
let r2: ValidationResult<i32, String> = ValidationResult::new_with_error("e2".to_string());
66+
67+
let merged = merge_many_v0(vec![r1, r2]);
68+
assert_eq!(merged.data, Some(vec![]));
69+
assert_eq!(merged.errors, vec!["e1".to_string(), "e2".to_string()]);
70+
}
71+
}

packages/rs-dpp/src/validation/validation_result/merge_many/v1/mod.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,47 @@ where
3838
ValidationResult::new_with_data_and_errors(aggregate_data, aggregate_errors)
3939
}
4040
}
41+
42+
#[cfg(test)]
43+
mod tests {
44+
use super::*;
45+
46+
#[test]
47+
fn collects_non_empty_data() {
48+
let r1: ValidationResult<i32, String> = ValidationResult::new_with_data(1);
49+
let r2: ValidationResult<i32, String> = ValidationResult::new_with_data(2);
50+
let r3: ValidationResult<i32, String> = ValidationResult::new_with_error("e".to_string());
51+
52+
let merged = merge_many_v1(vec![r1, r2, r3]);
53+
assert_eq!(merged.data, Some(vec![1, 2]));
54+
assert_eq!(merged.errors, vec!["e".to_string()]);
55+
}
56+
57+
#[test]
58+
fn empty_input_returns_none() {
59+
let merged: ValidationResult<Vec<i32>, String> =
60+
merge_many_v1(std::iter::empty::<ValidationResult<i32, String>>());
61+
assert!(merged.data.is_none());
62+
assert!(merged.errors.is_empty());
63+
}
64+
65+
#[test]
66+
fn all_inputs_no_data_returns_none() {
67+
let r1: ValidationResult<i32, String> = ValidationResult::new_with_error("e1".to_string());
68+
let r2: ValidationResult<i32, String> = ValidationResult::new_with_error("e2".to_string());
69+
70+
let merged = merge_many_v1(vec![r1, r2]);
71+
assert!(merged.data.is_none());
72+
assert_eq!(merged.errors, vec!["e1".to_string(), "e2".to_string()]);
73+
}
74+
75+
#[test]
76+
fn some_data_returns_some() {
77+
let r1: ValidationResult<i32, String> = ValidationResult::new_with_error("e1".to_string());
78+
let r2: ValidationResult<i32, String> = ValidationResult::new_with_data(7);
79+
80+
let merged = merge_many_v1(vec![r1, r2]);
81+
assert_eq!(merged.data, Some(vec![7]));
82+
assert_eq!(merged.errors, vec!["e1".to_string()]);
83+
}
84+
}

packages/rs-dpp/src/validation/validation_result/mod.rs

Lines changed: 2 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -570,182 +570,11 @@ mod tests {
570570
assert_eq!(result.errors, vec!["bad".to_string()]);
571571
}
572572

573-
// -- flatten::v1::flatten_v1() (canonical, honors data.is_none() ⇔ no work done) --
574-
575-
#[test]
576-
fn test_v1_flatten_merges_non_empty_data() {
577-
let r1: ValidationResult<Vec<i32>, String> = ValidationResult::new_with_data(vec![1, 2]);
578-
let r2: ValidationResult<Vec<i32>, String> =
579-
ValidationResult::new_with_data_and_errors(vec![3], vec!["e".to_string()]);
580-
let r3: ValidationResult<Vec<i32>, String> =
581-
ValidationResult::new_with_error("e2".to_string());
582-
583-
let flat = flatten::v1::flatten_v1(vec![r1, r2, r3]);
584-
assert_eq!(flat.data, Some(vec![1, 2, 3]));
585-
assert_eq!(flat.errors, vec!["e".to_string(), "e2".to_string()]);
586-
}
587-
588-
#[test]
589-
fn test_v1_flatten_empty_input_returns_none_data() {
590-
let flat: ValidationResult<Vec<i32>, String> =
591-
flatten::v1::flatten_v1(std::iter::empty::<ValidationResult<Vec<i32>, String>>());
592-
assert_eq!(flat.data, None);
593-
assert!(flat.errors.is_empty());
594-
}
595-
596-
#[test]
597-
fn test_v1_flatten_all_inputs_no_data_returns_none() {
598-
// When no input contributed data, return data:None — not
599-
// Some(empty_vec). Downstream code
600-
// (process_validation_result_v0:241) keys on data.is_none() to
601-
// route to UnpaidConsensusError.
602-
let r1: ValidationResult<Vec<i32>, String> =
603-
ValidationResult::new_with_error("e1".to_string());
604-
let r2: ValidationResult<Vec<i32>, String> =
605-
ValidationResult::new_with_error("e2".to_string());
606-
607-
let flat = flatten::v1::flatten_v1(vec![r1, r2]);
608-
assert!(flat.data.is_none());
609-
assert_eq!(flat.errors, vec!["e1".to_string(), "e2".to_string()]);
610-
}
611-
612-
#[test]
613-
fn test_v1_flatten_some_empty_some_non_empty_returns_some() {
614-
// Mixed input: one had data:Some(empty_vec), another had
615-
// Some(non_empty). The aggregate is non-empty → data:Some(...).
616-
let r1: ValidationResult<Vec<i32>, String> = ValidationResult::new_with_data(vec![]);
617-
let r2: ValidationResult<Vec<i32>, String> = ValidationResult::new_with_data(vec![42]);
618-
619-
let flat = flatten::v1::flatten_v1(vec![r1, r2]);
620-
assert_eq!(flat.data, Some(vec![42]));
621-
assert!(flat.errors.is_empty());
622-
}
623-
624-
#[test]
625-
fn test_v1_flatten_all_some_empty_returns_none() {
626-
// All inputs had data:Some(empty_vec). The aggregate Vec is
627-
// empty → data:None.
628-
let r1: ValidationResult<Vec<i32>, String> = ValidationResult::new_with_data(vec![]);
629-
let r2: ValidationResult<Vec<i32>, String> = ValidationResult::new_with_data(vec![]);
630-
631-
let flat = flatten::v1::flatten_v1(vec![r1, r2]);
632-
assert!(flat.data.is_none());
633-
assert!(flat.errors.is_empty());
634-
}
635-
636-
// -- merge_many::v1::merge_many_v1() (canonical) --
637-
638-
#[test]
639-
fn test_v1_merge_many_collects_non_empty_data() {
640-
let r1: ValidationResult<i32, String> = ValidationResult::new_with_data(1);
641-
let r2: ValidationResult<i32, String> = ValidationResult::new_with_data(2);
642-
let r3: ValidationResult<i32, String> = ValidationResult::new_with_error("e".to_string());
643-
644-
let merged = merge_many::v1::merge_many_v1(vec![r1, r2, r3]);
645-
assert_eq!(merged.data, Some(vec![1, 2]));
646-
assert_eq!(merged.errors, vec!["e".to_string()]);
647-
}
648-
649-
#[test]
650-
fn test_v1_merge_many_empty_input_returns_none_data() {
651-
let merged: ValidationResult<Vec<i32>, String> =
652-
merge_many::v1::merge_many_v1(std::iter::empty::<ValidationResult<i32, String>>());
653-
assert!(merged.data.is_none());
654-
assert!(merged.errors.is_empty());
655-
}
656-
657-
#[test]
658-
fn test_v1_merge_many_all_inputs_no_data_returns_none() {
659-
let r1: ValidationResult<i32, String> = ValidationResult::new_with_error("e1".to_string());
660-
let r2: ValidationResult<i32, String> = ValidationResult::new_with_error("e2".to_string());
661-
662-
let merged = merge_many::v1::merge_many_v1(vec![r1, r2]);
663-
assert!(merged.data.is_none());
664-
assert_eq!(merged.errors, vec!["e1".to_string(), "e2".to_string()]);
665-
}
666-
667-
#[test]
668-
fn test_v1_merge_many_some_data_returns_some() {
669-
let r1: ValidationResult<i32, String> = ValidationResult::new_with_error("e1".to_string());
670-
let r2: ValidationResult<i32, String> = ValidationResult::new_with_data(7);
671-
672-
let merged = merge_many::v1::merge_many_v1(vec![r1, r2]);
673-
assert_eq!(merged.data, Some(vec![7]));
674-
assert_eq!(merged.errors, vec!["e1".to_string()]);
675-
}
676-
677-
// -- flatten::v0::flatten_v0() / merge_many::v0::merge_many_v0() --
678-
// These pin the legacy `Some(empty_vec)`-on-no-data behavior preserved
679-
// for PROTOCOL_VERSION_11 and below.
680-
681-
#[test]
682-
fn test_v0_flatten_merges_data_and_errors() {
683-
let r1: ValidationResult<Vec<i32>, String> = ValidationResult::new_with_data(vec![1, 2]);
684-
let r2: ValidationResult<Vec<i32>, String> =
685-
ValidationResult::new_with_data_and_errors(vec![3], vec!["e".to_string()]);
686-
let r3: ValidationResult<Vec<i32>, String> =
687-
ValidationResult::new_with_error("e2".to_string());
688-
689-
let flat = flatten::v0::flatten_v0(vec![r1, r2, r3]);
690-
assert_eq!(flat.data, Some(vec![1, 2, 3]));
691-
assert_eq!(flat.errors, vec!["e".to_string(), "e2".to_string()]);
692-
}
693-
694-
#[test]
695-
fn test_v0_flatten_empty_input_returns_some_empty() {
696-
let flat: ValidationResult<Vec<i32>, String> =
697-
flatten::v0::flatten_v0(std::iter::empty::<ValidationResult<Vec<i32>, String>>());
698-
// Legacy v11 behavior: Some(empty_vec), not None.
699-
assert_eq!(flat.data, Some(vec![]));
700-
assert!(flat.errors.is_empty());
701-
}
702-
703-
#[test]
704-
fn test_v0_flatten_all_inputs_no_data_returns_some_empty() {
705-
let r1: ValidationResult<Vec<i32>, String> =
706-
ValidationResult::new_with_error("e1".to_string());
707-
let r2: ValidationResult<Vec<i32>, String> =
708-
ValidationResult::new_with_error("e2".to_string());
709-
710-
let flat = flatten::v0::flatten_v0(vec![r1, r2]);
711-
assert_eq!(flat.data, Some(vec![]));
712-
assert_eq!(flat.errors, vec!["e1".to_string(), "e2".to_string()]);
713-
}
714-
715-
#[test]
716-
fn test_v0_merge_many_collects_data_into_vec() {
717-
let r1: ValidationResult<i32, String> = ValidationResult::new_with_data(1);
718-
let r2: ValidationResult<i32, String> = ValidationResult::new_with_data(2);
719-
let r3: ValidationResult<i32, String> = ValidationResult::new_with_error("e".to_string());
720-
721-
let merged = merge_many::v0::merge_many_v0(vec![r1, r2, r3]);
722-
assert_eq!(merged.data, Some(vec![1, 2]));
723-
assert_eq!(merged.errors, vec!["e".to_string()]);
724-
}
725-
726-
#[test]
727-
fn test_v0_merge_many_empty_input_returns_some_empty() {
728-
let merged: ValidationResult<Vec<i32>, String> =
729-
merge_many::v0::merge_many_v0(std::iter::empty::<ValidationResult<i32, String>>());
730-
// Legacy v11 behavior: Some(empty_vec), not None.
731-
assert_eq!(merged.data, Some(vec![]));
732-
assert!(merged.errors.is_empty());
733-
}
734-
735-
#[test]
736-
fn test_v0_merge_many_all_inputs_no_data_returns_some_empty() {
737-
let r1: ValidationResult<i32, String> = ValidationResult::new_with_error("e1".to_string());
738-
let r2: ValidationResult<i32, String> = ValidationResult::new_with_error("e2".to_string());
739-
740-
let merged = merge_many::v0::merge_many_v0(vec![r1, r2]);
741-
assert_eq!(merged.data, Some(vec![]));
742-
assert_eq!(merged.errors, vec!["e1".to_string(), "e2".to_string()]);
743-
}
744-
745573
// -- facade dispatch (flatten / merge_many take platform_version) --
746574
//
747575
// These verify the version field on PlatformVersion correctly steers the
748-
// facade to v0 vs v1 semantics.
576+
// facade to v0 vs v1 semantics. Per-version behavior is tested in each
577+
// version's own module (e.g. `flatten::v1::tests`).
749578

750579
#[test]
751580
fn test_facade_flatten_v0_returns_some_empty_on_no_data() {

0 commit comments

Comments
 (0)