blob: 755dd57a009a5d3b4cafab6b9fcbbf52b84de8aa [file] [log] [blame]
James Kuszmaulf5eb4682023-09-22 17:16:59 -07001#include "absl/strings/str_format.h"
2#include "absl/strings/str_join.h"
3#include "gmock/gmock.h"
4#include "gtest/gtest.h"
5
6#include "aos/flatbuffers.h"
7#include "aos/flatbuffers/builder.h"
8#include "aos/flatbuffers/static_flatbuffers.h"
9#include "aos/flatbuffers/test_dir/type_coverage_static.h"
10#include "aos/flatbuffers/test_static.h"
11#include "aos/json_to_flatbuffer.h"
12#include "aos/testing/path.h"
13#include "aos/testing/tmpdir.h"
14#include "aos/util/file.h"
15
16namespace aos::fbs::testing {
17
18class StaticFlatbuffersFuzzTest : public ::testing::Test {
19 protected:
20 template <typename T>
21 void VerifyJson(const std::string_view data) {
22 Builder<T> json_builder = aos::JsonToStaticFlatbuffer<T>(data);
23
24 EXPECT_EQ(data, aos::FlatbufferToJson(json_builder.AsFlatbufferSpan(),
25 {.multi_line = true}));
26 }
27};
28
29namespace {
30void Combine(const std::span<const std::vector<std::string_view>> &strings,
31 std::function<void(const std::vector<std::string_view> &)> handler,
32 const std::vector<std::string_view> &current_combination) {
33 if (strings.empty()) {
34 handler(current_combination);
35 return;
36 }
37 for (const std::string_view &str : strings.front()) {
38 std::vector<std::string_view> combination = current_combination;
39 combination.push_back(str);
40 Combine(strings.subspan(1), handler, combination);
41 }
42}
43void Combine(
44 const std::vector<std::vector<std::string_view>> &strings,
45 std::function<void(const std::vector<std::string_view> &)> handler) {
46 Combine(std::span<const std::vector<std::string_view>>{strings.data(),
47 strings.size()},
48 handler, {});
49}
50} // namespace
51
52// Iterate over lots of variations of different flatbuffers to try to see if we
53// can exercise weird corner-cases.
54TEST_F(StaticFlatbuffersFuzzTest, JsonFuzzing) {
55 std::vector<std::vector<std::string_view>> stanzas{
56 {"", "\"scalar\": 1323"},
57 {"", "\"vector_of_scalars\": [\n \n ]",
58 "\"vector_of_scalars\": [\n 123\n ]",
59 "\"vector_of_scalars\": [\n 123,\n 456\n ]"},
60 {"", "\"string\": \"\"", "\"string\": \"abcdef\"",
61 "\"string\": \"abcdefghijklmnopqrstuvwxyz\""},
62 {
63 "",
64 "\"vector_of_strings\": [\n \n ]",
65 "\"vector_of_strings\": [\n \"\",\n \"abcdef\"\n ]",
66 "\"vector_of_strings\": [\n \"\",\n \"abcdef\",\n "
67 "\"abcdefghijklmnopqrstuvwxyz\"\n ]",
68 "\"vector_of_strings\": [\n \"\",\n \"abcdef\",\n \"971\",\n "
69 "\"abcdefghijklmnopqrstuvwxyz\"\n ]",
70 "\"vector_of_strings\": [\n \"\",\n \"abcdef\",\n "
71 "\"abcdefghijklmnopqrstuvwxyz\",\n \"971\",\n \"123\"\n ]",
72 "\"vector_of_strings\": [\n \"\",\n \"abcdef\",\n \"xyz\",\n "
73 "\"971\",\n \"123\"\n ]",
74 },
75 {
76 "",
James Kuszmaul98c798d2024-04-24 15:58:09 -070077 "\"substruct\": {\n \"x\": 971,\n \"y\": 123\n }",
James Kuszmaulf5eb4682023-09-22 17:16:59 -070078 },
79 {
80 "",
81 "\"subtable\": {\n\n }",
82 "\"subtable\": {\n \"baz\": 1.23\n }",
83 "\"subtable\": {\n \"foo\": 123,\n \"baz\": 1.23\n }",
84 },
85 {
86 "",
87 "\"vector_aligned\": [\n \n ]",
88 "\"vector_aligned\": [\n 678\n ]",
89 "\"vector_aligned\": [\n 678,\n 456\n ]",
90 "\"vector_aligned\": [\n 7,\n 6,\n 5,\n 4,\n 3,\n 2,\n 1,\n "
91 "0\n ]",
92 },
93 {
94 "",
95 "\"vector_of_structs\": [\n \n ]",
96 R"json("vector_of_structs": [
97 {
James Kuszmaul98c798d2024-04-24 15:58:09 -070098 "x": 1,
99 "y": 2
James Kuszmaulf5eb4682023-09-22 17:16:59 -0700100 }
101 ])json",
102 R"json("vector_of_structs": [
103 {
James Kuszmaul98c798d2024-04-24 15:58:09 -0700104 "x": 1,
105 "y": 2
James Kuszmaulf5eb4682023-09-22 17:16:59 -0700106 },
107 {
James Kuszmaul98c798d2024-04-24 15:58:09 -0700108 "x": 3,
109 "y": 4
James Kuszmaulf5eb4682023-09-22 17:16:59 -0700110 },
111 {
James Kuszmaul98c798d2024-04-24 15:58:09 -0700112 "x": 5,
113 "y": 6
James Kuszmaulf5eb4682023-09-22 17:16:59 -0700114 }
115 ])json",
116 R"json("vector_of_structs": [
117 {
James Kuszmaul98c798d2024-04-24 15:58:09 -0700118 "x": 1,
119 "y": 2
James Kuszmaulf5eb4682023-09-22 17:16:59 -0700120 },
121 {
James Kuszmaul98c798d2024-04-24 15:58:09 -0700122 "x": 3,
123 "y": 4
James Kuszmaulf5eb4682023-09-22 17:16:59 -0700124 },
125 {
James Kuszmaul98c798d2024-04-24 15:58:09 -0700126 "x": 5,
127 "y": 6
James Kuszmaulf5eb4682023-09-22 17:16:59 -0700128 },
129 {
James Kuszmaul98c798d2024-04-24 15:58:09 -0700130 "x": 7,
131 "y": 8
James Kuszmaulf5eb4682023-09-22 17:16:59 -0700132 },
133 {
James Kuszmaul98c798d2024-04-24 15:58:09 -0700134 "x": 9,
135 "y": 10
James Kuszmaulf5eb4682023-09-22 17:16:59 -0700136 }
137 ])json",
138 },
139 {
140 "",
141 "\"vector_of_tables\": [\n \n ]",
142 R"json("vector_of_tables": [
143 {
144
145 }
146 ])json",
147 R"json("vector_of_tables": [
148 {
149 "foo": 1
150 }
151 ])json",
152 R"json("vector_of_tables": [
153 {
154 "foo": 1
155 },
156 {
157 "foo": 2
158 },
159 {
160 "foo": 3
161 },
162 {
163 "foo": 4
164 },
165 {
166 "foo": 5
167 },
168 {
169 "foo": 6
170 }
171 ])json",
172 },
173 {
174 "",
175 "\"included_table\": {\n\n }",
176 "\"included_table\": {\n \"foo\": \"A\"\n }",
177 },
178 {
179 "",
180 "\"unspecified_length_vector\": [\n \n ]",
181 "\"unspecified_length_vector\": [\n 123\n ]",
182 "\"unspecified_length_vector\": [\n 123,\n 100\n ]",
183 },
184 {
185 "",
186 "\"unspecified_length_string\": \"\"",
187 "\"unspecified_length_string\": \"Hello, World!\"",
188 },
189 {
190 "",
191 "\"unspecified_length_vector_of_strings\": [\n \n ]",
192 "\"unspecified_length_vector_of_strings\": [\n \"\"\n ]",
193 "\"unspecified_length_vector_of_strings\": [\n \"Goodbye, \",\n "
194 "\"World!\"\n ]",
195 },
196 };
197 Combine(stanzas, [this](const std::vector<std::string_view> &strings) {
198 std::vector<std::string_view> no_empty_strings;
199 for (const std::string_view &str : strings) {
200 if (!str.empty()) {
201 no_empty_strings.push_back(str);
202 }
203 }
204 if (no_empty_strings.empty()) {
205 VerifyJson<TestTableStatic>("{\n\n}");
206 } else {
207 VerifyJson<TestTableStatic>(
208 "{\n " + absl::StrJoin(no_empty_strings, ",\n ") + "\n}");
209 }
210 });
211}
212} // namespace aos::fbs::testing