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