/root/bitcoin/src/test/fuzz/minisketch.cpp
Line | Count | Source |
1 | | // Copyright (c) 2021-present 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 | 2.67k | { |
19 | 2.67k | return Assert(Minisketch(32, impl, capacity)); |
20 | 2.67k | } |
21 | | |
22 | | } // namespace |
23 | | |
24 | | FUZZ_TARGET(minisketch) |
25 | 672 | { |
26 | 672 | FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()}; |
27 | | |
28 | 672 | const auto capacity{fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 200)}; |
29 | 672 | const uint32_t impl{fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, Minisketch::MaxImplementation())}; |
30 | 672 | if (!Minisketch::ImplementationSupported(32, impl)) return; Branch (30:9): [True: 3, False: 669]
|
31 | | |
32 | 669 | Minisketch sketch_a{MakeFuzzMinisketch32(capacity, impl)}; |
33 | 669 | Minisketch sketch_b{MakeFuzzMinisketch32(capacity, impl)}; |
34 | 669 | sketch_a.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); |
35 | 669 | sketch_b.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); |
36 | | |
37 | | // Fill two sets and keep the difference in a map |
38 | 669 | std::map<uint32_t, bool> diff; |
39 | 52.1k | LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 10000) { |
40 | 52.1k | const auto entry{fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(1, std::numeric_limits<uint32_t>::max() - 1)}; |
41 | 52.1k | const auto KeepDiff{[&] { |
42 | 50.0k | bool& mut{diff[entry]}; |
43 | 50.0k | mut = !mut; |
44 | 50.0k | }}; |
45 | 52.1k | CallOneOf( |
46 | 52.1k | fuzzed_data_provider, |
47 | 52.1k | [&] { |
48 | 31.7k | sketch_a.Add(entry); |
49 | 31.7k | KeepDiff(); |
50 | 31.7k | }, |
51 | 52.1k | [&] { |
52 | 18.2k | sketch_b.Add(entry); |
53 | 18.2k | KeepDiff(); |
54 | 18.2k | }, |
55 | 52.1k | [&] { |
56 | 2.16k | sketch_a.Add(entry); |
57 | 2.16k | sketch_b.Add(entry); |
58 | 2.16k | }); |
59 | 52.1k | } |
60 | 22.4k | const auto num_diff{std::accumulate(diff.begin(), diff.end(), size_t{0}, [](auto n, const auto& e) { return n + e.second; })}; |
61 | | |
62 | 669 | Minisketch sketch_ar{MakeFuzzMinisketch32(capacity, impl)}; |
63 | 669 | Minisketch sketch_br{MakeFuzzMinisketch32(capacity, impl)}; |
64 | 669 | sketch_ar.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); |
65 | 669 | sketch_br.SetSeed(fuzzed_data_provider.ConsumeIntegral<uint64_t>()); |
66 | | |
67 | 669 | sketch_ar.Deserialize(sketch_a.Serialize()); |
68 | 669 | sketch_br.Deserialize(sketch_b.Serialize()); |
69 | | |
70 | 669 | Minisketch sketch_diff{std::move(fuzzed_data_provider.ConsumeBool() ? sketch_a : sketch_ar)}; Branch (70:38): [True: 193, False: 476]
|
71 | 669 | sketch_diff.Merge(fuzzed_data_provider.ConsumeBool() ? sketch_b : sketch_br); Branch (71:23): [True: 121, False: 548]
|
72 | | |
73 | 669 | if (capacity >= num_diff) { Branch (73:9): [True: 656, False: 13]
|
74 | 656 | const auto max_elements{fuzzed_data_provider.ConsumeIntegralInRange<size_t>(num_diff, capacity)}; |
75 | 656 | const auto dec{*Assert(sketch_diff.Decode(max_elements))}; |
76 | 656 | Assert(dec.size() == num_diff); |
77 | 20.7k | for (auto d : dec) { Branch (77:21): [True: 20.7k, False: 656]
|
78 | 20.7k | Assert(diff.at(d)); |
79 | 20.7k | } |
80 | 656 | } |
81 | 669 | } |