// Copyright 2021 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #include #include "src/core/lib/avl/avl.h" #include "src/libfuzzer/libfuzzer_macro.h" #include "test/core/avl/avl_fuzzer.pb.h" bool squelch = true; bool leak_check = true; namespace grpc_core { class Fuzzer { public: Fuzzer() { CheckEqual(); } ~Fuzzer() { CheckEqual(); } void Run(const avl_fuzzer::Action& action) { switch (action.action_case()) { case avl_fuzzer::Action::kSet: avl_ = avl_.Add(action.key(), action.set()); map_[action.key()] = action.set(); break; case avl_fuzzer::Action::kDel: avl_ = avl_.Remove(action.key()); map_.erase(action.key()); break; case avl_fuzzer::Action::kGet: { auto* p = avl_.Lookup(action.key()); auto it = map_.find(action.key()); if (it == map_.end() && p != nullptr) abort(); if (it != map_.end() && p == nullptr) abort(); if (it != map_.end() && it->second != *p) abort(); } break; case avl_fuzzer::Action::ACTION_NOT_SET: break; } } private: void CheckEqual() { auto it = map_.begin(); avl_.ForEach([&](int key, int value) { if (it == map_.end()) abort(); if (it->first != key) abort(); if (it->second != value) abort(); ++it; }); if (it != map_.end()) abort(); } AVL avl_; std::map map_; }; template AVL AvlFromProto(const RepeatedField& p) { AVL a; for (const auto& kv : p) { a = a.Add(kv.key(), kv.value()); } return a; } template std::map MapFromProto(const RepeatedField& p) { std::map a; for (const auto& kv : p) { a[kv.key()] = kv.value(); } return a; } } // namespace grpc_core DEFINE_PROTO_FUZZER(const avl_fuzzer::Msg& msg) { grpc_core::Fuzzer fuzzer; for (const auto& action : msg.actions()) { grpc_core::Fuzzer().Run(action); } for (const auto& cmp : msg.compares()) { auto left_avl = grpc_core::AvlFromProto(cmp.left()); auto left_map = grpc_core::MapFromProto(cmp.left()); auto right_avl = grpc_core::AvlFromProto(cmp.right()); auto right_map = grpc_core::MapFromProto(cmp.right()); if ((left_avl == right_avl) != (left_map == right_map)) abort(); if ((left_avl < right_avl) != (left_map < right_map)) abort(); } }