Test properties by exhaustively decoding all 2**(bits*capacity) sketches * with specified capacity and bits. */
| 47 | /** Test properties by exhaustively decoding all 2**(bits*capacity) sketches |
| 48 | * with specified capacity and bits. */ |
| 49 | void TestExhaustive(uint32_t bits, size_t capacity) { |
| 50 | auto sketches = CreateSketches(bits, capacity); |
| 51 | if (sketches.empty()) return; |
| 52 | auto sketches_rebuild = CreateSketches(bits, capacity); |
| 53 | |
| 54 | std::vector<unsigned char> serialized; |
| 55 | std::vector<unsigned char> serialized_empty; |
| 56 | std::vector<uint64_t> counts; //!< counts[i] = number of results with i elements |
| 57 | std::vector<uint64_t> elements_0; //!< Result vector for elements for impl=0 |
| 58 | std::vector<uint64_t> elements_other; //!< Result vector for elements for other impls |
| 59 | std::vector<uint64_t> elements_too_small; //!< Result vector that's too small |
| 60 | |
| 61 | counts.resize(capacity + 1); |
| 62 | serialized.resize(sketches[0].GetSerializedSize()); |
| 63 | serialized_empty.resize(sketches[0].GetSerializedSize()); |
| 64 | |
| 65 | // Iterate over all (bits)-bit sketches with (capacity) syndromes. |
| 66 | for (uint64_t x = 0; (x >> (bits * capacity)) == 0; ++x) { |
| 67 | // Construct the serialization. |
| 68 | for (size_t i = 0; i < serialized.size(); ++i) { |
| 69 | serialized[i] = (x >> (i * 8)) & 0xFF; |
| 70 | } |
| 71 | |
| 72 | // Compute all the solutions |
| 73 | sketches[0].Deserialize(serialized); |
| 74 | elements_0.resize(64); |
| 75 | bool decodable_0 = sketches[0].Decode(elements_0); |
| 76 | std::sort(elements_0.begin(), elements_0.end()); |
| 77 | |
| 78 | // Verify that decoding with other implementations agrees. |
| 79 | for (size_t impl = 1; impl < sketches.size(); ++impl) { |
| 80 | sketches[impl].Deserialize(serialized); |
| 81 | elements_other.resize(64); |
| 82 | bool decodable_other = sketches[impl].Decode(elements_other); |
| 83 | CHECK(decodable_other == decodable_0); |
| 84 | std::sort(elements_other.begin(), elements_other.end()); |
| 85 | CHECK(elements_other == elements_0); |
| 86 | } |
| 87 | |
| 88 | // If there are solutions: |
| 89 | if (decodable_0) { |
| 90 | if (!elements_0.empty()) { |
| 91 | // Decoding with limit one less than the number of elements should fail. |
| 92 | elements_too_small.resize(elements_0.size() - 1); |
| 93 | for (size_t impl = 0; impl < sketches.size(); ++impl) { |
| 94 | CHECK(!sketches[impl].Decode(elements_too_small)); |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | // Reconstruct the sketch from the solutions. |
| 99 | for (size_t impl = 0; impl < sketches.size(); ++impl) { |
| 100 | // Clear the sketch. |
| 101 | sketches_rebuild[impl].Deserialize(serialized_empty); |
| 102 | // Load all decoded elements into it. |
| 103 | for (uint64_t elem : elements_0) { |
| 104 | CHECK(elem != 0); |
| 105 | CHECK(elem >> bits == 0); |
| 106 | sketches_rebuild[impl].Add(elem); |
no test coverage detected