Test properties of sketches with random elements put in. */
| 124 | |
| 125 | /** Test properties of sketches with random elements put in. */ |
| 126 | void TestRandomized(uint32_t bits, size_t max_capacity, size_t iter) { |
| 127 | std::random_device rnd; |
| 128 | std::uniform_int_distribution<uint64_t> capacity_dist(0, std::min<uint64_t>(std::numeric_limits<uint64_t>::max() >> (64 - bits), max_capacity)); |
| 129 | std::uniform_int_distribution<uint64_t> element_dist(1, std::numeric_limits<uint64_t>::max() >> (64 - bits)); |
| 130 | std::uniform_int_distribution<uint64_t> rand64(0, std::numeric_limits<uint64_t>::max()); |
| 131 | std::uniform_int_distribution<int64_t> size_offset_dist(-3, 3); |
| 132 | |
| 133 | std::vector<uint64_t> decode_0; |
| 134 | std::vector<uint64_t> decode_other; |
| 135 | std::vector<uint64_t> decode_temp; |
| 136 | std::vector<uint64_t> elements; |
| 137 | |
| 138 | for (size_t i = 0; i < iter; ++i) { |
| 139 | // Determine capacity, and construct Minisketch objects for all implementations. |
| 140 | uint64_t capacity = capacity_dist(rnd); |
| 141 | auto sketches = CreateSketches(bits, capacity); |
| 142 | // Sanity checks |
| 143 | if (sketches.empty()) return; |
| 144 | for (size_t impl = 0; impl < sketches.size(); ++impl) { |
| 145 | CHECK(sketches[impl].GetBits() == bits); |
| 146 | CHECK(sketches[impl].GetCapacity() == capacity); |
| 147 | CHECK(sketches[impl].GetSerializedSize() == sketches[0].GetSerializedSize()); |
| 148 | } |
| 149 | // Determine the number of elements, and create a vector to store them in. |
| 150 | size_t element_count = std::max<int64_t>(0, std::max<int64_t>(0, capacity + size_offset_dist(rnd))); |
| 151 | elements.resize(element_count); |
| 152 | // Add the elements to all sketches |
| 153 | for (size_t j = 0; j < element_count; ++j) { |
| 154 | uint64_t elem = element_dist(rnd); |
| 155 | CHECK(elem != 0); |
| 156 | elements[j] = elem; |
| 157 | for (auto& sketch : sketches) sketch.Add(elem); |
| 158 | } |
| 159 | // Remove pairs of duplicates in elements, as they cancel out. |
| 160 | std::sort(elements.begin(), elements.end()); |
| 161 | size_t real_element_count = element_count; |
| 162 | for (size_t pos = 0; pos + 1 < elements.size(); ++pos) { |
| 163 | if (elements[pos] == elements[pos + 1]) { |
| 164 | real_element_count -= 2; |
| 165 | // Set both elements to 0; afterwards we will move these to the end. |
| 166 | elements[pos] = 0; |
| 167 | elements[pos + 1] = 0; |
| 168 | ++pos; |
| 169 | } |
| 170 | } |
| 171 | if (real_element_count < element_count) { |
| 172 | // Move all introduced zeroes (masking duplicates) to the end. |
| 173 | std::sort(elements.begin(), elements.end(), [](uint64_t a, uint64_t b) { return a != b && (b == 0 || (a != 0 && a < b)); }); |
| 174 | CHECK(elements[real_element_count] == 0); |
| 175 | elements.resize(real_element_count); |
| 176 | } |
| 177 | // Create and compare serializations |
| 178 | auto serialized_0 = sketches[0].Serialize(); |
| 179 | for (size_t impl = 1; impl < sketches.size(); ++impl) { |
| 180 | auto serialized_other = sketches[impl].Serialize(); |
| 181 | CHECK(serialized_other == serialized_0); |
| 182 | } |
| 183 | // Deserialize and reserialize them |
no test coverage detected