Line data Source code
1 : #include "backend/engine/disposition.h"
2 :
3 : #include <set>
4 : #include <string>
5 : #include <vector>
6 :
7 : #include "absl/strings/string_view.h"
8 : #include "gtest/gtest.h"
9 :
10 : namespace bigquery_emulator {
11 : namespace backend {
12 : namespace engine {
13 : namespace {
14 :
15 : // The full closed set of Disposition values. Centralised so each
16 : // test below can iterate over the same vector instead of
17 : // hand-listing the enum members. Adding a new enum value here AND
18 : // updating `kDispositionCount` triggers every assertion below to
19 : // exercise the new value as well.
20 3 : const std::vector<Disposition>& AllDispositions() {
21 3 : static const auto* kAll = new std::vector<Disposition>{
22 3 : Disposition::kDuckdbNative,
23 3 : Disposition::kDuckdbRewrite,
24 3 : Disposition::kDuckdbUdf,
25 3 : Disposition::kSemanticExecutor,
26 3 : Disposition::kControlOp,
27 3 : Disposition::kLocalStub,
28 3 : Disposition::kUnsupported,
29 3 : };
30 3 : return *kAll;
31 3 : }
32 :
33 1 : TEST(DispositionTest, ToStringRoundsTripCanonicalSpellings) {
34 : // The spellings here must match the YAML disposition column AND
35 : // the SHAPE_TRACKER.md `status` column verbatim; the parity
36 : // checker (`tools/check_disposition_parity`) consumes the same
37 : // strings.
38 1 : EXPECT_EQ(DispositionToString(Disposition::kDuckdbNative), "duckdb_native");
39 1 : EXPECT_EQ(DispositionToString(Disposition::kDuckdbRewrite), "duckdb_rewrite");
40 1 : EXPECT_EQ(DispositionToString(Disposition::kDuckdbUdf), "duckdb_udf");
41 1 : EXPECT_EQ(DispositionToString(Disposition::kSemanticExecutor),
42 1 : "semantic_executor");
43 1 : EXPECT_EQ(DispositionToString(Disposition::kControlOp), "control_op");
44 1 : EXPECT_EQ(DispositionToString(Disposition::kLocalStub), "local_stub");
45 1 : EXPECT_EQ(DispositionToString(Disposition::kUnsupported), "unsupported");
46 1 : }
47 :
48 1 : TEST(DispositionTest, ToStringIsTotalAndUnique) {
49 : // Every enum value maps to a non-empty, distinct lowercase
50 : // identifier-safe string. An accidental duplicate would silently
51 : // make `tools/check_disposition_parity` treat two routes as the
52 : // same.
53 1 : std::set<std::string> seen;
54 7 : for (Disposition d : AllDispositions()) {
55 7 : absl::string_view s = DispositionToString(d);
56 7 : SCOPED_TRACE(s);
57 7 : EXPECT_FALSE(s.empty());
58 7 : EXPECT_NE(s, "unknown");
59 7 : seen.insert(std::string(s));
60 7 : }
61 1 : EXPECT_EQ(seen.size(), AllDispositions().size());
62 1 : }
63 :
64 1 : TEST(DispositionTest, EnumCountMatchesAllDispositions) {
65 : // `kDispositionCount` is the build-time anchor the parity checker
66 : // and the generated `node_dispositions_table.inc` test consult.
67 : // Whenever a new disposition lands, this assertion is the canary
68 : // that fires first; bumping `kDispositionCount` then forces
69 : // updates everywhere else that iterates over the closed set.
70 1 : EXPECT_EQ(static_cast<int>(AllDispositions().size()), kDispositionCount);
71 1 : }
72 :
73 : } // namespace
74 : } // namespace engine
75 : } // namespace backend
76 : } // namespace bigquery_emulator
|