table_test.cc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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. #include "src/core/lib/gprpp/table.h"
  15. #include <string>
  16. #include <tuple>
  17. #include <gtest/gtest.h>
  18. #include "absl/types/optional.h"
  19. namespace grpc_core {
  20. namespace testing {
  21. TEST(Table, InstantiateEmpty) { Table<>(); }
  22. TEST(Table, NoOp) {
  23. Table<int, double, std::string> t;
  24. EXPECT_EQ(t.get<int>(), nullptr);
  25. EXPECT_EQ(t.get<double>(), nullptr);
  26. EXPECT_EQ(t.get<std::string>(), nullptr);
  27. EXPECT_EQ(t.get<0>(), nullptr);
  28. EXPECT_EQ(t.get<1>(), nullptr);
  29. EXPECT_EQ(t.get<2>(), nullptr);
  30. }
  31. TEST(Table, SetTheThings) {
  32. Table<int, double, std::string> t;
  33. t.set<int>(3);
  34. t.set<double>(2.9);
  35. t.set<std::string>("Hello world!");
  36. EXPECT_EQ(*t.get<int>(), 3);
  37. EXPECT_EQ(*t.get<double>(), 2.9);
  38. EXPECT_EQ(*t.get<std::string>(), "Hello world!");
  39. EXPECT_EQ(*t.get<0>(), 3);
  40. EXPECT_EQ(*t.get<1>(), 2.9);
  41. EXPECT_EQ(*t.get<2>(), "Hello world!");
  42. }
  43. TEST(Table, GetDefault) {
  44. Table<int, double, std::string> t;
  45. EXPECT_EQ(*t.get_or_create<std::string>(), "");
  46. EXPECT_EQ(*t.get_or_create<double>(), 0.0);
  47. EXPECT_EQ(*t.get_or_create<int>(), 0);
  48. }
  49. TEST(Table, GetDefaultIndexed) {
  50. Table<int, double, std::string> t;
  51. EXPECT_EQ(*t.get_or_create<2>(), "");
  52. EXPECT_EQ(*t.get_or_create<1>(), 0.0);
  53. EXPECT_EQ(*t.get_or_create<0>(), 0);
  54. }
  55. TEST(Table, Copy) {
  56. Table<int, std::string> t;
  57. t.set<std::string>("abcdefghijklmnopqrstuvwxyz");
  58. EXPECT_EQ(*t.get<std::string>(), "abcdefghijklmnopqrstuvwxyz");
  59. EXPECT_EQ(t.get<int>(), nullptr);
  60. Table<int, std::string> u(t);
  61. EXPECT_EQ(*u.get<std::string>(), "abcdefghijklmnopqrstuvwxyz");
  62. EXPECT_EQ(*t.get<std::string>(), "abcdefghijklmnopqrstuvwxyz");
  63. EXPECT_EQ(t.get<int>(), nullptr);
  64. EXPECT_EQ(u.get<int>(), nullptr);
  65. u.set<std::string>("hello");
  66. EXPECT_EQ(*u.get<1>(), "hello");
  67. EXPECT_EQ(*t.get<1>(), "abcdefghijklmnopqrstuvwxyz");
  68. t = u;
  69. EXPECT_EQ(*u.get<std::string>(), "hello");
  70. EXPECT_EQ(*t.get<std::string>(), "hello");
  71. }
  72. TEST(Table, Move) {
  73. Table<int, std::string> t;
  74. t.set<std::string>("abcdefghijklmnopqrstuvwxyz");
  75. EXPECT_EQ(*t.get<std::string>(), "abcdefghijklmnopqrstuvwxyz");
  76. EXPECT_EQ(t.get<int>(), nullptr);
  77. Table<int, std::string> u(std::move(t));
  78. EXPECT_NE(t.get<std::string>(), nullptr); // NOLINT(bugprone-use-after-move)
  79. EXPECT_EQ(*u.get<std::string>(), "abcdefghijklmnopqrstuvwxyz");
  80. EXPECT_EQ(t.get<int>(), nullptr);
  81. EXPECT_EQ(u.get<int>(), nullptr);
  82. u.set<std::string>("hello");
  83. EXPECT_EQ(*u.get<1>(), "hello");
  84. t = std::move(u);
  85. EXPECT_NE(u.get<std::string>(), nullptr); // NOLINT(bugprone-use-after-move)
  86. EXPECT_EQ(*t.get<std::string>(), "hello");
  87. }
  88. TEST(Table, SameTypes) {
  89. Table<std::string, std::string, std::string> t;
  90. // The following lines should not compile:
  91. // t.get<std::string>();
  92. // t.has<4>();
  93. // t.get<4>();
  94. // t.clear<4>();
  95. EXPECT_EQ(t.get<0>(), nullptr);
  96. EXPECT_EQ(t.get<1>(), nullptr);
  97. EXPECT_EQ(t.get<2>(), nullptr);
  98. t.set<1>("Hello!");
  99. EXPECT_EQ(t.get<0>(), nullptr);
  100. EXPECT_EQ(*t.get<1>(), "Hello!");
  101. EXPECT_EQ(t.get<2>(), nullptr);
  102. }
  103. TEST(Table, ForEach) {
  104. Table<int, int, int> t;
  105. t.set<0>(1);
  106. t.set<1>(2);
  107. t.set<2>(3);
  108. int i = 1;
  109. t.ForEach([&i](int x) {
  110. EXPECT_EQ(x, i);
  111. i++;
  112. });
  113. }
  114. #if !defined(_MSC_VER)
  115. // Test suite proving this is memory efficient compared to
  116. // tuple<optional<Ts>...>
  117. // TODO(ctiller): determine why this test doesn't compile under MSVC.
  118. // For now whether it passes or not in that one environment is probably
  119. // immaterial.
  120. template <typename T>
  121. struct TableSizeTest : public ::testing::Test {};
  122. using SizeTests = ::testing::Types<
  123. std::tuple<char>, std::tuple<char, char>, std::tuple<char, char, char>,
  124. std::tuple<int>, std::tuple<std::string>,
  125. std::tuple<int, int, int, int, int, int, int, int, int, int>>;
  126. TYPED_TEST_SUITE(TableSizeTest, SizeTests);
  127. template <typename... Ts>
  128. int sizeof_tuple_of_optionals(std::tuple<Ts...>*) {
  129. return sizeof(std::tuple<absl::optional<Ts>...>);
  130. }
  131. template <typename... Ts>
  132. int sizeof_table(std::tuple<Ts...>*) {
  133. return sizeof(Table<Ts...>);
  134. }
  135. TYPED_TEST(TableSizeTest, SmallerThanTupleOfOptionals) {
  136. EXPECT_GE(sizeof_tuple_of_optionals(static_cast<TypeParam*>(nullptr)),
  137. sizeof_table(static_cast<TypeParam*>(nullptr)));
  138. }
  139. #endif
  140. } // namespace testing
  141. } // namespace grpc_core
  142. int main(int argc, char** argv) {
  143. ::testing::InitGoogleTest(&argc, argv);
  144. return RUN_ALL_TESTS();
  145. }