@@ -65,26 +65,28 @@ pub fn eval_predicate(
6565 Pos :: new ( predicate. space0 . source_info . start . line , 0 ) ,
6666 ) ;
6767
68+ // `!=` already negates equality, so combine it with the `not` qualifier (XOR) for the prefix.
69+ let negated = predicate. not
70+ ^ matches ! (
71+ predicate. predicate_func. value,
72+ PredicateFuncValue :: NotEqual { .. }
73+ ) ;
74+ let not = if negated { "not " } else { "" } ;
75+
6876 if result. type_mismatch {
69- let not = if predicate. not { "not " } else { "" } ;
70- let expected = format ! ( "{}{}" , not, result. expected) ;
77+ let expected = format ! ( "{not}{}" , result. expected) ;
7178 let kind = RunnerErrorKind :: AssertFailure {
7279 actual : result. actual ,
7380 expected,
7481 type_mismatch : true ,
7582 } ;
7683 Err ( RunnerError :: new ( source_info, kind, true ) )
77- } else if predicate. not && result. success {
78- let kind = RunnerErrorKind :: AssertFailure {
79- actual : result. actual ,
80- expected : format ! ( "not {}" , result. expected) ,
81- type_mismatch : false ,
82- } ;
83- Err ( RunnerError :: new ( source_info, kind, true ) )
84- } else if !predicate. not && !result. success {
84+ } else if predicate. not == result. success {
85+ // Fail when the `not` qualifier and the predicate outcome agree.
86+ let expected = format ! ( "{not}{}" , result. expected) ;
8587 let kind = RunnerErrorKind :: AssertFailure {
8688 actual : result. actual ,
87- expected : result . expected ,
89+ expected,
8890 type_mismatch : false ,
8991 } ;
9092 Err ( RunnerError :: new ( source_info, kind, true ) )
@@ -900,6 +902,92 @@ mod tests {
900902 ) ;
901903 }
902904
905+ #[ test]
906+ fn test_predicate_not_equal_error_message ( ) {
907+ // A failing `!=` assert reports the value that should not have matched (#2841).
908+ let variables = VariableSet :: new ( ) ;
909+ let current_dir = Path :: new ( "/home" ) ;
910+ let file_root = Path :: new ( "file_root" ) ;
911+ let context_dir = ContextDir :: new ( current_dir, file_root) ;
912+
913+ // predicate: `!= 1`
914+ let predicate = Predicate {
915+ not : false ,
916+ space0 : whitespace ( ) ,
917+ predicate_func : PredicateFunc {
918+ value : PredicateFuncValue :: NotEqual {
919+ space0 : whitespace ( ) ,
920+ value : PredicateValue :: Number ( hurl_core:: ast:: Number :: Integer ( I64 :: new (
921+ 1 ,
922+ "1" . to_source ( ) ,
923+ ) ) ) ,
924+ } ,
925+ source_info : SourceInfo :: new ( Pos :: new ( 1 , 11 ) , Pos :: new ( 1 , 13 ) ) ,
926+ } ,
927+ } ;
928+
929+ // value: 1 => fails, expected is the negated value
930+ let error = eval_predicate (
931+ & predicate,
932+ & variables,
933+ & Some ( Value :: Number ( Number :: Integer ( 1 ) ) ) ,
934+ & context_dir,
935+ )
936+ . unwrap_err ( ) ;
937+ assert_eq ! (
938+ error. kind,
939+ RunnerErrorKind :: AssertFailure {
940+ actual: "integer <1>" . to_string( ) ,
941+ expected: "not integer <1>" . to_string( ) ,
942+ type_mismatch: false ,
943+ }
944+ ) ;
945+
946+ // no value => fails, the negated value is still reported
947+ let error = eval_predicate ( & predicate, & variables, & None , & context_dir) . unwrap_err ( ) ;
948+ assert_eq ! (
949+ error. kind,
950+ RunnerErrorKind :: AssertFailure {
951+ actual: "none" . to_string( ) ,
952+ expected: "not integer <1>" . to_string( ) ,
953+ type_mismatch: false ,
954+ }
955+ ) ;
956+
957+ // predicate: `not != 1`, the two negations cancel
958+ let predicate = Predicate {
959+ not : true ,
960+ space0 : whitespace ( ) ,
961+ predicate_func : PredicateFunc {
962+ value : PredicateFuncValue :: NotEqual {
963+ space0 : whitespace ( ) ,
964+ value : PredicateValue :: Number ( hurl_core:: ast:: Number :: Integer ( I64 :: new (
965+ 1 ,
966+ "1" . to_source ( ) ,
967+ ) ) ) ,
968+ } ,
969+ source_info : SourceInfo :: new ( Pos :: new ( 1 , 11 ) , Pos :: new ( 1 , 13 ) ) ,
970+ } ,
971+ } ;
972+
973+ // value: 2 => fails, no `not` prefix
974+ let error = eval_predicate (
975+ & predicate,
976+ & variables,
977+ & Some ( Value :: Number ( Number :: Integer ( 2 ) ) ) ,
978+ & context_dir,
979+ )
980+ . unwrap_err ( ) ;
981+ assert_eq ! (
982+ error. kind,
983+ RunnerErrorKind :: AssertFailure {
984+ actual: "integer <2>" . to_string( ) ,
985+ expected: "integer <1>" . to_string( ) ,
986+ type_mismatch: false ,
987+ }
988+ ) ;
989+ }
990+
903991 #[ test]
904992 fn test_predicate_type_mismatch ( ) {
905993 let variables = VariableSet :: new ( ) ;
0 commit comments