Skip to content

Commit d4e7a2e

Browse files
FuzzTest Teamcopybara-github
authored andcommitted
Add flatbuffers domain
PiperOrigin-RevId: 732932597
1 parent 1d26596 commit d4e7a2e

24 files changed

+2126
-4
lines changed

.github/workflows/cmake_test.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ jobs:
7777
-D CMAKE_CXX_COMPILER_LAUNCHER=ccache \
7878
-D CMAKE_BUILD_TYPE=RelWithDebug \
7979
-D FUZZTEST_BUILD_TESTING=on \
80+
-D FUZZTEST_BUILD_FLATBUFFERS=on \
8081
&& cmake --build build -j $(nproc) \
8182
&& ctest --test-dir build -j $(nproc) --output-on-failure
8283
- name: Run all tests in default mode with gcc
@@ -90,6 +91,7 @@ jobs:
9091
-D CMAKE_CXX_COMPILER_LAUNCHER=ccache \
9192
-D CMAKE_BUILD_TYPE=RelWithDebug \
9293
-D FUZZTEST_BUILD_TESTING=on \
94+
-D FUZZTEST_BUILD_FLATBUFFERS=on \
9395
&& cmake --build build_gcc -j $(nproc) \
9496
&& ctest --test-dir build_gcc -j $(nproc) --output-on-failure
9597
- name: Run end-to-end tests in fuzzing mode
@@ -104,6 +106,7 @@ jobs:
104106
-D CMAKE_BUILD_TYPE=RelWithDebug \
105107
-D FUZZTEST_FUZZING_MODE=on \
106108
-D FUZZTEST_BUILD_TESTING=on \
109+
-D FUZZTEST_BUILD_FLATBUFFERS=on \
107110
&& cmake --build build -j $(nproc) \
108111
&& ctest --test-dir build -j $(nproc) --output-on-failure -R "functional_test"
109112
- name: Save new cache based on main

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ cmake_minimum_required(VERSION 3.19)
1616
project(fuzztest)
1717

1818
option(FUZZTEST_BUILD_TESTING "Building the tests." OFF)
19+
option(FUZZTEST_BUILD_FLATBUFFERS "Building the flatbuffers support." OFF)
1920
option(FUZZTEST_FUZZING_MODE "Building the fuzztest in fuzzing mode." OFF)
2021
set(FUZZTEST_COMPATIBILITY_MODE "" CACHE STRING "Compatibility mode. Available options: <empty>, libfuzzer")
2122
set(CMAKE_CXX_STANDARD 17)

MODULE.bazel

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ bazel_dep(
3535
name = "platforms",
3636
version = "0.0.10",
3737
)
38+
bazel_dep(
39+
name = "flatbuffers",
40+
version = "25.2.10"
41+
)
3842
# GoogleTest is not a dev dependency, because it's needed when FuzzTest is used
3943
# with GoogleTest integration (e.g., googletest_adaptor). Note that the FuzzTest
4044
# framework can be used without GoogleTest integration as well.
@@ -48,8 +52,6 @@ bazel_dep(
4852
name = "protobuf",
4953
version = "31.1",
5054
)
51-
# TODO(lszekeres): Make this a dev dependency, as the protobuf library is only
52-
# required for testing.
5355
bazel_dep(
5456
name = "rules_proto",
5557
version = "7.1.0",

cmake/BuildDependencies.cmake

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ set(proto_TAG v30.2)
3535
set(nlohmann_json_URL https://github.com/nlohmann/json.git)
3636
set(nlohmann_json_TAG v3.11.3)
3737

38+
set(flatbuffers_URL https://github.com/google/flatbuffers.git)
39+
set(flatbuffers_TAG v25.2.10)
40+
3841
if(POLICY CMP0135)
3942
cmake_policy(SET CMP0135 NEW)
4043
set(CMAKE_POLICY_DEFAULT_CMP0135 NEW)
@@ -64,6 +67,14 @@ FetchContent_Declare(
6467
URL_HASH MD5=${antlr_cpp_MD5}
6568
)
6669

70+
if (FUZZTEST_BUILD_FLATBUFFERS)
71+
FetchContent_Declare(
72+
flatbuffers
73+
GIT_REPOSITORY ${flatbuffers_URL}
74+
GIT_TAG ${flatbuffers_TAG}
75+
)
76+
endif()
77+
6778
if (FUZZTEST_BUILD_TESTING)
6879

6980
FetchContent_Declare(
@@ -101,3 +112,9 @@ if (FUZZTEST_BUILD_TESTING)
101112
FetchContent_MakeAvailable(nlohmann_json)
102113

103114
endif ()
115+
116+
if (FUZZTEST_BUILD_FLATBUFFERS)
117+
set(FLATBUFFERS_BUILD_TESTS OFF)
118+
set(FLATBUFFERS_BUILD_INSTALL OFF)
119+
FetchContent_MakeAvailable(flatbuffers)
120+
endif()

cmake/FuzzTestHelpers.cmake

Lines changed: 188 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,4 +338,191 @@ function(fuzztest_proto_library)
338338

339339
add_library(fuzztest::${FUZZTEST_PROTO_LIB_NAME} ALIAS ${_NAME})
340340

341-
endfunction()
341+
endfunction()
342+
343+
# fuzztest_flatbuffers_generate_headers()
344+
#
345+
# Modified version of `flatbuffers_generate_headers`
346+
# from https://github.com/google/flatbuffers/blob/master/CMake/BuildFlatBuffers.cmake
347+
# Supports having the embedded schema header in the output set.
348+
#
349+
# Creates a target that can be linked against that generates flatbuffer headers.
350+
#
351+
# This function takes a target name and a list of schemas. You can also specify
352+
# other flagc flags using the FLAGS option to change the behavior of the flatc
353+
# tool.
354+
#
355+
# When the target_link_libraries is done within a different directory than
356+
# flatbuffers_generate_headers is called, then the target should also be dependent
357+
# the custom generation target called fuzztest_GENERATE_<TARGET>.
358+
#
359+
# Arguments:
360+
# TARGET: The name of the target to generate.
361+
# SCHEMAS: The list of schema files to generate code for.
362+
# BINARY_SCHEMAS_DIR: Optional. The directory in which to generate binary
363+
# schemas. Binary schemas will only be generated if a path is provided.
364+
# INCLUDE: Optional. Search for includes in the specified paths. (Use this
365+
# instead of "-I <path>" and the FLAGS option so that CMake is aware of
366+
# the directories that need to be searched).
367+
# INCLUDE_PREFIX: Optional. The directory in which to place the generated
368+
# files. Use this instead of the --include-prefix option.
369+
# FLAGS: Optional. A list of any additional flags that you would like to pass
370+
# to flatc.
371+
# TESTONLY: When added, this target will only be built if both
372+
# BUILD_TESTING=ON and FUZZTEST_BUILD_TESTING=ON.
373+
#
374+
# Example:
375+
#
376+
# fuzztest_flatbuffers_library(
377+
# TARGET my_generated_headers_target
378+
# INCLUDE_PREFIX ${MY_INCLUDE_PREFIX}"
379+
# SCHEMAS ${MY_SCHEMA_FILES}
380+
# BINARY_SCHEMAS_DIR "${MY_BINARY_SCHEMA_DIRECTORY}"
381+
# FLAGS --gen-object-api)
382+
#
383+
# target_link_libraries(MyExecutableTarget
384+
# PRIVATE fuzztest_my_generated_headers_target
385+
# )
386+
#
387+
# Optional (only needed within different directory):
388+
# add_dependencies(app fuzztest_GENERATE_my_generated_headers_target)
389+
function(fuzztest_flatbuffers_generate_headers)
390+
# Parse function arguments.
391+
set(options TESTONLY)
392+
set(one_value_args
393+
"TARGET"
394+
"INCLUDE_PREFIX"
395+
"BINARY_SCHEMAS_DIR")
396+
set(multi_value_args
397+
"SCHEMAS"
398+
"INCLUDE"
399+
"FLAGS")
400+
cmake_parse_arguments(
401+
PARSE_ARGV 0
402+
FLATBUFFERS_GENERATE_HEADERS
403+
"${options}"
404+
"${one_value_args}"
405+
"${multi_value_args}")
406+
407+
if(FLATBUFFERS_GENERATE_HEADERS_TESTONLY AND NOT (BUILD_TESTING AND FUZZTEST_BUILD_TESTING))
408+
return()
409+
endif()
410+
411+
# Test if including from FindFlatBuffers
412+
if(FLATBUFFERS_FLATC_EXECUTABLE)
413+
set(FLATC_TARGET "")
414+
set(FLATC ${FLATBUFFERS_FLATC_EXECUTABLE})
415+
elseif(TARGET flatbuffers::flatc)
416+
set(FLATC_TARGET flatbuffers::flatc)
417+
set(FLATC flatbuffers::flatc)
418+
else()
419+
set(FLATC_TARGET flatc)
420+
set(FLATC flatc)
421+
endif()
422+
423+
set(working_dir "${CMAKE_CURRENT_SOURCE_DIR}")
424+
425+
# Generate the include files parameters.
426+
set(include_params "")
427+
foreach (include_dir ${FLATBUFFERS_GENERATE_HEADERS_INCLUDE})
428+
set(include_params -I ${include_dir} ${include_params})
429+
endforeach()
430+
431+
# Create a directory to place the generated code.
432+
set(generated_target_dir "${CMAKE_CURRENT_BINARY_DIR}")
433+
set(generated_include_dir "${generated_target_dir}")
434+
if (NOT ${FLATBUFFERS_GENERATE_HEADERS_INCLUDE_PREFIX} STREQUAL "")
435+
set(generated_include_dir "${generated_include_dir}/${FLATBUFFERS_GENERATE_HEADERS_INCLUDE_PREFIX}")
436+
list(APPEND FLATBUFFERS_GENERATE_HEADERS_FLAGS
437+
"--include-prefix" ${FLATBUFFERS_GENERATE_HEADERS_INCLUDE_PREFIX})
438+
endif()
439+
440+
set(generated_custom_commands)
441+
442+
# Create rules to generate the code for each schema.
443+
foreach(schema ${FLATBUFFERS_GENERATE_HEADERS_SCHEMAS})
444+
get_filename_component(filename ${schema} NAME_WE)
445+
set(generated_include "${generated_include_dir}/${filename}_generated.h")
446+
# Add the embedded schema header in the output set if requested.
447+
if("${FLATBUFFERS_GENERATE_HEADERS_FLAGS}" MATCHES "--bfbs-gen-embed")
448+
list(APPEND generated_include "${generated_include_dir}/${filename}_bfbs_generated.h")
449+
endif()
450+
451+
# Generate files for grpc if needed
452+
set(generated_source_file)
453+
if("${FLATBUFFERS_GENERATE_HEADERS_FLAGS}" MATCHES "--grpc")
454+
# Check if schema file contain a rpc_service definition
455+
file(STRINGS ${schema} has_grpc REGEX "rpc_service")
456+
if(has_grpc)
457+
list(APPEND generated_include "${generated_include_dir}/${filename}.grpc.fb.h")
458+
set(generated_source_file "${generated_include_dir}/${filename}.grpc.fb.cc")
459+
endif()
460+
endif()
461+
462+
add_custom_command(
463+
OUTPUT ${generated_include} ${generated_source_file}
464+
COMMAND ${FLATC} ${FLATC_ARGS}
465+
-o ${generated_include_dir}
466+
${include_params}
467+
-c ${schema}
468+
${FLATBUFFERS_GENERATE_HEADERS_FLAGS}
469+
DEPENDS ${FLATC_TARGET} ${schema}
470+
WORKING_DIRECTORY "${working_dir}"
471+
COMMENT "Building ${schema} flatbuffers...")
472+
list(APPEND all_generated_header_files ${generated_include})
473+
list(APPEND all_generated_source_files ${generated_source_file})
474+
list(APPEND generated_custom_commands "${generated_include}" "${generated_source_file}")
475+
476+
# Generate the binary flatbuffers schemas if instructed to.
477+
if (NOT ${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR} STREQUAL "")
478+
set(binary_schema
479+
"${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR}/${filename}.bfbs")
480+
add_custom_command(
481+
OUTPUT ${binary_schema}
482+
COMMAND ${FLATC} -b --schema
483+
-o ${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR}
484+
${include_params}
485+
${schema}
486+
DEPENDS ${FLATC_TARGET} ${schema}
487+
WORKING_DIRECTORY "${working_dir}")
488+
list(APPEND generated_custom_commands "${binary_schema}")
489+
list(APPEND all_generated_binary_files ${binary_schema})
490+
endif()
491+
endforeach()
492+
493+
# Create an additional target as add_custom_command scope is only within same directory (CMakeFile.txt)
494+
set(generate_target fuzztest_GENERATE_${FLATBUFFERS_GENERATE_HEADERS_TARGET})
495+
add_custom_target(${generate_target} ALL
496+
DEPENDS ${generated_custom_commands}
497+
COMMENT "Generating flatbuffer target fuzztest_${FLATBUFFERS_GENERATE_HEADERS_TARGET}")
498+
499+
# Set up interface library
500+
add_library(fuzztest_${FLATBUFFERS_GENERATE_HEADERS_TARGET} INTERFACE)
501+
add_dependencies(
502+
fuzztest_${FLATBUFFERS_GENERATE_HEADERS_TARGET}
503+
${FLATC}
504+
${FLATBUFFERS_GENERATE_HEADERS_SCHEMAS})
505+
target_include_directories(
506+
fuzztest_${FLATBUFFERS_GENERATE_HEADERS_TARGET}
507+
INTERFACE ${generated_target_dir})
508+
509+
# Organize file layout for IDEs.
510+
source_group(
511+
TREE "${generated_target_dir}"
512+
PREFIX "Flatbuffers/Generated/Headers Files"
513+
FILES ${all_generated_header_files})
514+
source_group(
515+
TREE "${generated_target_dir}"
516+
PREFIX "Flatbuffers/Generated/Source Files"
517+
FILES ${all_generated_source_files})
518+
source_group(
519+
TREE ${working_dir}
520+
PREFIX "Flatbuffers/Schemas"
521+
FILES ${FLATBUFFERS_GENERATE_HEADERS_SCHEMAS})
522+
if (NOT ${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR} STREQUAL "")
523+
source_group(
524+
TREE "${FLATBUFFERS_GENERATE_HEADERS_BINARY_SCHEMAS_DIR}"
525+
PREFIX "Flatbuffers/Generated/Binary Schemas"
526+
FILES ${all_generated_binary_files})
527+
endif()
528+
endfunction()

cmake/generate_cmake_from_bazel.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
"@abseil-cpp//absl/types:optional": "absl::optional",
6767
"@abseil-cpp//absl/types:span": "absl::span",
6868
"@abseil-cpp//absl/types:variant": "absl::variant",
69+
"@flatbuffers//:runtime_cc": "flatbuffers",
6970
"@googletest//:gtest": "GTest::gtest",
7071
"@googletest//:gtest_main": "GTest::gmock_main",
7172
"@protobuf//:protobuf": "protobuf::libprotobuf",

domain_tests/BUILD

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,23 @@ cc_test(
3737
],
3838
)
3939

40+
cc_test(
41+
name = "arbitrary_domains_flatbuffers_test",
42+
srcs = ["arbitrary_domains_flatbuffers_test.cc"],
43+
deps = [
44+
":domain_testing",
45+
"@abseil-cpp//absl/container:flat_hash_map",
46+
"@abseil-cpp//absl/random",
47+
"@com_google_fuzztest//fuzztest:domain",
48+
"@com_google_fuzztest//fuzztest:flatbuffers",
49+
"@com_google_fuzztest//fuzztest:fuzztest_macros",
50+
"@com_google_fuzztest//fuzztest/internal:meta",
51+
"@com_google_fuzztest//fuzztest/internal:test_flatbuffers_cc_fbs",
52+
"@flatbuffers//:runtime_cc",
53+
"@googletest//:gtest_main",
54+
],
55+
)
56+
4057
cc_test(
4158
name = "arbitrary_domains_protobuf_test",
4259
srcs = ["arbitrary_domains_protobuf_test.cc"],

domain_tests/CMakeLists.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,30 @@ fuzztest_cc_test(
1818
GTest::gmock_main
1919
)
2020

21+
if (FUZZTEST_BUILD_FLATBUFFERS)
22+
fuzztest_cc_test(
23+
NAME
24+
arbitrary_domains_flatbuffers_test
25+
SRCS
26+
"arbitrary_domains_flatbuffers_test.cc"
27+
DEPS
28+
absl::flat_hash_set
29+
absl::random_bit_gen_ref
30+
absl::random_random
31+
absl::strings
32+
flatbuffers
33+
fuzztest::domain
34+
fuzztest::domain_testing
35+
fuzztest::flatbuffers
36+
fuzztest::fuzztest_macros
37+
GTest::gmock_main
38+
fuzztest_test_flatbuffers_headers
39+
)
40+
add_dependencies(fuzztest_arbitrary_domains_flatbuffers_test
41+
fuzztest_GENERATE_test_flatbuffers_headers
42+
)
43+
endif()
44+
2145
fuzztest_cc_test(
2246
NAME
2347
arbitrary_domains_protobuf_test

0 commit comments

Comments
 (0)