1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <stdlib.h>
16
17 #include <algorithm>
18 #include <functional>
19 #include <map>
20 #include <utility>
21
22 #include "src/core/lib/avl/avl.h"
23 #include "src/libfuzzer/libfuzzer_macro.h"
24 #include "test/core/avl/avl_fuzzer.pb.h"
25
26 bool squelch = true;
27 bool leak_check = true;
28
29 namespace grpc_core {
30
31 class Fuzzer {
32 public:
Fuzzer()33 Fuzzer() { CheckEqual(); }
~Fuzzer()34 ~Fuzzer() { CheckEqual(); }
Run(const avl_fuzzer::Action & action)35 void Run(const avl_fuzzer::Action& action) {
36 switch (action.action_case()) {
37 case avl_fuzzer::Action::kSet:
38 avl_ = avl_.Add(action.key(), action.set());
39 map_[action.key()] = action.set();
40 break;
41 case avl_fuzzer::Action::kDel:
42 avl_ = avl_.Remove(action.key());
43 map_.erase(action.key());
44 break;
45 case avl_fuzzer::Action::kGet: {
46 auto* p = avl_.Lookup(action.key());
47 auto it = map_.find(action.key());
48 if (it == map_.end() && p != nullptr) abort();
49 if (it != map_.end() && p == nullptr) abort();
50 if (it != map_.end() && it->second != *p) abort();
51 } break;
52 case avl_fuzzer::Action::ACTION_NOT_SET:
53 break;
54 }
55 }
56
57 private:
CheckEqual()58 void CheckEqual() {
59 auto it = map_.begin();
60 avl_.ForEach([&](int key, int value) {
61 if (it == map_.end()) abort();
62 if (it->first != key) abort();
63 if (it->second != value) abort();
64 ++it;
65 });
66 if (it != map_.end()) abort();
67 }
68
69 AVL<int, int> avl_;
70 std::map<int, int> map_;
71 };
72
73 template <typename RepeatedField>
AvlFromProto(const RepeatedField & p)74 AVL<int, int> AvlFromProto(const RepeatedField& p) {
75 AVL<int, int> a;
76 for (const auto& kv : p) {
77 a = a.Add(kv.key(), kv.value());
78 }
79 return a;
80 }
81
82 template <typename RepeatedField>
MapFromProto(const RepeatedField & p)83 std::map<int, int> MapFromProto(const RepeatedField& p) {
84 std::map<int, int> a;
85 for (const auto& kv : p) {
86 a[kv.key()] = kv.value();
87 }
88 return a;
89 }
90
91 } // namespace grpc_core
92
DEFINE_PROTO_FUZZER(const avl_fuzzer::Msg & msg)93 DEFINE_PROTO_FUZZER(const avl_fuzzer::Msg& msg) {
94 grpc_core::Fuzzer fuzzer;
95 for (const auto& action : msg.actions()) {
96 grpc_core::Fuzzer().Run(action);
97 }
98
99 for (const auto& cmp : msg.compares()) {
100 auto left_avl = grpc_core::AvlFromProto(cmp.left());
101 auto left_map = grpc_core::MapFromProto(cmp.left());
102 auto right_avl = grpc_core::AvlFromProto(cmp.right());
103 auto right_map = grpc_core::MapFromProto(cmp.right());
104 if ((left_avl == right_avl) != (left_map == right_map)) abort();
105 if ((left_avl < right_avl) != (left_map < right_map)) abort();
106 }
107 }
108