Skip to content

Commit dd66f0a

Browse files
FuzzTest Teamcopybara-github
FuzzTest Team
authored andcommitted
Add flatbuffers domain
PiperOrigin-RevId: 732932597
1 parent b8e43c7 commit dd66f0a

File tree

6 files changed

+1112
-0
lines changed

6 files changed

+1112
-0
lines changed

domain_tests/BUILD

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@ cc_test(
3333
],
3434
)
3535

36+
cc_test(
37+
name = "arbitrary_domains_flatbuffers_test",
38+
srcs = ["arbitrary_domains_flatbuffers_test.cc"],
39+
deps = [
40+
":domain_testing",
41+
"//third_party/flatbuffers:runtime_cc",
42+
"@com_google_absl//absl/container:flat_hash_map",
43+
"@com_google_absl//absl/random",
44+
"@com_google_fuzztest//fuzztest:domain",
45+
"@com_google_fuzztest//fuzztest:domain_core",
46+
"@com_google_fuzztest//fuzztest:test_flatbuffers_cc_fbs",
47+
"@com_google_googletest//:gtest_main",
48+
],
49+
)
50+
3651
cc_test(
3752
name = "arbitrary_domains_protobuf_test",
3853
srcs = ["arbitrary_domains_protobuf_test.cc"],
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
#include <optional>
2+
#include <string_view>
3+
#include <utility>
4+
#include <vector>
5+
6+
#include "gmock/gmock.h"
7+
#include "gtest/gtest.h"
8+
#include "absl/random/random.h"
9+
#include "third_party/flatbuffers/include/flatbuffers/buffer.h"
10+
#include "third_party/flatbuffers/include/flatbuffers/flatbuffer_builder.h"
11+
#include "third_party/flatbuffers/include/flatbuffers/reflection.h"
12+
#include "third_party/flatbuffers/include/flatbuffers/reflection_generated.h"
13+
#include "third_party/flatbuffers/include/flatbuffers/table.h"
14+
#include "third_party/flatbuffers/include/flatbuffers/verifier.h"
15+
#include "./fuzztest/domain.h"
16+
#include "./domain_tests/domain_testing.h"
17+
#include "./fuzztest/internal/domains/flatbuffers_domain_impl.h"
18+
#include "./fuzztest/test_flatbuffers_generated.h"
19+
20+
namespace fuzztest {
21+
namespace {
22+
using internal::OptionalRequiredTestFbsTable;
23+
using internal::SimpleTestFbsTable;
24+
using ::testing::Contains;
25+
using ::testing::IsTrue;
26+
using ::testing::ResultOf;
27+
28+
TEST(FlatbuffersTableImplTest, SimpleTestFbsTableValueRoundTrip) {
29+
auto domain =
30+
internal::FlatbuffersTableImpl<SimpleTestFbsTable, flatbuffers::Table,
31+
reflection::Schema, flatbuffers::Verifier>{
32+
reflection::GetSchema, reflection::VerifySchemaBuffer,
33+
flatbuffers::GetTypeSize, flatbuffers::GetRoot<SimpleTestFbsTable>};
34+
35+
flatbuffers::FlatBufferBuilder fbb;
36+
auto table_offset = internal::CreateSimpleTestFbsTableDirect(
37+
fbb, true, 1.0, "foo bar baz", internal::TestFbsEnum_Second);
38+
fbb.Finish(table_offset);
39+
auto table = flatbuffers::GetRoot<SimpleTestFbsTable>(fbb.GetBufferPointer());
40+
41+
auto corpus = domain.FromValue(table);
42+
ASSERT_TRUE(corpus.has_value());
43+
ASSERT_OK(domain.ValidateCorpusValue(*corpus));
44+
45+
auto ir = domain.SerializeCorpus(corpus.value());
46+
47+
auto new_corpus = domain.ParseCorpus(ir);
48+
ASSERT_TRUE(new_corpus.has_value());
49+
ASSERT_OK(domain.ValidateCorpusValue(*new_corpus));
50+
51+
auto new_table = domain.GetValue(*new_corpus);
52+
EXPECT_EQ(new_table->b(), true);
53+
EXPECT_EQ(new_table->f(), 1.0);
54+
EXPECT_EQ(new_table->str()->str(), "foo bar baz");
55+
EXPECT_TRUE(new_table->e() == internal::TestFbsEnum_Second);
56+
}
57+
58+
TEST(FlatbuffersTableImplTest, InitGeneratesSeeds) {
59+
auto domain =
60+
internal::FlatbuffersTableImpl<SimpleTestFbsTable, flatbuffers::Table,
61+
reflection::Schema, flatbuffers::Verifier>{
62+
reflection::GetSchema, reflection::VerifySchemaBuffer,
63+
flatbuffers::GetTypeSize, flatbuffers::GetRoot<SimpleTestFbsTable>};
64+
65+
flatbuffers::FlatBufferBuilder fbb;
66+
auto table_offset = internal::CreateSimpleTestFbsTableDirect(
67+
fbb, true, 1.0, "foo bar baz", internal::TestFbsEnum_Second);
68+
fbb.Finish(table_offset);
69+
auto table = flatbuffers::GetRoot<SimpleTestFbsTable>(fbb.GetBufferPointer());
70+
71+
domain = domain.WithSeeds({table});
72+
73+
std::vector<Value<decltype(domain)>> values;
74+
absl::BitGen bitgen;
75+
values.reserve(1000);
76+
for (int i = 0; i < 1000; ++i) {
77+
Value value(domain, bitgen);
78+
values.push_back(std::move(value));
79+
}
80+
81+
EXPECT_THAT(
82+
values,
83+
Contains(ResultOf(
84+
[table](const auto& val) {
85+
bool has_same_str =
86+
val.user_value->str() == nullptr && table->str() == nullptr;
87+
if (val.user_value->str() != nullptr && table->str() != nullptr) {
88+
has_same_str =
89+
val.user_value->str()->str() == table->str()->str();
90+
}
91+
return (val.user_value->b() == table->b() &&
92+
val.user_value->f() == table->f() &&
93+
val.user_value->e() == table->e() && has_same_str);
94+
},
95+
IsTrue())));
96+
}
97+
98+
TEST(FlatbuffersTableImplTest, EventuallyMutatesAllTableFields) {
99+
auto domain =
100+
internal::FlatbuffersTableImpl<SimpleTestFbsTable, flatbuffers::Table,
101+
reflection::Schema, flatbuffers::Verifier>{
102+
reflection::GetSchema, reflection::VerifySchemaBuffer,
103+
flatbuffers::GetTypeSize, flatbuffers::GetRoot<SimpleTestFbsTable>};
104+
105+
absl::BitGen bitgen;
106+
Value val(domain, bitgen);
107+
108+
const auto verify_field_changes = [&](std::string_view name, auto has,
109+
auto get) {
110+
Set<decltype(get(val.user_value))> values;
111+
112+
int iterations = 10'000;
113+
while (--iterations > 0 && values.size() < 2) {
114+
values.insert(get(val.user_value));
115+
val.Mutate(domain, bitgen, {}, false);
116+
}
117+
EXPECT_GT(iterations, 0)
118+
<< "Field: " << name << " -- " << testing::PrintToString(values);
119+
};
120+
121+
verify_field_changes(
122+
"b", [](auto v) { return true; }, [](auto v) { return v->b(); });
123+
verify_field_changes(
124+
"f", [](auto v) { return true; }, [](auto v) { return v->f(); });
125+
verify_field_changes(
126+
"str", [](auto v) { return v->str() != nullptr; },
127+
[](auto v) { return v->str()->str(); });
128+
verify_field_changes(
129+
"e", [](auto v) { return true; }, [](auto v) { return v->e(); });
130+
}
131+
132+
TEST(FlatbuffersTableImplTest, OptionalFieldsEventuallyBecomeEmpty) {
133+
auto domain =
134+
internal::FlatbuffersTableImpl<OptionalRequiredTestFbsTable,
135+
flatbuffers::Table, reflection::Schema,
136+
flatbuffers::Verifier>{
137+
reflection::GetSchema, reflection::VerifySchemaBuffer,
138+
flatbuffers::GetTypeSize,
139+
flatbuffers::GetRoot<OptionalRequiredTestFbsTable>};
140+
141+
absl::BitGen bitgen;
142+
Value val(domain, bitgen);
143+
144+
const auto verify_field_becomes_null = [&](std::string_view name, auto has) {
145+
for (int i = 0; i < 10'000; ++i) {
146+
val.Mutate(domain, bitgen, {}, false);
147+
if (!has(val.user_value)) {
148+
break;
149+
}
150+
}
151+
EXPECT_FALSE(has(val.user_value)) << "Field never became unset: " << name;
152+
};
153+
154+
verify_field_becomes_null("opt_scalar",
155+
[](auto v) { return v->opt_scalar().has_value(); });
156+
verify_field_becomes_null("opt_str",
157+
[](auto v) { return v->opt_str() != nullptr; });
158+
}
159+
160+
TEST(FlatbuffersTableImplTest, DefaultAndRequiredFieldsAlwaysSet) {
161+
auto domain =
162+
internal::FlatbuffersTableImpl<OptionalRequiredTestFbsTable,
163+
flatbuffers::Table, reflection::Schema,
164+
flatbuffers::Verifier>{
165+
reflection::GetSchema, reflection::VerifySchemaBuffer,
166+
flatbuffers::GetTypeSize,
167+
flatbuffers::GetRoot<OptionalRequiredTestFbsTable>};
168+
169+
absl::BitGen bitgen;
170+
Value val(domain, bitgen);
171+
172+
const auto verify_field_always_set = [&](std::string_view name, auto has) {
173+
for (int i = 0; i < 10'000; ++i) {
174+
val.Mutate(domain, bitgen, {}, false);
175+
if (!has(val.user_value)) {
176+
break;
177+
}
178+
}
179+
EXPECT_TRUE(has(val.user_value)) << "Field is not set: " << name;
180+
};
181+
182+
verify_field_always_set("def_scalar", [](auto v) { return true; });
183+
verify_field_always_set("req_str",
184+
[](auto v) { return v->req_str() != nullptr; });
185+
}
186+
} // namespace
187+
} // namespace fuzztest

fuzztest/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ cc_library(
330330
srcs = ["internal/domains/in_grammar_impl.cc"],
331331
hdrs = [
332332
"domain.h",
333+
"internal/domains/flatbuffers_domain_impl.h",
333334
"internal/domains/in_grammar_impl.h",
334335
"internal/domains/in_regexp_impl.h",
335336
"internal/domains/protobuf_domain_impl.h",
@@ -345,6 +346,7 @@ cc_library(
345346
":serialization",
346347
":status",
347348
":type_support",
349+
"@com_google_absl//absl/algorithm:container",
348350
"@com_google_absl//absl/base:core_headers",
349351
"@com_google_absl//absl/base:no_destructor",
350352
"@com_google_absl//absl/container:flat_hash_map",

fuzztest/domain.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#define FUZZTEST_FUZZTEST_DOMAIN_H_
2020

2121
#include "./fuzztest/domain_core.h" // IWYU pragma: export
22+
#include "./fuzztest/internal/domains/flatbuffers_domain_impl.h" // IWYU pragma: export
2223
#include "./fuzztest/internal/domains/in_regexp_impl.h"
2324
#include "./fuzztest/internal/domains/protobuf_domain_impl.h"
2425

0 commit comments

Comments
 (0)