testing.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Copyright 2018 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef FIRESTORE_CORE_TEST_UNIT_IMMUTABLE_TESTING_H_
  17. #define FIRESTORE_CORE_TEST_UNIT_IMMUTABLE_TESTING_H_
  18. #include <algorithm>
  19. #include <string>
  20. #include <type_traits>
  21. #include <utility>
  22. #include <vector>
  23. #include "Firestore/core/src/util/secure_random.h"
  24. #include "absl/strings/str_cat.h"
  25. #include "gtest/gtest.h"
  26. namespace firebase {
  27. namespace firestore {
  28. namespace immutable {
  29. template <typename K, typename V>
  30. std::string Describe(const std::pair<K, V>& pair) {
  31. return absl::StrCat("(", pair.first, ", ", pair.second, ")");
  32. }
  33. // Describes the given item by its std::to_string implementation (if
  34. // std::to_string is defined for V). The return type is not defined directly
  35. // in terms of std::string in order to allow specialization failure to select
  36. // a different overload.
  37. template <typename V>
  38. auto Describe(const V& item) -> decltype(std::to_string(item)) {
  39. return std::to_string(item);
  40. }
  41. template <typename Container, typename K>
  42. testing::AssertionResult NotFound(const Container& map, const K& key) {
  43. if (map.contains(key)) {
  44. return testing::AssertionFailure()
  45. << "Should not have found " << key << " using contains()";
  46. }
  47. auto found = map.find(key);
  48. if (found == map.end()) {
  49. return testing::AssertionSuccess();
  50. } else {
  51. return testing::AssertionFailure()
  52. << "Should not have found " << Describe(*found);
  53. }
  54. }
  55. /**
  56. * Asserts that the given key is found in the given container and that it maps
  57. * to the given value. This only works with map-type containers where value_type
  58. * is `std::pair<K, V>`.
  59. */
  60. template <typename Container, typename K, typename V>
  61. testing::AssertionResult Found(const Container& map,
  62. const K& key,
  63. const V& expected) {
  64. if (!map.contains(key)) {
  65. return testing::AssertionFailure()
  66. << "Did not find key " << key << " using contains()";
  67. }
  68. auto found = map.find(key);
  69. if (found == map.end()) {
  70. return testing::AssertionFailure()
  71. << "Did not find key " << key << " using find()";
  72. }
  73. if (found->second == expected) {
  74. return testing::AssertionSuccess();
  75. } else {
  76. return testing::AssertionFailure() << "Found entry was (" << found->first
  77. << ", " << found->second << ")";
  78. }
  79. }
  80. /**
  81. * Asserts that the given key is found in the given container without
  82. * necessarily checking that the key maps to any value. This also makes
  83. * this compatible with non-mapped containers where K is the value_type.
  84. */
  85. template <typename Container, typename K>
  86. testing::AssertionResult Found(const Container& container, const K& key) {
  87. if (!container.contains(key)) {
  88. return testing::AssertionFailure()
  89. << "Did not find key " << key << " using contains()";
  90. }
  91. auto found = container.find(key);
  92. if (found == container.end()) {
  93. return testing::AssertionFailure()
  94. << "Did not find key " << key << " using find()";
  95. }
  96. if (*found == key) {
  97. return testing::AssertionSuccess();
  98. } else {
  99. return testing::AssertionFailure()
  100. << "Found entry was " << Describe(*found);
  101. }
  102. }
  103. /** Creates an empty vector (for readability). */
  104. inline std::vector<int> Empty() {
  105. return {};
  106. }
  107. /**
  108. * Creates a vector containing a sequence of integers from the given starting
  109. * element up to, but not including, the given end element, with values
  110. * incremented by the given step.
  111. *
  112. * If step is negative the sequence is in descending order (but still starting
  113. * at start and ending before end).
  114. */
  115. inline std::vector<int> Sequence(int start, int end, int step = 1) {
  116. std::vector<int> result;
  117. if (step > 0) {
  118. for (int i = start; i < end; i += step) {
  119. result.push_back(i);
  120. }
  121. } else {
  122. for (int i = start; i > end; i += step) {
  123. result.push_back(i);
  124. }
  125. }
  126. return result;
  127. }
  128. /**
  129. * Creates a vector containing a sequence of integers with the given number of
  130. * elements, from zero up to, but not including the given value.
  131. */
  132. inline std::vector<int> Sequence(int num_elements) {
  133. return Sequence(0, num_elements);
  134. }
  135. /**
  136. * Creates a copy of the given vector with contents shuffled randomly.
  137. */
  138. inline std::vector<int> Shuffled(const std::vector<int>& values) {
  139. std::vector<int> result{values};
  140. util::SecureRandom rng;
  141. std::shuffle(result.begin(), result.end(), rng);
  142. return result;
  143. }
  144. /**
  145. * Creates a copy of the given vector with contents sorted.
  146. */
  147. inline std::vector<int> Sorted(const std::vector<int>& values) {
  148. std::vector<int> result{values};
  149. std::sort(result.begin(), result.end());
  150. return result;
  151. }
  152. /**
  153. * Creates a copy of the given vector with contents reversed.
  154. */
  155. inline std::vector<int> Reversed(const std::vector<int>& values) {
  156. std::vector<int> result{values};
  157. std::reverse(result.begin(), result.end());
  158. return result;
  159. }
  160. /**
  161. * Creates a vector of pairs where each pair has the same first and second
  162. * corresponding to an element in the given vector.
  163. */
  164. inline std::vector<std::pair<int, int>> Pairs(const std::vector<int>& values) {
  165. std::vector<std::pair<int, int>> result;
  166. for (auto&& value : values) {
  167. result.emplace_back(value, value);
  168. }
  169. return result;
  170. }
  171. /**
  172. * Creates a SortedMap by inserting a pair for each value in the vector.
  173. * Each pair will have the same key and value.
  174. */
  175. template <typename Container>
  176. Container ToMap(const std::vector<int>& values) {
  177. Container result;
  178. for (auto&& value : values) {
  179. result = result.insert(value, value);
  180. }
  181. return result;
  182. }
  183. template <typename Container>
  184. std::vector<int> Keys(const Container& container) {
  185. std::vector<int> keys;
  186. for (const auto& element : container) {
  187. keys.push_back(element.first);
  188. }
  189. return keys;
  190. }
  191. /**
  192. * Appends the contents of the given container to a new vector.
  193. */
  194. template <typename Container>
  195. std::vector<typename Container::value_type> Collect(
  196. const Container& container) {
  197. return {container.begin(), container.end()};
  198. }
  199. #define ASSERT_SEQ_EQ(x, y) ASSERT_EQ((x), Collect(y));
  200. #define EXPECT_SEQ_EQ(x, y) EXPECT_EQ((x), Collect(y));
  201. } // namespace immutable
  202. } // namespace firestore
  203. } // namespace firebase
  204. #endif // FIRESTORE_CORE_TEST_UNIT_IMMUTABLE_TESTING_H_