| // Copyright 2022 Google LLC |
| // |
| // 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. |
| |
| // Tests of character and string domains. |
| |
| #include <cctype> |
| #include <deque> |
| #include <optional> |
| #include <string> |
| #include <string_view> |
| #include <vector> |
| |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| #include "absl/container/flat_hash_set.h" |
| #include "absl/random/random.h" |
| #include "./fuzztest/domain.h" |
| #include "./domain_tests/domain_testing.h" |
| |
| namespace fuzztest { |
| namespace { |
| |
| using ::testing::AllOf; |
| using ::testing::Contains; |
| using ::testing::Each; |
| using ::testing::Eq; |
| using ::testing::Ge; |
| using ::testing::Gt; |
| using ::testing::IsTrue; |
| using ::testing::Lt; |
| using ::testing::Matches; |
| using ::testing::ResultOf; |
| using ::testing::SizeIs; |
| |
| template <typename T> |
| class HandleTypeTest : public testing::Test {}; |
| |
| using HandleTypeTypes = |
| testing::Types<std::string_view, std::vector<std::string_view>>; |
| |
| TYPED_TEST_SUITE(HandleTypeTest, HandleTypeTypes); |
| |
| TYPED_TEST(HandleTypeTest, Arbitrary) { |
| absl::BitGen bitgen; |
| |
| Domain<TypeParam> domain = Arbitrary<TypeParam>(); |
| |
| // Handle types contain pointers/references to the corpus_type so we have to |
| // handle them with care. |
| // We use a std::deque to make sure we don't invalidate them. |
| std::deque<Value<Domain<TypeParam>>> values; |
| |
| Set<TypeParam> unique; |
| |
| for (int i = 0; i < 100; ++i) { |
| values.emplace_back(domain, bitgen); |
| unique.insert(values.back().user_value); |
| } |
| |
| VerifyRoundTripThroughConversion(values, domain); |
| |
| // Some minimal checking to make sure we are generating many values. |
| EXPECT_THAT(unique, SizeIs(Gt(10))); |
| } |
| |
| TYPED_TEST(HandleTypeTest, InitGeneratesSeeds) { |
| auto domain = Arbitrary<TypeParam>(); |
| absl::BitGen bitgen; |
| auto seed = Value(domain, bitgen); |
| seed.RandomizeByRepeatedMutation(domain, bitgen); |
| domain.WithSeeds({seed.user_value}); |
| |
| EXPECT_THAT(GenerateInitialValues(domain, 1000), Contains(seed)); |
| } |
| |
| TEST(Domain, Forwarding) { |
| absl::BitGen bitgen; |
| |
| Domain<char> domain = InRange('a', 'z'); |
| absl::flat_hash_set<char> elems; |
| while (elems.size() < 'z' - 'a' + 1) { |
| elems.insert(Value(domain, bitgen).user_value); |
| } |
| |
| elems.clear(); |
| Value c(domain, bitgen); |
| while (elems.size() < 'z' - 'a' + 1) { |
| c.Mutate(domain, bitgen, false); |
| elems.insert(c.user_value); |
| } |
| } |
| |
| TEST(Domain, NonZeroChar) { |
| CheckValues(GenerateValues(NonZeroChar()), [](char c) { return c != '\0'; }); |
| } |
| |
| TEST(Domain, NumericChar) { |
| CheckValues(GenerateValues(NumericChar(), 5, 5), |
| [](char c) { return std::isdigit(c); }); |
| } |
| |
| TEST(Domain, LowerChar) { |
| CheckValues(GenerateValues(LowerChar(), 10, 10), |
| [](char c) { return std::islower(c); }); |
| } |
| |
| TEST(Domain, UpperChar) { |
| CheckValues(GenerateValues(UpperChar(), 10, 10), |
| [](char c) { return std::isupper(c); }); |
| } |
| |
| TEST(Domain, AlphaChar) { |
| CheckValues(GenerateValues(AlphaChar(), 20, 20), |
| [](char c) { return std::isalpha(c); }); |
| } |
| |
| TEST(Domain, AlphaNumericChar) { |
| CheckValues(GenerateValues(AlphaNumericChar(), 30, 30), |
| [](char c) { return std::isalnum(c); }); |
| } |
| |
| TEST(Domain, PrintableAsciiChar) { |
| CheckValues(GenerateValues(PrintableAsciiChar(), 40, 40), |
| [](char c) { return std::isprint(c); }); |
| } |
| |
| TEST(Domain, AsciiChar) { |
| CheckValues(GenerateValues(AsciiChar()), Matches(AllOf(Ge(0), Lt(128)))); |
| } |
| |
| TEST(Domain, AsciiString) { |
| Domain<std::string> domain = AsciiString(); |
| for (const auto& value : GenerateValues(domain)) { |
| for (int c : value.user_value) { |
| ASSERT_GE(c, 0); |
| ASSERT_LT(c, 128); |
| } |
| } |
| } |
| |
| TEST(Domain, PrintableAsciiString) { |
| Domain<std::string> domain = PrintableAsciiString(); |
| for (const auto& value : GenerateValues(domain)) { |
| for (int c : value.user_value) { |
| EXPECT_TRUE(isprint(c)); |
| } |
| } |
| } |
| } // namespace |
| } // namespace fuzztest |