Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion eval/compiler/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -501,16 +501,18 @@ cc_test(
],
deps = [
":cel_expression_builder_flat_impl",
"//base:builtins",
"//eval/public:activation",
"//eval/public:cel_attribute",
"//eval/public:cel_expression",
"//eval/public:cel_value",
"//eval/public:unknown_attribute_set",
"//eval/public:unknown_set",
"//internal:testing",
"//parser",
"//parser:options",
"//runtime:runtime_options",
"//runtime/internal:runtime_env_testing",
"@com_google_absl//absl/log:absl_check",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_protobuf//:protobuf",
Expand Down
6 changes: 3 additions & 3 deletions eval/compiler/flat_expr_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2193,10 +2193,10 @@ void BinaryCondVisitor::PostVisitArg(int arg_num, const cel::Expr* expr) {
std::unique_ptr<JumpStepBase> jump_step;
switch (cond_) {
case BinaryCond::kAnd:
jump_step = CreateCondJumpStep(false, true, {}, expr->id());
jump_step = CreateCondJumpStep(false, {}, expr->id());
break;
case BinaryCond::kOr:
jump_step = CreateCondJumpStep(true, true, {}, expr->id());
jump_step = CreateCondJumpStep(true, {}, expr->id());
break;
default:
ABSL_UNREACHABLE();
Expand Down Expand Up @@ -2321,7 +2321,7 @@ void TernaryCondVisitor::PostVisitArg(int arg_num, const cel::Expr* expr) {
// Value is to be removed from the stack.
ProgramStepIndex cond_jump_pos = visitor_->GetCurrentIndex();
auto* jump_to_second =
visitor_->AddStep(CreateCondJumpStep(false, false, {}, expr->id()));
visitor_->AddStep(CreateTernaryCondJumpStep({}, expr->id()));
if (jump_to_second) {
jump_to_second_ =
Jump(cond_jump_pos, static_cast<JumpStepBase*>(jump_to_second));
Expand Down
134 changes: 39 additions & 95 deletions eval/compiler/flat_expr_builder_short_circuiting_conformance_test.cc
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// A collection of tests that confirm that short-circuit and non-short-circuit
// produce expressions with the same outputs.
#include <memory>
#include <string>
#include <tuple>

#include "absl/log/absl_check.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "base/builtins.h"
#include "eval/compiler/cel_expression_builder_flat_impl.h"
#include "eval/public/activation.h"
#include "eval/public/cel_attribute.h"
Expand All @@ -14,75 +16,22 @@
#include "eval/public/unknown_attribute_set.h"
#include "eval/public/unknown_set.h"
#include "internal/testing.h"
#include "parser/options.h"
#include "parser/parser.h"
#include "runtime/internal/runtime_env_testing.h"
#include "runtime/runtime_options.h"
#include "google/protobuf/arena.h"
#include "google/protobuf/text_format.h"

namespace google::api::expr::runtime {

namespace {

using ::cel::runtime_internal::NewTestingRuntimeEnv;
using ::cel::expr::Expr;
using ::google::api::expr::parser::Parse;
using ::testing::Eq;
using ::testing::SizeIs;

constexpr char kTwoLogicalOp[] = R"cel(
id: 1
call_expr {
function: "$0"
args {
id: 2
ident_expr {
name: "var1",
}
}
args {
id: 3
call_expr {
function: "$0"
args {
id: 4
ident_expr {
name: "var2"
}
}
args {
id: 5
ident_expr {
name: "var3"
}
}
}
}
}
)cel";

constexpr char kTernaryExpr[] = R"cel(
id: 1
call_expr {
function: "_?_:_"
args {
id: 2
ident_expr {
name: "cond"
}
}
args {
id: 3
ident_expr {
name: "arg1"
}
}
args {
id: 4
ident_expr {
name: "arg2"
}
}
})cel";

void BuildAndEval(CelExpressionBuilder* builder, const Expr& expr,
const Activation& activation, google::protobuf::Arena* arena,
CelValue* result) {
Expand All @@ -95,12 +44,16 @@ void BuildAndEval(CelExpressionBuilder* builder, const Expr& expr,
*result = *value;
}

class ShortCircuitingTest : public testing::TestWithParam<bool> {
class ShortCircuitingTest
: public testing::TestWithParam<std::tuple<bool, bool>> {
public:
bool short_circuiting() const { return std::get<0>(GetParam()); }
bool enable_variadic() const { return std::get<1>(GetParam()); }

std::unique_ptr<CelExpressionBuilder> GetBuilder(
bool enable_unknowns = false) {
cel::RuntimeOptions options;
options.short_circuiting = GetParam();
options.short_circuiting = short_circuiting();
if (enable_unknowns) {
options.unknown_processing =
cel::UnknownProcessingOptions::kAttributeAndFunction;
Expand All @@ -109,14 +62,20 @@ class ShortCircuitingTest : public testing::TestWithParam<bool> {
NewTestingRuntimeEnv(), options);
return result;
}

Expr ParseExpr(absl::string_view expression) {
cel::ParserOptions options;
options.enable_variadic_logical_operators = enable_variadic();
auto parsed_expr = Parse(expression, "<input>", options);
ABSL_CHECK_OK(parsed_expr.status());
return parsed_expr->expr();
}
};

TEST_P(ShortCircuitingTest, BasicAnd) {
Expr expr;
Expr expr = ParseExpr("var1 && var2 && var3");
Activation activation;
google::protobuf::Arena arena;
ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(
absl::Substitute(kTwoLogicalOp, ::cel::builtin::kAnd), &expr));
auto builder = GetBuilder();

activation.InsertValue("var1", CelValue::CreateBool(true));
Expand All @@ -140,11 +99,9 @@ TEST_P(ShortCircuitingTest, BasicAnd) {
}

TEST_P(ShortCircuitingTest, BasicOr) {
Expr expr;
Expr expr = ParseExpr("var1 || var2 || var3");
Activation activation;
google::protobuf::Arena arena;
ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(
absl::Substitute(kTwoLogicalOp, ::cel::builtin::kOr), &expr));
auto builder = GetBuilder();

activation.InsertValue("var1", CelValue::CreateBool(false));
Expand All @@ -168,11 +125,9 @@ TEST_P(ShortCircuitingTest, BasicOr) {
}

TEST_P(ShortCircuitingTest, ErrorAnd) {
Expr expr;
Expr expr = ParseExpr("var1 && var2 && var3");
Activation activation;
google::protobuf::Arena arena;
ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(
absl::Substitute(kTwoLogicalOp, ::cel::builtin::kAnd), &expr));
auto builder = GetBuilder();
absl::Status error = absl::InternalError("error");

Expand All @@ -198,11 +153,9 @@ TEST_P(ShortCircuitingTest, ErrorAnd) {
}

TEST_P(ShortCircuitingTest, ErrorOr) {
Expr expr;
Expr expr = ParseExpr("var1 || var2 || var3");
Activation activation;
google::protobuf::Arena arena;
ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(
absl::Substitute(kTwoLogicalOp, ::cel::builtin::kOr), &expr));
auto builder = GetBuilder();
absl::Status error = absl::InternalError("error");

Expand All @@ -228,11 +181,9 @@ TEST_P(ShortCircuitingTest, ErrorOr) {
}

TEST_P(ShortCircuitingTest, UnknownAnd) {
Expr expr;
Expr expr = ParseExpr("var1 && var2 && var3");
Activation activation;
google::protobuf::Arena arena;
ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(
absl::Substitute(kTwoLogicalOp, ::cel::builtin::kAnd), &expr));
auto builder = GetBuilder(/* enable_unknowns=*/true);
absl::Status error = absl::InternalError("error");

Expand Down Expand Up @@ -260,11 +211,9 @@ TEST_P(ShortCircuitingTest, UnknownAnd) {
}

TEST_P(ShortCircuitingTest, UnknownOr) {
Expr expr;
Expr expr = ParseExpr("var1 || var2 || var3");
Activation activation;
google::protobuf::Arena arena;
ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(
absl::Substitute(kTwoLogicalOp, ::cel::builtin::kOr), &expr));
auto builder = GetBuilder(/* enable_unknowns=*/true);
absl::Status error = absl::InternalError("error");

Expand Down Expand Up @@ -292,10 +241,9 @@ TEST_P(ShortCircuitingTest, UnknownOr) {
}

TEST_P(ShortCircuitingTest, BasicTernary) {
Expr expr;
Expr expr = ParseExpr("cond ? arg1 : arg2");
Activation activation;
google::protobuf::Arena arena;
ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(kTernaryExpr, &expr));
auto builder = GetBuilder();

activation.InsertValue("cond", CelValue::CreateBool(true));
Expand All @@ -319,10 +267,9 @@ TEST_P(ShortCircuitingTest, BasicTernary) {
}

TEST_P(ShortCircuitingTest, TernaryErrorHandling) {
Expr expr;
Expr expr = ParseExpr("cond ? arg1 : arg2");
Activation activation;
google::protobuf::Arena arena;
ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(kTernaryExpr, &expr));
auto builder = GetBuilder();

absl::Status error1 = absl::InternalError("error1");
Expand All @@ -349,10 +296,9 @@ TEST_P(ShortCircuitingTest, TernaryErrorHandling) {
}

TEST_P(ShortCircuitingTest, TernaryUnknownCondHandling) {
Expr expr;
Expr expr = ParseExpr("cond ? arg1 : arg2");
Activation activation;
google::protobuf::Arena arena;
ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(kTernaryExpr, &expr));
auto builder = GetBuilder(/*enable_unknowns=*/true);

absl::Status error = absl::InternalError("error1");
Expand Down Expand Up @@ -386,10 +332,9 @@ TEST_P(ShortCircuitingTest, TernaryUnknownCondHandling) {
}

TEST_P(ShortCircuitingTest, TernaryUnknownArgsHandling) {
Expr expr;
Expr expr = ParseExpr("cond ? arg1 : arg2");
Activation activation;
google::protobuf::Arena arena;
ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(kTernaryExpr, &expr));
auto builder = GetBuilder(/*enable_unknowns=*/true);

absl::Status error = absl::InternalError("error1");
Expand Down Expand Up @@ -421,10 +366,9 @@ TEST_P(ShortCircuitingTest, TernaryUnknownArgsHandling) {
}

TEST_P(ShortCircuitingTest, TernaryUnknownAndErrorHandling) {
Expr expr;
Expr expr = ParseExpr("cond ? arg1 : arg2");
Activation activation;
google::protobuf::Arena arena;
ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(kTernaryExpr, &expr));
auto builder = GetBuilder(/*enable_unknowns=*/true);

absl::Status error = absl::InternalError("error1");
Expand Down Expand Up @@ -457,16 +401,16 @@ TEST_P(ShortCircuitingTest, TernaryUnknownAndErrorHandling) {
EXPECT_EQ(attrs.begin()->variable_name(), "cond");
}

const char* TestName(testing::TestParamInfo<bool> info) {
if (info.param) {
return "short_circuit_enabled";
} else {
return "short_circuit_disabled";
}
std::string TestName(testing::TestParamInfo<std::tuple<bool, bool>> info) {
return absl::StrCat(
std::get<0>(info.param) ? "short_circuit_enabled"
: "short_circuit_disabled",
"_", std::get<1>(info.param) ? "variadic_enabled" : "variadic_disabled");
}

INSTANTIATE_TEST_SUITE_P(Test, ShortCircuitingTest,
testing::Values(false, true), &TestName);
testing::Combine(testing::Bool(), testing::Bool()),
&TestName);

} // namespace

Expand Down
Loading
Loading