1fd4e5da5Sopenharmony_ci// Copyright (c) 2019 Google LLC 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#include <set> 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include "source/fuzz/equivalence_relation.h" 18fd4e5da5Sopenharmony_ci 19fd4e5da5Sopenharmony_ci#include "gmock/gmock.h" 20fd4e5da5Sopenharmony_ci#include "gtest/gtest.h" 21fd4e5da5Sopenharmony_ci 22fd4e5da5Sopenharmony_cinamespace spvtools { 23fd4e5da5Sopenharmony_cinamespace fuzz { 24fd4e5da5Sopenharmony_cinamespace { 25fd4e5da5Sopenharmony_ci 26fd4e5da5Sopenharmony_cistruct UInt32Equals { 27fd4e5da5Sopenharmony_ci bool operator()(const uint32_t* first, const uint32_t* second) const { 28fd4e5da5Sopenharmony_ci return *first == *second; 29fd4e5da5Sopenharmony_ci } 30fd4e5da5Sopenharmony_ci}; 31fd4e5da5Sopenharmony_ci 32fd4e5da5Sopenharmony_cistruct UInt32Hash { 33fd4e5da5Sopenharmony_ci size_t operator()(const uint32_t* element) const { 34fd4e5da5Sopenharmony_ci return static_cast<size_t>(*element); 35fd4e5da5Sopenharmony_ci } 36fd4e5da5Sopenharmony_ci}; 37fd4e5da5Sopenharmony_ci 38fd4e5da5Sopenharmony_cistd::vector<uint32_t> ToUIntVector( 39fd4e5da5Sopenharmony_ci const std::vector<const uint32_t*>& pointers) { 40fd4e5da5Sopenharmony_ci std::vector<uint32_t> result; 41fd4e5da5Sopenharmony_ci for (auto pointer : pointers) { 42fd4e5da5Sopenharmony_ci result.push_back(*pointer); 43fd4e5da5Sopenharmony_ci } 44fd4e5da5Sopenharmony_ci return result; 45fd4e5da5Sopenharmony_ci} 46fd4e5da5Sopenharmony_ci 47fd4e5da5Sopenharmony_ciTEST(EquivalenceRelationTest, BasicTest) { 48fd4e5da5Sopenharmony_ci EquivalenceRelation<uint32_t, UInt32Hash, UInt32Equals> relation; 49fd4e5da5Sopenharmony_ci ASSERT_TRUE(relation.GetAllKnownValues().empty()); 50fd4e5da5Sopenharmony_ci 51fd4e5da5Sopenharmony_ci for (uint32_t element = 0; element < 100; element++) { 52fd4e5da5Sopenharmony_ci relation.Register(element); 53fd4e5da5Sopenharmony_ci } 54fd4e5da5Sopenharmony_ci 55fd4e5da5Sopenharmony_ci for (uint32_t element = 2; element < 80; element += 2) { 56fd4e5da5Sopenharmony_ci relation.MakeEquivalent(0, element); 57fd4e5da5Sopenharmony_ci relation.MakeEquivalent(element - 1, element + 1); 58fd4e5da5Sopenharmony_ci } 59fd4e5da5Sopenharmony_ci 60fd4e5da5Sopenharmony_ci for (uint32_t element = 82; element < 100; element += 2) { 61fd4e5da5Sopenharmony_ci relation.MakeEquivalent(80, element); 62fd4e5da5Sopenharmony_ci relation.MakeEquivalent(element - 1, element + 1); 63fd4e5da5Sopenharmony_ci } 64fd4e5da5Sopenharmony_ci 65fd4e5da5Sopenharmony_ci relation.MakeEquivalent(78, 80); 66fd4e5da5Sopenharmony_ci 67fd4e5da5Sopenharmony_ci std::vector<uint32_t> class1; 68fd4e5da5Sopenharmony_ci for (uint32_t element = 0; element < 98; element += 2) { 69fd4e5da5Sopenharmony_ci ASSERT_TRUE(relation.IsEquivalent(0, element)); 70fd4e5da5Sopenharmony_ci ASSERT_TRUE(relation.IsEquivalent(element, element + 2)); 71fd4e5da5Sopenharmony_ci class1.push_back(element); 72fd4e5da5Sopenharmony_ci } 73fd4e5da5Sopenharmony_ci class1.push_back(98); 74fd4e5da5Sopenharmony_ci 75fd4e5da5Sopenharmony_ci ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(0)), 76fd4e5da5Sopenharmony_ci testing::WhenSorted(class1)); 77fd4e5da5Sopenharmony_ci ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(4)), 78fd4e5da5Sopenharmony_ci testing::WhenSorted(class1)); 79fd4e5da5Sopenharmony_ci ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(40)), 80fd4e5da5Sopenharmony_ci testing::WhenSorted(class1)); 81fd4e5da5Sopenharmony_ci 82fd4e5da5Sopenharmony_ci std::vector<uint32_t> class2; 83fd4e5da5Sopenharmony_ci for (uint32_t element = 1; element < 79; element += 2) { 84fd4e5da5Sopenharmony_ci ASSERT_TRUE(relation.IsEquivalent(1, element)); 85fd4e5da5Sopenharmony_ci ASSERT_TRUE(relation.IsEquivalent(element, element + 2)); 86fd4e5da5Sopenharmony_ci class2.push_back(element); 87fd4e5da5Sopenharmony_ci } 88fd4e5da5Sopenharmony_ci class2.push_back(79); 89fd4e5da5Sopenharmony_ci ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(1)), 90fd4e5da5Sopenharmony_ci testing::WhenSorted(class2)); 91fd4e5da5Sopenharmony_ci ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(11)), 92fd4e5da5Sopenharmony_ci testing::WhenSorted(class2)); 93fd4e5da5Sopenharmony_ci ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(31)), 94fd4e5da5Sopenharmony_ci testing::WhenSorted(class2)); 95fd4e5da5Sopenharmony_ci 96fd4e5da5Sopenharmony_ci std::vector<uint32_t> class3; 97fd4e5da5Sopenharmony_ci for (uint32_t element = 81; element < 99; element += 2) { 98fd4e5da5Sopenharmony_ci ASSERT_TRUE(relation.IsEquivalent(81, element)); 99fd4e5da5Sopenharmony_ci ASSERT_TRUE(relation.IsEquivalent(element, element + 2)); 100fd4e5da5Sopenharmony_ci class3.push_back(element); 101fd4e5da5Sopenharmony_ci } 102fd4e5da5Sopenharmony_ci class3.push_back(99); 103fd4e5da5Sopenharmony_ci ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(81)), 104fd4e5da5Sopenharmony_ci testing::WhenSorted(class3)); 105fd4e5da5Sopenharmony_ci ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(91)), 106fd4e5da5Sopenharmony_ci testing::WhenSorted(class3)); 107fd4e5da5Sopenharmony_ci ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(99)), 108fd4e5da5Sopenharmony_ci testing::WhenSorted(class3)); 109fd4e5da5Sopenharmony_ci 110fd4e5da5Sopenharmony_ci bool first = true; 111fd4e5da5Sopenharmony_ci std::vector<const uint32_t*> previous_class; 112fd4e5da5Sopenharmony_ci for (auto representative : relation.GetEquivalenceClassRepresentatives()) { 113fd4e5da5Sopenharmony_ci std::vector<const uint32_t*> current_class = 114fd4e5da5Sopenharmony_ci relation.GetEquivalenceClass(*representative); 115fd4e5da5Sopenharmony_ci ASSERT_TRUE(std::find(current_class.begin(), current_class.end(), 116fd4e5da5Sopenharmony_ci representative) != current_class.end()); 117fd4e5da5Sopenharmony_ci if (!first) { 118fd4e5da5Sopenharmony_ci ASSERT_TRUE(std::find(previous_class.begin(), previous_class.end(), 119fd4e5da5Sopenharmony_ci representative) == previous_class.end()); 120fd4e5da5Sopenharmony_ci } 121fd4e5da5Sopenharmony_ci previous_class = current_class; 122fd4e5da5Sopenharmony_ci first = false; 123fd4e5da5Sopenharmony_ci } 124fd4e5da5Sopenharmony_ci} 125fd4e5da5Sopenharmony_ci 126fd4e5da5Sopenharmony_ciTEST(EquivalenceRelationTest, DeterministicEquivalenceClassOrder) { 127fd4e5da5Sopenharmony_ci EquivalenceRelation<uint32_t, UInt32Hash, UInt32Equals> relation1; 128fd4e5da5Sopenharmony_ci EquivalenceRelation<uint32_t, UInt32Hash, UInt32Equals> relation2; 129fd4e5da5Sopenharmony_ci 130fd4e5da5Sopenharmony_ci for (uint32_t i = 0; i < 1000; ++i) { 131fd4e5da5Sopenharmony_ci relation1.Register(i); 132fd4e5da5Sopenharmony_ci relation2.Register(i); 133fd4e5da5Sopenharmony_ci } 134fd4e5da5Sopenharmony_ci 135fd4e5da5Sopenharmony_ci for (uint32_t i = 0; i < 1000; ++i) { 136fd4e5da5Sopenharmony_ci if (i >= 10) { 137fd4e5da5Sopenharmony_ci relation1.MakeEquivalent(i, i - 10); 138fd4e5da5Sopenharmony_ci relation2.MakeEquivalent(i, i - 10); 139fd4e5da5Sopenharmony_ci } 140fd4e5da5Sopenharmony_ci } 141fd4e5da5Sopenharmony_ci 142fd4e5da5Sopenharmony_ci // We constructed the equivalence relations in the same way, so we would like 143fd4e5da5Sopenharmony_ci // them to have identical representatives, and identically-ordered equivalence 144fd4e5da5Sopenharmony_ci // classes per representative. 145fd4e5da5Sopenharmony_ci ASSERT_THAT(ToUIntVector(relation1.GetEquivalenceClassRepresentatives()), 146fd4e5da5Sopenharmony_ci ToUIntVector(relation2.GetEquivalenceClassRepresentatives())); 147fd4e5da5Sopenharmony_ci for (auto representative : relation1.GetEquivalenceClassRepresentatives()) { 148fd4e5da5Sopenharmony_ci ASSERT_THAT(ToUIntVector(relation1.GetEquivalenceClass(*representative)), 149fd4e5da5Sopenharmony_ci ToUIntVector(relation2.GetEquivalenceClass(*representative))); 150fd4e5da5Sopenharmony_ci } 151fd4e5da5Sopenharmony_ci} 152fd4e5da5Sopenharmony_ci 153fd4e5da5Sopenharmony_ci} // namespace 154fd4e5da5Sopenharmony_ci} // namespace fuzz 155fd4e5da5Sopenharmony_ci} // namespace spvtools 156