diff options
author | Lars Wirzenius <liw@sequoia-pgp.org> | 2022-07-06 11:10:50 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@sequoia-pgp.org> | 2022-07-15 15:49:17 +0300 |
commit | f771d80fd81f1e71dbe010b82654e436ba31fc26 (patch) | |
tree | d0d5f64e4845317cc5a358bb450b60ae2d36b578 /sq/subplot | |
parent | af1a9b57b7efcff3c5bb26a66d43f1145da371db (diff) |
sq: update subplot to test JSON output for 'sq keyring list' works
Sponsored-by: NLnet Foundation; NGI Assure
Diffstat (limited to 'sq/subplot')
-rw-r--r-- | sq/subplot/sq-subplot.rs | 90 | ||||
-rw-r--r-- | sq/subplot/sq-subplot.yaml | 10 |
2 files changed, 100 insertions, 0 deletions
diff --git a/sq/subplot/sq-subplot.rs b/sq/subplot/sq-subplot.rs index dba22e9e..6c7aa3b8 100644 --- a/sq/subplot/sq-subplot.rs +++ b/sq/subplot/sq-subplot.rs @@ -1,7 +1,9 @@ // Rust support for running sq-subplot.md scenarios. +use subplotlib::file::SubplotDataFile; use subplotlib::steplibrary::runcmd::Runcmd; +use std::collections::HashMap; use std::path::Path; #[step] @@ -32,3 +34,91 @@ fn install_sq(context: &ScenarioContext) { )?; } } + +/// Remember values between steps. +#[derive(Default, Debug, Clone)] +struct Memory { + map: HashMap<String, String>, +} + +impl ContextElement for Memory { + fn scenario_starts(&mut self) -> StepResult { + self.map.clear(); + Ok(()) + } +} + +impl Memory { + /// Remember a key, value pair. + pub fn remember(&mut self, key: &str, value: &str) { + eprintln!("remember {}={:?}", key, value); + self.map.insert(key.into(), value.into()); + } + + /// Retrieve the value for a key. Panics if key hasn't been set. + pub fn get(&self, key: &str) -> &str { + eprintln!("recall {}: {:?}", key, self.map.get(key)); + self.map.get(key).unwrap() + } +} + +#[step] +#[context(Memory)] +#[context(Runcmd)] +fn remember_fingerprint_in_variable(context: &ScenarioContext, name: &str) { + let stdout = context.with(|runcmd: &Runcmd| Ok(runcmd.stdout_as_string()), false)?; + const PAT: &str = "Fingerprint: "; + if let Some(i) = stdout.find(PAT) { + let s = &stdout[i + PAT.len()..]; + if let Some(j) = s.find('\n') { + let fpr = &s[..j]; + context.with_mut(|memory: &mut Memory| Ok(memory.remember(name, fpr)), false)?; + } else { + panic!("stdout didn't include newline after {:?}", PAT); + } + } else { + panic!("STDOUT didn't include {:?}", PAT); + } +} + +#[step] +#[context(Memory)] +#[context(Runcmd)] +fn stdout_matches_json_template(context: &ScenarioContext, file: SubplotDataFile) { + let memory = context.with(|memory: &Memory| Ok(memory.clone()), false)?; + let template = String::from_utf8_lossy(file.data()); + let wanted = expand_from_memory(&template, &memory); + eprintln!("parsing JSON"); + let wanted: serde_json::Value = serde_json::from_str(&wanted)?; + eprintln!("matches JSON template: wanted: {:#?}", wanted); + + let stdout = context.with(|runcmd: &Runcmd| Ok(runcmd.stdout_as_string()), false)?; + let actual: serde_json::Value = serde_json::from_str(&stdout)?; + eprintln!("matches JSON template: actual: {:#?}", actual); + + assert_eq!(actual, wanted); +} + +fn expand_from_memory(mut s: &str, memory: &Memory) -> String { + let mut result = String::new(); + while !s.is_empty() { + let before = s; + if let Some(i) = s.find("${") { + result.push_str(&s[..i]); + s = &s[i..]; + if let Some(j) = s.find("}") { + let name = &s[2..j]; + result.push_str(memory.get(name)); + s = &s[j+1..]; + } else { + result.push_str(&s[..2]); + s = &s[2..]; + } + } else { + result.push_str(s); + s = ""; + } + assert!(s != before); + } + result +} diff --git a/sq/subplot/sq-subplot.yaml b/sq/subplot/sq-subplot.yaml index 084d7e2e..f9008253 100644 --- a/sq/subplot/sq-subplot.yaml +++ b/sq/subplot/sq-subplot.yaml @@ -2,3 +2,13 @@ impl: rust: function: install_sq + +- then: "I remember the fingerprint as {name}" + impl: + rust: + function: remember_fingerprint_in_variable + +- then: "stdout, as JSON, matches pattern {file:file}" + impl: + rust: + function: stdout_matches_json_template |