xref: /aosp_15_r20/external/grpc-grpc/test/core/gprpp/table_test.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/core/lib/gprpp/table.h"
16 
17 #include <string>
18 #include <tuple>
19 #include <variant>
20 
21 #include "absl/types/optional.h"
22 #include "gtest/gtest.h"
23 
24 namespace grpc_core {
25 namespace testing {
26 
TEST(Table,InstantiateEmpty)27 TEST(Table, InstantiateEmpty) { Table<>(); }
28 
TEST(Table,NoOp)29 TEST(Table, NoOp) {
30   Table<int, double, std::string> t;
31   EXPECT_EQ(t.get<int>(), nullptr);
32   EXPECT_EQ(t.get<double>(), nullptr);
33   EXPECT_EQ(t.get<std::string>(), nullptr);
34   EXPECT_EQ(t.get<0>(), nullptr);
35   EXPECT_EQ(t.get<1>(), nullptr);
36   EXPECT_EQ(t.get<2>(), nullptr);
37 }
38 
TEST(Table,SetTheThings)39 TEST(Table, SetTheThings) {
40   Table<int, double, std::string> t;
41   t.set<int>(3);
42   t.set<double>(2.9);
43   t.set<std::string>("Hello world!");
44   EXPECT_EQ(*t.get<int>(), 3);
45   EXPECT_EQ(*t.get<double>(), 2.9);
46   EXPECT_EQ(*t.get<std::string>(), "Hello world!");
47   EXPECT_EQ(*t.get<0>(), 3);
48   EXPECT_EQ(*t.get<1>(), 2.9);
49   EXPECT_EQ(*t.get<2>(), "Hello world!");
50 }
51 
TEST(Table,GetDefault)52 TEST(Table, GetDefault) {
53   Table<int, double, std::string> t;
54   EXPECT_EQ(*t.get_or_create<std::string>(), "");
55   EXPECT_EQ(*t.get_or_create<double>(), 0.0);
56   EXPECT_EQ(*t.get_or_create<int>(), 0);
57 }
58 
TEST(Table,GetDefaultIndexed)59 TEST(Table, GetDefaultIndexed) {
60   Table<int, double, std::string> t;
61   EXPECT_EQ(*t.get_or_create<2>(), "");
62   EXPECT_EQ(*t.get_or_create<1>(), 0.0);
63   EXPECT_EQ(*t.get_or_create<0>(), 0);
64 }
65 
TEST(Table,Copy)66 TEST(Table, Copy) {
67   Table<int, std::string> t;
68   t.set<std::string>("abcdefghijklmnopqrstuvwxyz");
69   EXPECT_EQ(*t.get<std::string>(), "abcdefghijklmnopqrstuvwxyz");
70   EXPECT_EQ(t.get<int>(), nullptr);
71   Table<int, std::string> u(t);
72   EXPECT_EQ(*u.get<std::string>(), "abcdefghijklmnopqrstuvwxyz");
73   EXPECT_EQ(*t.get<std::string>(), "abcdefghijklmnopqrstuvwxyz");
74   EXPECT_EQ(t.get<int>(), nullptr);
75   EXPECT_EQ(u.get<int>(), nullptr);
76   u.set<std::string>("hello");
77   EXPECT_EQ(*u.get<1>(), "hello");
78   EXPECT_EQ(*t.get<1>(), "abcdefghijklmnopqrstuvwxyz");
79   t = u;
80   EXPECT_EQ(*u.get<std::string>(), "hello");
81   EXPECT_EQ(*t.get<std::string>(), "hello");
82 }
83 
TEST(Table,Move)84 TEST(Table, Move) {
85   Table<int, std::string> t;
86   t.set<std::string>("abcdefghijklmnopqrstuvwxyz");
87   EXPECT_EQ(*t.get<std::string>(), "abcdefghijklmnopqrstuvwxyz");
88   EXPECT_EQ(t.get<int>(), nullptr);
89   Table<int, std::string> u(std::move(t));
90   EXPECT_NE(t.get<std::string>(), nullptr);  // NOLINT(bugprone-use-after-move)
91   EXPECT_EQ(*u.get<std::string>(), "abcdefghijklmnopqrstuvwxyz");
92   EXPECT_EQ(t.get<int>(), nullptr);
93   EXPECT_EQ(u.get<int>(), nullptr);
94   u.set<std::string>("hello");
95   EXPECT_EQ(*u.get<1>(), "hello");
96   t = std::move(u);
97   EXPECT_NE(u.get<std::string>(), nullptr);  // NOLINT(bugprone-use-after-move)
98   EXPECT_EQ(*t.get<std::string>(), "hello");
99 }
100 
TEST(Table,SameTypes)101 TEST(Table, SameTypes) {
102   Table<std::string, std::string, std::string> t;
103   // The following lines should not compile:
104   // t.get<std::string>();
105   // t.has<4>();
106   // t.get<4>();
107   // t.clear<4>();
108   EXPECT_EQ(t.get<0>(), nullptr);
109   EXPECT_EQ(t.get<1>(), nullptr);
110   EXPECT_EQ(t.get<2>(), nullptr);
111   t.set<1>("Hello!");
112   EXPECT_EQ(t.get<0>(), nullptr);
113   EXPECT_EQ(*t.get<1>(), "Hello!");
114   EXPECT_EQ(t.get<2>(), nullptr);
115 }
116 
TEST(Table,ForEach)117 TEST(Table, ForEach) {
118   Table<int, int, int> t;
119   t.set<0>(1);
120   t.set<1>(2);
121   t.set<2>(3);
122   int i = 1;
123   t.ForEach([&i](int x) {
124     EXPECT_EQ(x, i);
125     i++;
126   });
127 }
128 
129 #if !defined(_MSC_VER)
130 // Test suite proving this is memory efficient compared to
131 // tuple<optional<Ts>...>
132 // TODO(ctiller): determine why this test doesn't compile under MSVC.
133 // For now whether it passes or not in that one environment is probably
134 // immaterial.
135 
136 template <typename T>
137 struct TableSizeTest : public ::testing::Test {};
138 
139 using SizeTests = ::testing::Types<
140     std::tuple<char>, std::tuple<char, char>, std::tuple<char, char, char>,
141     std::tuple<int>, std::tuple<std::string>,
142     std::tuple<int, int, int, int, int, int, int, int, int, int>>;
143 
144 TYPED_TEST_SUITE(TableSizeTest, SizeTests);
145 
146 template <typename... Ts>
sizeof_tuple_of_optionals(std::tuple<Ts...> *)147 int sizeof_tuple_of_optionals(std::tuple<Ts...>*) {
148   return sizeof(std::tuple<absl::optional<Ts>...>);
149 }
150 
151 template <typename... Ts>
sizeof_table(std::tuple<Ts...> *)152 int sizeof_table(std::tuple<Ts...>*) {
153   return sizeof(Table<Ts...>);
154 }
155 
TYPED_TEST(TableSizeTest,SmallerThanTupleOfOptionals)156 TYPED_TEST(TableSizeTest, SmallerThanTupleOfOptionals) {
157   EXPECT_GE(sizeof_tuple_of_optionals(static_cast<TypeParam*>(nullptr)),
158             sizeof_table(static_cast<TypeParam*>(nullptr)));
159 }
160 #endif
161 
162 }  // namespace testing
163 }  // namespace grpc_core
164 
main(int argc,char ** argv)165 int main(int argc, char** argv) {
166   ::testing::InitGoogleTest(&argc, argv);
167   return RUN_ALL_TESTS();
168 }
169