• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "json_test.h"
2 
3 #include "flatbuffers/flatbuffers.h"
4 #include "flatbuffers/idl.h"
5 #include "monster_test_bfbs_generated.h"
6 #include "monster_test_generated.h"
7 #include "optional_scalars_generated.h"
8 #include "test_assert.h"
9 
10 namespace flatbuffers {
11 namespace tests {
12 
13 using namespace MyGame::Example;
14 
15 // Check stringify of an default enum value to json
JsonDefaultTest(const std::string & tests_data_path)16 void JsonDefaultTest(const std::string &tests_data_path) {
17   // load FlatBuffer schema (.fbs) from disk
18   std::string schemafile;
19   TEST_EQ(flatbuffers::LoadFile((tests_data_path + "monster_test.fbs").c_str(),
20                                 false, &schemafile),
21           true);
22   // parse schema first, so we can use it to parse the data after
23   flatbuffers::Parser parser;
24   auto include_test_path =
25       flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
26   const char *include_directories[] = { tests_data_path.c_str(),
27                                         include_test_path.c_str(), nullptr };
28 
29   TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
30   // create incomplete monster and store to json
31   parser.opts.output_default_scalars_in_json = true;
32   parser.opts.output_enum_identifiers = true;
33   flatbuffers::FlatBufferBuilder builder;
34   auto name = builder.CreateString("default_enum");
35   MonsterBuilder color_monster(builder);
36   color_monster.add_name(name);
37   FinishMonsterBuffer(builder, color_monster.Finish());
38   std::string jsongen;
39   auto result = GenText(parser, builder.GetBufferPointer(), &jsongen);
40   TEST_NULL(result);
41   // default value of the "color" field is Blue
42   TEST_EQ(std::string::npos != jsongen.find("color: \"Blue\""), true);
43   // default value of the "testf" field is 3.14159
44   TEST_EQ(std::string::npos != jsongen.find("testf: 3.14159"), true);
45 }
46 
JsonEnumsTest(const std::string & tests_data_path)47 void JsonEnumsTest(const std::string &tests_data_path) {
48   // load FlatBuffer schema (.fbs) from disk
49   std::string schemafile;
50   TEST_EQ(flatbuffers::LoadFile((tests_data_path + "monster_test.fbs").c_str(),
51                                 false, &schemafile),
52           true);
53   // parse schema first, so we can use it to parse the data after
54   flatbuffers::Parser parser;
55   auto include_test_path =
56       flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
57   const char *include_directories[] = { tests_data_path.c_str(),
58                                         include_test_path.c_str(), nullptr };
59   parser.opts.output_enum_identifiers = true;
60   TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
61   flatbuffers::FlatBufferBuilder builder;
62   auto name = builder.CreateString("bitflag_enum");
63   MonsterBuilder color_monster(builder);
64   color_monster.add_name(name);
65   color_monster.add_color(Color(Color_Blue | Color_Red));
66   FinishMonsterBuffer(builder, color_monster.Finish());
67   std::string jsongen;
68   auto result = GenText(parser, builder.GetBufferPointer(), &jsongen);
69   TEST_NULL(result);
70   TEST_EQ(std::string::npos != jsongen.find("color: \"Red Blue\""), true);
71   // Test forward compatibility with 'output_enum_identifiers = true'.
72   // Current Color doesn't have '(1u << 2)' field, let's add it.
73   builder.Clear();
74   std::string future_json;
75   auto future_name = builder.CreateString("future bitflag_enum");
76   MonsterBuilder future_color(builder);
77   future_color.add_name(future_name);
78   future_color.add_color(
79       static_cast<Color>((1u << 2) | Color_Blue | Color_Red));
80   FinishMonsterBuffer(builder, future_color.Finish());
81   result = GenText(parser, builder.GetBufferPointer(), &future_json);
82   TEST_NULL(result);
83   TEST_EQ(std::string::npos != future_json.find("color: 13"), true);
84 }
85 
JsonOptionalTest(const std::string & tests_data_path,bool default_scalars)86 void JsonOptionalTest(const std::string &tests_data_path,
87                       bool default_scalars) {
88   // load FlatBuffer schema (.fbs) and JSON from disk
89   std::string schemafile;
90   std::string jsonfile;
91   TEST_EQ(
92       flatbuffers::LoadFile((tests_data_path + "optional_scalars.fbs").c_str(),
93                             false, &schemafile),
94       true);
95   TEST_EQ(flatbuffers::LoadFile((tests_data_path + "optional_scalars" +
96                                  (default_scalars ? "_defaults" : "") + ".json")
97                                     .c_str(),
98                                 false, &jsonfile),
99           true);
100 
101   auto include_test_path =
102       flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
103   const char *include_directories[] = { tests_data_path.c_str(),
104                                         include_test_path.c_str(), nullptr };
105 
106   // parse schema first, so we can use it to parse the data after
107   flatbuffers::Parser parser;
108   parser.opts.output_default_scalars_in_json = default_scalars;
109   TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
110   TEST_EQ(parser.ParseJson(jsonfile.c_str()), true);
111 
112   // here, parser.builder_ contains a binary buffer that is the parsed data.
113 
114   // First, verify it, just in case:
115   flatbuffers::Verifier verifier(parser.builder_.GetBufferPointer(),
116                                  parser.builder_.GetSize());
117   TEST_EQ(optional_scalars::VerifyScalarStuffBuffer(verifier), true);
118 
119   // to ensure it is correct, we now generate text back from the binary,
120   // and compare the two:
121   std::string jsongen;
122   auto result = GenText(parser, parser.builder_.GetBufferPointer(), &jsongen);
123   TEST_NULL(result);
124   TEST_EQ_STR(jsongen.c_str(), jsonfile.c_str());
125 }
126 
ParseIncorrectMonsterJsonTest(const std::string & tests_data_path)127 void ParseIncorrectMonsterJsonTest(const std::string &tests_data_path) {
128   std::string schemafile;
129   TEST_EQ(flatbuffers::LoadFile((tests_data_path + "monster_test.bfbs").c_str(),
130                                 true, &schemafile),
131           true);
132   flatbuffers::Parser parser;
133   flatbuffers::Verifier verifier(
134       reinterpret_cast<const uint8_t *>(schemafile.c_str()), schemafile.size());
135   TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
136   TEST_EQ(
137       parser.Deserialize(reinterpret_cast<const uint8_t *>(schemafile.c_str()),
138                          schemafile.size()),
139       true);
140   TEST_EQ(parser.ParseJson("{name:\"monster\"}"), true);
141   TEST_EQ(parser.ParseJson(""), false);
142   TEST_EQ(parser.ParseJson("{name: 1}"), false);
143   TEST_EQ(parser.ParseJson("{name:+1}"), false);
144   TEST_EQ(parser.ParseJson("{name:-1}"), false);
145   TEST_EQ(parser.ParseJson("{name:-f}"), false);
146   TEST_EQ(parser.ParseJson("{name:+f}"), false);
147 }
148 
JsonUnsortedArrayTest()149 void JsonUnsortedArrayTest() {
150   flatbuffers::Parser parser;
151   TEST_EQ(parser.Deserialize(MyGame::Example::MonsterBinarySchema::data(),
152                              MyGame::Example::MonsterBinarySchema::size()),
153           true);
154   auto jsonStr = R"(
155   {
156     "name": "lookupTest",
157     "testarrayoftables": [
158       { "name": "aaa" },
159       { "name": "ccc" },
160       { "name": "bbb" }
161     ]
162   }
163   )";
164   TEST_EQ(parser.ParseJson(jsonStr), true);
165   auto monster = flatbuffers::GetRoot<MyGame::Example::Monster>(
166       parser.builder_.GetBufferPointer());
167 
168   TEST_NOTNULL(monster->testarrayoftables()->LookupByKey("aaa"));
169   TEST_NOTNULL(monster->testarrayoftables()->LookupByKey("bbb"));
170   TEST_NOTNULL(monster->testarrayoftables()->LookupByKey("ccc"));
171 }
172 
JsonUnionStructTest()173 void JsonUnionStructTest() {
174   // schema to parse data
175   auto schema = R"(
176 struct MyStruct { field: int; }
177 union UnionWithStruct { MyStruct }
178 table JsonUnionStructTest { union_with_struct: UnionWithStruct; }
179 root_type JsonUnionStructTest;
180 )";
181   // source text to parse and expected result of generation text back
182   auto json_source = R"({
183   union_with_struct_type: "MyStruct",
184   union_with_struct: {
185     field: 12345
186   }
187 }
188 )";
189 
190   flatbuffers::Parser parser;
191   // set output language to JSON, so we assure that is supported
192   parser.opts.lang_to_generate = IDLOptions::kJson;
193   // parse schema first, so we assure that output language is supported
194   // and can use it to parse the data after
195   TEST_EQ(true, parser.Parse(schema));
196   TEST_EQ(true, parser.ParseJson(json_source));
197 
198   // now generate text back from the binary, and compare the two:
199   std::string json_generated;
200   auto generate_result =
201       GenText(parser, parser.builder_.GetBufferPointer(), &json_generated);
202   TEST_NULL(generate_result);
203   TEST_EQ_STR(json_source, json_generated.c_str());
204 }
205 
206 }  // namespace tests
207 }  // namespace flatbuffers
208