1mod compatibility;
4pub mod decision_logic;
5pub mod decision_tables;
6mod diagrams;
7mod examples;
8mod exhaustive;
9mod full_model;
10pub mod input_data;
11pub mod item_definition;
12
13pub use compatibility::*;
14pub use diagrams::*;
15pub use examples::valid::*;
16pub use examples::*;
17pub use exhaustive::*;
18pub use full_model::*;
19
20#[cfg(test)]
21mod utilities {
22 use std::collections::BTreeSet;
23 use std::fmt::Write;
24 use walkdir::WalkDir;
25
26 #[test]
28 #[rustfmt::skip]
29 pub fn generate_decision_table_variants() {
30 let mut buffer = String::new();
31 let orientation = ["horizontal", "vertical", "crosstab"];
32 let information_item = ["absent", "present" ];
33 let output_label = ["absent", "present" ];
34 let allowed_values = ["absent", "present"];
35 let inputs = ["absent", "single", "double", "multiple"];
36 let outputs = ["single", "double", "multiple"];
37 let annotations = ["absent", "single", "double", "multiple"];
38 let _ = writeln!(&mut buffer, "┌──────┬─────────────┬─────────────┬─────────┬─────────┬──────────┬──────────┬─────────────┬─────────┬────────┐");
39 let _ = writeln!(&mut buffer, "│ No. │ Preferred │ Information │ Output │ Allowed │ Inputs │ Outputs │ Annotations │ Example │ Status │");
40 let _ = writeln!(&mut buffer, "│ │ orientation │ item name │ label │ values │ │ │ │ │ │");
41 let _ = writeln!(&mut buffer, "├──────┼─────────────┼─────────────┼─────────┼─────────┼──────────┼──────────┼─────────────┼─────────┼────────┤");
42 let mut counter = 1;
43 for v_decision_table_orientation in orientation {
44 for v_information_item_name in information_item {
45 for v_output_label in output_label {
46 for v_allowed_values in allowed_values {
47 for v_inputs in inputs {
48 for v_outputs in outputs {
49 for v_annotations in annotations {
50 let _ = writeln!(&mut buffer, "│ {counter:>4} │{v_decision_table_orientation:^13}│{v_information_item_name:^13}│{v_output_label:^9}│{v_allowed_values:^9}│{v_inputs:^10}│{v_outputs:^10}│{v_annotations:^13}│ DT_{counter:04} │ │");
51 counter += 1;
52 }
53 }
54 }
55 }
56 }
57 }
58 }
59 let _ = writeln!(&mut buffer, "└──────┴─────────────┴─────────────┴─────────┴─────────┴──────────┴──────────┴─────────────┴─────────┴────────┘");
60 println!("{}", buffer);
61 assert_eq!(1157, buffer.lines().count());
62 }
63
64 #[test]
67 fn compare_the_number_of_models() {
68 let tck_models = count_models("../../tck/TestCases");
69 let tck_adjusted_models = tck_models
70 .iter()
71 .filter_map(|s| {
72 let segments = s.split('/').collect::<Vec<&str>>();
73 let first_segment = segments[0]
74 .replace("compliance-level-2", "level_2")
75 .replace("compliance-level-3", "level_3")
76 .replace("non-compliant", "non_compliant");
77 let last_segment = segments[2][0..4].to_string();
78 if last_segment.chars().next().unwrap().is_ascii_digit() {
79 Some(format!("{}/{}", first_segment, last_segment))
80 } else {
81 None
82 }
83 })
84 .collect::<BTreeSet<String>>();
85
86 let dsntk_models = count_models("src/compatibility");
87 let dsntk_adjusted_models = dsntk_models
88 .iter()
89 .map(|s| {
90 let segments = s.split('/').collect::<Vec<&str>>();
91 let first_segment = segments[0];
92 let last_segment = segments[1][2..6].to_string();
93 format!("{}/{}", first_segment, last_segment)
94 })
95 .collect::<BTreeSet<String>>();
96
97 let mut all_keys = BTreeSet::new();
98 all_keys.append(&mut tck_adjusted_models.clone());
99 all_keys.append(&mut dsntk_adjusted_models.clone());
100
101 println!("────────────────────────────────");
102 println!(" Model TCK DSNTK");
103 println!("────────────────────────────────");
104 for key in &all_keys {
105 println!(
106 "{:20} {:>2} {:>2}",
107 key,
108 if tck_adjusted_models.contains(key) { "OK" } else { "-" },
109 if dsntk_adjusted_models.contains(key) { "OK" } else { "-" }
110 )
111 }
112 }
113
114 fn count_models(root_dir: &str) -> BTreeSet<String> {
116 let mut results = BTreeSet::new();
117 for entry_result in WalkDir::new(root_dir).into_iter() {
118 let entry = entry_result.unwrap();
119 let path = entry.path();
120 if path.is_file() && path.extension().is_some_and(|ext| ext == "dmn") {
121 results.insert(path.strip_prefix(root_dir).unwrap().display().to_string());
122 }
123 }
124 results
125 }
126}