208 lines
8.0 KiB
C++
208 lines
8.0 KiB
C++
#include "json_test.h"
|
|
|
|
#include "flatbuffers/flatbuffers.h"
|
|
#include "flatbuffers/idl.h"
|
|
#include "monster_test_bfbs_generated.h"
|
|
#include "monster_test_generated.h"
|
|
#include "optional_scalars_generated.h"
|
|
#include "test_assert.h"
|
|
|
|
namespace flatbuffers {
|
|
namespace tests {
|
|
|
|
using namespace MyGame::Example;
|
|
|
|
// Check stringify of an default enum value to json
|
|
void JsonDefaultTest(const std::string &tests_data_path) {
|
|
// load FlatBuffer schema (.fbs) from disk
|
|
std::string schemafile;
|
|
TEST_EQ(flatbuffers::LoadFile((tests_data_path + "monster_test.fbs").c_str(),
|
|
false, &schemafile),
|
|
true);
|
|
// parse schema first, so we can use it to parse the data after
|
|
flatbuffers::Parser parser;
|
|
auto include_test_path =
|
|
flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
|
|
const char *include_directories[] = { tests_data_path.c_str(),
|
|
include_test_path.c_str(), nullptr };
|
|
|
|
TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
|
|
// create incomplete monster and store to json
|
|
parser.opts.output_default_scalars_in_json = true;
|
|
parser.opts.output_enum_identifiers = true;
|
|
flatbuffers::FlatBufferBuilder builder;
|
|
auto name = builder.CreateString("default_enum");
|
|
MonsterBuilder color_monster(builder);
|
|
color_monster.add_name(name);
|
|
FinishMonsterBuffer(builder, color_monster.Finish());
|
|
std::string jsongen;
|
|
auto result = GenText(parser, builder.GetBufferPointer(), &jsongen);
|
|
TEST_NULL(result);
|
|
// default value of the "color" field is Blue
|
|
TEST_EQ(std::string::npos != jsongen.find("color: \"Blue\""), true);
|
|
// default value of the "testf" field is 3.14159
|
|
TEST_EQ(std::string::npos != jsongen.find("testf: 3.14159"), true);
|
|
}
|
|
|
|
void JsonEnumsTest(const std::string &tests_data_path) {
|
|
// load FlatBuffer schema (.fbs) from disk
|
|
std::string schemafile;
|
|
TEST_EQ(flatbuffers::LoadFile((tests_data_path + "monster_test.fbs").c_str(),
|
|
false, &schemafile),
|
|
true);
|
|
// parse schema first, so we can use it to parse the data after
|
|
flatbuffers::Parser parser;
|
|
auto include_test_path =
|
|
flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
|
|
const char *include_directories[] = { tests_data_path.c_str(),
|
|
include_test_path.c_str(), nullptr };
|
|
parser.opts.output_enum_identifiers = true;
|
|
TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
|
|
flatbuffers::FlatBufferBuilder builder;
|
|
auto name = builder.CreateString("bitflag_enum");
|
|
MonsterBuilder color_monster(builder);
|
|
color_monster.add_name(name);
|
|
color_monster.add_color(Color(Color_Blue | Color_Red));
|
|
FinishMonsterBuffer(builder, color_monster.Finish());
|
|
std::string jsongen;
|
|
auto result = GenText(parser, builder.GetBufferPointer(), &jsongen);
|
|
TEST_NULL(result);
|
|
TEST_EQ(std::string::npos != jsongen.find("color: \"Red Blue\""), true);
|
|
// Test forward compatibility with 'output_enum_identifiers = true'.
|
|
// Current Color doesn't have '(1u << 2)' field, let's add it.
|
|
builder.Clear();
|
|
std::string future_json;
|
|
auto future_name = builder.CreateString("future bitflag_enum");
|
|
MonsterBuilder future_color(builder);
|
|
future_color.add_name(future_name);
|
|
future_color.add_color(
|
|
static_cast<Color>((1u << 2) | Color_Blue | Color_Red));
|
|
FinishMonsterBuffer(builder, future_color.Finish());
|
|
result = GenText(parser, builder.GetBufferPointer(), &future_json);
|
|
TEST_NULL(result);
|
|
TEST_EQ(std::string::npos != future_json.find("color: 13"), true);
|
|
}
|
|
|
|
void JsonOptionalTest(const std::string &tests_data_path,
|
|
bool default_scalars) {
|
|
// load FlatBuffer schema (.fbs) and JSON from disk
|
|
std::string schemafile;
|
|
std::string jsonfile;
|
|
TEST_EQ(
|
|
flatbuffers::LoadFile((tests_data_path + "optional_scalars.fbs").c_str(),
|
|
false, &schemafile),
|
|
true);
|
|
TEST_EQ(flatbuffers::LoadFile((tests_data_path + "optional_scalars" +
|
|
(default_scalars ? "_defaults" : "") + ".json")
|
|
.c_str(),
|
|
false, &jsonfile),
|
|
true);
|
|
|
|
auto include_test_path =
|
|
flatbuffers::ConCatPathFileName(tests_data_path, "include_test");
|
|
const char *include_directories[] = { tests_data_path.c_str(),
|
|
include_test_path.c_str(), nullptr };
|
|
|
|
// parse schema first, so we can use it to parse the data after
|
|
flatbuffers::Parser parser;
|
|
parser.opts.output_default_scalars_in_json = default_scalars;
|
|
TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
|
|
TEST_EQ(parser.ParseJson(jsonfile.c_str()), true);
|
|
|
|
// here, parser.builder_ contains a binary buffer that is the parsed data.
|
|
|
|
// First, verify it, just in case:
|
|
flatbuffers::Verifier verifier(parser.builder_.GetBufferPointer(),
|
|
parser.builder_.GetSize());
|
|
TEST_EQ(optional_scalars::VerifyScalarStuffBuffer(verifier), true);
|
|
|
|
// to ensure it is correct, we now generate text back from the binary,
|
|
// and compare the two:
|
|
std::string jsongen;
|
|
auto result = GenText(parser, parser.builder_.GetBufferPointer(), &jsongen);
|
|
TEST_NULL(result);
|
|
TEST_EQ_STR(jsongen.c_str(), jsonfile.c_str());
|
|
}
|
|
|
|
void ParseIncorrectMonsterJsonTest(const std::string &tests_data_path) {
|
|
std::string schemafile;
|
|
TEST_EQ(flatbuffers::LoadFile((tests_data_path + "monster_test.bfbs").c_str(),
|
|
true, &schemafile),
|
|
true);
|
|
flatbuffers::Parser parser;
|
|
flatbuffers::Verifier verifier(
|
|
reinterpret_cast<const uint8_t *>(schemafile.c_str()), schemafile.size());
|
|
TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
|
|
TEST_EQ(
|
|
parser.Deserialize(reinterpret_cast<const uint8_t *>(schemafile.c_str()),
|
|
schemafile.size()),
|
|
true);
|
|
TEST_EQ(parser.ParseJson("{name:\"monster\"}"), true);
|
|
TEST_EQ(parser.ParseJson(""), false);
|
|
TEST_EQ(parser.ParseJson("{name: 1}"), false);
|
|
TEST_EQ(parser.ParseJson("{name:+1}"), false);
|
|
TEST_EQ(parser.ParseJson("{name:-1}"), false);
|
|
TEST_EQ(parser.ParseJson("{name:-f}"), false);
|
|
TEST_EQ(parser.ParseJson("{name:+f}"), false);
|
|
}
|
|
|
|
void JsonUnsortedArrayTest() {
|
|
flatbuffers::Parser parser;
|
|
TEST_EQ(parser.Deserialize(MyGame::Example::MonsterBinarySchema::data(),
|
|
MyGame::Example::MonsterBinarySchema::size()),
|
|
true);
|
|
auto jsonStr = R"(
|
|
{
|
|
"name": "lookupTest",
|
|
"testarrayoftables": [
|
|
{ "name": "aaa" },
|
|
{ "name": "ccc" },
|
|
{ "name": "bbb" }
|
|
]
|
|
}
|
|
)";
|
|
TEST_EQ(parser.ParseJson(jsonStr), true);
|
|
auto monster = flatbuffers::GetRoot<MyGame::Example::Monster>(
|
|
parser.builder_.GetBufferPointer());
|
|
|
|
TEST_NOTNULL(monster->testarrayoftables()->LookupByKey("aaa"));
|
|
TEST_NOTNULL(monster->testarrayoftables()->LookupByKey("bbb"));
|
|
TEST_NOTNULL(monster->testarrayoftables()->LookupByKey("ccc"));
|
|
}
|
|
|
|
void JsonUnionStructTest() {
|
|
// schema to parse data
|
|
auto schema = R"(
|
|
struct MyStruct { field: int; }
|
|
union UnionWithStruct { MyStruct }
|
|
table JsonUnionStructTest { union_with_struct: UnionWithStruct; }
|
|
root_type JsonUnionStructTest;
|
|
)";
|
|
// source text to parse and expected result of generation text back
|
|
auto json_source = R"({
|
|
union_with_struct_type: "MyStruct",
|
|
union_with_struct: {
|
|
field: 12345
|
|
}
|
|
}
|
|
)";
|
|
|
|
flatbuffers::Parser parser;
|
|
// set output language to JSON, so we assure that is supported
|
|
parser.opts.lang_to_generate = IDLOptions::kJson;
|
|
// parse schema first, so we assure that output language is supported
|
|
// and can use it to parse the data after
|
|
TEST_EQ(true, parser.Parse(schema));
|
|
TEST_EQ(true, parser.ParseJson(json_source));
|
|
|
|
// now generate text back from the binary, and compare the two:
|
|
std::string json_generated;
|
|
auto generate_result =
|
|
GenText(parser, parser.builder_.GetBufferPointer(), &json_generated);
|
|
TEST_NULL(generate_result);
|
|
TEST_EQ_STR(json_source, json_generated.c_str());
|
|
}
|
|
|
|
} // namespace tests
|
|
} // namespace flatbuffers
|