Line data Source code
1 : #include "backend/engine/semantic/stubs/dispatch.h"
2 :
3 : #include <optional>
4 : #include <string>
5 :
6 : #include "absl/status/status.h"
7 : #include "absl/status/statusor.h"
8 : #include "backend/engine/semantic/error.h"
9 : #include "backend/engine/semantic/value.h"
10 : #include "gmock/gmock.h"
11 : #include "googlesql/public/type.h"
12 : #include "googlesql/public/type.pb.h"
13 : #include "googlesql/public/value.h"
14 : #include "gtest/gtest.h"
15 :
16 : namespace bigquery_emulator {
17 : namespace backend {
18 : namespace engine {
19 : namespace semantic {
20 : namespace stubs {
21 : namespace {
22 :
23 : using ::testing::HasSubstr;
24 :
25 1 : TEST(StubDispatchTest, KeysNewKeysetIsDispatched) {
26 : // `keys.new_keyset` is the dotted BigQuery name the route
27 : // classifier (`route_classifier.cc::CheckFunction`) writes by
28 : // calling `Function::FullName(/*include_group=*/false)`. The
29 : // semantic executor (`eval_expr.cc::DispatchFunctionByName`)
30 : // hands that name verbatim to this Dispatch table. A regression
31 : // that renames the key on either side breaks the round-trip
32 : // silently; pinning the key here forces an explicit update.
33 1 : Value key_type = Value::String("AEAD_AES_GCM_256");
34 1 : auto r = Dispatch("keys.new_keyset", {key_type}, /*return_type=*/nullptr);
35 1 : ASSERT_TRUE(r.has_value());
36 2 : ASSERT_TRUE(r->ok()) << r->status();
37 1 : EXPECT_EQ(r->value().type_kind(), ::googlesql::TYPE_BYTES);
38 1 : }
39 :
40 1 : TEST(StubDispatchTest, KeysKeysetLengthIsDispatched) {
41 1 : Value keyset = Value::Bytes("anything");
42 1 : auto r = Dispatch("keys.keyset_length", {keyset}, /*return_type=*/nullptr);
43 1 : ASSERT_TRUE(r.has_value());
44 2 : ASSERT_TRUE(r->ok()) << r->status();
45 1 : EXPECT_EQ(r->value().type_kind(), ::googlesql::TYPE_INT64);
46 1 : EXPECT_EQ(r->value().int64_value(), 1);
47 1 : }
48 :
49 1 : TEST(StubDispatchTest, UnknownNameReturnsNullopt) {
50 1 : auto r = Dispatch("not.a.stub.family", {}, /*return_type=*/nullptr);
51 1 : EXPECT_FALSE(r.has_value());
52 1 : }
53 :
54 1 : TEST(StubDispatchTest, InvalidArgsBubbleUpAsStatus) {
55 : // When the stub fires but the caller passed the wrong type, the
56 : // dispatch returns `optional<StatusOr<Value>>` with a non-OK
57 : // status. The caller treats it as "stub fired, evaluation
58 : // failed" and surfaces the status verbatim -- it does NOT fall
59 : // through to its own NOT_IMPLEMENTED branch (which would mask a
60 : // real argument-shape failure as a missing-function error).
61 1 : Value wrong_type = Value::Int64(7);
62 1 : auto r = Dispatch("keys.new_keyset", {wrong_type}, /*return_type=*/nullptr);
63 1 : ASSERT_TRUE(r.has_value());
64 1 : EXPECT_EQ(r->status().code(), absl::StatusCode::kInvalidArgument);
65 1 : EXPECT_THAT(std::string(r->status().message()), HasSubstr("STRING"));
66 1 : }
67 :
68 : } // namespace
69 : } // namespace stubs
70 : } // namespace semantic
71 : } // namespace engine
72 : } // namespace backend
73 : } // namespace bigquery_emulator
|