assertions: use assert_matches!

Closes #12348
This commit is contained in:
xtqqczze
2026-01-18 13:17:16 +00:00
committed by Johannes Altmanninger
parent 524c73d8b7
commit 17129f64db
18 changed files with 83 additions and 57 deletions

9
Cargo.lock generated
View File

@@ -67,6 +67,12 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "assert_matches"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9"
[[package]]
name = "autocfg"
version = "1.5.0"
@@ -256,6 +262,7 @@ checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff"
name = "fish"
version = "4.3.3"
dependencies = [
"assert_matches",
"bitflags",
"cc",
"cfg-if",
@@ -376,6 +383,7 @@ version = "0.0.0"
name = "fish-printf"
version = "0.2.1"
dependencies = [
"assert_matches",
"libc",
"unicode-segmentation",
"unicode-width",
@@ -413,6 +421,7 @@ dependencies = [
name = "fish-wgetopt"
version = "0.0.0"
dependencies = [
"assert_matches",
"fish-wcstringutil",
"fish-widestring",
]

View File

@@ -11,6 +11,7 @@ repository = "https://github.com/fish-shell/fish-shell"
license = "GPL-2.0-only AND LGPL-2.0-or-later AND MIT AND PSF-2.0"
[workspace.dependencies]
assert_matches = "1.5.0"
bitflags = "2.5.0"
cc = "1.0.94"
cfg-if = "1.0.3"
@@ -94,6 +95,7 @@ homepage = "https://fishshell.com"
readme = "README.rst"
[dependencies]
assert_matches.workspace = true
bitflags.workspace = true
cfg-if.workspace = true
errno.workspace = true

View File

@@ -8,10 +8,11 @@ description = "printf implementation, based on musl"
license = "MIT"
[dependencies]
assert_matches.workspace = true
libc.workspace = true
widestring = { workspace = true, optional = true }
unicode-segmentation.workspace = true
unicode-width.workspace = true
widestring = { workspace = true, optional = true }
[lints]
workspace = true

View File

@@ -199,27 +199,28 @@ fn to_arg(self) -> Arg<'a> {
#[cfg(test)]
mod tests {
use super::*;
use assert_matches::assert_matches;
#[cfg(feature = "widestring")]
use widestring::utf32str;
#[test]
fn test_to_arg() {
assert!(matches!("test".to_arg(), Arg::Str("test")));
assert!(matches!(String::from("test").to_arg(), Arg::Str(_)));
assert_matches!("test".to_arg(), Arg::Str("test"));
assert_matches!(String::from("test").to_arg(), Arg::Str(_));
#[cfg(feature = "widestring")]
assert!(matches!(utf32str!("test").to_arg(), Arg::WStr(_)));
assert_matches!(utf32str!("test").to_arg(), Arg::WStr(_));
#[cfg(feature = "widestring")]
assert!(matches!(WString::from("test").to_arg(), Arg::WStr(_)));
assert!(matches!(42f32.to_arg(), Arg::Float(_)));
assert!(matches!(42f64.to_arg(), Arg::Float(_)));
assert!(matches!('x'.to_arg(), Arg::UInt(120)));
assert_matches!(WString::from("test").to_arg(), Arg::WStr(_));
assert_matches!(42f32.to_arg(), Arg::Float(_));
assert_matches!(42f64.to_arg(), Arg::Float(_));
assert_matches!('x'.to_arg(), Arg::UInt(120));
let mut usize_val: usize = 0;
assert!(matches!((&mut usize_val).to_arg(), Arg::USizeRef(_)));
assert!(matches!(42i8.to_arg(), Arg::SInt(42)));
assert!(matches!(42i16.to_arg(), Arg::SInt(42)));
assert!(matches!(42i32.to_arg(), Arg::SInt(42)));
assert!(matches!(42i64.to_arg(), Arg::SInt(42)));
assert!(matches!(42isize.to_arg(), Arg::SInt(42)));
assert_matches!((&mut usize_val).to_arg(), Arg::USizeRef(_));
assert_matches!(42i8.to_arg(), Arg::SInt(42));
assert_matches!(42i16.to_arg(), Arg::SInt(42));
assert_matches!(42i32.to_arg(), Arg::SInt(42));
assert_matches!(42i64.to_arg(), Arg::SInt(42));
assert_matches!(42isize.to_arg(), Arg::SInt(42));
assert_eq!((-42i8).to_arg(), Arg::SInt(-42));
assert_eq!((-42i16).to_arg(), Arg::SInt(-42));
@@ -227,14 +228,14 @@ fn test_to_arg() {
assert_eq!((-42i64).to_arg(), Arg::SInt(-42));
assert_eq!((-42isize).to_arg(), Arg::SInt(-42));
assert!(matches!(42u8.to_arg(), Arg::UInt(42)));
assert!(matches!(42u16.to_arg(), Arg::UInt(42)));
assert!(matches!(42u32.to_arg(), Arg::UInt(42)));
assert!(matches!(42u64.to_arg(), Arg::UInt(42)));
assert!(matches!(42usize.to_arg(), Arg::UInt(42)));
assert_matches!(42u8.to_arg(), Arg::UInt(42));
assert_matches!(42u16.to_arg(), Arg::UInt(42));
assert_matches!(42u32.to_arg(), Arg::UInt(42));
assert_matches!(42u64.to_arg(), Arg::UInt(42));
assert_matches!(42usize.to_arg(), Arg::UInt(42));
let ptr = std::ptr::from_ref(&42f32);
assert!(matches!(ptr.to_arg(), Arg::UInt(_)));
assert_matches!(ptr.to_arg(), Arg::UInt(_));
}
#[test]

View File

@@ -4,6 +4,7 @@
use super::locale::Locale;
use super::printf_impl::{ConversionSpec, Error, ModifierFlags, pad};
use assert_matches::debug_assert_matches;
use decimal::{DIGIT_WIDTH, Decimal, DigitLimit};
use std::cmp::min;
use std::fmt::Write;
@@ -129,10 +130,10 @@ pub(crate) fn format_float(
) -> Result<usize, Error> {
// Only float conversions are expected.
type CS = ConversionSpec;
debug_assert!(matches!(
debug_assert_matches!(
conv_spec,
CS::e | CS::E | CS::f | CS::F | CS::g | CS::G | CS::a | CS::A
));
);
let prefix = match (y.is_sign_negative(), flags.mark_pos, flags.pad_pos) {
(true, _, _) => "-",
(false, true, _) => "+",

View File

@@ -2,6 +2,7 @@
use super::arg::Arg;
use super::fmt_fp::format_float;
use super::locale::Locale;
use assert_matches::assert_matches;
use std::fmt::{self, Write};
use std::mem;
use std::result::Result;
@@ -301,7 +302,7 @@ pub(super) fn pad(
min_width: usize,
current_width: usize,
) -> fmt::Result {
assert!(c == '0' || c == ' ');
assert_matches!(c, '0' | ' ');
if current_width >= min_width {
return Ok(());
}

View File

@@ -7,6 +7,7 @@ repository.workspace = true
license.workspace = true
[dependencies]
assert_matches.workspace = true
fish-wcstringutil.workspace = true
fish-widestring.workspace = true

View File

@@ -24,6 +24,7 @@
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
use assert_matches::assert_matches;
use fish_widestring::prelude::*;
/// Special char used with [`Ordering::ReturnInOrder`].
@@ -397,7 +398,7 @@ fn update_long_opt(
option_index: usize,
) -> char {
self.wopt_index += 1;
assert!(matches!(self.remaining_text.char_at(name_end), '\0' | '='));
assert_matches!(self.remaining_text.char_at(name_end), '\0' | '=');
if self.remaining_text.char_at(name_end) == '=' {
if opt_found.arg_type == ArgType::NoArgument {

View File

@@ -263,7 +263,7 @@ trait NodeMut: Node + AcceptorMut {}
impl<T> NodeMut for T where T: Node + AcceptorMut {}
/// The different kinds of nodes. Note that Token and Keyword have different subtypes.
#[derive(Copy, Clone)]
#[derive(Debug, Copy, Clone)]
pub enum Kind<'a> {
Redirection(&'a Redirection),
Token(&'a dyn Token),

View File

@@ -51,11 +51,13 @@ enum AssetDir {
Completions,
}
#[derive(Debug)]
pub enum AutoloadPath {
Embedded(String),
Path(WString),
}
#[derive(Debug)]
pub enum AutoloadResult {
Path(AutoloadPath),
Loaded,
@@ -455,6 +457,7 @@ mod tests {
use super::{Autoload, AutoloadResult};
use crate::prelude::*;
use crate::tests::prelude::*;
use assert_matches::assert_matches;
#[test]
#[serial]
@@ -505,39 +508,39 @@ fn touch_file(path: &wstr) {
autoload.invalidate_cache();
assert!(!autoload.autoload_in_progress(L!("file1")));
assert!(matches!(
assert_matches!(
autoload.resolve_command_impl(L!("file1"), paths),
AutoloadResult::Path(_)
));
assert!(matches!(
);
assert_matches!(
autoload.resolve_command_impl(L!("file1"), paths),
AutoloadResult::Pending
));
);
assert!(autoload.autoload_in_progress(L!("file1")));
assert_eq!(autoload.get_autoloaded_commands(), vec![L!("file1")]);
autoload.mark_autoload_finished(L!("file1"));
assert!(!autoload.autoload_in_progress(L!("file1")));
assert_eq!(autoload.get_autoloaded_commands(), vec![L!("file1")]);
assert!(matches!(
assert_matches!(
autoload.resolve_command_impl(L!("file1"), paths),
AutoloadResult::Loaded
));
);
assert!(
autoload
.resolve_command_impl(L!("nothing"), paths)
.is_none()
);
assert!(autoload.resolve_command_impl(L!("file2"), paths).is_some());
assert!(matches!(
assert_matches!(
autoload.resolve_command_impl(L!("file2"), paths),
AutoloadResult::Pending
));
);
autoload.mark_autoload_finished(L!("file2"));
assert!(matches!(
assert_matches!(
autoload.resolve_command_impl(L!("file2"), paths),
AutoloadResult::Loaded
));
);
assert_eq!(
autoload.get_autoloaded_commands(),
vec![L!("file1"), L!("file2")]
@@ -546,26 +549,26 @@ fn touch_file(path: &wstr) {
autoload.clear();
assert!(autoload.resolve_command_impl(L!("file1"), paths).is_some());
autoload.mark_autoload_finished(L!("file1"));
assert!(matches!(
assert_matches!(
autoload.resolve_command_impl(L!("file1"), paths),
AutoloadResult::Loaded
));
);
assert!(
autoload
.resolve_command_impl(L!("nothing"), paths)
.is_none()
);
assert!(autoload.resolve_command_impl(L!("file2"), paths).is_some());
assert!(matches!(
assert_matches!(
autoload.resolve_command_impl(L!("file2"), paths),
AutoloadResult::Pending
));
);
autoload.mark_autoload_finished(L!("file2"));
assert!(matches!(
assert_matches!(
autoload.resolve_command_impl(L!("file1"), paths),
AutoloadResult::Loaded
));
);
touch_file(&sprintf!("%s/file1.fish", p1));
autoload.invalidate_cache();
assert!(autoload.resolve_command_impl(L!("file1"), paths).is_some());

View File

@@ -30,6 +30,7 @@
use crate::tokenizer::{TOK_SHOW_BLANK_LINES, TOK_SHOW_COMMENTS, TokenType, Tokenizer};
use crate::topic_monitor::topic_monitor_init;
use crate::wutil::fish_iswalnum;
use assert_matches::assert_matches;
use fish_wcstringutil::count_preceding_backslashes;
use fish_wgetopt::{ArgType, WGetopter, WOption, wopt};
use std::fmt::Write as _;
@@ -394,7 +395,7 @@ fn gap_text_flags_before_node(&self, node: &dyn Node) -> GapFlags {
return result;
}
let p = self.traversal.parent(p);
assert!(matches!(p.kind(), Kind::Statement(_)));
assert_matches!(p.kind(), Kind::Statement(_));
let p = self.traversal.parent(p);
if let Kind::JobPipeline(job) = p.kind() {
if !job.variables.is_empty() {

View File

@@ -45,6 +45,7 @@
localization::{LocalizableString, localizable_string},
reader::{get_quote, is_backslashed},
};
use assert_matches::assert_matches;
use bitflags::bitflags;
use fish_util::wcsfilecmp;
use fish_wcstringutil::{
@@ -720,7 +721,7 @@ fn perform_for_commandline_impl(&mut self, cmdline: WString) {
}
for tok in &tokens {
// If there was an error, it was in the last token.
assert!(matches!(tok.type_, TokenType::String | TokenType::Redirect));
assert_matches!(tok.type_, TokenType::String | TokenType::Redirect);
}
// If we are completing a variable name or a tilde expansion user name, we do that and
// return. No need for any other completions.

3
src/env/var.rs vendored
View File

@@ -323,6 +323,7 @@ mod tests {
use crate::env::environment::{EnvStack, Environment};
use crate::prelude::*;
use crate::tests::prelude::*;
use assert_matches::assert_matches;
use std::{
mem::MaybeUninit,
time::{SystemTime, UNIX_EPOCH},
@@ -361,7 +362,7 @@ fn test_timezone_env_vars() {
let first_tstamp = return_timezone_hour(tstamp, L!("UTC-1"));
let second_tstamp = return_timezone_hour(tstamp, L!("UTC-2"));
let delta = second_tstamp - first_tstamp;
assert!(delta == 1 || delta == -23);
assert_matches!(delta, 1 | -23);
}
// Verify that setting special env vars have the expected effect on the current shell process.

View File

@@ -473,6 +473,7 @@ mod tests {
use std::thread;
use std::time::Duration;
use assert_matches::assert_matches;
use errno::errno;
use crate::fd_monitor::{FdEventSignaller, FdMonitor};
@@ -694,8 +695,9 @@ fn test_dup2_during_select_ebadf() {
Some(read_fd)
};
let result = do_something_bad_during_select(dup2_it);
assert!(
matches!(result, Err(libc::EBADF) | Ok(0 | 1)),
assert_matches!(
result,
Err(libc::EBADF) | Ok(0 | 1),
"select/poll should have failed with EBADF or timed out or the fd should be ready"
);
// Ensure these stay alive until after thread is joined.

View File

@@ -35,6 +35,7 @@
use crate::wait_handle::WaitHandleStore;
use crate::wutil::perror;
use crate::{flog, flogf, function};
use assert_matches::assert_matches;
use fish_util::get_time;
use fish_widestring::WExt;
use libc::c_int;
@@ -568,7 +569,7 @@ pub fn eval_parsed_source(
block_type: BlockType,
test_only_suppress_stderr: bool,
) -> EvalRes {
assert!(matches!(block_type, BlockType::top | BlockType::subst));
assert_matches!(block_type, BlockType::top | BlockType::subst);
let job_list = ps.top_job_list();
if !job_list.is_empty() {
// Execute the top job list.
@@ -647,8 +648,9 @@ pub fn eval_node<T: Node>(
test_only_suppress_stderr: bool,
) -> EvalRes {
// Only certain blocks are allowed.
assert!(
matches!(block_type, BlockType::top | BlockType::subst),
assert_matches!(
block_type,
BlockType::top | BlockType::subst,
"Invalid block type"
);

View File

@@ -142,6 +142,7 @@
use crate::wildcard::wildcard_has;
use crate::wutil::{fstat, perror, write_to_fd, wstat};
use crate::{abbrs, event, function};
use assert_matches::assert_matches;
use fish_fallback::fish_wcwidth;
use fish_wcstringutil::{
CaseSensitivity, StringFuzzyMatch, count_preceding_backslashes, join_strings,
@@ -6782,10 +6783,7 @@ fn reader_can_replace(s: &wstr, flags: CompleteFlags) -> bool {
impl<'a> Reader<'a> {
/// Compute completions and update the pager and/or commandline as needed.
fn compute_and_apply_completions(&mut self, c: ReadlineCmd) {
assert!(matches!(
c,
ReadlineCmd::Complete | ReadlineCmd::CompleteAndSearch
));
assert_matches!(c, ReadlineCmd::Complete | ReadlineCmd::CompleteAndSearch);
assert!(
!get_tty_protocols_active(),
"should not be called with TTY protocols active"

View File

@@ -39,14 +39,14 @@ pub fn set_color_support(val: ColorSupport) {
COLOR_SUPPORT.store(val.bits(), Ordering::Relaxed);
}
#[derive(Clone, Copy)]
#[derive(Debug, Clone, Copy)]
pub(crate) enum Paintable {
Foreground,
Background,
Underline,
}
#[derive(Clone)]
#[derive(Debug, Clone)]
pub(crate) enum TerminalCommand<'a> {
// Text attributes
ExitAttributeMode,
@@ -311,7 +311,7 @@ fn rgb_color(out: &mut impl Output, paintable: Paintable, rgb: Color24) -> bool
true
}
#[derive(Clone)]
#[derive(Debug, Clone)]
pub(crate) enum CardinalDirection {
Up,
Left,

View File

@@ -331,6 +331,7 @@ fn next(&mut self) -> Option<Self::Item> {
mod tests {
use super::{DirEntryType, DirIter};
use crate::prelude::*;
use assert_matches::assert_matches;
use fish_widestring::L;
use nix::sys::stat::Mode;
use std::fs::File;
@@ -383,7 +384,7 @@ fn test_dir_iter() {
panic!("Expected error");
};
let err = err.raw_os_error().expect("Should have an errno value");
assert!(err == ENOENT || err == EACCES);
assert_matches!(err, ENOENT | EACCES);
let temp_dir = fish_tempfile::new_dir().unwrap();
let basepath = WString::from(temp_dir.path().to_str().unwrap());