1e2fa0adbef87a1e9777f97fd1efeae8a8ed68d8
[platform/upstream/flatbuffers.git] / tests / test_builder.h
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