Home | History | Annotate | Download | only in tests
      1 #ifndef TEST_BUILDER_H
      2 #define TEST_BUILDER_H
      3 
      4 #include <set>
      5 #include <type_traits>
      6 #include "monster_test_generated.h"
      7 #include "flatbuffers/flatbuffers.h"
      8 #include "test_assert.h"
      9 
     10 using MyGame::Example::Color;
     11 using MyGame::Example::Monster;
     12 
     13 namespace flatbuffers {
     14 namespace grpc {
     15 class MessageBuilder;
     16 }
     17 }
     18 
     19 template <class T, class U>
     20 struct is_same {
     21   static const bool value = false;
     22 };
     23 
     24 template <class T>
     25 struct is_same<T, T> {
     26   static const bool value = true;
     27 };
     28 
     29 extern const std::string m1_name;
     30 extern const Color m1_color;
     31 extern const std::string m2_name;
     32 extern const Color m2_color;
     33 
     34 flatbuffers::Offset<Monster> populate1(flatbuffers::FlatBufferBuilder &builder);
     35 flatbuffers::Offset<Monster> populate2(flatbuffers::FlatBufferBuilder &builder);
     36 
     37 uint8_t *release_raw_base(flatbuffers::FlatBufferBuilder &fbb, size_t &size, size_t &offset);
     38 
     39 void free_raw(flatbuffers::grpc::MessageBuilder &mbb, uint8_t *buf);
     40 void free_raw(flatbuffers::FlatBufferBuilder &fbb, uint8_t *buf);
     41 
     42 bool verify(const flatbuffers::DetachedBuffer &buf, const std::string &expected_name, Color color);
     43 bool verify(const uint8_t *buf, size_t offset, const std::string &expected_name, Color color);
     44 
     45 bool release_n_verify(flatbuffers::FlatBufferBuilder &fbb, const std::string &expected_name, Color color);
     46 bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb, const std::string &expected_name, Color color);
     47 
     48 // clang-format off
     49 #if !defined(FLATBUFFERS_CPP98_STL)
     50 // clang-format on
     51 // Invokes this function when testing the following Builder types
     52 // FlatBufferBuilder, TestHeapBuilder, and GrpcLikeMessageBuilder
     53 template <class Builder>
     54 void builder_move_assign_after_releaseraw_test(Builder b1) {
     55   auto root_offset1 = populate1(b1);
     56   b1.Finish(root_offset1);
     57   size_t size, offset;
     58   std::shared_ptr<uint8_t> raw(b1.ReleaseRaw(size, offset), [size](uint8_t *ptr) {
     59     flatbuffers::DefaultAllocator::dealloc(ptr, size);
     60   });
     61   Builder src;
     62   auto root_offset2 = populate2(src);
     63   src.Finish(root_offset2);
     64   auto src_size = src.GetSize();
     65   // Move into a released builder.
     66   b1 = std::move(src);
     67   TEST_EQ_FUNC(b1.GetSize(), src_size);
     68   TEST_ASSERT_FUNC(release_n_verify(b1, m2_name, m2_color));
     69   TEST_EQ_FUNC(src.GetSize(), 0);
     70 }
     71 // clang-format off
     72 #endif  // !defined(FLATBUFFERS_CPP98_STL)
     73 // clang-format on
     74 
     75 void builder_move_assign_after_releaseraw_test(flatbuffers::grpc::MessageBuilder b1);
     76 
     77 template <class DestBuilder, class SrcBuilder = DestBuilder>
     78 struct BuilderTests {
     79   // clang-format off
     80   #if !defined(FLATBUFFERS_CPP98_STL)
     81   // clang-format on
     82   static void empty_builder_movector_test() {
     83     SrcBuilder src;
     84     size_t src_size = src.GetSize();
     85     DestBuilder dst(std::move(src));
     86     size_t dst_size = dst.GetSize();
     87     TEST_EQ_FUNC(src_size, 0);
     88     TEST_EQ_FUNC(src_size, dst_size);
     89   }
     90 
     91   static void nonempty_builder_movector_test() {
     92     SrcBuilder src;
     93     populate1(src);
     94     size_t src_size = src.GetSize();
     95     DestBuilder dst(std::move(src));
     96     TEST_EQ_FUNC(src_size, dst.GetSize());
     97     TEST_EQ_FUNC(src.GetSize(), 0);
     98   }
     99 
    100   static void builder_movector_before_finish_test() {
    101     SrcBuilder src;
    102     auto root_offset1 = populate1(src);
    103     DestBuilder dst(std::move(src));
    104     dst.Finish(root_offset1);
    105     TEST_ASSERT_FUNC(release_n_verify(dst, m1_name, m1_color));
    106     TEST_EQ_FUNC(src.GetSize(), 0);
    107   }
    108 
    109   static void builder_movector_after_finish_test() {
    110     SrcBuilder src;
    111     auto root_offset1 = populate1(src);
    112     src.Finish(root_offset1);
    113     auto src_size = src.GetSize();
    114     DestBuilder dst(std::move(src));
    115     TEST_EQ_FUNC(dst.GetSize(), src_size);
    116     TEST_ASSERT_FUNC(release_n_verify(dst, m1_name, m1_color));
    117     TEST_EQ_FUNC(src.GetSize(), 0);
    118   }
    119 
    120   static void builder_move_assign_before_finish_test() {
    121     SrcBuilder src;
    122     auto root_offset1 = populate1(src);
    123     DestBuilder dst;
    124     populate2(dst);
    125     dst = std::move(src);
    126     dst.Finish(root_offset1);
    127     TEST_ASSERT_FUNC(release_n_verify(dst, m1_name, m1_color));
    128     TEST_EQ_FUNC(src.GetSize(), 0);
    129   }
    130 
    131   static void builder_move_assign_after_finish_test() {
    132     SrcBuilder src;
    133     auto root_offset1 = populate1(src);
    134     src.Finish(root_offset1);
    135     auto src_size = src.GetSize();
    136     DestBuilder dst;
    137     auto root_offset2 = populate2(dst);
    138     dst.Finish(root_offset2);
    139     dst = std::move(src);
    140     TEST_EQ_FUNC(dst.GetSize(), src_size);
    141     TEST_ASSERT_FUNC(release_n_verify(dst, m1_name, m1_color));
    142     TEST_EQ_FUNC(src.GetSize(), 0);
    143   }
    144 
    145   static void builder_move_assign_after_release_test() {
    146     DestBuilder dst;
    147     auto root_offset1 = populate1(dst);
    148     dst.Finish(root_offset1);
    149     {
    150       flatbuffers::DetachedBuffer dst_detached = dst.Release();
    151       // detached buffer is deleted
    152     }
    153     SrcBuilder src;
    154     auto root_offset2 = populate2(src);
    155     src.Finish(root_offset2);
    156     auto src_size = src.GetSize();
    157     // Move into a released builder.
    158     dst = std::move(src);
    159     TEST_EQ_FUNC(dst.GetSize(), src_size);
    160     TEST_ASSERT_FUNC(release_n_verify(dst, m2_name, m2_color));
    161     TEST_EQ_FUNC(src.GetSize(), 0);
    162   }
    163   // clang-format off
    164   #endif  // !defined(FLATBUFFERS_CPP98_STL)
    165   // clang-format on
    166 
    167   static void builder_swap_before_finish_test(bool run = is_same<DestBuilder, SrcBuilder>::value) {
    168     /// Swap is allowed only when lhs and rhs are the same concrete type.
    169     if(run) {
    170       SrcBuilder src;
    171       auto root_offset1 = populate1(src);
    172       auto size1 = src.GetSize();
    173       DestBuilder dst;
    174       auto root_offset2 = populate2(dst);
    175       auto size2 = dst.GetSize();
    176       src.Swap(dst);
    177       src.Finish(root_offset2);
    178       dst.Finish(root_offset1);
    179       TEST_EQ_FUNC(src.GetSize() > size2, true);
    180       TEST_EQ_FUNC(dst.GetSize() > size1, true);
    181       TEST_ASSERT_FUNC(release_n_verify(src, m2_name, m2_color));
    182       TEST_ASSERT_FUNC(release_n_verify(dst, m1_name, m1_color));
    183     }
    184   }
    185 
    186   static void builder_swap_after_finish_test(bool run = is_same<DestBuilder, SrcBuilder>::value) {
    187     /// Swap is allowed only when lhs and rhs are the same concrete type.
    188     if(run) {
    189       SrcBuilder src;
    190       auto root_offset1 = populate1(src);
    191       src.Finish(root_offset1);
    192       auto size1 = src.GetSize();
    193       DestBuilder dst;
    194       auto root_offset2 = populate2(dst);
    195       dst.Finish(root_offset2);
    196       auto size2 = dst.GetSize();
    197       src.Swap(dst);
    198       TEST_EQ_FUNC(src.GetSize(), size2);
    199       TEST_EQ_FUNC(dst.GetSize(), size1);
    200       TEST_ASSERT_FUNC(release_n_verify(src, m2_name, m2_color));
    201       TEST_ASSERT_FUNC(release_n_verify(dst, m1_name, m1_color));
    202     }
    203   }
    204 
    205   static void all_tests() {
    206     // clang-format off
    207     #if !defined(FLATBUFFERS_CPP98_STL)
    208     // clang-format on
    209     empty_builder_movector_test();
    210     nonempty_builder_movector_test();
    211     builder_movector_before_finish_test();
    212     builder_movector_after_finish_test();
    213     builder_move_assign_before_finish_test();
    214     builder_move_assign_after_finish_test();
    215     builder_move_assign_after_release_test();
    216     builder_move_assign_after_releaseraw_test(DestBuilder());
    217     // clang-format off
    218     #endif   // !defined(FLATBUFFERS_CPP98_STL)
    219     // clang-format on
    220     builder_swap_before_finish_test();
    221     builder_swap_after_finish_test();
    222   }
    223 };
    224 
    225 enum BuilderReuseTestSelector {
    226   REUSABLE_AFTER_RELEASE = 1,
    227   REUSABLE_AFTER_RELEASE_RAW = 2,
    228   REUSABLE_AFTER_RELEASE_MESSAGE = 3,
    229   REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN = 4,
    230   REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN = 5,
    231   REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN = 6
    232 };
    233 
    234 typedef std::set<BuilderReuseTestSelector> TestSelector;
    235 
    236 template <class DestBuilder, class SrcBuilder>
    237 struct BuilderReuseTests {
    238   static void builder_reusable_after_release_test(TestSelector selector) {
    239     if (!selector.count(REUSABLE_AFTER_RELEASE)) {
    240       return;
    241     }
    242 
    243     DestBuilder fbb;
    244     std::vector<flatbuffers::DetachedBuffer> buffers;
    245     for (int i = 0; i < 5; ++i) {
    246       auto root_offset1 = populate1(fbb);
    247       fbb.Finish(root_offset1);
    248       buffers.push_back(fbb.Release());
    249       TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
    250     }
    251   }
    252 
    253   static void builder_reusable_after_releaseraw_test(TestSelector selector) {
    254     if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) {
    255       return;
    256     }
    257 
    258     DestBuilder fbb;
    259     for (int i = 0; i < 5; ++i) {
    260       auto root_offset1 = populate1(fbb);
    261       fbb.Finish(root_offset1);
    262       size_t size, offset;
    263       uint8_t *buf = release_raw_base(fbb, size, offset);
    264       TEST_ASSERT_FUNC(verify(buf, offset, m1_name, m1_color));
    265       free_raw(fbb, buf);
    266     }
    267   }
    268 
    269   // clang-format off
    270   #if !defined(FLATBUFFERS_CPP98_STL)
    271   // clang-format on
    272   static void builder_reusable_after_release_and_move_assign_test(TestSelector selector) {
    273     if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) {
    274       return;
    275     }
    276 
    277     DestBuilder dst;
    278     std::vector<flatbuffers::DetachedBuffer> buffers;
    279     for (int i = 0; i < 5; ++i) {
    280       auto root_offset1 = populate1(dst);
    281       dst.Finish(root_offset1);
    282       buffers.push_back(dst.Release());
    283       TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
    284       SrcBuilder src;
    285       dst = std::move(src);
    286       TEST_EQ_FUNC(src.GetSize(), 0);
    287     }
    288   }
    289 
    290   static void builder_reusable_after_releaseraw_and_move_assign_test(TestSelector selector) {
    291     if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) {
    292       return;
    293     }
    294 
    295     DestBuilder dst;
    296     for (int i = 0; i < 5; ++i) {
    297       auto root_offset1 = populate1(dst);
    298       dst.Finish(root_offset1);
    299       size_t size, offset;
    300       uint8_t *buf = release_raw_base(dst, size, offset);
    301       TEST_ASSERT_FUNC(verify(buf, offset, m1_name, m1_color));
    302       free_raw(dst, buf);
    303       SrcBuilder src;
    304       dst = std::move(src);
    305       TEST_EQ_FUNC(src.GetSize(), 0);
    306     }
    307   }
    308   // clang-format off
    309   #endif  // !defined(FLATBUFFERS_CPP98_STL)
    310   // clang-format on
    311 
    312   static void run_tests(TestSelector selector) {
    313     builder_reusable_after_release_test(selector);
    314     builder_reusable_after_releaseraw_test(selector);
    315     // clang-format off
    316     #if !defined(FLATBUFFERS_CPP98_STL)
    317     // clang-format on
    318     builder_reusable_after_release_and_move_assign_test(selector);
    319     builder_reusable_after_releaseraw_and_move_assign_test(selector);
    320     // clang-format off
    321     #endif  // !defined(FLATBUFFERS_CPP98_STL)
    322     // clang-format on
    323   }
    324 };
    325 
    326 #endif // TEST_BUILDER_H
    327