xref: /aosp_15_r20/external/grpc-grpc/test/core/avl/avl_fuzzer.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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