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
// Copyright (c) 2022 PHPER Framework Team
// PHPER is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan
// PSL v2. You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//! Test tools for php cli program.
use crate::context::Context;
use std::{
panic::{catch_unwind, resume_unwind, UnwindSafe},
path::Path,
process::{Child, Output},
};
/// Check your extension by executing the php script, if the all executing
/// return success, than the test is pass.
///
/// - `lib_path` is the path of extension lib.
///
/// - `scripts` is the path of your php test scripts.
///
/// See [example hello integration test](https://github.com/phper-framework/phper/blob/master/examples/hello/tests/integration.rs).
pub fn test_php_scripts(lib_path: impl AsRef<Path>, scripts: &[&dyn AsRef<Path>]) {
let condition = |output: Output| output.status.success();
let scripts = scripts
.iter()
.map(|s| (*s, &condition as _))
.collect::<Vec<_>>();
test_php_scripts_with_condition(lib_path, &scripts);
}
/// Script and condition pair.
pub type ScriptCondition<'a> = (&'a dyn AsRef<Path>, &'a dyn Fn(Output) -> bool);
/// Check your extension by executing the php script, if the all your specified
/// checkers are pass, than the test is pass.
///
/// - `exec_path` is the path of the make executable, which will be used to
/// detect the path of
/// extension lib.
///
/// - `scripts` is the slice of the tuple, format is `(path of your php test
/// script, checker function or closure)`.
///
/// See [example logging integration test](https://github.com/phper-framework/phper/blob/master/examples/logging/tests/integration.rs).
pub fn test_php_scripts_with_condition(
lib_path: impl AsRef<Path>, scripts: &[ScriptCondition<'_>],
) {
let context = Context::get_global();
for (script, condition) in scripts {
let mut cmd = context.create_command_with_lib(&lib_path, script);
let output = cmd.output().unwrap();
let path = script.as_ref().to_str().unwrap();
let mut stdout = String::from_utf8(output.stdout.clone()).unwrap();
if stdout.is_empty() {
stdout.push_str("<empty>");
}
let mut stderr = String::from_utf8(output.stderr.clone()).unwrap();
if stderr.is_empty() {
stderr.push_str("<empty>");
}
eprintln!(
"===== command =====\n{} {}\n===== stdout ======\n{}\n===== stderr ======\n{}",
&context.php_bin,
cmd.get_args().join(" "),
stdout,
stderr,
);
#[cfg(target_os = "linux")]
if output.status.code().is_none() {
use std::os::unix::process::ExitStatusExt;
eprintln!(
"===== signal ======\nExitStatusExt is None, the signal is: {:?}",
output.status.signal()
);
}
if !condition(output) {
panic!("test php file `{}` failed", path);
}
}
}
/// Check your extension by executing the long term php script such as http
/// server, if the all your specified checkers are pass, than the test is pass.
pub fn test_long_term_php_script_with_condition(
lib_path: impl AsRef<Path>, script: impl AsRef<Path>,
condition: impl FnOnce(&Child) + UnwindSafe,
) {
let context = Context::get_global();
let mut command = context.create_command_with_lib(lib_path, script);
let mut child = command.spawn().unwrap();
let r = catch_unwind(|| condition(&child));
child.kill().unwrap();
if let Err(e) = r {
resume_unwind(e);
}
}