diff --git a/Cargo.lock b/Cargo.lock index 7ee0e3c28..0c66b92bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3578,6 +3578,7 @@ version = "0.1.0" dependencies = [ "clap", "libc", + "thiserror 2.0.12", "uucore", ] diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 6190e8ba6..6328b3f6e 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -1379,6 +1379,7 @@ version = "0.1.0" dependencies = [ "clap", "libc", + "thiserror", "uucore", ] diff --git a/src/uu/test/Cargo.toml b/src/uu/test/Cargo.toml index c59f9fcb4..53cf597af 100644 --- a/src/uu/test/Cargo.toml +++ b/src/uu/test/Cargo.toml @@ -21,6 +21,7 @@ path = "src/test.rs" clap = { workspace = true } libc = { workspace = true } uucore = { workspace = true, features = ["process"] } +thiserror = { workspace = true } [[bin]] name = "test" diff --git a/src/uu/test/locales/en-US.ftl b/src/uu/test/locales/en-US.ftl index 0f7a67394..86871637f 100644 --- a/src/uu/test/locales/en-US.ftl +++ b/src/uu/test/locales/en-US.ftl @@ -63,9 +63,17 @@ test-after-help = Exit with the status determined by EXPRESSION. NOTE: Binary -a and -o are inherently ambiguous. Use test EXPR1 && test EXPR2 or test EXPR1 || test EXPR2 instead. - - NOTE: [ honors the --help and --version options, but test does not. + NOTE: {"["} honors the --help and --version options, but test does not. test treats each of those as it treats any other nonempty STRING. - - NOTE: your shell may have its own version of test and/or [, which usually supersedes the version described here. + NOTE: your shell may have its own version of test and/or {"["}, which usually supersedes the version described here. Please refer to your shell's documentation for details about the options it supports. + +# Error messages +test-error-missing-closing-bracket = missing '{"]"}' +test-error-expected = expected { $value } +test-error-expected-value = expected value +test-error-missing-argument = missing argument after { $argument } +test-error-extra-argument = extra argument { $argument } +test-error-unknown-operator = unknown operator { $operator } +test-error-invalid-integer = invalid integer { $value } +test-error-unary-operator-expected = { $operator }: unary operator expected diff --git a/src/uu/test/locales/fr-FR.ftl b/src/uu/test/locales/fr-FR.ftl new file mode 100644 index 000000000..78cae9b44 --- /dev/null +++ b/src/uu/test/locales/fr-FR.ftl @@ -0,0 +1,79 @@ +test-about = Vérifier les types de fichiers et comparer les valeurs. +test-usage = test EXPRESSION + test + {"[ EXPRESSION ]"} + {"[ ]"} + {"[ OPTION ]"} +test-after-help = Quitter avec le statut déterminé par EXPRESSION. + + Une EXPRESSION omise vaut false par défaut. + Sinon, EXPRESSION est true ou false et définit le statut de sortie. + + Il peut s'agir de : + + - ( EXPRESSION ) EXPRESSION est vraie + - ! EXPRESSION EXPRESSION est fausse + - EXPRESSION1 -a EXPRESSION2 EXPRESSION1 et EXPRESSION2 sont toutes deux vraies + - EXPRESSION1 -o EXPRESSION2 EXPRESSION1 ou EXPRESSION2 est vraie + + Opérations sur les chaînes : + - -n STRING la longueur de STRING est non nulle + - STRING équivalent à -n STRING + - -z STRING la longueur de STRING est nulle + - STRING1 = STRING2 les chaînes sont égales + - STRING1 != STRING2 les chaînes ne sont pas égales + + Comparaisons d'entiers : + - INTEGER1 -eq INTEGER2 INTEGER1 est égal à INTEGER2 + - INTEGER1 -ge INTEGER2 INTEGER1 est supérieur ou égal à INTEGER2 + - INTEGER1 -gt INTEGER2 INTEGER1 est supérieur à INTEGER2 + - INTEGER1 -le INTEGER2 INTEGER1 est inférieur ou égal à INTEGER2 + - INTEGER1 -lt INTEGER2 INTEGER1 est inférieur à INTEGER2 + - INTEGER1 -ne INTEGER2 INTEGER1 n'est pas égal à INTEGER2 + + Opérations sur les fichiers : + - FILE1 -ef FILE2 FILE1 et FILE2 ont les mêmes numéros de périphérique et d'inode + - FILE1 -nt FILE2 FILE1 est plus récent (date de modification) que FILE2 + - FILE1 -ot FILE2 FILE1 est plus ancien que FILE2 + + - -b FILE FILE existe et est un fichier spécial de type bloc + - -c FILE FILE existe et est un fichier spécial de type caractère + - -d FILE FILE existe et est un répertoire + - -e FILE FILE existe + - -f FILE FILE existe et est un fichier régulier + - -g FILE FILE existe et a le bit set-group-ID + - -G FILE FILE existe et appartient à l'ID de groupe effectif + - -h FILE FILE existe et est un lien symbolique (identique à -L) + - -k FILE FILE existe et a son bit sticky défini + - -L FILE FILE existe et est un lien symbolique (identique à -h) + - -N FILE FILE existe et a été modifié depuis sa dernière lecture + - -O FILE FILE existe et appartient à l'ID utilisateur effectif + - -p FILE FILE existe et est un tube nommé + - -r FILE FILE existe et la permission de lecture est accordée + - -s FILE FILE existe et a une taille supérieure à zéro + - -S FILE FILE existe et est un socket + - -t FD le descripteur de fichier FD est ouvert sur un terminal + - -u FILE FILE existe et son bit set-user-ID est défini + - -w FILE FILE existe et la permission d'écriture est accordée + - -x FILE FILE existe et la permission d'exécution (ou de recherche) est accordée + + À l'exception de -h et -L, tous les tests liés aux FILE déréférencent (suivent) les liens symboliques. + Attention : les parenthèses doivent être échappées (par exemple, par des barres obliques inverses) pour les shells. + INTEGER peut aussi être -l STRING, qui évalue la longueur de STRING. + + NOTE : Les -a et -o binaires sont intrinsèquement ambigus. + Utilisez test EXPR1 && test EXPR2 ou test EXPR1 || test EXPR2 à la place. + NOTE : {"["} honore les options --help et --version, mais test ne le fait pas. + test traite chacune de celles-ci comme il traite toute autre STRING non vide. + NOTE : votre shell peut avoir sa propre version de test et/ou {"["}, qui remplace généralement la version décrite ici. + Veuillez vous référer à la documentation de votre shell pour les détails sur les options qu'il prend en charge. + +# Messages d'erreur +test-error-missing-closing-bracket = '{"]"}' manquant +test-error-expected = { $value } attendu +test-error-expected-value = valeur attendue +test-error-missing-argument = argument manquant après { $argument } +test-error-extra-argument = argument supplémentaire { $argument } +test-error-unknown-operator = opérateur inconnu { $operator } +test-error-invalid-integer = entier invalide { $value } +test-error-unary-operator-expected = { $operator } : opérateur unaire attendu diff --git a/src/uu/test/src/error.rs b/src/uu/test/src/error.rs index e392216e1..fd66641a9 100644 --- a/src/uu/test/src/error.rs +++ b/src/uu/test/src/error.rs @@ -2,42 +2,36 @@ // // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. + +use std::collections::HashMap; +use thiserror::Error; +use uucore::locale::{get_message, get_message_with_args}; + /// Represents an error encountered while parsing a test expression -#[derive(Debug)] +#[derive(Error, Debug)] pub enum ParseError { + #[error("{}", get_message("test-error-expected-value"))] ExpectedValue, + #[error("{}", get_message_with_args("test-error-expected", HashMap::from([("value".to_string(), .0.to_string())])))] Expected(String), + #[error("{}", get_message_with_args("test-error-extra-argument", HashMap::from([("argument".to_string(), .0.to_string())])))] ExtraArgument(String), + #[error("{}", get_message_with_args("test-error-missing-argument", HashMap::from([("argument".to_string(), .0.to_string())])))] MissingArgument(String), + #[error("{}", get_message_with_args("test-error-unknown-operator", HashMap::from([("operator".to_string(), .0.to_string())])))] UnknownOperator(String), + #[error("{}", get_message_with_args("test-error-invalid-integer", HashMap::from([("value".to_string(), .0.to_string())])))] InvalidInteger(String), + #[error("{}", get_message_with_args("test-error-unary-operator-expected", HashMap::from([("operator".to_string(), .0.to_string())])))] UnaryOperatorExpected(String), } /// A Result type for parsing test expressions pub type ParseResult = Result; -/// Implement Display trait for ParseError to make it easier to print useful errors. -impl std::fmt::Display for ParseError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Expected(s) => write!(f, "expected {s}"), - Self::ExpectedValue => write!(f, "expected value"), - Self::MissingArgument(s) => write!(f, "missing argument after {s}"), - Self::ExtraArgument(s) => write!(f, "extra argument {s}"), - Self::UnknownOperator(s) => write!(f, "unknown operator {s}"), - Self::InvalidInteger(s) => write!(f, "invalid integer {s}"), - Self::UnaryOperatorExpected(op) => write!(f, "{op}: unary operator expected"), - } - } -} - /// Implement UError trait for ParseError to make it easier to return useful error codes from main(). impl uucore::error::UError for ParseError { fn code(&self) -> i32 { 2 } } - -/// Implement standard Error trait for UError -impl std::error::Error for ParseError {} diff --git a/src/uu/test/src/test.rs b/src/uu/test/src/test.rs index 674e70dd3..0f4263b7b 100644 --- a/src/uu/test/src/test.rs +++ b/src/uu/test/src/test.rs @@ -55,7 +55,10 @@ pub fn uumain(mut args: impl uucore::Args) -> UResult<()> { // If invoked via name '[', matching ']' must be in the last arg let last = args.pop(); if last.as_deref() != Some(OsStr::new("]")) { - return Err(USimpleError::new(2, "missing ']'")); + return Err(USimpleError::new( + 2, + get_message("test-error-missing-closing-bracket"), + )); } }