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