blob: 5555e907175fd8db65fc74f61020dbc0c593e585 [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001#ifndef TEST_BUILDER_H
2#define TEST_BUILDER_H
3
4#include <set>
5#include <type_traits>
Austin Schuh272c6132020-11-14 16:37:52 -08006
Austin Schuhe89fa2d2019-08-14 20:24:23 -07007#include "flatbuffers/flatbuffers.h"
Austin Schuh272c6132020-11-14 16:37:52 -08008#include "monster_test_generated.h"
Austin Schuhe89fa2d2019-08-14 20:24:23 -07009#include "test_assert.h"
10
11using MyGame::Example::Color;
12using MyGame::Example::Monster;
13
14namespace flatbuffers {
15namespace grpc {
16class MessageBuilder;
17}
Austin Schuh272c6132020-11-14 16:37:52 -080018} // namespace flatbuffers
19
20template<class T, class U> struct is_same { static const bool value = false; };
21
22template<class T> struct is_same<T, T> { static const bool value = true; };
23
24inline std::string m1_name() { return "Cyberdemon"; }
25inline std::string m2_name() { return "Imp"; }
26inline MyGame::Example::Color m1_color() {
27 return MyGame::Example::Color_Red;
Austin Schuhe89fa2d2019-08-14 20:24:23 -070028}
Austin Schuh272c6132020-11-14 16:37:52 -080029inline MyGame::Example::Color m2_color() {
30 return MyGame::Example::Color_Green;
31}
32inline void m1_color_check() {
33 // Ensure that all compilation units see the same monster_test_generated.h.
34 extern void CheckTestGeneratedIsValid(const MyGame::Example::Color&);
35 CheckTestGeneratedIsValid(m1_color());
36}
Austin Schuhe89fa2d2019-08-14 20:24:23 -070037
38flatbuffers::Offset<Monster> populate1(flatbuffers::FlatBufferBuilder &builder);
39flatbuffers::Offset<Monster> populate2(flatbuffers::FlatBufferBuilder &builder);
40
Austin Schuh272c6132020-11-14 16:37:52 -080041uint8_t *release_raw_base(flatbuffers::FlatBufferBuilder &fbb, size_t &size,
42 size_t &offset);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070043
44void free_raw(flatbuffers::grpc::MessageBuilder &mbb, uint8_t *buf);
45void free_raw(flatbuffers::FlatBufferBuilder &fbb, uint8_t *buf);
46
Austin Schuh272c6132020-11-14 16:37:52 -080047bool verify(const flatbuffers::DetachedBuffer &buf,
48 const std::string &expected_name, Color color);
49bool verify(const uint8_t *buf, size_t offset, const std::string &expected_name,
50 Color color);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070051
Austin Schuh272c6132020-11-14 16:37:52 -080052bool release_n_verify(flatbuffers::FlatBufferBuilder &fbb,
53 const std::string &expected_name, Color color);
54bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb,
55 const std::string &expected_name, Color color);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070056
57// clang-format off
58#if !defined(FLATBUFFERS_CPP98_STL)
59// clang-format on
60// Invokes this function when testing the following Builder types
61// FlatBufferBuilder, TestHeapBuilder, and GrpcLikeMessageBuilder
Austin Schuh272c6132020-11-14 16:37:52 -080062template<class Builder>
Austin Schuhe89fa2d2019-08-14 20:24:23 -070063void builder_move_assign_after_releaseraw_test(Builder b1) {
64 auto root_offset1 = populate1(b1);
65 b1.Finish(root_offset1);
66 size_t size, offset;
Austin Schuh272c6132020-11-14 16:37:52 -080067 std::shared_ptr<uint8_t> raw(
68 b1.ReleaseRaw(size, offset), [size](uint8_t *ptr) {
69 flatbuffers::DefaultAllocator::dealloc(ptr, size);
70 });
Austin Schuhe89fa2d2019-08-14 20:24:23 -070071 Builder src;
72 auto root_offset2 = populate2(src);
73 src.Finish(root_offset2);
74 auto src_size = src.GetSize();
75 // Move into a released builder.
76 b1 = std::move(src);
77 TEST_EQ_FUNC(b1.GetSize(), src_size);
Austin Schuh272c6132020-11-14 16:37:52 -080078 TEST_ASSERT_FUNC(release_n_verify(b1, m2_name(), m2_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -070079 TEST_EQ_FUNC(src.GetSize(), 0);
80}
81// clang-format off
82#endif // !defined(FLATBUFFERS_CPP98_STL)
83// clang-format on
84
Austin Schuh272c6132020-11-14 16:37:52 -080085void builder_move_assign_after_releaseraw_test(
86 flatbuffers::grpc::MessageBuilder b1);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070087
Austin Schuh272c6132020-11-14 16:37:52 -080088template<class DestBuilder, class SrcBuilder = DestBuilder>
Austin Schuhe89fa2d2019-08-14 20:24:23 -070089struct BuilderTests {
90 // clang-format off
91 #if !defined(FLATBUFFERS_CPP98_STL)
92 // clang-format on
93 static void empty_builder_movector_test() {
94 SrcBuilder src;
95 size_t src_size = src.GetSize();
96 DestBuilder dst(std::move(src));
97 size_t dst_size = dst.GetSize();
98 TEST_EQ_FUNC(src_size, 0);
99 TEST_EQ_FUNC(src_size, dst_size);
100 }
101
102 static void nonempty_builder_movector_test() {
103 SrcBuilder src;
104 populate1(src);
105 size_t src_size = src.GetSize();
106 DestBuilder dst(std::move(src));
107 TEST_EQ_FUNC(src_size, dst.GetSize());
108 TEST_EQ_FUNC(src.GetSize(), 0);
109 }
110
111 static void builder_movector_before_finish_test() {
112 SrcBuilder src;
113 auto root_offset1 = populate1(src);
114 DestBuilder dst(std::move(src));
115 dst.Finish(root_offset1);
Austin Schuh272c6132020-11-14 16:37:52 -0800116 TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700117 TEST_EQ_FUNC(src.GetSize(), 0);
118 }
119
120 static void builder_movector_after_finish_test() {
121 SrcBuilder src;
122 auto root_offset1 = populate1(src);
123 src.Finish(root_offset1);
124 auto src_size = src.GetSize();
125 DestBuilder dst(std::move(src));
126 TEST_EQ_FUNC(dst.GetSize(), src_size);
Austin Schuh272c6132020-11-14 16:37:52 -0800127 TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700128 TEST_EQ_FUNC(src.GetSize(), 0);
129 }
130
131 static void builder_move_assign_before_finish_test() {
132 SrcBuilder src;
133 auto root_offset1 = populate1(src);
134 DestBuilder dst;
135 populate2(dst);
136 dst = std::move(src);
137 dst.Finish(root_offset1);
Austin Schuh272c6132020-11-14 16:37:52 -0800138 TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700139 TEST_EQ_FUNC(src.GetSize(), 0);
140 }
141
142 static void builder_move_assign_after_finish_test() {
143 SrcBuilder src;
144 auto root_offset1 = populate1(src);
145 src.Finish(root_offset1);
146 auto src_size = src.GetSize();
147 DestBuilder dst;
148 auto root_offset2 = populate2(dst);
149 dst.Finish(root_offset2);
150 dst = std::move(src);
151 TEST_EQ_FUNC(dst.GetSize(), src_size);
Austin Schuh272c6132020-11-14 16:37:52 -0800152 TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700153 TEST_EQ_FUNC(src.GetSize(), 0);
154 }
155
156 static void builder_move_assign_after_release_test() {
157 DestBuilder dst;
158 auto root_offset1 = populate1(dst);
159 dst.Finish(root_offset1);
160 {
161 flatbuffers::DetachedBuffer dst_detached = dst.Release();
162 // detached buffer is deleted
163 }
164 SrcBuilder src;
165 auto root_offset2 = populate2(src);
166 src.Finish(root_offset2);
167 auto src_size = src.GetSize();
168 // Move into a released builder.
169 dst = std::move(src);
170 TEST_EQ_FUNC(dst.GetSize(), src_size);
Austin Schuh272c6132020-11-14 16:37:52 -0800171 TEST_ASSERT_FUNC(release_n_verify(dst, m2_name(), m2_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700172 TEST_EQ_FUNC(src.GetSize(), 0);
173 }
174 // clang-format off
175 #endif // !defined(FLATBUFFERS_CPP98_STL)
176 // clang-format on
177
Austin Schuh272c6132020-11-14 16:37:52 -0800178 static void builder_swap_before_finish_test(
179 bool run = is_same<DestBuilder, SrcBuilder>::value) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700180 /// Swap is allowed only when lhs and rhs are the same concrete type.
Austin Schuh272c6132020-11-14 16:37:52 -0800181 if (run) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700182 SrcBuilder src;
183 auto root_offset1 = populate1(src);
184 auto size1 = src.GetSize();
185 DestBuilder dst;
186 auto root_offset2 = populate2(dst);
187 auto size2 = dst.GetSize();
188 src.Swap(dst);
189 src.Finish(root_offset2);
190 dst.Finish(root_offset1);
191 TEST_EQ_FUNC(src.GetSize() > size2, true);
192 TEST_EQ_FUNC(dst.GetSize() > size1, true);
Austin Schuh272c6132020-11-14 16:37:52 -0800193 TEST_ASSERT_FUNC(release_n_verify(src, m2_name(), m2_color()));
194 TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700195 }
196 }
197
Austin Schuh272c6132020-11-14 16:37:52 -0800198 static void builder_swap_after_finish_test(
199 bool run = is_same<DestBuilder, SrcBuilder>::value) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700200 /// Swap is allowed only when lhs and rhs are the same concrete type.
Austin Schuh272c6132020-11-14 16:37:52 -0800201 if (run) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700202 SrcBuilder src;
203 auto root_offset1 = populate1(src);
204 src.Finish(root_offset1);
205 auto size1 = src.GetSize();
206 DestBuilder dst;
207 auto root_offset2 = populate2(dst);
208 dst.Finish(root_offset2);
209 auto size2 = dst.GetSize();
210 src.Swap(dst);
211 TEST_EQ_FUNC(src.GetSize(), size2);
212 TEST_EQ_FUNC(dst.GetSize(), size1);
Austin Schuh272c6132020-11-14 16:37:52 -0800213 TEST_ASSERT_FUNC(release_n_verify(src, m2_name(), m2_color()));
214 TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700215 }
216 }
217
218 static void all_tests() {
219 // clang-format off
220 #if !defined(FLATBUFFERS_CPP98_STL)
221 // clang-format on
222 empty_builder_movector_test();
223 nonempty_builder_movector_test();
224 builder_movector_before_finish_test();
225 builder_movector_after_finish_test();
226 builder_move_assign_before_finish_test();
227 builder_move_assign_after_finish_test();
228 builder_move_assign_after_release_test();
229 builder_move_assign_after_releaseraw_test(DestBuilder());
230 // clang-format off
231 #endif // !defined(FLATBUFFERS_CPP98_STL)
232 // clang-format on
233 builder_swap_before_finish_test();
234 builder_swap_after_finish_test();
235 }
236};
237
238enum BuilderReuseTestSelector {
239 REUSABLE_AFTER_RELEASE = 1,
240 REUSABLE_AFTER_RELEASE_RAW = 2,
241 REUSABLE_AFTER_RELEASE_MESSAGE = 3,
242 REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN = 4,
243 REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN = 5,
244 REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN = 6
245};
246
247typedef std::set<BuilderReuseTestSelector> TestSelector;
248
Austin Schuh272c6132020-11-14 16:37:52 -0800249template<class DestBuilder, class SrcBuilder> struct BuilderReuseTests {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700250 static void builder_reusable_after_release_test(TestSelector selector) {
Austin Schuh272c6132020-11-14 16:37:52 -0800251 if (!selector.count(REUSABLE_AFTER_RELEASE)) { return; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700252
253 DestBuilder fbb;
254 std::vector<flatbuffers::DetachedBuffer> buffers;
255 for (int i = 0; i < 5; ++i) {
256 auto root_offset1 = populate1(fbb);
257 fbb.Finish(root_offset1);
258 buffers.push_back(fbb.Release());
Austin Schuh272c6132020-11-14 16:37:52 -0800259 TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700260 }
261 }
262
263 static void builder_reusable_after_releaseraw_test(TestSelector selector) {
Austin Schuh272c6132020-11-14 16:37:52 -0800264 if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { return; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700265
266 DestBuilder fbb;
267 for (int i = 0; i < 5; ++i) {
268 auto root_offset1 = populate1(fbb);
269 fbb.Finish(root_offset1);
270 size_t size, offset;
271 uint8_t *buf = release_raw_base(fbb, size, offset);
Austin Schuh272c6132020-11-14 16:37:52 -0800272 TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700273 free_raw(fbb, buf);
274 }
275 }
276
277 // clang-format off
278 #if !defined(FLATBUFFERS_CPP98_STL)
279 // clang-format on
Austin Schuh272c6132020-11-14 16:37:52 -0800280 static void builder_reusable_after_release_and_move_assign_test(
281 TestSelector selector) {
282 if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) { return; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700283
284 DestBuilder dst;
285 std::vector<flatbuffers::DetachedBuffer> buffers;
286 for (int i = 0; i < 5; ++i) {
287 auto root_offset1 = populate1(dst);
288 dst.Finish(root_offset1);
289 buffers.push_back(dst.Release());
Austin Schuh272c6132020-11-14 16:37:52 -0800290 TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700291 SrcBuilder src;
292 dst = std::move(src);
293 TEST_EQ_FUNC(src.GetSize(), 0);
294 }
295 }
296
Austin Schuh272c6132020-11-14 16:37:52 -0800297 static void builder_reusable_after_releaseraw_and_move_assign_test(
298 TestSelector selector) {
299 if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) { return; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700300
301 DestBuilder dst;
302 for (int i = 0; i < 5; ++i) {
303 auto root_offset1 = populate1(dst);
304 dst.Finish(root_offset1);
305 size_t size, offset;
306 uint8_t *buf = release_raw_base(dst, size, offset);
Austin Schuh272c6132020-11-14 16:37:52 -0800307 TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700308 free_raw(dst, buf);
309 SrcBuilder src;
310 dst = std::move(src);
311 TEST_EQ_FUNC(src.GetSize(), 0);
312 }
313 }
314 // clang-format off
315 #endif // !defined(FLATBUFFERS_CPP98_STL)
316 // clang-format on
317
318 static void run_tests(TestSelector selector) {
319 builder_reusable_after_release_test(selector);
320 builder_reusable_after_releaseraw_test(selector);
321 // clang-format off
322 #if !defined(FLATBUFFERS_CPP98_STL)
323 // clang-format on
324 builder_reusable_after_release_and_move_assign_test(selector);
325 builder_reusable_after_releaseraw_and_move_assign_test(selector);
326 // clang-format off
327 #endif // !defined(FLATBUFFERS_CPP98_STL)
328 // clang-format on
329 }
330};
331
Austin Schuh272c6132020-11-14 16:37:52 -0800332#endif // TEST_BUILDER_H