diff --git a/Cargo.lock b/Cargo.lock index 7907837..7a27dd9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,6 +14,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "allocator-api2" version = "0.2.18" @@ -417,6 +426,35 @@ dependencies = [ "bitflags 2.5.0", ] +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + [[package]] name = "req" version = "0.1.0" @@ -426,6 +464,7 @@ dependencies = [ "crossterm 0.27.0", "indexmap", "ratatui", + "regex", "rsn", "serde", "serde_yaml", diff --git a/Cargo.toml b/Cargo.toml index 2af9727..86fd101 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ clap = { version = "4.5.4", features = ["derive"] } crossterm = "0.27.0" indexmap = { version = "2.2.6", features = ["serde"] } ratatui = "0.26.2" +regex = "1.10.4" rsn = "0.1.0" serde = { version = "1.0.201", features = ["derive"] } serde_yaml = "0.9.34" diff --git a/out.md b/out.md index c5b4d4f..feee318 100644 --- a/out.md +++ b/out.md @@ -75,8 +75,8 @@ how long the tool waits before checking if new files are available. - **_SEC-6.2_ - GDPR compliance:** The tool **_MUST NOT_** upload data if the user has not agreed to share this information. ### _TOPIC-7_ - Testing -- **_TEST-7.1_ - Unit Tests:** Comprehensive unit tests **_SHOULD_** be written to cover major functionalities. -- **_TEST-7.2_ - Integration Tests:** Integration tests **_SHOULD_** be conducted to ensure all parts of the tool work together seamlessly. +- **_TST-7.1_ - Unit Tests:** Comprehensive unit tests **_SHOULD_** be written to cover major functionalities. +- **_TST-7.2_ - Integration Tests:** Integration tests **_SHOULD_** be conducted to ensure all parts of the tool work together seamlessly. ## Definitions diff --git a/out.pdf b/out.pdf index 9d4a2f2..91ddd2e 100644 Binary files a/out.pdf and b/out.pdf differ diff --git a/src/bin/checker.rs b/src/bin/checker.rs new file mode 100644 index 0000000..5d6f598 --- /dev/null +++ b/src/bin/checker.rs @@ -0,0 +1,112 @@ +use std::path::PathBuf; + +use clap::Parser; +use indexmap::{ + map::{Keys, Values}, + IndexMap, +}; +use regex::Regex; +use req::*; +use stringlit::s; + +#[derive(Parser)] +struct Args { + #[arg(short, long, default_value = "REQ-.*")] + allowed_requirements: String, + requirements: PathBuf, + test_results: PathBuf, +} + +fn nl() -> String { + s!("") +} + +fn check_requirements( + test_results: &str, + output: &mut Vec, + requirements: &IndexMap, + allowed_requirements: &Regex, +) { + for (id, requirement) in requirements { + if allowed_requirements.is_match(&id) { + let status = if test_results.contains(&format!("{id} succeeded")) { + ":white_check_mark:" + } else if test_results.contains(&format!("{id} failed")) { + ":x:" + } else { + ":warning:" + }; + output.push(format!("- _{id}_ - {}: {status}", requirement.name)); + } + } +} + +fn has_valid_requirements( + mut requirements: Keys, + allowed_requirements: &Regex, +) -> bool { + requirements.any(|id| allowed_requirements.is_match(&id)) +} + +fn has_valid_topics(mut topics: Values, allowed_requirements: &Regex) -> bool { + topics.any(|topic| { + has_valid_requirements(topic.requirements.keys(), allowed_requirements) + || has_valid_topics(topic.subtopics.values(), allowed_requirements) + }) +} + +fn check_topics( + test_results: &str, + output: &mut Vec, + topics: &IndexMap, + allowed_requirements: &Regex, + level: usize, +) { + if !has_valid_topics(topics.values(), allowed_requirements) { + return; + } + for (id, topic) in topics { + if !has_valid_topics(topic.subtopics.values(), allowed_requirements) + && !has_valid_requirements(topic.requirements.keys(), allowed_requirements) + { + continue; + } + output.push(format!("{} _{id}_ - {}", "#".repeat(level), topic.name)); + if !topic.requirements.is_empty() { + check_requirements( + test_results, + output, + &topic.requirements, + allowed_requirements, + ); + output.push(nl()); + } + if !topic.subtopics.is_empty() { + check_topics( + test_results, + output, + &topic.subtopics, + allowed_requirements, + level + 1, + ); + output.push(nl()); + } + } +} + +fn main() -> anyhow::Result<()> { + let Args { + allowed_requirements, + requirements, + test_results, + } = Args::parse(); + let re = Regex::new(&allowed_requirements).unwrap(); + let test_results = std::fs::read_to_string(test_results)?; + let project: Project = serde_yaml::from_str(&std::fs::read_to_string(requirements)?)?; + let mut output = vec![format!("# Test Results - {}", project.name)]; + check_topics(&test_results, &mut output, &project.topics, &re, 2); + + let output = output.join("\n"); + println!("{output}"); + Ok(()) +} diff --git a/src/bin/tui.rs b/src/bin/tui.rs index 0c1ef5b..cbffab6 100644 --- a/src/bin/tui.rs +++ b/src/bin/tui.rs @@ -4,7 +4,6 @@ use crossterm::{ style::Color, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, }; -use indexmap::indexmap; use ratatui::{ backend::CrosstermBackend, layout::{Constraint, Direction, Layout}, @@ -12,7 +11,6 @@ use ratatui::{ widgets::{Block, Borders, List, ListItem, ListState}, Terminal, }; -use stringlit::s; use std::io; use std::sync::mpsc; diff --git a/test_result.md b/test_result.md new file mode 100644 index 0000000..05eb278 --- /dev/null +++ b/test_result.md @@ -0,0 +1,36 @@ +# Test Results - journal-uploader +## _TOPIC-1_ - Journal Watcher +### _SUB-1.1_ - File Monitoring +- _REQ-1.1.1_ - Continuous Monitoring: :white_check_mark: + +### _SUB-1.2_ - File Detection +- _REQ-1.2.1_ - Detection of New Files: :white_check_mark: +- _REQ-1.2.2_ - Avoid Re-processing: :x: + + +## _TOPIC-2_ - Traced Logging +### _SUB-2.1_ - File Processing +- _REQ-2.1.1_ - Reading Log Messages: :white_check_mark: +- _REQ-2.1.2_ - Filtering Log Messages: :white_check_mark: +- _REQ-2.1.3_ - No Duplicate Log Messages: :x: + +### _SUB-2.2_ - Traced Log Rotation +- _REQ-2.2.1_ - Rotating Files: :white_check_mark: +- _REQ-2.2.2_ - Compression of Rotated Files: :white_check_mark: +- _REQ-2.2.3_ - Rotating Directory: :x: + + +## _TOPIC-3_ - Remote Journal Logging +### _SUB-3.1_ - Service Activation +- _REQ-3.1.1_ - Cloud Activation: :white_check_mark: +- _REQ-3.1.2_ - Duration: :white_check_mark: +- _REQ-3.1.3_ - Max Interval: :x: +- _REQ-3.1.4_ - Analytics Not Accepted: :white_check_mark: + +### _SUB-3.2_ - File Processing +- _REQ-3.2.1_ - File Upload: :white_check_mark: +- _REQ-3.2.2_ - No Duplicate Files: :x: +- _REQ-3.2.3_ - Revoking Analytics: :white_check_mark: +- _REQ-3.2.4_ - Duration Expired: :warning: + + diff --git a/test_result.txt b/test_result.txt new file mode 100644 index 0000000..3b64661 --- /dev/null +++ b/test_result.txt @@ -0,0 +1,16 @@ +REQ-1.1.1 succeeded +REQ-1.2.1 succeeded +REQ-1.2.2 failed +REQ-2.1.1 succeeded +REQ-2.1.2 succeeded +REQ-2.1.3 failed +REQ-2.2.1 succeeded +REQ-2.2.2 succeeded +REQ-2.2.3 failed +REQ-3.1.1 succeeded +REQ-3.1.2 succeeded +REQ-3.1.3 failed +REQ-3.1.4 succeeded +REQ-3.2.1 succeeded +REQ-3.2.2 failed +REQ-3.2.3 succeeded