mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-25 09:39:52 +08:00
Turn FFI tests into native Rust tests
Keep running tests serially to avoid breaking assumptions. I think many of these tests can run in parallel and/or don't need test_init(). Use the safe variant everywhere, to get it done faster.
This commit is contained in:
parent
ae9e7a25f8
commit
77550a2f0d
|
@ -266,14 +266,12 @@ regressions in the future (i.e., we don’t reintroduce the bug).
|
|||
|
||||
The tests can be found in three places:
|
||||
|
||||
- src/fish_tests.cpp for tests to the core C++ code
|
||||
- fish-rust/src/tests for unit tests.
|
||||
- tests/checks for script tests, run by `littlecheck <https://github.com/ridiculousfish/littlecheck>`__
|
||||
- tests/pexpects for interactive tests using `pexpect <https://pexpect.readthedocs.io/en/stable/>`__
|
||||
|
||||
When in doubt, the bulk of the tests should be added as a littlecheck test in tests/checks, as they are the easiest to modify and run, and much faster and more dependable than pexpect tests. The syntax is fairly self-explanatory. It's a fish script with the expected output in ``# CHECK:`` or ``# CHECKERR:`` (for stderr) comments.
|
||||
|
||||
fish_tests.cpp is mostly useful for unit tests - if you wish to test that a function does the correct thing for given input, use it.
|
||||
|
||||
The pexpects are written in python and can simulate input and output to/from a terminal, so they are needed for anything that needs actual interactivity. The runner is in build_tools/pexpect_helper.py, in case you need to modify something there.
|
||||
|
||||
Local testing
|
||||
|
|
110
Cargo.lock
generated
110
Cargo.lock
generated
|
@ -8,7 +8,7 @@ version = "0.8.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
@ -183,6 +183,12 @@ dependencies = [
|
|||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
@ -200,6 +206,15 @@ dependencies = [
|
|||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
|
@ -339,7 +354,6 @@ dependencies = [
|
|||
"fast-float",
|
||||
"git-version",
|
||||
"hexponent",
|
||||
"inventory",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"lru",
|
||||
|
@ -353,6 +367,7 @@ dependencies = [
|
|||
"rand",
|
||||
"rand_pcg",
|
||||
"rsconf",
|
||||
"serial_test",
|
||||
"unixstring",
|
||||
"widestring",
|
||||
"widestring-suffix",
|
||||
|
@ -364,7 +379,7 @@ version = "0.2.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
@ -455,12 +470,6 @@ version = "1.0.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306"
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a53088c87cf71c9d4f3372a2cb9eea1e7b8a0b1bf8b7f7d23fe5b76dbb07e63b"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.9.0"
|
||||
|
@ -518,7 +527,7 @@ version = "0.7.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
@ -537,6 +546,15 @@ version = "0.4.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
|
@ -604,7 +622,7 @@ checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4"
|
|||
dependencies = [
|
||||
"autocfg",
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
@ -644,6 +662,30 @@ version = "1.18.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b93f386bb233083c799e6e642a9d73db98c24a5deeb95ffc85bf281255dffc98"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"cloudabi",
|
||||
"libc",
|
||||
"redox_syscall 0.1.57",
|
||||
"smallvec",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pcre2"
|
||||
version = "0.2.3"
|
||||
|
@ -791,6 +833,12 @@ dependencies = [
|
|||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.3.5"
|
||||
|
@ -868,6 +916,12 @@ version = "1.0.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.7"
|
||||
|
@ -905,12 +959,40 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serial_test"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fef5f7c7434b2f2c598adc6f9494648a1e41274a75c0ba4056f680ae0c117fd6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"parking_lot",
|
||||
"serial_test_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serial_test_derive"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d08338d8024b227c62bd68a12c7c9883f5c66780abaef15c550dc56f46ee6515"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.24.3"
|
||||
|
@ -952,9 +1034,9 @@ version = "3.7.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"fastrand",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.3.5",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
@ -994,7 +1076,7 @@ version = "1.1.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cfg-if 1.0.0",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ autocxx = "0.23.1"
|
|||
bitflags = "2.4.0"
|
||||
cxx = "1.0"
|
||||
errno = "0.2.8"
|
||||
inventory = { version = "0.3.3", optional = true}
|
||||
lazy_static = "1.4.0"
|
||||
libc = "0.2.137"
|
||||
lru = "0.10.0"
|
||||
|
@ -62,6 +61,9 @@ widestring = "1.0.2"
|
|||
rand_pcg = "0.3.1"
|
||||
git-version = "0.3"
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "0.4.0"
|
||||
|
||||
[build-dependencies]
|
||||
autocxx-build = "0.23.1"
|
||||
cc = { git = "https://github.com/mqudsi/cc-rs", branch = "fish" }
|
||||
|
@ -74,10 +76,7 @@ crate-type = ["staticlib"]
|
|||
path = "fish-rust/src/lib.rs"
|
||||
|
||||
[features]
|
||||
# The fish-ffi-tests feature causes tests to be built which need to use the FFI.
|
||||
# These tests are run by fish_tests().
|
||||
default = ["fish-ffi-tests"]
|
||||
fish-ffi-tests = ["inventory"]
|
||||
default = []
|
||||
benchmark = []
|
||||
|
||||
# The following features are auto-detected by the build-script and should not be enabled manually.
|
||||
|
|
|
@ -25,7 +25,7 @@ set(fish_rust_target "fish-rust")
|
|||
|
||||
set(fish_autocxx_gen_dir "${CMAKE_BINARY_DIR}/fish-autocxx-gen/")
|
||||
|
||||
set(FISH_CRATE_FEATURES "fish-ffi-tests")
|
||||
set(FISH_CRATE_FEATURES)
|
||||
if(NOT DEFINED CARGO_FLAGS)
|
||||
# Corrosion doesn't like an empty string as FLAGS. This is basically a no-op alternative.
|
||||
# See https://github.com/corrosion-rs/corrosion/issues/356
|
||||
|
@ -33,13 +33,13 @@ if(NOT DEFINED CARGO_FLAGS)
|
|||
endif()
|
||||
if(DEFINED ASAN)
|
||||
list(APPEND CARGO_FLAGS "-Z" "build-std")
|
||||
list(APPEND FISH_CRATE_FEATURES "asan")
|
||||
list(APPEND FISH_CRATE_FEATURES FEATURES "asan")
|
||||
endif()
|
||||
|
||||
corrosion_import_crate(
|
||||
MANIFEST_PATH "${CMAKE_SOURCE_DIR}/Cargo.toml"
|
||||
CRATES "fish-rust"
|
||||
FEATURES "${FISH_CRATE_FEATURES}"
|
||||
"${FISH_CRATE_FEATURES}"
|
||||
FLAGS "${CARGO_FLAGS}"
|
||||
)
|
||||
|
||||
|
|
|
@ -113,7 +113,6 @@ fn main() {
|
|||
"fish-rust/src/fd_readable_set.rs",
|
||||
"fish-rust/src/fds.rs",
|
||||
"fish-rust/src/ffi_init.rs",
|
||||
"fish-rust/src/ffi_tests.rs",
|
||||
"fish-rust/src/fish_indent.rs",
|
||||
"fish-rust/src/fish_key_reader.rs",
|
||||
"fish-rust/src/fish.rs",
|
||||
|
@ -138,7 +137,6 @@ fn main() {
|
|||
"fish-rust/src/redirection.rs",
|
||||
"fish-rust/src/screen.rs",
|
||||
"fish-rust/src/signal.rs",
|
||||
"fish-rust/src/smoke.rs",
|
||||
"fish-rust/src/termsize.rs",
|
||||
"fish-rust/src/threads.rs",
|
||||
"fish-rust/src/timer.rs",
|
||||
|
|
|
@ -11,6 +11,8 @@ use once_cell::sync::Lazy;
|
|||
|
||||
use crate::abbrs::abbrs_ffi::abbrs_replacer_t;
|
||||
use crate::parse_constants::SourceRange;
|
||||
#[cfg(test)]
|
||||
use crate::tests::prelude::*;
|
||||
use pcre2::utf32::Regex;
|
||||
|
||||
use self::abbrs_ffi::{abbreviation_t, abbrs_position_t, abbrs_replacement_t};
|
||||
|
@ -439,8 +441,10 @@ impl<'a> GlobalAbbrs<'a> {
|
|||
self.g.erase(name.as_wstr());
|
||||
}
|
||||
}
|
||||
use crate::ffi_tests::add_test;
|
||||
add_test!("rename_abbrs", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn rename_abbrs() {
|
||||
test_init();
|
||||
use crate::abbrs::{Abbreviation, Position};
|
||||
use crate::wchar::prelude::*;
|
||||
|
||||
|
@ -473,4 +477,4 @@ add_test!("rename_abbrs", || {
|
|||
assert!(abbrs_g.erase(L!("gcc")));
|
||||
assert!(!abbrs_g.erase(L!("gcc")));
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ use crate::parse_constants::{
|
|||
SOURCE_OFFSET_INVALID,
|
||||
};
|
||||
use crate::parse_tree::ParseToken;
|
||||
#[cfg(test)]
|
||||
use crate::tests::prelude::*;
|
||||
use crate::tokenizer::{
|
||||
variable_assignment_equals_pos, TokFlags, TokenType, Tokenizer, TokenizerError,
|
||||
TOK_ACCEPT_UNFINISHED, TOK_CONTINUE_AFTER_ERROR, TOK_SHOW_COMMENTS,
|
||||
|
@ -4011,12 +4013,14 @@ fn keyword_for_token(tok: TokenType, token: &wstr) -> ParseKeyword {
|
|||
result
|
||||
}
|
||||
|
||||
use crate::ffi_tests::add_test;
|
||||
add_test!("test_ast_parse", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_ast_parse() {
|
||||
test_init();
|
||||
let src = L!("echo");
|
||||
let ast = Ast::parse(src, ParseTreeFlags::empty(), None);
|
||||
assert!(!ast.any_error);
|
||||
});
|
||||
}
|
||||
|
||||
pub use ast_ffi::{Category, Type};
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ use crate::common::{escape, ScopeGuard};
|
|||
use crate::env::Environment;
|
||||
use crate::io::IoChain;
|
||||
use crate::parser::Parser;
|
||||
#[cfg(test)]
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::{wstr, WString, L};
|
||||
use crate::wutil::{file_id_for_path, FileId, INVALID_FILE_ID};
|
||||
use lru::LruCache;
|
||||
|
@ -315,9 +317,11 @@ impl AutoloadFileCache {
|
|||
}
|
||||
}
|
||||
|
||||
use crate::ffi_tests::add_test;
|
||||
#[widestring_suffix::widestrs]
|
||||
add_test!("test_autoload", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_autoload() {
|
||||
test_init();
|
||||
use crate::common::{charptr2wcstring, wcs2zstring, write_loop};
|
||||
use crate::fds::wopen_cloexec;
|
||||
use crate::wutil::sprintf;
|
||||
|
@ -387,4 +391,4 @@ add_test!("test_autoload", || {
|
|||
|
||||
run!("rm -Rf %ls"L, p1);
|
||||
run!("rm -Rf %ls"L, p2);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ pub mod r#type;
|
|||
pub mod ulimit;
|
||||
pub mod wait;
|
||||
|
||||
// Note these tests will NOT run with cfg(test).
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
mod prelude {
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
use crate::ffi_tests::add_test;
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
|
||||
add_test! {"test_string", || {
|
||||
use crate::parser::Parser;
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_string() {
|
||||
test_init();
|
||||
use crate::builtins::shared::{STATUS_CMD_ERROR, STATUS_CMD_OK, STATUS_INVALID_ARGS};
|
||||
use crate::builtins::string::string;
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::common::escape;
|
||||
use crate::builtins::shared::{STATUS_CMD_ERROR,STATUS_CMD_OK, STATUS_INVALID_ARGS};
|
||||
use crate::io::{IoStreams, OutputStream, StringOutputStream};
|
||||
|
||||
use crate::future_feature_flags::{scoped_test, FeatureFlag};
|
||||
use crate::io::{IoStreams, OutputStream, StringOutputStream};
|
||||
use crate::parser::Parser;
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
|
||||
test_init();
|
||||
|
||||
// avoid 1.3k L!()'s
|
||||
macro_rules! test_cases {
|
||||
|
@ -26,13 +32,21 @@ add_test! {"test_string", || {
|
|||
|
||||
let rc = string(parser, &mut streams, args.as_mut_slice()).expect("string failed");
|
||||
|
||||
assert_eq!(expected_rc.unwrap(), rc, "string builtin returned unexpected return code");
|
||||
assert_eq!(
|
||||
expected_rc.unwrap(),
|
||||
rc,
|
||||
"string builtin returned unexpected return code"
|
||||
);
|
||||
|
||||
let actual = escape(outs.contents());
|
||||
let expected = escape(expected_out);
|
||||
assert_eq!(expected, actual, "string builtin returned unexpected output");
|
||||
assert_eq!(
|
||||
expected, actual,
|
||||
"string builtin returned unexpected output"
|
||||
);
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
let tests = test_cases![
|
||||
(["string", "escape"], STATUS_CMD_ERROR, ""),
|
||||
(["string", "escape", ""], STATUS_CMD_OK, "''\n"),
|
||||
|
@ -269,6 +283,7 @@ add_test! {"test_string", || {
|
|||
string_test(cmd, expected_status, expected_stdout);
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
let qmark_noglob_tests = test_cases![
|
||||
(["string", "match", "a*b?c", "axxb?c"], STATUS_CMD_OK, "axxb?c\n"),
|
||||
(["string", "match", "*?", "a"], STATUS_CMD_ERROR, ""),
|
||||
|
@ -284,6 +299,7 @@ add_test! {"test_string", || {
|
|||
}
|
||||
});
|
||||
|
||||
#[rustfmt::skip]
|
||||
let qmark_glob_tests = test_cases![
|
||||
(["string", "match", "a*b?c", "axxbyc"], STATUS_CMD_OK, "axxbyc\n"),
|
||||
(["string", "match", "*?", "a"], STATUS_CMD_OK, "a\n"),
|
||||
|
@ -298,5 +314,4 @@ add_test! {"test_string", || {
|
|||
string_test(cmd, expected_status, expected_stdout);
|
||||
}
|
||||
});
|
||||
|
||||
}}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::builtins::prelude::*;
|
||||
use crate::builtins::test::test as builtin_test;
|
||||
use crate::io::OutputStream;
|
||||
use crate::tests::prelude::*;
|
||||
|
||||
fn run_one_test_test_mbracket(expected: i32, lst: &[&str], bracket: bool) -> bool {
|
||||
let parser = Parser::principal_parser();
|
||||
|
@ -164,7 +165,10 @@ fn test_test() {
|
|||
assert!(run_test_test(2, &["1", "-eq", "-99999999999999999999999999.9"]));
|
||||
}
|
||||
|
||||
crate::ffi_tests::add_test!("test_test_builtin", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_test_builtin() {
|
||||
test_init();
|
||||
test_test_brackets();
|
||||
test_test();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use crate::common::wcs2zstring;
|
||||
use crate::flog::FLOG;
|
||||
#[cfg(test)]
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::wutil::perror;
|
||||
use libc::{
|
||||
|
@ -292,7 +294,10 @@ pub fn make_fd_blocking(fd: RawFd) -> Result<(), io::Error> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
crate::ffi_tests::add_test!("test_pipes", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_pipes() {
|
||||
test_init();
|
||||
// Here we just test that each pipe has CLOEXEC set and is in the high range.
|
||||
// Note pipe creation may fail due to fd exhaustion; don't fail in that case.
|
||||
let mut pipes = vec![];
|
||||
|
@ -309,4 +314,4 @@ crate::ffi_tests::add_test!("test_pipes", || {
|
|||
assert!(flags & FD_CLOEXEC != 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
//! Support for tests which need to cross the FFI.
|
||||
//!
|
||||
//! Because the C++ is not compiled by `cargo test` and there is no natural way to
|
||||
//! do it, use the following facilities for tests which need to use C++ types.
|
||||
//! This uses the inventory crate to build a custom-test harness
|
||||
//! as described at <https://www.infinyon.com/blog/2021/04/rust-custom-test-harness/>
|
||||
//! See smoke.rs add_test for an example of how to use this.
|
||||
|
||||
#[cfg(all(feature = "fish-ffi-tests", not(test)))]
|
||||
mod ffi_tests_impl {
|
||||
/// A test which needs to cross the FFI.
|
||||
#[derive(Debug)]
|
||||
pub struct FFITest {
|
||||
pub name: &'static str,
|
||||
pub func: fn(),
|
||||
}
|
||||
|
||||
/// Add a new test.
|
||||
/// Example usage:
|
||||
/// ```
|
||||
/// add_test!("test_name", || {
|
||||
/// assert!(1 + 2 == 3);
|
||||
/// });
|
||||
/// ```
|
||||
macro_rules! add_test {
|
||||
($name:literal, $func:expr) => {
|
||||
inventory::submit!(crate::ffi_tests::FFITest {
|
||||
name: $name,
|
||||
func: $func,
|
||||
});
|
||||
};
|
||||
}
|
||||
pub(crate) use add_test;
|
||||
|
||||
inventory::collect!(crate::ffi_tests::FFITest);
|
||||
|
||||
/// Runs all ffi tests.
|
||||
pub fn run_ffi_tests() {
|
||||
for test in inventory::iter::<crate::ffi_tests::FFITest> {
|
||||
println!("Running ffi test {}", test.name);
|
||||
(test.func)();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(all(feature = "fish-ffi-tests", not(test))))]
|
||||
mod ffi_tests_impl {
|
||||
macro_rules! add_test {
|
||||
($name:literal, $func:expr) => {};
|
||||
}
|
||||
pub(crate) use add_test;
|
||||
pub fn run_ffi_tests() {}
|
||||
}
|
||||
|
||||
pub(crate) use ffi_tests_impl::*;
|
||||
|
||||
#[allow(clippy::module_inception)]
|
||||
#[cxx::bridge(namespace = rust)]
|
||||
mod ffi_tests {
|
||||
extern "Rust" {
|
||||
fn run_ffi_tests();
|
||||
}
|
||||
}
|
|
@ -31,8 +31,6 @@ mod future_feature_flags_ffi {
|
|||
extern "Rust" {
|
||||
#[cxx_name = "feature_test"]
|
||||
fn test(flag: FeatureFlag) -> bool;
|
||||
#[cxx_name = "feature_set"]
|
||||
fn set(flag: FeatureFlag, value: bool);
|
||||
#[cxx_name = "feature_set_from_string"]
|
||||
fn set_from_string(str: wcharz_t);
|
||||
}
|
||||
|
@ -106,7 +104,7 @@ pub const METADATA: &[FeatureMetadata] = &[
|
|||
];
|
||||
|
||||
thread_local!(
|
||||
#[cfg(any(test, feature = "fish-ffi-tests"))]
|
||||
#[cfg(test)]
|
||||
static LOCAL_FEATURES: std::cell::RefCell<Option<Features>> = std::cell::RefCell::new(None);
|
||||
);
|
||||
|
||||
|
@ -115,11 +113,11 @@ static FEATURES: Features = Features::new();
|
|||
|
||||
/// Perform a feature test on the global set of features.
|
||||
pub fn test(flag: FeatureFlag) -> bool {
|
||||
#[cfg(any(test, feature = "fish-ffi-tests"))]
|
||||
#[cfg(test)]
|
||||
{
|
||||
LOCAL_FEATURES.with(|fc| fc.borrow().as_ref().unwrap_or(&FEATURES).test(flag))
|
||||
}
|
||||
#[cfg(not(any(test, feature = "fish-ffi-tests")))]
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
FEATURES.test(flag)
|
||||
}
|
||||
|
@ -128,7 +126,7 @@ pub fn test(flag: FeatureFlag) -> bool {
|
|||
pub use test as feature_test;
|
||||
|
||||
/// Set a flag.
|
||||
#[cfg(any(test, feature = "fish-ffi-tests"))]
|
||||
#[cfg(test)]
|
||||
pub fn set(flag: FeatureFlag, value: bool) {
|
||||
LOCAL_FEATURES.with(|fc| fc.borrow().as_ref().unwrap_or(&FEATURES).set(flag, value));
|
||||
}
|
||||
|
@ -139,7 +137,7 @@ pub fn set(flag: FeatureFlag, value: bool) {
|
|||
/// Unknown features are silently ignored.
|
||||
pub fn set_from_string<'a>(str: impl Into<&'a wstr>) {
|
||||
let wstr: &wstr = str.into();
|
||||
#[cfg(any(test, feature = "fish-ffi-tests"))]
|
||||
#[cfg(test)]
|
||||
{
|
||||
LOCAL_FEATURES.with(|fc| {
|
||||
fc.borrow()
|
||||
|
@ -148,7 +146,7 @@ pub fn set_from_string<'a>(str: impl Into<&'a wstr>) {
|
|||
.set_from_string(wstr)
|
||||
});
|
||||
}
|
||||
#[cfg(not(any(test, feature = "fish-ffi-tests")))]
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
FEATURES.set_from_string(wstr)
|
||||
}
|
||||
|
@ -216,7 +214,7 @@ impl Features {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "fish-ffi-tests"))]
|
||||
#[cfg(test)]
|
||||
pub fn scoped_test(flag: FeatureFlag, value: bool, test_fn: impl FnOnce()) {
|
||||
LOCAL_FEATURES.with(|fc| {
|
||||
assert!(
|
||||
|
|
|
@ -2,7 +2,6 @@ use crate::common::{get_by_sorted_name, shell_modes, str2wcstring, Named};
|
|||
use crate::curses;
|
||||
use crate::env::{EnvMode, Environment, CURSES_INITIALIZED};
|
||||
use crate::event;
|
||||
use crate::ffi_tests::add_test;
|
||||
use crate::flog::FLOG;
|
||||
use crate::input_common::{
|
||||
CharEvent, CharEventType, CharInputStyle, InputEventQueuer, ReadlineCmd, R_END_INPUT_FUNCTIONS,
|
||||
|
@ -13,6 +12,8 @@ use crate::reader::{
|
|||
reader_reading_interrupted, reader_reset_interrupted, reader_schedule_prompt_repaint,
|
||||
};
|
||||
use crate::signal::signal_clear_cancel;
|
||||
#[cfg(test)]
|
||||
use crate::tests::prelude::*;
|
||||
use crate::threads::assert_is_main_thread;
|
||||
use crate::wchar::prelude::*;
|
||||
use errno::{set_errno, Errno};
|
||||
|
@ -1191,7 +1192,10 @@ pub fn input_function_get_code(name: &wstr) -> Option<ReadlineCmd> {
|
|||
get_by_sorted_name(name, INPUT_FUNCTION_METADATA).map(|md| md.code)
|
||||
}
|
||||
|
||||
add_test!("test_input", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_input() {
|
||||
test_init();
|
||||
use crate::env::EnvStack;
|
||||
let parser = Parser::new(Arc::pin(EnvStack::new()), false);
|
||||
let mut input = Inputter::new(parser, libc::STDIN_FILENO);
|
||||
|
@ -1233,4 +1237,4 @@ add_test!("test_input", || {
|
|||
} else if evt.get_readline() != ReadlineCmd::DownLine {
|
||||
panic!("Expected to read char down_line");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@ mod fds;
|
|||
#[allow(unused_imports)]
|
||||
mod ffi;
|
||||
mod ffi_init;
|
||||
mod ffi_tests;
|
||||
mod fish;
|
||||
mod fish_indent;
|
||||
mod fish_key_reader;
|
||||
|
@ -98,7 +97,6 @@ mod reader_history_search;
|
|||
mod redirection;
|
||||
mod screen;
|
||||
mod signal;
|
||||
mod smoke;
|
||||
mod termsize;
|
||||
mod threads;
|
||||
mod timer;
|
||||
|
@ -118,6 +116,6 @@ mod widecharwidth;
|
|||
mod wildcard;
|
||||
mod wutil;
|
||||
|
||||
#[cfg(any(test, feature = "fish-ffi-tests"))]
|
||||
#[cfg(test)]
|
||||
#[allow(unused_imports)] // Easy way to suppress warnings while we have two testing modes.
|
||||
mod tests;
|
||||
|
|
|
@ -9,7 +9,6 @@ use crate::expand::{
|
|||
expand_one, expand_to_command_and_args, ExpandFlags, ExpandResultCode, BRACE_BEGIN, BRACE_END,
|
||||
BRACE_SEP, INTERNAL_SEPARATOR, VARIABLE_EXPAND, VARIABLE_EXPAND_EMPTY, VARIABLE_EXPAND_SINGLE,
|
||||
};
|
||||
use crate::ffi_tests::add_test;
|
||||
use crate::future_feature_flags::{feature_test, FeatureFlag};
|
||||
use crate::operation_context::OperationContext;
|
||||
use crate::parse_constants::{
|
||||
|
@ -20,6 +19,8 @@ use crate::parse_constants::{
|
|||
ERROR_NOT_PID, ERROR_NOT_STATUS, ERROR_NO_VAR_NAME, INVALID_BREAK_ERR_MSG,
|
||||
INVALID_CONTINUE_ERR_MSG, INVALID_PIPELINE_CMD_ERR_MSG, UNKNOWN_BUILTIN_ERR_MSG,
|
||||
};
|
||||
#[cfg(test)]
|
||||
use crate::tests::prelude::*;
|
||||
use crate::tokenizer::{
|
||||
comment_end, is_token_delimiter, quote_end, Tok, TokenType, Tokenizer, TOK_ACCEPT_UNFINISHED,
|
||||
TOK_SHOW_COMMENTS,
|
||||
|
@ -1785,7 +1786,10 @@ const TIME_IN_PIPELINE_ERR_MSG: &str =
|
|||
/// Maximum length of a variable name to show in error reports before truncation
|
||||
const var_err_len: usize = 16;
|
||||
|
||||
add_test!("test_parse_util_cmdsubst_extent", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_parse_util_cmdsubst_extent() {
|
||||
test_init();
|
||||
const a: &wstr = L!("echo (echo (echo hi");
|
||||
assert_eq!(parse_util_cmdsubst_extent(a, 0), 0..a.len());
|
||||
assert_eq!(parse_util_cmdsubst_extent(a, 1), 0..a.len());
|
||||
|
@ -1799,9 +1803,12 @@ add_test!("test_parse_util_cmdsubst_extent", || {
|
|||
parse_util_cmdsubst_extent(a, 17),
|
||||
"echo (echo (".chars().count()..a.len()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_escape_quotes", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_escape_quotes() {
|
||||
test_init();
|
||||
macro_rules! validate {
|
||||
($cmd:expr, $quote:expr, $no_tilde:expr, $expected:expr) => {
|
||||
assert_eq!(
|
||||
|
@ -1839,9 +1846,12 @@ add_test!("test_escape_quotes", || {
|
|||
validate!("~abc'def", Some('"'), true, "~abc'def");
|
||||
validate!("foo\nba'r", Some('"'), false, "foo\"\\n\"ba'r");
|
||||
validate!("foo\\\\bar", Some('"'), false, "foo\\\\\\\\bar");
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_indents", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_indents() {
|
||||
test_init();
|
||||
// A struct which is either text or a new indent.
|
||||
struct Segment {
|
||||
// The indent to set
|
||||
|
@ -2025,7 +2035,7 @@ add_test!("test_indents", || {
|
|||
0, "\nend"
|
||||
);
|
||||
})();
|
||||
});
|
||||
}
|
||||
|
||||
#[cxx::bridge]
|
||||
mod parse_util_ffi {
|
||||
|
|
|
@ -582,19 +582,20 @@ impl From<Signal> for NonZeroI32 {
|
|||
}
|
||||
|
||||
// Need to use add_test for wgettext support.
|
||||
use crate::ffi_tests::add_test;
|
||||
|
||||
add_test!("test_signal_name", || {
|
||||
#[test]
|
||||
fn test_signal_name() {
|
||||
let sig = Signal::new(libc::SIGINT);
|
||||
assert_eq!(sig.name(), "SIGINT");
|
||||
});
|
||||
}
|
||||
|
||||
fn new_sighupint_checker() -> Box<SigChecker> {
|
||||
Box::new(SigChecker::new_sighupint())
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
add_test!("test_signal_parse", || {
|
||||
#[test]
|
||||
fn test_signal_parse() {
|
||||
assert_eq!(Signal::parse(L!("SIGHUP")), Some(Signal::new(libc::SIGHUP)));
|
||||
assert_eq!(Signal::parse(L!("sigwinch")), Some(Signal::new(libc::SIGWINCH)));
|
||||
assert_eq!(Signal::parse(L!("TSTP")), Some(Signal::new(libc::SIGTSTP)));
|
||||
|
@ -609,7 +610,7 @@ add_test!("test_signal_parse", || {
|
|||
assert_eq!(Signal::parse(L!("0")), None);
|
||||
assert_eq!(Signal::parse(L!("-0")), None);
|
||||
assert_eq!(Signal::parse(L!("-1")), None);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
#[cxx::bridge(namespace = rust)]
|
||||
mod ffi {
|
||||
extern "Rust" {
|
||||
fn add(left: usize, right: usize) -> usize;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(left: usize, right: usize) -> usize {
|
||||
left + right
|
||||
}
|
||||
|
||||
use crate::ffi_tests::add_test;
|
||||
add_test!("test_add", || {
|
||||
assert_eq!(add(2, 3), 5);
|
||||
});
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
use crate::common::assert_sync;
|
||||
use crate::env::{EnvMode, EnvVar, Environment};
|
||||
use crate::flog::FLOG;
|
||||
#[cfg(test)]
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::wutil::fish_wcstoi;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
||||
|
@ -288,10 +290,11 @@ pub fn termsize_invalidate_tty() {
|
|||
TermsizeContainer::invalidate_tty();
|
||||
}
|
||||
|
||||
use crate::ffi_tests::add_test;
|
||||
|
||||
use self::termsize_ffi::Parser;
|
||||
add_test!("test_termsize", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_termsize() {
|
||||
test_init();
|
||||
let env_global = EnvMode::GLOBAL;
|
||||
let parser = Parser::principal_parser();
|
||||
let vars = parser.vars();
|
||||
|
@ -364,4 +367,4 @@ add_test!("test_termsize", || {
|
|||
assert_eq!(ts.last(), Termsize::new(83, 38));
|
||||
TermsizeContainer::handle_winch();
|
||||
assert_eq!(ts2.updating(parser), stubby_termsize().unwrap());
|
||||
});
|
||||
}
|
||||
|
|
|
@ -7,9 +7,13 @@ use crate::reader::{
|
|||
combine_command_and_autosuggestion, completion_apply_to_command_line,
|
||||
reader_expand_abbreviation_at_cursor,
|
||||
};
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
|
||||
crate::ffi_tests::add_test!("test_abbreviations", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_abbreviations() {
|
||||
test_init();
|
||||
{
|
||||
let mut abbrs = abbrs_get_set();
|
||||
abbrs.add(Abbreviation::new(
|
||||
|
@ -136,4 +140,4 @@ crate::ffi_tests::add_test!("test_abbreviations", || {
|
|||
|
||||
// yin/yang expands everywhere.
|
||||
validate!("command yin", None, "command yang");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ use crate::complete::{
|
|||
CompletionList, CompletionMode, CompletionRequestOptions,
|
||||
};
|
||||
use crate::env::{EnvMode, Environment};
|
||||
use crate::ffi_tests::add_test;
|
||||
use crate::io::IoChain;
|
||||
use crate::operation_context::{
|
||||
no_cancel, OperationContext, EXPANSION_LIMIT_BACKGROUND, EXPANSION_LIMIT_DEFAULT,
|
||||
|
@ -13,6 +12,7 @@ use crate::operation_context::{
|
|||
use crate::parser::Parser;
|
||||
use crate::reader::completion_apply_to_command_line;
|
||||
use crate::tests::prelude::*;
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::wcstringutil::join_strings;
|
||||
use std::collections::HashMap;
|
||||
|
@ -23,7 +23,10 @@ fn comma_join(lst: Vec<WString>) -> WString {
|
|||
join_strings(&lst, ',')
|
||||
}
|
||||
|
||||
add_test!("test_complete", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_complete() {
|
||||
test_init();
|
||||
let vars = PwdEnvironment {
|
||||
parent: TestEnvironment {
|
||||
vars: HashMap::from([
|
||||
|
@ -424,11 +427,14 @@ add_test!("test_complete", || {
|
|||
complete_remove_wrapper(L!("cdwrap1").into(), L!("cd"));
|
||||
complete_remove_wrapper(L!("cdwrap2").into(), L!("cdwrap1"));
|
||||
popd();
|
||||
});
|
||||
}
|
||||
|
||||
// Testing test_autosuggest_suggest_special, in particular for properly handling quotes and
|
||||
// backslashes.
|
||||
add_test!("test_autosuggest_suggest_special", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_autosuggest_suggest_special() {
|
||||
test_init();
|
||||
macro_rules! perform_one_autosuggestion_cd_test {
|
||||
($command:literal, $expected:literal, $vars:expr) => {
|
||||
let mut comps = complete(
|
||||
|
@ -593,9 +599,12 @@ add_test!("test_autosuggest_suggest_special", || {
|
|||
.vars()
|
||||
.remove(L!("HOME"), EnvMode::LOCAL | EnvMode::EXPORT);
|
||||
popd();
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_autosuggestion_ignores", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_autosuggestion_ignores() {
|
||||
test_init();
|
||||
// Testing scenarios that should produce no autosuggestions
|
||||
macro_rules! perform_one_autosuggestion_should_ignore_test {
|
||||
($command:literal) => {
|
||||
|
@ -613,4 +622,4 @@ add_test!("test_autosuggestion_ignores", || {
|
|||
perform_one_autosuggestion_should_ignore_test!("echo PIPE_TEST&");
|
||||
perform_one_autosuggestion_should_ignore_test!("echo PIPE_TEST#comment");
|
||||
perform_one_autosuggestion_should_ignore_test!("echo PIPE_TEST;");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,14 +5,17 @@ use std::sync::{
|
|||
use std::time::Duration;
|
||||
|
||||
use crate::common::ScopeGuard;
|
||||
use crate::ffi_tests::add_test;
|
||||
use crate::global_safety::RelaxedAtomicBool;
|
||||
use crate::parser::Parser;
|
||||
use crate::reader::{reader_current_data, reader_pop, reader_push, ReaderConfig, ReaderData};
|
||||
use crate::tests::prelude::*;
|
||||
use crate::threads::{iothread_drain_all, iothread_service_main, Debounce};
|
||||
use crate::wchar::prelude::*;
|
||||
|
||||
add_test!("test_debounce", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_debounce() {
|
||||
test_init();
|
||||
// Run 8 functions using a condition variable.
|
||||
// Only the first and last should run.
|
||||
let db = Debounce::new(Duration::from_secs(0));
|
||||
|
@ -80,9 +83,12 @@ add_test!("test_debounce", || {
|
|||
assert_eq!(ctx.handler_ran[idx].load(), ctx.completion_ran[idx].load());
|
||||
}
|
||||
assert!(total_ran <= 2);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_debounce_timeout", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_debounce_timeout() {
|
||||
test_init();
|
||||
// Verify that debounce doesn't wait forever.
|
||||
// Use a shared_ptr so we don't have to join our threads.
|
||||
let timeout = Duration::from_millis(500);
|
||||
|
@ -126,4 +132,4 @@ add_test!("test_debounce_timeout", || {
|
|||
let mut exit_ok = data.exit_ok.lock().unwrap();
|
||||
*exit_ok = true;
|
||||
data.cv.notify_all();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use crate::env::{EnvMode, EnvVar, EnvVarFlags, Environment};
|
||||
use crate::ffi_tests::add_test;
|
||||
use crate::parser::Parser;
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
|
@ -89,7 +88,10 @@ fn test_timezone_env_vars() {
|
|||
}
|
||||
|
||||
// Verify that setting special env vars have the expected effect on the current shell process.
|
||||
add_test!("test_env_vars", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_env_vars() {
|
||||
test_init();
|
||||
test_timezone_env_vars();
|
||||
// TODO: Add tests for the locale and ncurses vars.
|
||||
|
||||
|
@ -103,9 +105,12 @@ add_test!("test_env_vars", || {
|
|||
assert!(v1 == v2 && !(v1 != v2));
|
||||
assert!(v1 != v3 && !(v1 == v3));
|
||||
assert!(v1 != v4 && !(v1 == v4));
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_env_snapshot", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_env_snapshot() {
|
||||
test_init();
|
||||
std::fs::create_dir_all("test/fish_env_snapshot_test/").unwrap();
|
||||
pushd("test/fish_env_snapshot_test/");
|
||||
let vars = Parser::principal_parser().vars();
|
||||
|
@ -171,4 +176,4 @@ add_test!("test_env_snapshot", || {
|
|||
|
||||
vars.pop();
|
||||
popd();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@ use crate::common::wcs2osstring;
|
|||
use crate::common::ScopeGuard;
|
||||
use crate::env::{EnvVar, EnvVarFlags, VarTable};
|
||||
use crate::env_universal_common::{CallbackDataList, EnvUniversal, UvarFormat};
|
||||
use crate::ffi_tests::add_test;
|
||||
use crate::flog::FLOG;
|
||||
use crate::parser::Parser;
|
||||
use crate::reader::{reader_current_data, reader_pop, reader_push, ReaderConfig};
|
||||
use crate::tests::prelude::*;
|
||||
use crate::threads::{iothread_drain_all, iothread_perform};
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::wutil::file_id_for_path;
|
||||
|
@ -15,6 +15,7 @@ const UVARS_PER_THREAD: usize = 8;
|
|||
const UVARS_TEST_PATH: &wstr = L!("test/fish_uvars_test/varsfile.txt");
|
||||
|
||||
fn test_universal_helper(x: usize) {
|
||||
test_init();
|
||||
let mut callbacks = CallbackDataList::new();
|
||||
let mut uvars = EnvUniversal::new();
|
||||
uvars.initialize_at_path(&mut callbacks, UVARS_TEST_PATH.to_owned());
|
||||
|
@ -36,7 +37,10 @@ fn test_universal_helper(x: usize) {
|
|||
assert!(synced, "Failed to sync universal variables after deletion");
|
||||
}
|
||||
|
||||
add_test!("test_universal", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_universal() {
|
||||
test_init();
|
||||
let _ = std::fs::remove_dir_all("test/fish_uvars_test/");
|
||||
std::fs::create_dir_all("test/fish_uvars_test/").unwrap();
|
||||
|
||||
|
@ -70,9 +74,12 @@ add_test!("test_universal", || {
|
|||
}
|
||||
|
||||
std::fs::remove_dir_all("test/fish_uvars_test/").unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_universal_output", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_universal_output() {
|
||||
test_init();
|
||||
let flag_export = EnvVarFlags::EXPORT;
|
||||
let flag_pathvar = EnvVarFlags::PATHVAR;
|
||||
|
||||
|
@ -116,9 +123,10 @@ add_test!("test_universal_output", || {
|
|||
)
|
||||
.as_bytes();
|
||||
assert_eq!(text, expected);
|
||||
});
|
||||
}
|
||||
|
||||
fn test_universal_parsing() {
|
||||
test_init();
|
||||
let input = concat!(
|
||||
"# This file contains fish universal variable definitions.\n",
|
||||
"# VERSION: 3.0\n",
|
||||
|
@ -167,7 +175,10 @@ fn test_universal_parsing() {
|
|||
assert_eq!(vars, parsed_vars);
|
||||
}
|
||||
|
||||
add_test!("test_universal_parsing_legacy", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_universal_parsing_legacy() {
|
||||
test_init();
|
||||
let input = concat!(
|
||||
"# This file contains fish universal variable definitions.\n",
|
||||
"SET varA:ValA1\\x1eValA2\n",
|
||||
|
@ -191,9 +202,12 @@ add_test!("test_universal_parsing_legacy", || {
|
|||
let mut parsed_vars = VarTable::new();
|
||||
EnvUniversal::populate_variables(input, &mut parsed_vars);
|
||||
assert_eq!(vars, parsed_vars);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_universal_callbacks", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_universal_callbacks() {
|
||||
test_init();
|
||||
std::fs::create_dir_all("test/fish_uvars_test/").unwrap();
|
||||
let mut callbacks = CallbackDataList::new();
|
||||
let mut uvars1 = EnvUniversal::new();
|
||||
|
@ -245,9 +259,12 @@ add_test!("test_universal_callbacks", || {
|
|||
assert_eq!(callbacks[2].key, L!("delta"));
|
||||
assert_eq!(callbacks[2].val, None);
|
||||
std::fs::remove_dir_all("test/fish_uvars_test/").unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_universal_formats", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_universal_formats() {
|
||||
test_init();
|
||||
macro_rules! validate {
|
||||
( $version_line:literal, $expected_format:expr ) => {
|
||||
assert_eq!(
|
||||
|
@ -264,9 +281,12 @@ add_test!("test_universal_formats", || {
|
|||
validate!(b"# blah\n#VERSION: 3.0", UvarFormat::fish_3_0);
|
||||
validate!(b"# blah\n#VERSION:3.0", UvarFormat::fish_3_0);
|
||||
validate!(b"# blah\n#VERSION:3.1", UvarFormat::future);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_universal_ok_to_save", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_universal_ok_to_save() {
|
||||
test_init();
|
||||
// Ensure we don't try to save after reading from a newer fish.
|
||||
std::fs::create_dir_all("test/fish_uvars_test/").unwrap();
|
||||
let contents = b"# VERSION: 99999.99\n";
|
||||
|
@ -297,4 +317,4 @@ add_test!("test_universal_ok_to_save", || {
|
|||
"UVARS_TEST_PATH should not have changed",
|
||||
);
|
||||
std::fs::remove_dir_all("test/fish_uvars_test/").unwrap();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@ use crate::abbrs::{with_abbrs, with_abbrs_mut};
|
|||
use crate::complete::{CompletionList, CompletionReceiver};
|
||||
use crate::env::{EnvMode, EnvStackSetResult};
|
||||
use crate::expand::{expand_to_receiver, ExpandResultCode};
|
||||
use crate::ffi_tests::add_test;
|
||||
use crate::operation_context::{no_cancel, EXPANSION_LIMIT_DEFAULT};
|
||||
use crate::parse_constants::ParseErrorList;
|
||||
use crate::parser::Parser;
|
||||
use crate::tests::prelude::*;
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wildcard::ANY_STRING;
|
||||
use crate::{
|
||||
expand::{expand_string, ExpandFlags},
|
||||
|
@ -63,7 +63,10 @@ fn expand_test_impl(
|
|||
}
|
||||
|
||||
// Test globbing and other parameter expansion.
|
||||
add_test!("test_expand", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_expand() {
|
||||
test_init();
|
||||
/// Perform parameter expansion and test if the output equals the zero-terminated parameter list /// supplied.
|
||||
///
|
||||
/// \param in the string to expand
|
||||
|
@ -342,9 +345,12 @@ add_test!("test_expand", || {
|
|||
expand_test!("l///n", fuzzy_comp, "lol///nub/", "Wrong fuzzy matching 6");
|
||||
|
||||
popd();
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_expand_overflow", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_expand_overflow() {
|
||||
test_init();
|
||||
// Testing overflowing expansions
|
||||
// Ensure that we have sane limits on number of expansions - see #7497.
|
||||
|
||||
|
@ -376,9 +382,12 @@ add_test!("test_expand_overflow", || {
|
|||
assert_eq!(res, ExpandResultCode::error);
|
||||
|
||||
parser.vars().pop();
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_abbreviations", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_abbreviations() {
|
||||
test_init();
|
||||
// Testing abbreviations
|
||||
|
||||
with_abbrs_mut(|abbrset| {
|
||||
|
@ -442,6 +451,4 @@ add_test!("test_abbreviations", || {
|
|||
);
|
||||
|
||||
assert_eq!(abbr_expand_1(L!("foo"), cmd), Some(L!("bar").into()));
|
||||
|
||||
// todo!("port the rest");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::fd_monitor::{
|
|||
FdEventSignaller, FdMonitor, FdMonitorItem, FdMonitorItemId, ItemWakeReason,
|
||||
};
|
||||
use crate::fds::{make_autoclose_pipes, AutoCloseFd};
|
||||
use crate::ffi_tests::add_test;
|
||||
use crate::tests::prelude::*;
|
||||
|
||||
/// Helper to make an item which counts how many times its callback was invoked.
|
||||
///
|
||||
|
@ -104,7 +104,10 @@ impl ItemMaker {
|
|||
}
|
||||
}
|
||||
|
||||
add_test!("fd_monitor_items", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn fd_monitor_items() {
|
||||
test_init();
|
||||
let monitor = FdMonitor::new();
|
||||
|
||||
// Items which will never receive data or be called.
|
||||
|
@ -189,7 +192,7 @@ add_test!("fd_monitor_items", || {
|
|||
assert_eq!(item_pokee.length_read.load(Ordering::Relaxed), 0);
|
||||
assert_eq!(item_pokee.total_calls.load(Ordering::Relaxed), 1);
|
||||
assert_eq!(item_pokee.pokes.load(Ordering::Relaxed), 1);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fd_event_signaller() {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::common::ScopeGuard;
|
||||
use crate::env::EnvMode;
|
||||
use crate::ffi_tests::add_test;
|
||||
use crate::future_feature_flags::{self, FeatureFlag};
|
||||
use crate::parser::Parser;
|
||||
use crate::tests::prelude::*;
|
||||
|
@ -25,7 +24,10 @@ fn get_overlong_path() -> String {
|
|||
longpath
|
||||
}
|
||||
|
||||
add_test!("test_is_potential_path", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_is_potential_path() {
|
||||
test_init();
|
||||
// Directories
|
||||
std::fs::create_dir_all("test/is_potential_path_test/alpha/").unwrap();
|
||||
std::fs::create_dir_all("test/is_potential_path_test/beta/").unwrap();
|
||||
|
@ -156,9 +158,12 @@ add_test!("test_is_potential_path", || {
|
|||
&ctx,
|
||||
PathFlags::PATH_REQUIRE_DIR
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_highlighting", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_highlighting() {
|
||||
test_init();
|
||||
// Testing syntax highlighting
|
||||
pushd("test/fish_highlight_test/");
|
||||
let _popd = ScopeGuard::new((), |_| popd());
|
||||
|
@ -634,4 +639,4 @@ add_test!("test_highlighting", || {
|
|||
(">", fg(HighlightRole::error)),
|
||||
("echo", fg(HighlightRole::error)),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ use crate::common::{
|
|||
};
|
||||
use crate::env::{EnvDyn, EnvMode, EnvStack, Environment};
|
||||
use crate::fds::{wopen_cloexec, AutoCloseFd};
|
||||
use crate::ffi_tests::add_test;
|
||||
use crate::history::{self, History, HistoryItem, HistorySearch, PathList, SearchDirection};
|
||||
use crate::path::path_get_data;
|
||||
use crate::tests::prelude::*;
|
||||
use crate::tests::prelude::*;
|
||||
use crate::tests::string_escape::ESCAPE_TEST_CHAR;
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::wcstringutil::{string_prefixes_string, string_prefixes_string_case_insensitive};
|
||||
|
@ -43,7 +43,10 @@ fn random_string() -> WString {
|
|||
result
|
||||
}
|
||||
|
||||
add_test!("test_history", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_history() {
|
||||
test_init();
|
||||
macro_rules! test_history_matches {
|
||||
($search:expr, $expected:expr) => {
|
||||
let expected: Vec<&wstr> = $expected;
|
||||
|
@ -199,7 +202,7 @@ add_test!("test_history", || {
|
|||
|
||||
// Clean up after our tests.
|
||||
history.clear();
|
||||
});
|
||||
}
|
||||
|
||||
// Wait until the next second.
|
||||
fn time_barrier() {
|
||||
|
@ -226,6 +229,7 @@ fn generate_history_lines(item_count: usize, idx: usize) -> Vec<WString> {
|
|||
}
|
||||
|
||||
fn test_history_races_pound_on_history(item_count: usize, idx: usize) {
|
||||
test_init();
|
||||
// Called in child thread to modify history.
|
||||
let hist = History::new(L!("race_test"));
|
||||
let hist_lines = generate_history_lines(item_count, idx);
|
||||
|
@ -235,7 +239,10 @@ fn test_history_races_pound_on_history(item_count: usize, idx: usize) {
|
|||
}
|
||||
}
|
||||
|
||||
add_test!("test_history_races", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_history_races() {
|
||||
test_init();
|
||||
// This always fails under WSL
|
||||
if is_windows_subsystem_for_linux() {
|
||||
return;
|
||||
|
@ -331,9 +338,12 @@ add_test!("test_history_races", || {
|
|||
assert_eq!(list, Vec::<WString>::new(), "Lines still left in the array");
|
||||
}
|
||||
hist.clear();
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_history_merge", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_history_merge() {
|
||||
test_init();
|
||||
// In a single fish process, only one history is allowed to exist with the given name But it's
|
||||
// common to have multiple history instances with the same name active in different processes,
|
||||
// e.g. when you have multiple shells open. We try to get that right and merge all their history
|
||||
|
@ -437,9 +447,12 @@ add_test!("test_history_merge", || {
|
|||
}
|
||||
}
|
||||
everything.clear();
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_history_path_detection", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_history_path_detection() {
|
||||
test_init();
|
||||
// Regression test for #7582.
|
||||
let tmpdirbuff = CString::new("/tmp/fish_test_history.XXXXXX").unwrap();
|
||||
let tmpdir = unsafe { libc::mkdtemp(tmpdirbuff.into_raw()) };
|
||||
|
@ -541,7 +554,7 @@ add_test!("test_history_path_detection", || {
|
|||
std::thread::sleep(std::time::Duration::from_millis(2));
|
||||
}
|
||||
history.clear();
|
||||
});
|
||||
}
|
||||
|
||||
fn install_sample_history(name: &wstr) {
|
||||
let path = path_get_data().expect("Failed to get data directory");
|
||||
|
@ -552,7 +565,10 @@ fn install_sample_history(name: &wstr) {
|
|||
.unwrap();
|
||||
}
|
||||
|
||||
add_test!("test_history_formats", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_history_formats() {
|
||||
test_init();
|
||||
// Test inferring and reading legacy and bash history formats.
|
||||
let name = L!("history_sample_fish_2_0");
|
||||
install_sample_history(name);
|
||||
|
@ -598,4 +614,4 @@ add_test!("test_history_formats", || {
|
|||
];
|
||||
assert_eq!(test_history_imported_from_corrupted.get_history(), expected);
|
||||
test_history_imported_from_corrupted.clear();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
use crate::wchar::prelude::*;
|
||||
|
||||
mod abbrs;
|
||||
#[cfg(test)]
|
||||
mod common;
|
||||
mod complete;
|
||||
mod debounce;
|
||||
#[cfg(test)]
|
||||
mod editable_line;
|
||||
#[cfg(test)]
|
||||
mod encoding;
|
||||
mod env;
|
||||
mod env_universal_common;
|
||||
|
@ -18,15 +15,11 @@ mod history;
|
|||
mod pager;
|
||||
mod parse_util;
|
||||
mod parser;
|
||||
#[cfg(test)]
|
||||
mod reader;
|
||||
#[cfg(test)]
|
||||
mod redirection;
|
||||
mod screen;
|
||||
mod string_escape;
|
||||
#[cfg(test)]
|
||||
mod threads;
|
||||
#[cfg(test)]
|
||||
mod tokenizer;
|
||||
mod topic_monitor;
|
||||
mod wgetopt;
|
||||
|
@ -87,4 +80,6 @@ pub mod prelude {
|
|||
EnvStack::principal().set_pwd_from_getcwd();
|
||||
});
|
||||
}
|
||||
|
||||
pub use serial_test::serial;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
use crate::common::get_ellipsis_char;
|
||||
use crate::complete::{CompleteFlags, Completion};
|
||||
use crate::ffi_tests::add_test;
|
||||
use crate::pager::{Pager, SelectionMotion};
|
||||
use crate::termsize::Termsize;
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::wchar_ext::WExt;
|
||||
use crate::wcstringutil::StringFuzzyMatch;
|
||||
|
||||
add_test!("test_pager_navigation", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_pager_navigation() {
|
||||
test_init();
|
||||
// Generate 19 strings of width 10. There's 2 spaces between completions, and our term size is
|
||||
// 80; these can therefore fit into 6 columns (6 * 12 - 2 = 70) or 5 columns (58) but not 7
|
||||
// columns (7 * 12 - 2 = 82).
|
||||
|
@ -92,9 +95,12 @@ add_test!("test_pager_navigation", || {
|
|||
validate!(pager, render, SelectionMotion::North, 2);
|
||||
validate!(pager, render, SelectionMotion::PageNorth, 0);
|
||||
validate!(pager, render, SelectionMotion::PageSouth, 3);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_pager_layout", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_pager_layout() {
|
||||
test_init();
|
||||
// These tests are woefully incomplete
|
||||
// They only test the truncation logic for a single completion
|
||||
|
||||
|
@ -189,4 +195,4 @@ add_test!("test_pager_layout", || {
|
|||
validate!(&mut pager, 18, L!("abcdefghijklmnopq…"));
|
||||
validate!(&mut pager, 17, L!("abcdefghijklmnop…"));
|
||||
validate!(&mut pager, 16, L!("abcdefghijklmno…"));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
use pcre2::utf32::Regex;
|
||||
|
||||
use crate::ffi_tests::add_test;
|
||||
use crate::parse_constants::{
|
||||
ERROR_BAD_VAR_CHAR1, ERROR_BRACKETED_VARIABLE1, ERROR_BRACKETED_VARIABLE_QUOTED1,
|
||||
ERROR_NOT_ARGV_AT, ERROR_NOT_ARGV_COUNT, ERROR_NOT_ARGV_STAR, ERROR_NOT_PID, ERROR_NOT_STATUS,
|
||||
ERROR_NO_VAR_NAME,
|
||||
};
|
||||
use crate::parse_util::parse_util_detect_errors;
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::wchar_ext::WExt;
|
||||
|
||||
add_test!("test_error_messages", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_error_messages() {
|
||||
test_init();
|
||||
// Given a format string, returns a list of non-empty strings separated by format specifiers. The
|
||||
// format specifiers themselves are omitted.
|
||||
fn separate_by_format_specifiers(format: &wstr) -> Vec<&wstr> {
|
||||
|
@ -67,4 +70,4 @@ add_test!("test_error_messages", || {
|
|||
validate!("echo foo\"$\"bar", ERROR_NO_VAR_NAME);
|
||||
validate!("echo \"foo\"$\"bar\"", ERROR_NO_VAR_NAME);
|
||||
validate!("echo foo $ bar", ERROR_NO_VAR_NAME);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -13,14 +13,17 @@ use crate::reader::{
|
|||
};
|
||||
use crate::signal::{signal_clear_cancel, signal_reset_handlers, signal_set_handlers};
|
||||
use crate::tests::prelude::*;
|
||||
use crate::tests::prelude::*;
|
||||
use crate::threads::{iothread_drain_all, iothread_perform};
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::wcstringutil::join_strings;
|
||||
use libc::SIGINT;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::ffi_tests::add_test;
|
||||
add_test!("test_parser", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_parser() {
|
||||
test_init();
|
||||
macro_rules! detect_errors {
|
||||
($src:literal) => {
|
||||
parse_util_detect_errors(L!($src), None, true /* accept incomplete */)
|
||||
|
@ -297,9 +300,12 @@ add_test!("test_parser", || {
|
|||
detect_errors!("true || \n") == Err(ParserTestErrorBits::INCOMPLETE),
|
||||
"unterminated conjunction not reported properly"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_new_parser_correctness", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_new_parser_correctness() {
|
||||
test_init();
|
||||
macro_rules! validate {
|
||||
($src:expr, $ok:expr) => {
|
||||
let ast = Ast::parse(L!($src), ParseTreeFlags::default(), None);
|
||||
|
@ -324,9 +330,12 @@ add_test!("test_new_parser_correctness", || {
|
|||
validate!("true || ||", false);
|
||||
validate!("|| true", false);
|
||||
validate!("true || \n\n false", true);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_new_parser_correctness", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_new_parser_correctness_by_fuzzing() {
|
||||
test_init();
|
||||
let fuzzes = [
|
||||
L!("if"),
|
||||
L!("else"),
|
||||
|
@ -379,13 +388,16 @@ add_test!("test_new_parser_correctness", || {
|
|||
Ast::parse(&src, ParseTreeFlags::default(), None);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Test the LL2 (two token lookahead) nature of the parser by exercising the special builtin and
|
||||
// command handling. In particular, 'command foo' should be a decorated statement 'foo' but 'command
|
||||
// -help' should be an undecorated statement 'command' with argument '--help', and NOT attempt to
|
||||
// run a command called '--help'.
|
||||
add_test!("test_new_parser_ll2", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_new_parser_ll2() {
|
||||
test_init();
|
||||
// Parse a statement, returning the command, args (joined by spaces), and the decoration. Returns
|
||||
// true if successful.
|
||||
fn test_1_parse_ll2(src: &wstr) -> Option<(WString, WString, StatementDecoration)> {
|
||||
|
@ -501,9 +513,12 @@ add_test!("test_new_parser_ll2", || {
|
|||
check_function_help!("function --help", ast::Type::decorated_statement);
|
||||
check_function_help!("function --foo; end", ast::Type::function_header);
|
||||
check_function_help!("function foo; end", ast::Type::function_header);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_new_parser_ad_hoc", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_new_parser_ad_hoc() {
|
||||
test_init();
|
||||
// Very ad-hoc tests for issues encountered.
|
||||
|
||||
// Ensure that 'case' terminates a job list.
|
||||
|
@ -559,9 +574,12 @@ add_test!("test_new_parser_ad_hoc", || {
|
|||
);
|
||||
assert!(errors.len() == 1);
|
||||
assert!(errors[0].code == ParseErrorCode::tokenizer_unterminated_quote);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_new_parser_errors", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_new_parser_errors() {
|
||||
test_init();
|
||||
macro_rules! validate {
|
||||
($src:expr, $expected_code:expr) => {
|
||||
let mut errors = vec![];
|
||||
|
@ -590,9 +608,12 @@ add_test!("test_new_parser_errors", || {
|
|||
validate!("true | and", ParseErrorCode::andor_in_pipeline);
|
||||
|
||||
validate!("a=", ParseErrorCode::bare_variable_assignment);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_eval_recursion_detection", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_eval_recursion_detection() {
|
||||
test_init();
|
||||
// Ensure that we don't crash on infinite self recursion and mutual recursion. These must use
|
||||
// the principal parser because we cannot yet execute jobs on other parsers.
|
||||
let parser = Parser::principal_parser().shared();
|
||||
|
@ -608,9 +629,12 @@ add_test!("test_eval_recursion_detection", || {
|
|||
)),
|
||||
&IoChain::new(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_eval_illegal_exit_code", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_eval_illegal_exit_code() {
|
||||
test_init();
|
||||
macro_rules! validate {
|
||||
($cmd:expr, $result:expr) => {
|
||||
let parser = Parser::principal_parser();
|
||||
|
@ -637,17 +661,23 @@ add_test!("test_eval_illegal_exit_code", || {
|
|||
validate!(L!("?"), STATUS_UNMATCHED_WILDCARD.unwrap());
|
||||
validate!(L!("abc?def"), STATUS_UNMATCHED_WILDCARD.unwrap());
|
||||
popd();
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_eval_empty_function_name", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_eval_empty_function_name() {
|
||||
test_init();
|
||||
let parser = Parser::principal_parser().shared();
|
||||
parser.eval(
|
||||
L!("function '' ; echo fail; exit 42 ; end ; ''"),
|
||||
&IoChain::new(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_expand_argument_list", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_expand_argument_list() {
|
||||
test_init();
|
||||
let parser = Parser::principal_parser().shared();
|
||||
let comps: Vec<WString> = Parser::expand_argument_list(
|
||||
L!("alpha 'beta gamma' delta"),
|
||||
|
@ -658,7 +688,7 @@ add_test!("test_expand_argument_list", || {
|
|||
.map(|c| c.completion)
|
||||
.collect();
|
||||
assert_eq!(comps, &[L!("alpha"), L!("beta gamma"), L!("delta"),]);
|
||||
});
|
||||
}
|
||||
|
||||
fn test_1_cancellation(src: &wstr) {
|
||||
let filler = IoBufferfill::create().unwrap();
|
||||
|
@ -688,7 +718,10 @@ fn test_1_cancellation(src: &wstr) {
|
|||
}
|
||||
}
|
||||
|
||||
add_test!("test_cancellation", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_cancellation() {
|
||||
test_init();
|
||||
reader_push(Parser::principal_parser(), L!(""), ReaderConfig::default());
|
||||
let _pop = ScopeGuard::new((), |()| reader_pop());
|
||||
|
||||
|
@ -717,4 +750,4 @@ add_test!("test_cancellation", || {
|
|||
// Ensure that we don't think we should cancel.
|
||||
reader_reset_interrupted();
|
||||
signal_clear_cancel();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
use crate::common::get_ellipsis_char;
|
||||
use crate::ffi_tests::add_test;
|
||||
use crate::screen::{LayoutCache, PromptCacheEntry, PromptLayout};
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::wcstringutil::join_strings;
|
||||
|
||||
add_test!("test_complete", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_complete() {
|
||||
test_init();
|
||||
let mut lc = LayoutCache::new();
|
||||
assert_eq!(lc.escape_code_length(L!("")), 0);
|
||||
assert_eq!(lc.escape_code_length(L!("abcd")), 0);
|
||||
|
@ -34,9 +37,12 @@ add_test!("test_complete", || {
|
|||
);
|
||||
assert_eq!(lc.escape_code_length(L!("\x1B]blahblahblah\x1B\\")), 16);
|
||||
assert_eq!(lc.escape_code_length(L!("\x1B]blahblahblah\x07")), 15);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_layout_cache", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_layout_cache() {
|
||||
test_init();
|
||||
let mut seqs = LayoutCache::new();
|
||||
|
||||
// Verify escape code cache.
|
||||
|
@ -105,9 +111,12 @@ add_test!("test_layout_cache", || {
|
|||
seqs.prompt_cache.front().unwrap().layout.max_line_width,
|
||||
100
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_prompt_truncation", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_prompt_truncation() {
|
||||
test_init();
|
||||
let mut cache = LayoutCache::new();
|
||||
let mut trunc = WString::new();
|
||||
|
||||
|
@ -235,4 +244,4 @@ add_test!("test_prompt_truncation", || {
|
|||
},
|
||||
);
|
||||
assert_eq!(trunc, ellipsis());
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
use crate::ffi_tests::add_test;
|
||||
use crate::tests::prelude::*;
|
||||
use crate::topic_monitor::{topic_monitor_t, topic_t, GenerationsList};
|
||||
use std::sync::{
|
||||
atomic::{AtomicU32, AtomicU64, Ordering},
|
||||
Arc,
|
||||
};
|
||||
|
||||
add_test!("test_topic_monitor", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_topic_monitor() {
|
||||
test_init();
|
||||
let monitor = topic_monitor_t::default();
|
||||
let gens = GenerationsList::new();
|
||||
let t = topic_t::sigchld;
|
||||
|
@ -26,9 +29,12 @@ add_test!("test_topic_monitor", || {
|
|||
let changed = monitor.check(&gens, true /* wait */);
|
||||
assert!(changed);
|
||||
assert_eq!(gens.sigchld.get(), 2);
|
||||
});
|
||||
}
|
||||
|
||||
add_test!("test_topic_monitor_torture", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_topic_monitor_torture() {
|
||||
test_init();
|
||||
let monitor = Arc::new(topic_monitor_t::default());
|
||||
const THREAD_COUNT: usize = 64;
|
||||
let t1 = topic_t::sigchld;
|
||||
|
@ -68,4 +74,4 @@ add_test!("test_topic_monitor_torture", || {
|
|||
for t in threads {
|
||||
t.join().unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -23,7 +23,10 @@ impl FloggableDebug for ThreadId {}
|
|||
/// The thread id of the main thread, as set by [`init()`] at startup.
|
||||
static mut MAIN_THREAD_ID: Option<ThreadId> = None;
|
||||
/// Used to bypass thread assertions when testing.
|
||||
#[cfg(not(test))]
|
||||
static THREAD_ASSERTS_CFG_FOR_TESTING: AtomicBool = AtomicBool::new(false);
|
||||
#[cfg(test)]
|
||||
static THREAD_ASSERTS_CFG_FOR_TESTING: AtomicBool = AtomicBool::new(true);
|
||||
/// This allows us to notice when we've forked.
|
||||
static IS_FORKED_PROC: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@ use std::sync::Mutex;
|
|||
|
||||
use crate::common::{charptr2wcstring, wcs2zstring};
|
||||
use crate::fish::PACKAGE_NAME;
|
||||
#[cfg(test)]
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::wchar_ffi::wchar_t;
|
||||
use errno::{errno, set_errno};
|
||||
|
@ -150,10 +152,12 @@ macro_rules! wgettext_maybe_fmt {
|
|||
}
|
||||
pub(crate) use wgettext_maybe_fmt;
|
||||
|
||||
use crate::ffi_tests::add_test;
|
||||
add_test!("test_untranslated", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_untranslated() {
|
||||
test_init();
|
||||
let s: &'static wstr = wgettext!("abc");
|
||||
assert_eq!(s, "abc");
|
||||
let s2: &'static wstr = wgettext!("static");
|
||||
assert_eq!(s2, "static");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::ffi_tests::add_test;
|
||||
use crate::tests::prelude::*;
|
||||
use libc::{c_void, O_CREAT, O_RDWR, O_TRUNC, SEEK_SET};
|
||||
use rand::random;
|
||||
use std::{ffi::CString, ptr};
|
||||
|
@ -57,7 +57,10 @@ fn test_wdirname_wbasename() {
|
|||
assert_eq!(wbasename(&longpath), "overlong"L);
|
||||
}
|
||||
|
||||
add_test!("test_wwrite_to_fd", || {
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_wwrite_to_fd() {
|
||||
test_init();
|
||||
let (fd, filename) =
|
||||
fish_mkstemp_cloexec(CString::new("/tmp/fish_test_wwrite.XXXXXX").unwrap());
|
||||
{
|
||||
|
@ -98,4 +101,4 @@ add_test!("test_wwrite_to_fd", || {
|
|||
assert_eq!(&contents, &narrow);
|
||||
}
|
||||
unsafe { libc::remove(filename.as_ptr()) };
|
||||
});
|
||||
}
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
#include "fds.h"
|
||||
#include "ffi_baggage.h"
|
||||
#include "ffi_init.rs.h"
|
||||
#include "ffi_tests.rs.h"
|
||||
#include "function.h"
|
||||
#include "future_feature_flags.h"
|
||||
#include "global_safety.h"
|
||||
|
@ -90,7 +89,6 @@
|
|||
#include "redirection.h"
|
||||
#include "screen.h"
|
||||
#include "signals.h"
|
||||
#include "smoke.rs.h"
|
||||
#include "termsize.h"
|
||||
#include "threads.rs.h"
|
||||
#include "tokenizer.h"
|
||||
|
@ -801,13 +799,6 @@ void test_dirname_basename() {
|
|||
do_test(wbasename(longpath) == L"overlong");
|
||||
}
|
||||
|
||||
void test_rust_smoke() {
|
||||
size_t x = rust::add(37, 5);
|
||||
do_test(x == 42);
|
||||
}
|
||||
|
||||
void test_rust_ffi() { rust::run_ffi_tests(); }
|
||||
|
||||
// typedef void (test_entry_point_t)();
|
||||
using test_entry_point_t = void (*)();
|
||||
struct test_t {
|
||||
|
@ -841,8 +832,6 @@ static const test_t s_tests[]{
|
|||
{TEST_GROUP("maybe"), test_maybe},
|
||||
{TEST_GROUP("normalize"), test_normalize_path},
|
||||
{TEST_GROUP("dirname"), test_dirname_basename},
|
||||
{TEST_GROUP("rust_smoke"), test_rust_smoke},
|
||||
{TEST_GROUP("rust_ffi"), test_rust_ffi},
|
||||
};
|
||||
|
||||
void list_tests() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user