summaryrefslogtreecommitdiffstats
path: root/sq/subplot
diff options
context:
space:
mode:
authorLars Wirzenius <liw@sequoia-pgp.org>2022-07-06 11:10:50 +0300
committerLars Wirzenius <liw@sequoia-pgp.org>2022-07-15 15:49:17 +0300
commitf771d80fd81f1e71dbe010b82654e436ba31fc26 (patch)
treed0d5f64e4845317cc5a358bb450b60ae2d36b578 /sq/subplot
parentaf1a9b57b7efcff3c5bb26a66d43f1145da371db (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.rs90
-rw-r--r--sq/subplot/sq-subplot.yaml10
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