1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
// Rust support for running sq-subplot.md scenarios.
use subplotlib::file::SubplotDataFile;
use subplotlib::steplibrary::datadir::Datadir;
use subplotlib::steplibrary::runcmd::Runcmd;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
#[step]
#[context(Runcmd)]
#[context(Datadir)]
fn install_sq(context: &ScenarioContext) {
// The SQ_DIR variable can be set to test an installed sq rather
// than the one built from the source tree.
if let Some(bindir) = std::env::var_os("SQ_DIR") {
println!("Found SQ_DIR environment variable, using that");
context.with_mut(
|rc: &mut Runcmd| {
rc.prepend_to_path(bindir);
Ok(())
},
false,
)?;
} else {
let target_exe = env!("CARGO_BIN_EXE_sq");
let target_path = Path::new(target_exe);
let target_path = target_path.parent().ok_or("No parent?")?;
context.with_mut(
|context: &mut Runcmd| {
context.prepend_to_path(target_path);
Ok(())
},
false,
)?;
}
// Create a state directory and set SEQUOIA_HOME so that sq will
// use it.
let home = PathBuf::from(".sequoia-home");
let mut absolute_home = Default::default();
context.with_mut(
|datadir: &mut Datadir| {
datadir.create_dir_all(&home)?;
absolute_home = datadir.base_path().join(home);
Ok(())
}, false)?;
context.with_mut(
|runcmd: &mut Runcmd| {
runcmd.setenv("SEQUOIA_HOME", absolute_home);
Ok(())
}, false)?;
}
/// 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);
}
}
#[cfg(all(unix, not(unix)))] // Bottom.
#[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);
}
#[allow(unused)]
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
}
|