@@ -2750,9 +2750,9 @@ public void isAlwaysTrue_operationError_counterexampleFormat() throws Exception
27502750 }
27512751
27522752 @ Test
2753- public void isAlwaysTrue_dynamicFunction_nan_violated () throws Exception {
2754- // request() == request() is a tautology only if request() does not evaluate to NaN.
2755- // Since request() returns DYN, Z3 can assign NaN to its return value, and NaN == NaN is false .
2753+ public void isAlwaysTrue_dynamicFunction_inconclusive () throws Exception {
2754+ // request() == request() fails only if request() returns NaN. The solver may pick NaN for an
2755+ // uninterpreted function, but the actual function may never return it .
27562756 CelCompiler celCompiler =
27572757 CEL .toCompilerBuilder ()
27582758 .setContainer (CelContainer .ofName ("cel.expr.conformance.proto3" ))
@@ -2764,8 +2764,26 @@ public void isAlwaysTrue_dynamicFunction_nan_violated() throws Exception {
27642764 CelAbstractSyntaxTree ast = celCompiler .compile ("request() == request()" ).getAst ();
27652765 CelVerificationResult result = VERIFIER .isAlwaysTrue (ast );
27662766
2767+ assertThat (result .status ()).isEqualTo (VerificationStatus .INCONCLUSIVE );
2768+ assertThat (result .message ()).contains ("depends on approximations" );
2769+ }
2770+
2771+ @ Test
2772+ public void isAlwaysTrue_dynamicFunctionShortCircuited_violated () throws Exception {
2773+ // x == 0 falsifies the condition regardless of request()'s value.
2774+ CelCompiler celCompiler =
2775+ CEL .toCompilerBuilder ()
2776+ .setContainer (CelContainer .ofName ("cel.expr.conformance.proto3" ))
2777+ .addFunctionDeclarations (
2778+ CelFunctionDecl .newFunctionDeclaration (
2779+ "request" ,
2780+ CelOverloadDecl .newGlobalOverload ("request_overload" , SimpleType .DYN )))
2781+ .build ();
2782+ CelAbstractSyntaxTree ast = celCompiler .compile ("x != 0 && request() == 1" ).getAst ();
2783+ CelVerificationResult result = VERIFIER .isAlwaysTrue (ast );
2784+
27672785 assertThat (result .status ()).isEqualTo (VerificationStatus .VIOLATED );
2768- assertThat (result .message ()).contains ("request = NaN " );
2786+ assertThat (result .message ()).contains ("x = 0 " );
27692787 }
27702788
27712789 @ Test
@@ -2785,9 +2803,46 @@ public void isAlwaysTrue_boolFunction_verified() throws Exception {
27852803 }
27862804
27872805 @ Test
2788- public void verifyEquivalence_functionError_equivalent () throws Exception {
2789- // request() and request() are equivalent, even if request() throws an Error,
2790- // because Error == Error structurally in Z3 equivalence.
2806+ public void isAlwaysTrue_distinctFunctionSymbols_inconclusive (
2807+ @ TestParameter ({
2808+ // Member and global overloads of the same name.
2809+ "fx(role, country) == role.fx(country)" ,
2810+ // Overloads whose argument values coincide (empty lists of different element types).
2811+ "size(int_list) == 0 && size(string_list) == 0 ? f(int_list) == f(string_list) : true" ,
2812+ // A zero-arity function and a variable of the same name.
2813+ "g() == g"
2814+ })
2815+ String expression )
2816+ throws Exception {
2817+ CelCompiler celCompiler =
2818+ CEL .toCompilerBuilder ()
2819+ .addVar ("string_list" , ListType .create (SimpleType .STRING ))
2820+ .addVar ("g" , SimpleType .INT )
2821+ .addFunctionDeclarations (
2822+ CelFunctionDecl .newFunctionDeclaration (
2823+ "fx" ,
2824+ CelOverloadDecl .newGlobalOverload (
2825+ "fx_global" , SimpleType .BOOL , SimpleType .STRING , SimpleType .STRING ),
2826+ CelOverloadDecl .newMemberOverload (
2827+ "fx_member" , SimpleType .BOOL , SimpleType .STRING , SimpleType .STRING )),
2828+ CelFunctionDecl .newFunctionDeclaration (
2829+ "f" ,
2830+ CelOverloadDecl .newGlobalOverload (
2831+ "f_list_int" , SimpleType .INT , ListType .create (SimpleType .INT )),
2832+ CelOverloadDecl .newGlobalOverload (
2833+ "f_list_string" , SimpleType .INT , ListType .create (SimpleType .STRING ))),
2834+ CelFunctionDecl .newFunctionDeclaration (
2835+ "g" , CelOverloadDecl .newGlobalOverload ("g_zero" , SimpleType .INT )))
2836+ .build ();
2837+ CelAbstractSyntaxTree ast = celCompiler .compile (expression ).getAst ();
2838+ CelVerificationResult result = VERIFIER .isAlwaysTrue (ast );
2839+
2840+ assertThat (result .status ()).isEqualTo (VerificationStatus .INCONCLUSIVE );
2841+ }
2842+
2843+ @ Test
2844+ public void verifyEquivalence_identicalFunctionCalls_equivalent () throws Exception {
2845+ // Identical calls to an uninterpreted function always produce identical results.
27912846 CelCompiler celCompiler =
27922847 CEL .toCompilerBuilder ()
27932848 .setContainer (CelContainer .ofName ("cel.expr.conformance.proto3" ))
0 commit comments