/root/bitcoin/src/test/fuzz/minisketch.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2021 The Bitcoin Core developers |
2 | | // Distributed under the MIT software license, see the accompanying |
3 | | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
4 | | |
5 | | #include <minisketch.h> |
6 | | #include <node/minisketchwrapper.h> |
7 | | #include <test/fuzz/FuzzedDataProvider.h> |
8 | | #include <test/fuzz/fuzz.h> |
9 | | #include <test/fuzz/util.h> |
10 | | #include <util/check.h> |
11 | | |
12 | | #include <map> |
13 | | #include <numeric> |
14 | | |
15 | | namespace { |
16 | | |
17 | | Minisketch MakeFuzzMinisketch32(size_t capacity, uint32_t impl) |
18 | 0 | { |
19 | 0 | return Assert(Minisketch(32, impl, capacity)); |
20 | 0 | } |
21 | | |
22 | | } // namespace |
23 | | |
24 | | FUZZ_TARGET(minisketch) |
25 | 0 | { |
26 | 0 | FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; |
27 | |
|
28 | 0 | const auto capacity{fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 200)}; |
29 | 0 | const uint32_t impl{fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, Minisketch::MaxImplementation())}; |
30 | 0 | if (!Minisketch::ImplementationSupported(32, impl)) return; |
31 | | |
32 | 0 | Minisketch sketch_a{MakeFuzzMinisketch32(capacity, impl)}; |
33 | 0 | Minisketch sketch_b{MakeFuzzMinisketch32(capacity, impl)}; |
34 | 0 | sketch_a.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); |
35 | 0 | sketch_b.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); |
36 | | |
37 | | // Fill two sets and keep the difference in a map |
38 | 0 | std::map<uint32_t, bool> diff; |
39 | 0 | LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) |
40 | 0 | { |
41 | 0 | const auto entry{fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(1, std::numeric_limits<uint32_t>::max() - 1)}; |
42 | 0 | const auto KeepDiff{[&] { |
43 | 0 | bool& mut{diff[entry]}; |
44 | 0 | mut = !mut; |
45 | 0 | }}; |
46 | 0 | CallOneOf( |
47 | 0 | fuzzed_data_provider, |
48 | 0 | [&] { |
49 | 0 | sketch_a.Add(entry); |
50 | 0 | KeepDiff(); |
51 | 0 | }, |
52 | 0 | [&] { |
53 | 0 | sketch_b.Add(entry); |
54 | 0 | KeepDiff(); |
55 | 0 | }, |
56 | 0 | [&] { |
57 | 0 | sketch_a.Add(entry); |
58 | 0 | sketch_b.Add(entry); |
59 | 0 | }); |
60 | 0 | } |
61 | 0 | const auto num_diff{std::accumulate(diff.begin(), diff.end(), size_t{0}, [](auto n, const auto& e) { return n + e.second; })}; |
62 | |
|
63 | 0 | Minisketch sketch_ar{MakeFuzzMinisketch32(capacity, impl)}; |
64 | 0 | Minisketch sketch_br{MakeFuzzMinisketch32(capacity, impl)}; |
65 | 0 | sketch_ar.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); |
66 | 0 | sketch_br.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); |
67 | |
|
68 | 0 | sketch_ar.Deserialize(sketch_a.Serialize()); |
69 | 0 | sketch_br.Deserialize(sketch_b.Serialize()); |
70 | |
|
71 | 0 | Minisketch sketch_diff{std::move(fuzzed_data_provider.ConsumeBool() ? sketch_a : sketch_ar)}; |
72 | 0 | sketch_diff.Merge(fuzzed_data_provider.ConsumeBool() ? sketch_b : sketch_br); |
73 | |
|
74 | 0 | if (capacity >= num_diff) { |
75 | 0 | const auto max_elements{fuzzed_data_provider.ConsumeIntegralInRange<size_t>(num_diff, capacity)}; |
76 | 0 | const auto dec{*Assert(sketch_diff.Decode(max_elements))}; |
77 | 0 | Assert(dec.size() == num_diff); |
78 | 0 | for (auto d : dec) { |
79 | 0 | Assert(diff.at(d)); |
80 | 0 | } |
81 | 0 | } |
82 | 0 | } |