File: test_builder.h

package info (click to toggle)
golang-github-google-flatbuffers 24.12.23-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 17,704 kB
  • sloc: cpp: 53,217; python: 6,900; cs: 5,566; java: 4,370; php: 1,460; javascript: 1,061; xml: 1,016; sh: 886; makefile: 13
file content (300 lines) | stat: -rw-r--r-- 9,954 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
#ifndef TEST_BUILDER_H
#define TEST_BUILDER_H

#include <set>
#include <type_traits>

#include "flatbuffers/flatbuffers.h"
#include "monster_test_generated.h"
#include "test_assert.h"

using MyGame::Example::Color;
using MyGame::Example::Monster;

namespace flatbuffers {
namespace grpc {
class MessageBuilder;
}
}  // namespace flatbuffers

inline std::string m1_name() { return "Cyberdemon"; }
inline std::string m2_name() { return "Imp"; }
inline MyGame::Example::Color m1_color() {
  return MyGame::Example::Color_Red;
}
inline MyGame::Example::Color m2_color() {
  return MyGame::Example::Color_Green;
}
inline void m1_color_check() {
  // Ensure that all compilation units see the same monster_test_generated.h.
  extern void CheckTestGeneratedIsValid(const MyGame::Example::Color&);
  CheckTestGeneratedIsValid(m1_color());
}

flatbuffers::Offset<Monster> populate1(flatbuffers::FlatBufferBuilder &builder);
flatbuffers::Offset<Monster> populate2(flatbuffers::FlatBufferBuilder &builder);

uint8_t *release_raw_base(flatbuffers::FlatBufferBuilder &fbb, size_t &size,
                          size_t &offset);

void free_raw(flatbuffers::grpc::MessageBuilder &mbb, uint8_t *buf);
void free_raw(flatbuffers::FlatBufferBuilder &fbb, uint8_t *buf);

bool verify(const flatbuffers::DetachedBuffer &buf,
            const std::string &expected_name, Color color);
bool verify(const uint8_t *buf, size_t offset, const std::string &expected_name,
            Color color);

bool release_n_verify(flatbuffers::FlatBufferBuilder &fbb,
                      const std::string &expected_name, Color color);
bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb,
                      const std::string &expected_name, Color color);

// Invokes this function when testing the following Builder types
// FlatBufferBuilder, TestHeapBuilder, and GrpcLikeMessageBuilder
template<class Builder>
void builder_move_assign_after_releaseraw_test(Builder b1) {
  auto root_offset1 = populate1(b1);
  b1.Finish(root_offset1);
  size_t size, offset;

  uint8_t *rr = b1.ReleaseRaw(size, offset);
  std::shared_ptr<uint8_t> raw(
      rr, [size](uint8_t *ptr) {
        flatbuffers::DefaultAllocator::dealloc(ptr, size);
      });
  Builder src;
  auto root_offset2 = populate2(src);
  src.Finish(root_offset2);
  auto src_size = src.GetSize();
  // Move into a released builder.
  b1 = std::move(src);
  TEST_EQ_FUNC(b1.GetSize(), src_size);
  TEST_ASSERT_FUNC(release_n_verify(b1, m2_name(), m2_color()));
  TEST_EQ_FUNC(src.GetSize(), 0);
}

void builder_move_assign_after_releaseraw_test(
    flatbuffers::grpc::MessageBuilder b1);

template<class DestBuilder, class SrcBuilder = DestBuilder>
struct BuilderTests {
  static void empty_builder_movector_test() {
    SrcBuilder src;
    size_t src_size = src.GetSize();
    DestBuilder dst(std::move(src));
    size_t dst_size = dst.GetSize();
    TEST_EQ_FUNC(src_size, 0);
    TEST_EQ_FUNC(src_size, dst_size);
  }

  static void nonempty_builder_movector_test() {
    SrcBuilder src;
    populate1(src);
    size_t src_size = src.GetSize();
    DestBuilder dst(std::move(src));
    TEST_EQ_FUNC(src_size, dst.GetSize());
    TEST_EQ_FUNC(src.GetSize(), 0);
  }

  static void builder_movector_before_finish_test() {
    SrcBuilder src;
    auto root_offset1 = populate1(src);
    DestBuilder dst(std::move(src));
    dst.Finish(root_offset1);
    TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
    TEST_EQ_FUNC(src.GetSize(), 0);
  }

  static void builder_movector_after_finish_test() {
    SrcBuilder src;
    auto root_offset1 = populate1(src);
    src.Finish(root_offset1);
    auto src_size = src.GetSize();
    DestBuilder dst(std::move(src));
    TEST_EQ_FUNC(dst.GetSize(), src_size);
    TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
    TEST_EQ_FUNC(src.GetSize(), 0);
  }

  static void builder_move_assign_before_finish_test() {
    SrcBuilder src;
    auto root_offset1 = populate1(src);
    DestBuilder dst;
    populate2(dst);
    dst = std::move(src);
    dst.Finish(root_offset1);
    TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
    TEST_EQ_FUNC(src.GetSize(), 0);
  }

  static void builder_move_assign_after_finish_test() {
    SrcBuilder src;
    auto root_offset1 = populate1(src);
    src.Finish(root_offset1);
    auto src_size = src.GetSize();
    DestBuilder dst;
    auto root_offset2 = populate2(dst);
    dst.Finish(root_offset2);
    dst = std::move(src);
    TEST_EQ_FUNC(dst.GetSize(), src_size);
    TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
    TEST_EQ_FUNC(src.GetSize(), 0);
  }

  static void builder_move_assign_after_release_test() {
    DestBuilder dst;
    auto root_offset1 = populate1(dst);
    dst.Finish(root_offset1);
    {
      flatbuffers::DetachedBuffer dst_detached = dst.Release();
      // detached buffer is deleted
    }
    SrcBuilder src;
    auto root_offset2 = populate2(src);
    src.Finish(root_offset2);
    auto src_size = src.GetSize();
    // Move into a released builder.
    dst = std::move(src);
    TEST_EQ_FUNC(dst.GetSize(), src_size);
    TEST_ASSERT_FUNC(release_n_verify(dst, m2_name(), m2_color()));
    TEST_EQ_FUNC(src.GetSize(), 0);
  }

  static void builder_swap_before_finish_test(
      bool run = std::is_same<DestBuilder, SrcBuilder>::value) {
    /// Swap is allowed only when lhs and rhs are the same concrete type.
    if (run) {
      SrcBuilder src;
      auto root_offset1 = populate1(src);
      auto size1 = src.GetSize();
      DestBuilder dst;
      auto root_offset2 = populate2(dst);
      auto size2 = dst.GetSize();
      src.Swap(dst);
      src.Finish(root_offset2);
      dst.Finish(root_offset1);
      TEST_EQ_FUNC(src.GetSize() > size2, true);
      TEST_EQ_FUNC(dst.GetSize() > size1, true);
      TEST_ASSERT_FUNC(release_n_verify(src, m2_name(), m2_color()));
      TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
    }
  }

  static void builder_swap_after_finish_test(
      bool run = std::is_same<DestBuilder, SrcBuilder>::value) {
    /// Swap is allowed only when lhs and rhs are the same concrete type.
    if (run) {
      SrcBuilder src;
      auto root_offset1 = populate1(src);
      src.Finish(root_offset1);
      auto size1 = src.GetSize();
      DestBuilder dst;
      auto root_offset2 = populate2(dst);
      dst.Finish(root_offset2);
      auto size2 = dst.GetSize();
      src.Swap(dst);
      TEST_EQ_FUNC(src.GetSize(), size2);
      TEST_EQ_FUNC(dst.GetSize(), size1);
      TEST_ASSERT_FUNC(release_n_verify(src, m2_name(), m2_color()));
      TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
    }
  }

  static void all_tests() {
    empty_builder_movector_test();
    nonempty_builder_movector_test();
    builder_movector_before_finish_test();
    builder_movector_after_finish_test();
    builder_move_assign_before_finish_test();
    builder_move_assign_after_finish_test();
    builder_move_assign_after_release_test();
    builder_move_assign_after_releaseraw_test(DestBuilder());
    builder_swap_before_finish_test();
    builder_swap_after_finish_test();
  }
};

enum BuilderReuseTestSelector {
  REUSABLE_AFTER_RELEASE = 1,
  REUSABLE_AFTER_RELEASE_RAW = 2,
  REUSABLE_AFTER_RELEASE_MESSAGE = 3,
  REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN = 4,
  REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN = 5,
  REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN = 6
};

typedef std::set<BuilderReuseTestSelector> TestSelector;

template<class DestBuilder, class SrcBuilder> struct BuilderReuseTests {
  static void builder_reusable_after_release_test(TestSelector selector) {
    if (!selector.count(REUSABLE_AFTER_RELEASE)) { return; }

    DestBuilder fbb;
    std::vector<flatbuffers::DetachedBuffer> buffers;
    for (int i = 0; i < 5; ++i) {
      auto root_offset1 = populate1(fbb);
      fbb.Finish(root_offset1);
      buffers.push_back(fbb.Release());
      TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
    }
  }

  static void builder_reusable_after_releaseraw_test(TestSelector selector) {
    if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { return; }

    DestBuilder fbb;
    for (int i = 0; i < 5; ++i) {
      auto root_offset1 = populate1(fbb);
      fbb.Finish(root_offset1);
      size_t size, offset;
      uint8_t *buf = release_raw_base(fbb, size, offset);
      TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
      free_raw(fbb, buf);
    }
  }

  static void builder_reusable_after_release_and_move_assign_test(
      TestSelector selector) {
    if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) { return; }

    DestBuilder dst;
    std::vector<flatbuffers::DetachedBuffer> buffers;
    for (int i = 0; i < 5; ++i) {
      auto root_offset1 = populate1(dst);
      dst.Finish(root_offset1);
      buffers.push_back(dst.Release());
      TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
      SrcBuilder src;
      dst = std::move(src);
      TEST_EQ_FUNC(src.GetSize(), 0);
    }
  }

  static void builder_reusable_after_releaseraw_and_move_assign_test(
      TestSelector selector) {
    if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) { return; }

    DestBuilder dst;
    for (int i = 0; i < 5; ++i) {
      auto root_offset1 = populate1(dst);
      dst.Finish(root_offset1);
      size_t size, offset;
      uint8_t *buf = release_raw_base(dst, size, offset);
      TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
      free_raw(dst, buf);
      SrcBuilder src;
      dst = std::move(src);
      TEST_EQ_FUNC(src.GetSize(), 0);
    }
  }

  static void run_tests(TestSelector selector) {
    builder_reusable_after_release_test(selector);
    builder_reusable_after_releaseraw_test(selector);
    builder_reusable_after_release_and_move_assign_test(selector);
    builder_reusable_after_releaseraw_and_move_assign_test(selector);
  }
};

#endif  // TEST_BUILDER_H