Files
2026-10-28 09:16:54 +01:00

127 lines
3.9 KiB
Rust

//! The explicit importer must preserve source paths and never start on help/error.
use std::{fs, path::PathBuf, process::Command};
struct Fixture {
_temporary: tempfile::TempDir,
root: PathBuf,
launcher: PathBuf,
arguments: PathBuf,
environment: PathBuf,
}
impl Fixture {
fn new() -> Self {
let temporary = tempfile::tempdir().unwrap();
let root = temporary.path().to_path_buf();
let project = root.join("new application");
fs::create_dir(&project).unwrap();
let launcher = project.join("import-python.sh");
fs::write(&launcher, include_str!("../import-python.sh")).unwrap();
fs::write(
project.join("start.sh"),
"#!/usr/bin/env bash\nset -euo pipefail\nprintf '%s\\0' \"$@\" > \"$IMPORT_TEST_ARGS\"\nprintf '%s\\0' \"${DATA_DIR-}\" \"${DATABASE_PATH-}\" > \"$IMPORT_TEST_ENV\"\nexit \"${IMPORT_TEST_STATUS:-0}\"\n",
)
.unwrap();
Self {
_temporary: temporary,
launcher,
arguments: root.join("arguments"),
environment: root.join("environment"),
root,
}
}
fn command(&self) -> Command {
let mut command = Command::new("bash");
command
.arg(&self.launcher)
.current_dir(&self.root)
.env("IMPORT_TEST_ARGS", &self.arguments)
.env("IMPORT_TEST_ENV", &self.environment)
.env_remove("IMPORT_TEST_STATUS");
command
}
fn arguments(&self) -> Vec<String> {
let mut bytes = fs::read(&self.arguments).unwrap();
assert_eq!(bytes.pop(), Some(0));
bytes
.split(|byte| *byte == 0)
.map(|part| String::from_utf8(part.to_vec()).unwrap())
.collect()
}
}
#[test]
fn help_and_invalid_sources_do_not_build_or_import() {
let fixture = Fixture::new();
let help = fixture.command().arg("--help").output().unwrap();
assert!(help.status.success());
assert!(
String::from_utf8(help.stdout)
.unwrap()
.contains("SOURCE_DIRECTORY")
);
assert!(!fixture.arguments.exists());
for arguments in [vec![], vec![""], vec!["missing source"]] {
let result = fixture.command().args(arguments).output().unwrap();
assert_eq!(result.status.code(), Some(2));
assert!(!fixture.arguments.exists());
}
}
#[test]
fn resolves_source_and_preserves_arguments_and_destination_settings() {
let fixture = Fixture::new();
let source_name = "old app; literal $(no-command)";
let source = fixture.root.join(source_name);
fs::create_dir(&source).unwrap();
let result = fixture
.command()
.args([
source_name,
"--database",
"docker-data/db/original data.db",
"--backup-root",
"/srv/original backups",
])
.env("DATA_DIR", "./new storage")
.env("DATABASE_PATH", "./new storage/custom.db")
.env("CDPATH", &fixture.root)
.output()
.unwrap();
assert!(result.status.success(), "{:?}", result);
assert_eq!(
fixture.arguments(),
[
"import-python",
"--source",
source.canonicalize().unwrap().to_str().unwrap(),
"--database",
"docker-data/db/original data.db",
"--backup-root",
"/srv/original backups",
]
);
assert_eq!(
fs::read(&fixture.environment).unwrap(),
b"./new storage\0./new storage/custom.db\0"
);
}
#[test]
fn forwards_import_failure_without_falling_back_to_serve() {
let fixture = Fixture::new();
fs::create_dir(fixture.root.join("source")).unwrap();
let result = fixture
.command()
.arg("source")
.env("IMPORT_TEST_STATUS", "23")
.output()
.unwrap();
assert_eq!(result.status.code(), Some(23));
assert_eq!(fixture.arguments().len(), 3);
assert_eq!(fixture.arguments()[0], "import-python");
}