#![warn(anonymous_parameters, bad_style, missing_docs)]
#![warn(unused, unused_extern_crates, unused_import_braces, unused_qualifications)]
#![warn(unsafe_code)]
use std::env;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::process;
fn self_dir() -> PathBuf {
let self_exe = env::current_exe().expect("Cannot get self's executable path");
let dir = self_exe.parent().expect("Cannot get self's directory");
assert!(dir.ends_with("target/debug/deps") || dir.ends_with("target/release/deps"));
dir.to_owned()
}
fn bin_path<P: AsRef<Path>>(name: P) -> PathBuf {
let test_dir = self_dir();
let debug_or_release_dir = test_dir.parent().expect("Failed to get parent directory");
debug_or_release_dir.join(name).with_extension(env::consts::EXE_EXTENSION)
}
fn src_path(name: &str) -> PathBuf {
let test_dir = self_dir();
let debug_or_release_dir = test_dir.parent().expect("Failed to get parent directory");
let target_dir = debug_or_release_dir.parent().expect("Failed to get parent directory");
let dir = target_dir.parent().expect("Failed to get parent directory");
assert!(dir.join("Cargo.toml").exists());
dir.join(name)
}
fn src_str(p: &str) -> String {
src_path(p).to_str().expect("Need paths to be valid strings").to_owned()
}
enum Behavior {
Null,
File(PathBuf),
}
fn read_golden(path: &Path) -> String {
let mut f = File::open(path).expect("Failed to open golden data file");
let mut golden = vec![];
f.read_to_end(&mut golden).expect("Failed to read golden data file");
let raw = String::from_utf8(golden).expect("Golden data file is not valid UTF-8");
if cfg!(target_os = "windows") {
raw.replace("\r\n", "\n")
} else {
raw
}
}
fn check<P: AsRef<Path>>(
bin: P,
args: &[&str],
exp_code: i32,
stdin_behavior: Behavior,
stdout_behavior: Behavior,
stderr_behavior: Behavior,
) {
let golden_stdin = match stdin_behavior {
Behavior::Null => process::Stdio::null(),
Behavior::File(path) => File::open(path).unwrap().into(),
};
let exp_stdout = match stdout_behavior {
Behavior::Null => "".to_owned(),
Behavior::File(path) => read_golden(&path),
};
let exp_stderr = match stderr_behavior {
Behavior::Null => "".to_owned(),
Behavior::File(path) => read_golden(&path),
};
let result = process::Command::new(bin.as_ref())
.args(args)
.stdin(golden_stdin)
.output()
.expect("Failed to execute subprocess");
let code = result.status.code().expect("Subprocess didn't exit cleanly");
let stdout = String::from_utf8(result.stdout).expect("Stdout not is not valid UTF-8");
let stderr = String::from_utf8(result.stderr).expect("Stderr not is not valid UTF-8");
if exp_code != code || exp_stdout != stdout || exp_stderr != stderr {
eprintln!("Exit code: {}", code);
eprintln!("stdout:\n{}", stdout);
eprintln!("stderr:\n{}", stderr);
assert_eq!(exp_code, code);
assert_eq!(exp_stdout, stdout);
assert_eq!(exp_stderr, stderr);
}
}
#[test]
fn test_example_script_runner() {
check(
bin_path("examples/script-runner"),
&[&src_str("std/tests/script.bas")],
0,
Behavior::Null,
Behavior::File(src_path("std/tests/script.out")),
Behavior::Null,
);
}
#[test]
fn test_example_script_runner_errors() {
check(
bin_path("examples/script-runner"),
&[&src_str("std/tests/script-errors.bas")],
1,
Behavior::Null,
Behavior::Null,
Behavior::File(src_path("std/tests/script-errors.err")),
);
}