chiark / gitweb /
wdt, at: Make wdriver into a portmanteau executable
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 14 Mar 2021 11:45:49 +0000 (11:45 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 14 Mar 2021 11:45:49 +0000 (11:45 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
12 files changed:
Makefile
apitest.rs
apitest/at-otter.rs
src/imports.rs
src/prelude.rs
wdriver/Cargo.toml
wdriver/bin [deleted symlink]
wdriver/src [deleted symlink]
wdriver/wdriver.rs [moved from wdriver.rs with 92% similarity]
wdriver/wdt-altergame.rs
wdriver/wdt-hand.rs
wdriver/wdt-simple.rs

index b7b73af4d7f3a000dcba1ed8950e5c77212dfb9f..e08c9c72916039532f5f65aeb033d4687731788c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -322,18 +322,21 @@ AT_DEPS = $(filter-out templates/script.js, $(RUNTEST_DEPS)) \
 WDT_DEPS =     $(RUNTEST_DEPS) \
                stamp/cargo-wdt.debug
 
-AT_WDT_RUN = $(NAILING_CARGO_JUST_RUN) $(abspath $<) $(basename $(notdir $@))
+AT_WDT_RUN = $(NAILING_CARGO_JUST_RUN) $(abspath $<)
+
+AT_RUN = $(AT_WDT_RUN) $(basename $(notdir $@))
+WDT_RUN = $(AT_WDT_RUN) wdriver --test=$(basename $(notdir $@))
 
 stamp/at-%.check:      $(AT_DEPS)
-       $(AT_WDT_RUN)
+       $(AT_RUN)
        $(stamp)
 
 stamp/wdt-%.check:     $(WDT_DEPS)
-       $(AT_WDT_RUN)
+       $(WDT_RUN)
        $(stamp)
 
 stamp/wdt-%.lcheck:    $(WDT_DEPS)
-       $(AT_WDT_RUN) --as-if=lwdt-$* --layout=Landscape
+       $(WDT_RUN) --as-if=lwdt-$* --layout=Landscape
        $(stamp)
 
 #---------- deployment ----------
index 56593d8648e0a0ef8dd464117e1537438613e5f0..960c8e00461dc89ba0ca8c89b389669db55d8805 100644 (file)
@@ -59,6 +59,9 @@ pub struct Opts {
 
   #[structopt(flatten)]
   pub tests: WantedTestsOpt,
+
+  #[structopt(long="--test")]
+  test_name: Option<String>,
 }
 
 #[derive(Debug)]
@@ -433,8 +436,11 @@ pub fn fork_something_which_prints(mut cmd: Command,
 
 // ==================== principal actual setup code ====================
 
+pub type EarlyArgPredicate<'f> = &'f mut dyn FnMut(&OsStr) -> bool;
+
 #[throws(AE)]
-pub fn reinvoke_via_bwrap(_opts: &Opts, current_exe: &str) -> Void {
+pub fn reinvoke_via_bwrap(_opts: &Opts, current_exe: &str,
+                          early: EarlyArgPredicate<'_>) -> Void {
   debug!("running bwrap");
   
   let mut bcmd = Command::new("bwrap");
@@ -443,9 +449,19 @@ pub fn reinvoke_via_bwrap(_opts: &Opts, current_exe: &str) -> Void {
            --dev-bind / / \
            --tmpfs /tmp \
            --die-with-parent".split(" "))
-    .arg(current_exe)
-    .arg("--no-bwrap")
-    .args(env::args_os().skip(1));
+    .arg(current_exe);
+
+  let (early, late) = {
+    let mut still_early = true;
+    env::args_os().skip(1)
+      .partition::<Vec<_>,_>(|s| {
+        still_early &= early(&s);
+        still_early
+      })
+  };
+  bcmd.args(early);
+  bcmd.arg("--no-bwrap");
+  bcmd.args(late);
 
   std::io::stdout().flush().context("flush stdout")?;
   let e: AE = bcmd.exec().into();
@@ -465,6 +481,8 @@ pub fn prepare_tmpdir<'x>(opts: &'x Opts, mut current_exe: &'x str) -> DirSubst
 
   if let Some(as_if) = &opts.as_if {
     current_exe = as_if;
+  } else if let Some(test_name) = &opts.test_name {
+    current_exe = test_name;
   }
 
   let start_dir = getcwd()
@@ -782,7 +800,7 @@ impl MgmtChannel {
 // ==================== core entrypoint, for wdriver too ====================
 
 #[throws(AE)]
-pub fn setup_core<O>(module_paths: &[&str]) ->
+pub fn setup_core<O>(module_paths: &[&str], early_args: EarlyArgPredicate) ->
   (O, cleanup_notify::Handle, Instance, SetupCore)
   where O: StructOpt + AsRef<Opts>
 {
@@ -813,7 +831,7 @@ pub fn setup_core<O>(module_paths: &[&str]) ->
     .to_owned();
 
   if !opts.no_bwrap {
-    reinvoke_via_bwrap(&opts, &current_exe)
+    reinvoke_via_bwrap(&opts, &current_exe, early_args)
       .context("reinvoke via bwrap")?;
   }
 
index 1764b17324cb71b65faf8405f41281066cab53eb..83a5490d96b055ef8df7bb44788d0417859e2005 100644 (file)
@@ -555,7 +555,10 @@ fn tests(mut c: Ctx) {
 #[throws(AE)]
 fn main() {
   {
-    let (opts, _cln, instance, mut su) = setup_core(&[module_path!()])?;
+    let (opts, _cln, instance, mut su) = setup_core(
+      &[module_path!()],
+      &mut |_|false
+    )?;
     let spec = su.ds.game_spec_data()?;
     let [alice, bob]: [Player; 2] = su.ds.setup_static_users(
       default(),
index af48fc21d594e4943896b901a192425ed853810a..c96f35262e87414d8e018bbd460b744f185d157c 100644 (file)
@@ -22,6 +22,7 @@ pub use htmlescape;
 pub use index_vec;
 pub use lazy_init;
 pub use lazy_static;
+pub use inventory;
 pub use itertools;
 pub use libc;
 pub use log;
index ea38053644bc5064cbb983c5cf3f437b60f1aff6..a2c0991760a96b9ab4e9247e7bcc5a9af4a0c37d 100644 (file)
@@ -16,6 +16,7 @@ pub use std::collections::{hash_map, HashMap, HashSet};
 pub use std::convert::{Infallible, TryFrom, TryInto};
 pub use std::env;
 pub use std::error::Error;
+pub use std::ffi::OsStr;
 pub use std::fmt::Formatter;
 pub use std::fmt::Write as _;
 pub use std::fmt::{self, Debug, Display};
index 8850f1b52effe8efc6fb82e01aab3fa437dedb76..2a9bdd62d3d1f2d13c408d020018d82f29116b3b 100644 (file)
@@ -24,6 +24,6 @@ serde = { version = "1", features = ["derive","rc"] }
 structopt = "0.3"
 strum = { version = "0.20", features = ['derive'] }
 
-[lib]
-name = "otter_webdriver_tests"
-path = "../wdriver.rs"
+[[bin]]
+name = "wdriver"
+path = "wdriver.rs"
diff --git a/wdriver/bin b/wdriver/bin
deleted file mode 120000 (symlink)
index 945c9b4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.
\ No newline at end of file
diff --git a/wdriver/src b/wdriver/src
deleted file mode 120000 (symlink)
index 945c9b4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-.
\ No newline at end of file
similarity index 92%
rename from wdriver.rs
rename to wdriver/wdriver.rs
index 46ea76c0077dac9c067f584db7e15ac1af0bcece..d71024a74bdd89474f69aab4fd2ccc068692dad0 100644 (file)
@@ -615,7 +615,10 @@ impl Drop for Setup {
 #[throws(AE)]
 pub fn setup(exe_module_path: &str) -> (Setup, Instance) {
   let (opts, cln, instance, core) =
-    apitest::setup_core(&[exe_module_path, "otter_webdriver_tests"])?;
+    apitest::setup_core(
+      &[exe_module_path, "otter_webdriver_tests"],
+      &mut |s: &OsStr| s.to_str().unwrap().starts_with("--test=")
+    )?;
 
   prepare_xserver(&cln, &core.ds).always_context("setup X server")?;
 
@@ -677,3 +680,54 @@ pub fn as_usual<F: FnOnce(UsualSetup) -> Result<(), AE>>(
   f(usual)?;
   info!("ok");
 }
+
+// ==================== portmanteau binary ====================
+
+pub struct PortmanteauMember {
+  path: &'static str,
+  f: fn() -> Result<(), AE>,
+}
+inventory::collect!(PortmanteauMember);
+
+macro_rules! portmanteau_has {
+  ($path:literal, $mod:ident) => {
+    #[path = $path] mod $mod;
+    inventory::submit!(PortmanteauMember { path: $path, f: $mod::main });
+  }
+}
+
+#[throws(AE)]
+fn main(){
+  let arg = 'arg: loop {
+    for (ai, s) in env::args().enumerate() {
+      let plausible = |s: &str| s.starts_with("wdt-");
+
+      break 'arg if ai == 0 {
+        let s = s.rsplitn(2,'/').next().unwrap();
+        if ! plausible(s) { continue }
+        s
+      } else {
+        let s = s.strip_prefix("--test=")
+          .expect("found non-long-option looking for --test=wdt-*");
+        if ! plausible(s) {
+          panic!("found non --no-bwrap --wdt-* option looking for --wdt-*");
+        }
+        s
+      }.to_owned();
+    }
+    panic!("ran out of options looking for --test=wdt-*");
+  };
+
+  let f = inventory::iter::<PortmanteauMember>.into_iter()
+    .find_map(|pm| {
+      let n = pm.path.strip_suffix(".rs").unwrap();
+      if n == arg { Some(pm.f) } else { None }
+    })
+    .expect("unrecognosed wdt-* portanteau member");
+
+  f()?;
+}
+
+portmanteau_has!("wdt-altergame.rs", wdt_altergame);
+portmanteau_has!("wdt-hand.rs",      wdt_hand);
+portmanteau_has!("wdt-simple.rs",    wdt_simple);
index 43dd916feb0310104c81dac769863f8bb7899410..d15564763f056717b2d1d06477cd740d1a04aee5 100644 (file)
@@ -2,7 +2,7 @@
 // SPDX-License-Identifier: AGPL-3.0-or-later
 // There is NO WARRANTY.
 
-use otter_webdriver_tests::*;
+use crate::*;
 
 use otter::spec::LinkKind;
 
@@ -90,4 +90,4 @@ fn tests(UsualSetup { su, alice, ..}: UsualSetup) {
 }
 
 #[throws(AE)]
-fn main() { as_usual(tests, module_path!())? }
+pub fn main() { as_usual(tests, module_path!())? }
index 74575fdf87b4838077dbcbbf01ed5dc0146ffe4c..0a2cc791a9c2f8d0a2932fa7612686a0ba7cc174 100644 (file)
@@ -2,7 +2,7 @@
 // SPDX-License-Identifier: AGPL-3.0-or-later
 // There is NO WARRANTY.
 
-use otter_webdriver_tests::*;
+use crate::*;
 
 struct Ctx {
   su: Setup,
@@ -104,4 +104,4 @@ fn tests(UsualSetup { su, alice, bob, ..}: UsualSetup) {
 }
 
 #[throws(AE)]
-fn main() { as_usual(tests, module_path!())? }
+pub fn main() { as_usual(tests, module_path!())? }
index 8116f7dd42f0da90b590782ea0cad07b55c09bd8..922e64cb946e722cbfd24626bd5383cd642636ee 100644 (file)
@@ -2,7 +2,7 @@
 // SPDX-License-Identifier: AGPL-3.0-or-later
 // There is NO WARRANTY.
 
-use otter_webdriver_tests::*;
+use crate::*;
 
 struct Ctx {
   su: Setup,
@@ -297,4 +297,4 @@ fn tests(UsualSetup { su, alice, bob, spec, ..}: UsualSetup) {
 }
 
 #[throws(AE)]
-fn main() { as_usual(tests, module_path!())? }
+pub fn main() { as_usual(tests, module_path!())? }