|  | // Copyright 2018 The Abseil Authors. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //      https://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | #ifndef ABSL_CONTAINER_BTREE_TEST_H_ | 
|  | #define ABSL_CONTAINER_BTREE_TEST_H_ | 
|  |  | 
|  | #include <algorithm> | 
|  | #include <cassert> | 
|  | #include <random> | 
|  | #include <string> | 
|  | #include <utility> | 
|  | #include <vector> | 
|  |  | 
|  | #include "absl/container/btree_map.h" | 
|  | #include "absl/container/btree_set.h" | 
|  | #include "absl/container/flat_hash_set.h" | 
|  | #include "absl/strings/cord.h" | 
|  | #include "absl/time/time.h" | 
|  |  | 
|  | namespace absl { | 
|  | ABSL_NAMESPACE_BEGIN | 
|  | namespace container_internal { | 
|  |  | 
|  | // Like remove_const but propagates the removal through std::pair. | 
|  | template <typename T> | 
|  | struct remove_pair_const { | 
|  | using type = typename std::remove_const<T>::type; | 
|  | }; | 
|  | template <typename T, typename U> | 
|  | struct remove_pair_const<std::pair<T, U> > { | 
|  | using type = std::pair<typename remove_pair_const<T>::type, | 
|  | typename remove_pair_const<U>::type>; | 
|  | }; | 
|  |  | 
|  | // Utility class to provide an accessor for a key given a value. The default | 
|  | // behavior is to treat the value as a pair and return the first element. | 
|  | template <typename K, typename V> | 
|  | struct KeyOfValue { | 
|  | struct type { | 
|  | const K& operator()(const V& p) const { return p.first; } | 
|  | }; | 
|  | }; | 
|  |  | 
|  | // Partial specialization of KeyOfValue class for when the key and value are | 
|  | // the same type such as in set<> and btree_set<>. | 
|  | template <typename K> | 
|  | struct KeyOfValue<K, K> { | 
|  | struct type { | 
|  | const K& operator()(const K& k) const { return k; } | 
|  | }; | 
|  | }; | 
|  |  | 
|  | inline char* GenerateDigits(char buf[16], unsigned val, unsigned maxval) { | 
|  | assert(val <= maxval); | 
|  | constexpr unsigned kBase = 64;  // avoid integer division. | 
|  | unsigned p = 15; | 
|  | buf[p--] = 0; | 
|  | while (maxval > 0) { | 
|  | buf[p--] = ' ' + (val % kBase); | 
|  | val /= kBase; | 
|  | maxval /= kBase; | 
|  | } | 
|  | return buf + p + 1; | 
|  | } | 
|  |  | 
|  | template <typename K> | 
|  | struct Generator { | 
|  | int maxval; | 
|  | explicit Generator(int m) : maxval(m) {} | 
|  | K operator()(int i) const { | 
|  | assert(i <= maxval); | 
|  | return K(i); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <> | 
|  | struct Generator<absl::Time> { | 
|  | int maxval; | 
|  | explicit Generator(int m) : maxval(m) {} | 
|  | absl::Time operator()(int i) const { return absl::FromUnixMillis(i); } | 
|  | }; | 
|  |  | 
|  | template <> | 
|  | struct Generator<std::string> { | 
|  | int maxval; | 
|  | explicit Generator(int m) : maxval(m) {} | 
|  | std::string operator()(int i) const { | 
|  | char buf[16]; | 
|  | return GenerateDigits(buf, i, maxval); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <> | 
|  | struct Generator<Cord> { | 
|  | int maxval; | 
|  | explicit Generator(int m) : maxval(m) {} | 
|  | Cord operator()(int i) const { | 
|  | char buf[16]; | 
|  | return Cord(GenerateDigits(buf, i, maxval)); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename T, typename U> | 
|  | struct Generator<std::pair<T, U> > { | 
|  | Generator<typename remove_pair_const<T>::type> tgen; | 
|  | Generator<typename remove_pair_const<U>::type> ugen; | 
|  |  | 
|  | explicit Generator(int m) : tgen(m), ugen(m) {} | 
|  | std::pair<T, U> operator()(int i) const { | 
|  | return std::make_pair(tgen(i), ugen(i)); | 
|  | } | 
|  | }; | 
|  |  | 
|  | // Generate n values for our tests and benchmarks. Value range is [0, maxval]. | 
|  | inline std::vector<int> GenerateNumbersWithSeed(int n, int maxval, int seed) { | 
|  | // NOTE: Some tests rely on generated numbers not changing between test runs. | 
|  | // We use std::minstd_rand0 because it is well-defined, but don't use | 
|  | // std::uniform_int_distribution because platforms use different algorithms. | 
|  | std::minstd_rand0 rng(seed); | 
|  |  | 
|  | std::vector<int> values; | 
|  | absl::flat_hash_set<int> unique_values; | 
|  | if (values.size() < n) { | 
|  | for (int i = values.size(); i < n; i++) { | 
|  | int value; | 
|  | do { | 
|  | value = static_cast<int>(rng()) % (maxval + 1); | 
|  | } while (!unique_values.insert(value).second); | 
|  |  | 
|  | values.push_back(value); | 
|  | } | 
|  | } | 
|  | return values; | 
|  | } | 
|  |  | 
|  | // Generates n values in the range [0, maxval]. | 
|  | template <typename V> | 
|  | std::vector<V> GenerateValuesWithSeed(int n, int maxval, int seed) { | 
|  | const std::vector<int> nums = GenerateNumbersWithSeed(n, maxval, seed); | 
|  | Generator<V> gen(maxval); | 
|  | std::vector<V> vec; | 
|  |  | 
|  | vec.reserve(n); | 
|  | for (int i = 0; i < n; i++) { | 
|  | vec.push_back(gen(nums[i])); | 
|  | } | 
|  |  | 
|  | return vec; | 
|  | } | 
|  |  | 
|  | }  // namespace container_internal | 
|  | ABSL_NAMESPACE_END | 
|  | }  // namespace absl | 
|  |  | 
|  | #endif  // ABSL_CONTAINER_BTREE_TEST_H_ |