Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions domain_tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,11 @@ cc_test(
srcs = ["bitgen_ref_domain_test.cc"],
deps = [
":domain_testing",
"@abseil-cpp//absl/container:flat_hash_set",
"@abseil-cpp//absl/random",
"@abseil-cpp//absl/random:bit_gen_ref",
"@com_google_fuzztest//fuzztest:domain_core",
"@com_google_fuzztest//fuzztest/internal:printer",
"@googletest//:gtest_main",
],
)
Expand Down
16 changes: 16 additions & 0 deletions domain_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,22 @@ fuzztest_cc_test(
GTest::gmock_main
)

fuzztest_cc_test(
NAME
bitgen_ref_domain_test
SRCS
"bitgen_ref_domain_test.cc"
DEPS
fuzztest::domain_testing
absl::flat_hash_set
absl::random_bit_gen_ref
absl::random_random
fuzztest::domain_core
fuzztest::meta
fuzztest::printer
GTest::gmock_main
)

fuzztest_cc_test(
NAME
container_combinators_test
Expand Down
55 changes: 38 additions & 17 deletions domain_tests/bitgen_ref_domain_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include <string>
#include <vector>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/container/flat_hash_set.h"
#include "absl/random/bit_gen_ref.h"
#include "absl/random/random.h"
#include "./fuzztest/domain_core.h"
#include "./domain_tests/domain_testing.h"
#include "./fuzztest/internal/printer.h"

namespace fuzztest {
namespace {
Expand All @@ -27,36 +31,53 @@ TEST(BitGenRefDomainTest, DistinctVariatesGeneratedByCallOperator) {
absl::BitGen bitgen_for_seeding;

Domain<absl::BitGenRef> domain = Arbitrary<absl::BitGenRef>();
Value v0(domain, bitgen_for_seeding);
Value v1(domain, bitgen_for_seeding);

// Discard the first value, which may be from the data stream.
// If the implementation of BitGenRefDomain changes this may break.
v0.user_value();
v1.user_value();
// Initialize a set of bitgen references.
std::vector<decltype(Value(domain, bitgen_for_seeding))> values;
values.reserve(10);
for (int i = 0; i < 10; ++i) {
values.emplace_back(domain, bitgen_for_seeding);
}

std::vector<absl::BitGenRef::result_type> a, b;
// Some of the "randomly initialized" streams should be different.
for (int i = 0; i < 10; ++i) {
a.push_back(v0.user_value());
b.push_back(v1.user_value());
absl::flat_hash_set<absl::BitGenRef::result_type> s;
for (auto& v : values) {
s.insert(v.user_value());
}
EXPECT_NE(s.size(), 1) << *s.begin();
}
EXPECT_NE(a, b);
}

TEST(BitGenRefDomainTest, AbseilUniformReturnsLowerBoundWhenExhausted) {
TEST(BitGenRefDomainTest, AbseilUniformIsFunctionalWhenExhausted) {
absl::BitGen bitgen_for_seeding;

Domain<absl::BitGenRef> domain = Arbitrary<absl::BitGenRef>();
Value v0(domain, bitgen_for_seeding);
Value v1(v0, domain);

// Discard the first value, which may be from the data stream.
// If the implementation of BitGenRefDomain changes this may break.
v0.user_value();

for (int i = 0; i < 10; ++i) {
EXPECT_EQ(absl::Uniform<int>(v0.user_value, 0, 100), 0);
// When the same domain is used to generate multiple values, the generated
// data sequence should be identical.
std::vector<int> values;
for (int i = 0; i < 100; ++i) {
EXPECT_EQ(absl::Uniform<int>(v0.user_value, 0, 100),
absl::Uniform<int>(v1.user_value, 0, 100))
<< i;
}
}

TEST(BitGenRefDomainTest, IsPrintable) {
absl::BitGen bitgen_for_seeding;

Domain<absl::BitGenRef> domain = Arbitrary<absl::BitGenRef>();
Value v0(domain, bitgen_for_seeding);

// Print corpus value
std::string s;
domain.GetPrinter().PrintCorpusValue(
v0.corpus_value, &s, domain_implementor::PrintMode::kHumanReadable);
EXPECT_THAT(s, testing::StartsWith("FuzzingBitGen"));
}

} // namespace
} // namespace fuzztest
11 changes: 10 additions & 1 deletion e2e_tests/functional_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1703,7 +1703,16 @@ TEST_P(FuzzingModeCrashFindingTest, VectorValueTestFindsAbortInFuzzingMode) {

TEST_P(FuzzingModeCrashFindingTest, BitGenRefTestFindsAbortInFuzzingMode) {
auto [status, std_out, std_err] = Run("MySuite.BitGenRef");
EXPECT_THAT_LOG(std_err, HasSubstr("argument 0: absl::BitGenRef{}"));
EXPECT_THAT_LOG(std_err, AnyOf(HasSubstr("argument 0: absl::BitGenRef{}"),
HasSubstr("argument 0: FuzzingBitGen")));
ExpectTargetAbort(status, std_err);
}

TEST_P(FuzzingModeCrashFindingTest,
BitGenRefShuffleTestFindsAbortInFuzzingMode) {
auto [status, std_out, std_err] = Run("MySuite.BitGenRefShuffle");
EXPECT_THAT_LOG(std_err, AnyOf(HasSubstr("argument 0: absl::BitGenRef{}"),
HasSubstr("argument 0: FuzzingBitGen")));
ExpectTargetAbort(status, std_err);
}

Expand Down
1 change: 1 addition & 0 deletions e2e_tests/testdata/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ cc_binary(
testonly = 1,
srcs = ["fuzz_tests_for_microbenchmarking.cc"],
deps = [
"@abseil-cpp//absl/container:flat_hash_set",
"@abseil-cpp//absl/random:bit_gen_ref",
"@abseil-cpp//absl/random:distributions",
"@abseil-cpp//absl/strings:str_format",
Expand Down
1 change: 1 addition & 0 deletions e2e_tests/testdata/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ target_link_libraries(
fuzztest::test_protobuf_cc_proto
absl::random_bit_gen_ref
absl::random_distributions
absl::flat_hash_set
absl::str_format
absl::string_view
)
Expand Down
30 changes: 25 additions & 5 deletions e2e_tests/testdata/fuzz_tests_for_microbenchmarking.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
// i.e., to check that the fuzzer behaves as expected and outputs the expected
// results. E.g., the fuzzer finds the abort() or bug.

#include <algorithm>
#include <array>
#include <cmath>
#include <cstdint>
Expand All @@ -33,10 +34,12 @@
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

#include "./fuzztest/fuzztest.h"
#include "absl/container/flat_hash_set.h"
#include "absl/random/bit_gen_ref.h"
#include "absl/random/distributions.h"
#include "absl/strings/str_format.h"
Expand Down Expand Up @@ -240,15 +243,32 @@ FUZZ_TEST(MySuite, FixedSizeVectorValue)
.WithDomains(fuzztest::VectorOf(fuzztest::Arbitrary<char>()).WithSize(4));

__attribute__((optnone)) void BitGenRef(absl::BitGenRef bitgen) {
if (absl::Uniform(bitgen, 0, 256) == 'F' &&
absl::Uniform(bitgen, 0, 256) == 'U' &&
absl::Uniform(bitgen, 0, 256) == 'Z' &&
absl::Uniform(bitgen, 0, 256) == 'Z') {
std::abort(); // Bug!
// Driving FuzzingBitGen towards specific sequences takes a long time,
// so here test that the min, mean, and max values are present along with
// one additional value.
constexpr int kMax = 256;

absl::flat_hash_set<int> seen;
for (size_t i = 0; i < 5; i++) {
seen.insert(absl::Uniform(absl::IntervalClosedClosed, bitgen, 0, kMax));
}
if (seen.contains(0) && seen.contains(kMax) && seen.contains(kMax / 2) &&
seen.size() == 5) {
std::abort();
}
}
FUZZ_TEST(MySuite, BitGenRef);

__attribute__((optnone)) void BitGenRefShuffle(absl::BitGenRef bitgen) {
// This uses FuzzingBitGen's operator().
std::vector<int> v = {4, 1, 3, 2, 5};
std::shuffle(v.begin(), v.end(), bitgen);
if (std::is_sorted(v.begin(), v.end())) {
std::abort(); // Bug!
}
}
FUZZ_TEST(MySuite, BitGenRefShuffle);

__attribute__((optnone)) void WithDomainClass(uint8_t a, double d) {
// This will only crash with a=10, to make it easier to check the results.
// d can have any value.
Expand Down
15 changes: 14 additions & 1 deletion fuzztest/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -219,19 +219,32 @@ cc_library(
],
)

cc_test(
name = "fuzzing_bit_gen_test",
srcs = ["fuzzing_bit_gen_test.cc"],
deps = [
":fuzzing_bit_gen",
"@abseil-cpp//absl/random",
"@abseil-cpp//absl/random:bit_gen_ref",
"@googletest//:gtest_main",
],
)

cc_library(
name = "fuzzing_bit_gen",
srcs = ["fuzzing_bit_gen.cc"],
hdrs = ["fuzzing_bit_gen.h"],
deps = [
"@abseil-cpp//absl/base:core_headers",
"@abseil-cpp//absl/base:fast_type_id",
"@abseil-cpp//absl/base:no_destructor",
"@abseil-cpp//absl/container:flat_hash_map",
"@abseil-cpp//absl/numeric:bits",
"@abseil-cpp//absl/numeric:int128",
"@abseil-cpp//absl/random:bit_gen_ref",
"@abseil-cpp//absl/types:span",
"@com_google_fuzztest//fuzztest/internal:register_fuzzing_mocks",
"@com_google_fuzztest//fuzztest/internal:fuzzing_mock_stream",
"@com_google_fuzztest//fuzztest/internal:register_absl_fuzzing_mocks",
],
)

Expand Down
16 changes: 15 additions & 1 deletion fuzztest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,28 @@ fuzztest_cc_library(
SRCS
"fuzzing_bit_gen.cc"
DEPS
absl::core_headers
absl::fast_type_id
absl::no_destructor
absl::flat_hash_map
absl::bits
absl::int128
absl::random_bit_gen_ref
absl::span
fuzztest::register_fuzzing_mocks
fuzztest::fuzzing_mock_stream
fuzztest::register_absl_fuzzing_mocks
)

fuzztest_cc_test(
NAME
fuzzing_bit_gen_test
SRCS
"fuzzing_bit_gen_test.cc"
DEPS
fuzztest::fuzzing_bit_gen
absl::random_random
absl::random_bit_gen_ref
GTest::gmock_main
)

fuzztest_cc_library(
Expand Down
Loading
Loading