blob: 1e2fa0adbef87a1e9777f97fd1efeae8a8ed68d8 [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>
6#include "monster_test_generated.h"
7#include "flatbuffers/flatbuffers.h"
8#include "test_assert.h"
9
10using MyGame::Example::Color;
11using MyGame::Example::Monster;
12
13namespace flatbuffers {
14namespace grpc {
15class MessageBuilder;
16}
17}
18
19template <class T, class U>
20struct is_same {
21 static const bool value = false;
22};
23
24template <class T>
25struct is_same<T, T> {
26 static const bool value = true;
27};
28
29extern const std::string m1_name;
30extern const Color m1_color;
31extern const std::string m2_name;
32extern const Color m2_color;
33
34flatbuffers::Offset<Monster> populate1(flatbuffers::FlatBufferBuilder &builder);
35flatbuffers::Offset<Monster> populate2(flatbuffers::FlatBufferBuilder &builder);
36
37uint8_t *release_raw_base(flatbuffers::FlatBufferBuilder &fbb, size_t &size, size_t &offset);
38
39void free_raw(flatbuffers::grpc::MessageBuilder &mbb, uint8_t *buf);
40void free_raw(flatbuffers::FlatBufferBuilder &fbb, uint8_t *buf);
41
42bool verify(const flatbuffers::DetachedBuffer &buf, const std::string &expected_name, Color color);
43bool verify(const uint8_t *buf, size_t offset, const std::string &expected_name, Color color);
44
45bool release_n_verify(flatbuffers::FlatBufferBuilder &fbb, const std::string &expected_name, Color color);
46bool 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
53template <class Builder>
54void 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
75void builder_move_assign_after_releaseraw_test(flatbuffers::grpc::MessageBuilder b1);
76
77template <class DestBuilder, class SrcBuilder = DestBuilder>
78struct 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
225enum 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
234typedef std::set<BuilderReuseTestSelector> TestSelector;
235
236template <class DestBuilder, class SrcBuilder>
237struct 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