...

Text file src/github.com/google/flatbuffers/tests/cpp17/test_cpp17.cpp

Documentation: github.com/google/flatbuffers/tests/cpp17

     1/*
     2 * Copyright 2014 Google Inc. All rights reserved.
     3 *
     4 * Licensed under the Apache License, Version 2.0 (the "License");
     5 * you may not use this file except in compliance with the License.
     6 * You may obtain a copy of the License at
     7 *
     8 *     http://www.apache.org/licenses/LICENSE-2.0
     9 *
    10 * Unless required by applicable law or agreed to in writing, software
    11 * distributed under the License is distributed on an "AS IS" BASIS,
    12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13 * See the License for the specific language governing permissions and
    14 * limitations under the License.
    15 */
    16
    17// This is a sandbox for modeling C++17 code generator.
    18// C++17 code generator: "flatc --cpp-std c++17".
    19// Warning:
    20// This is an experimental feature and could change at any time.
    21
    22#include "flatbuffers/flatbuffers.h"
    23#include "flatbuffers/flex_flat_util.h"
    24#include "flatbuffers/flexbuffers.h"
    25#include "flatbuffers/idl.h"
    26#include "flatbuffers/minireflect.h"
    27#include "flatbuffers/registry.h"
    28#include "flatbuffers/util.h"
    29#include "stringify_util.h"
    30#include "test_assert.h"
    31
    32// Embed generated code into an isolated namespace.
    33namespace cpp17 {
    34#include "generated_cpp17/monster_test_generated.h"
    35#include "generated_cpp17/optional_scalars_generated.h"
    36#include "generated_cpp17/union_vector_generated.h"
    37}  // namespace cpp17
    38
    39namespace cpp11 {
    40#include "../monster_test_generated.h"
    41#include "../optional_scalars_generated.h"
    42}  // namespace cpp11
    43
    44using ::cpp17::MyGame::Example::Monster;
    45using ::cpp17::MyGame::Example::Vec3;
    46
    47/*******************************************************************************
    48** Build some FB objects.
    49*******************************************************************************/
    50namespace {
    51const Monster *BuildMonster(flatbuffers::FlatBufferBuilder &fbb) {
    52  using ::cpp17::MyGame::Example::Color;
    53  using ::cpp17::MyGame::Example::MonsterBuilder;
    54  using ::cpp17::MyGame::Example::Test;
    55  auto name = fbb.CreateString("my_monster");
    56  auto inventory = fbb.CreateVector(std::vector<uint8_t>{ 4, 5, 6, 7 });
    57  MonsterBuilder builder(fbb);
    58  auto vec3 = Vec3{ /*x=*/1.1f,
    59                    /*y=*/2.2f,
    60                    /*z=*/3.3f,
    61                    /*test1=*/6.6,
    62                    /*test2=*/Color::Green,
    63                    /*test3=*/
    64                    Test(
    65                        /*a=*/11,
    66                        /*b=*/90) };
    67  builder.add_pos(&vec3);
    68  builder.add_name(name);
    69  builder.add_mana(1);
    70  builder.add_hp(2);
    71  builder.add_testbool(true);
    72  builder.add_testhashs32_fnv1(4);
    73  builder.add_testhashu32_fnv1(5);
    74  builder.add_testhashs64_fnv1(6);
    75  builder.add_testhashu64_fnv1(7);
    76  builder.add_testhashs32_fnv1a(8);
    77  builder.add_testhashu32_fnv1a(9);
    78  builder.add_testhashs64_fnv1a(10);
    79  builder.add_testhashu64_fnv1a(11);
    80  builder.add_testf(12.1f);
    81  builder.add_testf2(13.1f);
    82  builder.add_testf3(14.1f);
    83  builder.add_single_weak_reference(15);
    84  builder.add_co_owning_reference(16);
    85  builder.add_non_owning_reference(17);
    86  builder.add_inventory(inventory);
    87  fbb.Finish(builder.Finish());
    88  const Monster *monster =
    89      flatbuffers::GetRoot<Monster>(fbb.GetBufferPointer());
    90  return monster;
    91}
    92
    93/*******************************************************************************
    94** Test Case: Static Field Reflection Traits for Table & Structs.
    95*******************************************************************************/
    96// This test tests & demonstrates the power of the static reflection. Using it,
    97// we can given any Flatbuffer type to a generic function and it will be able to
    98// produce is full recursive string representation of it.
    99//
   100// This test covers all types: primitive types, structs, tables, Vectors, etc.
   101//
   102void StringifyAnyFlatbuffersTypeTest() {
   103  flatbuffers::FlatBufferBuilder fbb;
   104  // We are using a Monster here, but we could have used any type, because the
   105  // code that follows is totally generic!
   106  const auto *monster = BuildMonster(fbb);
   107
   108  std::string expected = R"(MyGame.Example.Monster{
   109        pos = MyGame.Example.Vec3{
   110          x = 1.1
   111          y = 2.2
   112          z = 3.3
   113          test1 = 6.6
   114          test2 = 2
   115          test3 = MyGame.Example.Test{
   116            a = 11
   117            b = 90
   118          }
   119        }
   120        mana = 1
   121        hp = 2
   122        name = "my_monster"
   123        inventory = [
   124          4,
   125          5,
   126          6,
   127          7
   128        ]
   129        color = 8
   130        test_type = 0
   131        testbool = 1
   132        testhashs32_fnv1 = 4
   133        testhashu32_fnv1 = 5
   134        testhashs64_fnv1 = 6
   135        testhashu64_fnv1 = 7
   136        testhashs32_fnv1a = 8
   137        testhashu32_fnv1a = 9
   138        testhashs64_fnv1a = 10
   139        testhashu64_fnv1a = 11
   140        testf = 12.1
   141        testf2 = 13.1
   142        testf3 = 14.1
   143        single_weak_reference = 15
   144        co_owning_reference = 16
   145        non_owning_reference = 17
   146        any_unique_type = 0
   147        any_ambiguous_type = 0
   148        signed_enum = -1
   149        long_enum_non_enum_default = 0
   150        long_enum_normal_default = 2
   151        nan_default = nan
   152        inf_default = inf
   153        positive_inf_default = inf
   154        infinity_default = inf
   155        positive_infinity_default = inf
   156        negative_inf_default = -inf
   157        negative_infinity_default = -inf
   158        double_inf_default = inf
   159      })";
   160
   161  // Call a generic function that has no specific knowledge of the flatbuffer we
   162  // are passing in; it should use only static reflection to produce a string
   163  // representations of the field names and values recursively. We give it an
   164  // initial indentation so that the result can be compared with our raw string
   165  // above, which we wanted to indent so that it will look nicer in this code.
   166  //
   167  // A note about JSON: as can be seen from the string above, this produces a
   168  // JSON-like notation, but we are not using any of Flatbuffers' JSON infra to
   169  // produce this! It is produced entirely using compile-time reflection, and
   170  // thus does not require any runtime access to the *.fbs definition files!
   171  std::optional<std::string> result =
   172      cpp17::StringifyFlatbufferValue(*monster, /*indent=*/"      ");
   173
   174  TEST_ASSERT(result.has_value());
   175  TEST_EQ_STR(expected.c_str(), result->c_str());
   176}
   177
   178/*******************************************************************************
   179** Test Traits::FieldType
   180*******************************************************************************/
   181using pos_type = Monster::Traits::FieldType<0>;
   182static_assert(std::is_same_v<pos_type, const Vec3 *>);
   183
   184using mana_type = Monster::Traits::FieldType<1>;
   185static_assert(std::is_same_v<mana_type, int16_t>);
   186
   187using name_type = Monster::Traits::FieldType<3>;
   188static_assert(std::is_same_v<name_type, const flatbuffers::String *>);
   189
   190/*******************************************************************************
   191** Generic Create Function Test.
   192*******************************************************************************/
   193void CreateTableByTypeTest() {
   194  flatbuffers::FlatBufferBuilder builder;
   195
   196  // We will create an object of this type using only the type.
   197  using type_to_create_t = cpp17::MyGame::Example::Stat;
   198
   199  [&builder] {
   200    auto id_str = builder.CreateString("my_id");
   201    auto table = type_to_create_t::Traits::Create(builder, id_str, 42, 7);
   202    // Be sure that the correct return type was inferred.
   203    static_assert(
   204        std::is_same_v<decltype(table), flatbuffers::Offset<type_to_create_t>>);
   205    builder.Finish(table);
   206  }();
   207
   208  // Access it.
   209  auto stat =
   210      flatbuffers::GetRoot<type_to_create_t>(builder.GetBufferPointer());
   211  TEST_EQ_STR(stat->id()->c_str(), "my_id");
   212  TEST_EQ(stat->val(), 42);
   213  TEST_EQ(stat->count(), 7);
   214}
   215
   216void OptionalScalarsTest() {
   217  static_assert(
   218      std::is_same<flatbuffers::Optional<float>, std::optional<float>>::value);
   219  static_assert(std::is_same<flatbuffers::nullopt_t, std::nullopt_t>::value);
   220
   221  // test C++ nullable
   222  flatbuffers::FlatBufferBuilder fbb;
   223  FinishScalarStuffBuffer(fbb, cpp17::optional_scalars::CreateScalarStuff(
   224                                   fbb, 1, static_cast<int8_t>(2)));
   225  auto opts =
   226      cpp17::optional_scalars::GetMutableScalarStuff(fbb.GetBufferPointer());
   227  TEST_ASSERT(!opts->maybe_bool());
   228  TEST_ASSERT(!opts->maybe_f32().has_value());
   229  TEST_ASSERT(opts->maybe_i8().has_value());
   230  TEST_EQ(opts->maybe_i8().value(), 2);
   231  TEST_ASSERT(opts->mutate_maybe_i8(3));
   232  TEST_ASSERT(opts->maybe_i8().has_value());
   233  TEST_EQ(opts->maybe_i8().value(), 3);
   234  TEST_ASSERT(!opts->mutate_maybe_i16(-10));
   235
   236  cpp17::optional_scalars::ScalarStuffT obj;
   237  opts->UnPackTo(&obj);
   238  TEST_ASSERT(!obj.maybe_bool);
   239  TEST_ASSERT(!obj.maybe_f32.has_value());
   240  TEST_ASSERT(obj.maybe_i8.has_value() && obj.maybe_i8.value() == 3);
   241  TEST_ASSERT(obj.maybe_i8 && *obj.maybe_i8 == 3);
   242  obj.maybe_i32 = -1;
   243
   244  fbb.Clear();
   245  FinishScalarStuffBuffer(
   246      fbb, cpp17::optional_scalars::ScalarStuff::Pack(fbb, &obj));
   247  opts = cpp17::optional_scalars::GetMutableScalarStuff(fbb.GetBufferPointer());
   248  TEST_ASSERT(opts->maybe_i8().has_value());
   249  TEST_EQ(opts->maybe_i8().value(), 3);
   250  TEST_ASSERT(opts->maybe_i32().has_value());
   251  TEST_EQ(opts->maybe_i32().value(), -1);
   252
   253  TEST_EQ(std::optional<int32_t>(opts->maybe_i32()).value(), -1);
   254  TEST_EQ(std::optional<int64_t>(opts->maybe_i32()).value(), -1);
   255  TEST_ASSERT(opts->maybe_i32() == std::optional<int64_t>(-1));
   256}
   257
   258int FlatBufferCpp17Tests() {
   259  CreateTableByTypeTest();
   260  OptionalScalarsTest();
   261  StringifyAnyFlatbuffersTypeTest();
   262  return 0;
   263}
   264}  // namespace
   265
   266int main(int /*argc*/, const char * /*argv*/[]) {
   267  InitTestEngine();
   268
   269  FlatBufferCpp17Tests();
   270
   271  if (!testing_fails) {
   272    TEST_OUTPUT_LINE("C++17: ALL TESTS PASSED");
   273  } else {
   274    TEST_OUTPUT_LINE("C++17: %d FAILED TESTS", testing_fails);
   275  }
   276  return CloseTestEngine();
   277}

View as plain text