blob: 75338b041594545d9a25b6f3b32717cadbc8cd24 [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
Austin Schuhe89fa2d2019-08-14 20:24:23 -070057// Invokes this function when testing the following Builder types
58// FlatBufferBuilder, TestHeapBuilder, and GrpcLikeMessageBuilder
Austin Schuh272c6132020-11-14 16:37:52 -080059template<class Builder>
Austin Schuhe89fa2d2019-08-14 20:24:23 -070060void builder_move_assign_after_releaseraw_test(Builder b1) {
61 auto root_offset1 = populate1(b1);
62 b1.Finish(root_offset1);
63 size_t size, offset;
James Kuszmaul8e62b022022-03-22 09:33:25 -070064
65 uint8_t *rr = b1.ReleaseRaw(size, offset);
Austin Schuh272c6132020-11-14 16:37:52 -080066 std::shared_ptr<uint8_t> raw(
James Kuszmaul8e62b022022-03-22 09:33:25 -070067 rr, [size](uint8_t *ptr) {
Austin Schuh272c6132020-11-14 16:37:52 -080068 flatbuffers::DefaultAllocator::dealloc(ptr, size);
69 });
Austin Schuhe89fa2d2019-08-14 20:24:23 -070070 Builder src;
71 auto root_offset2 = populate2(src);
72 src.Finish(root_offset2);
73 auto src_size = src.GetSize();
74 // Move into a released builder.
75 b1 = std::move(src);
76 TEST_EQ_FUNC(b1.GetSize(), src_size);
Austin Schuh272c6132020-11-14 16:37:52 -080077 TEST_ASSERT_FUNC(release_n_verify(b1, m2_name(), m2_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -070078 TEST_EQ_FUNC(src.GetSize(), 0);
79}
Austin Schuhe89fa2d2019-08-14 20:24:23 -070080
Austin Schuh272c6132020-11-14 16:37:52 -080081void builder_move_assign_after_releaseraw_test(
82 flatbuffers::grpc::MessageBuilder b1);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070083
Austin Schuh272c6132020-11-14 16:37:52 -080084template<class DestBuilder, class SrcBuilder = DestBuilder>
Austin Schuhe89fa2d2019-08-14 20:24:23 -070085struct BuilderTests {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070086 static void empty_builder_movector_test() {
87 SrcBuilder src;
88 size_t src_size = src.GetSize();
89 DestBuilder dst(std::move(src));
90 size_t dst_size = dst.GetSize();
91 TEST_EQ_FUNC(src_size, 0);
92 TEST_EQ_FUNC(src_size, dst_size);
93 }
94
95 static void nonempty_builder_movector_test() {
96 SrcBuilder src;
97 populate1(src);
98 size_t src_size = src.GetSize();
99 DestBuilder dst(std::move(src));
100 TEST_EQ_FUNC(src_size, dst.GetSize());
101 TEST_EQ_FUNC(src.GetSize(), 0);
102 }
103
104 static void builder_movector_before_finish_test() {
105 SrcBuilder src;
106 auto root_offset1 = populate1(src);
107 DestBuilder dst(std::move(src));
108 dst.Finish(root_offset1);
Austin Schuh272c6132020-11-14 16:37:52 -0800109 TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700110 TEST_EQ_FUNC(src.GetSize(), 0);
111 }
112
113 static void builder_movector_after_finish_test() {
114 SrcBuilder src;
115 auto root_offset1 = populate1(src);
116 src.Finish(root_offset1);
117 auto src_size = src.GetSize();
118 DestBuilder dst(std::move(src));
119 TEST_EQ_FUNC(dst.GetSize(), src_size);
Austin Schuh272c6132020-11-14 16:37:52 -0800120 TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700121 TEST_EQ_FUNC(src.GetSize(), 0);
122 }
123
124 static void builder_move_assign_before_finish_test() {
125 SrcBuilder src;
126 auto root_offset1 = populate1(src);
127 DestBuilder dst;
128 populate2(dst);
129 dst = std::move(src);
130 dst.Finish(root_offset1);
Austin Schuh272c6132020-11-14 16:37:52 -0800131 TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700132 TEST_EQ_FUNC(src.GetSize(), 0);
133 }
134
135 static void builder_move_assign_after_finish_test() {
136 SrcBuilder src;
137 auto root_offset1 = populate1(src);
138 src.Finish(root_offset1);
139 auto src_size = src.GetSize();
140 DestBuilder dst;
141 auto root_offset2 = populate2(dst);
142 dst.Finish(root_offset2);
143 dst = std::move(src);
144 TEST_EQ_FUNC(dst.GetSize(), src_size);
Austin Schuh272c6132020-11-14 16:37:52 -0800145 TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700146 TEST_EQ_FUNC(src.GetSize(), 0);
147 }
148
149 static void builder_move_assign_after_release_test() {
150 DestBuilder dst;
151 auto root_offset1 = populate1(dst);
152 dst.Finish(root_offset1);
153 {
154 flatbuffers::DetachedBuffer dst_detached = dst.Release();
155 // detached buffer is deleted
156 }
157 SrcBuilder src;
158 auto root_offset2 = populate2(src);
159 src.Finish(root_offset2);
160 auto src_size = src.GetSize();
161 // Move into a released builder.
162 dst = std::move(src);
163 TEST_EQ_FUNC(dst.GetSize(), src_size);
Austin Schuh272c6132020-11-14 16:37:52 -0800164 TEST_ASSERT_FUNC(release_n_verify(dst, m2_name(), m2_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700165 TEST_EQ_FUNC(src.GetSize(), 0);
166 }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700167
Austin Schuh272c6132020-11-14 16:37:52 -0800168 static void builder_swap_before_finish_test(
169 bool run = is_same<DestBuilder, SrcBuilder>::value) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700170 /// Swap is allowed only when lhs and rhs are the same concrete type.
Austin Schuh272c6132020-11-14 16:37:52 -0800171 if (run) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700172 SrcBuilder src;
173 auto root_offset1 = populate1(src);
174 auto size1 = src.GetSize();
175 DestBuilder dst;
176 auto root_offset2 = populate2(dst);
177 auto size2 = dst.GetSize();
178 src.Swap(dst);
179 src.Finish(root_offset2);
180 dst.Finish(root_offset1);
181 TEST_EQ_FUNC(src.GetSize() > size2, true);
182 TEST_EQ_FUNC(dst.GetSize() > size1, true);
Austin Schuh272c6132020-11-14 16:37:52 -0800183 TEST_ASSERT_FUNC(release_n_verify(src, m2_name(), m2_color()));
184 TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700185 }
186 }
187
Austin Schuh272c6132020-11-14 16:37:52 -0800188 static void builder_swap_after_finish_test(
189 bool run = is_same<DestBuilder, SrcBuilder>::value) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700190 /// Swap is allowed only when lhs and rhs are the same concrete type.
Austin Schuh272c6132020-11-14 16:37:52 -0800191 if (run) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700192 SrcBuilder src;
193 auto root_offset1 = populate1(src);
194 src.Finish(root_offset1);
195 auto size1 = src.GetSize();
196 DestBuilder dst;
197 auto root_offset2 = populate2(dst);
198 dst.Finish(root_offset2);
199 auto size2 = dst.GetSize();
200 src.Swap(dst);
201 TEST_EQ_FUNC(src.GetSize(), size2);
202 TEST_EQ_FUNC(dst.GetSize(), size1);
Austin Schuh272c6132020-11-14 16:37:52 -0800203 TEST_ASSERT_FUNC(release_n_verify(src, m2_name(), m2_color()));
204 TEST_ASSERT_FUNC(release_n_verify(dst, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700205 }
206 }
207
208 static void all_tests() {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700209 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());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700217 builder_swap_before_finish_test();
218 builder_swap_after_finish_test();
219 }
220};
221
222enum BuilderReuseTestSelector {
223 REUSABLE_AFTER_RELEASE = 1,
224 REUSABLE_AFTER_RELEASE_RAW = 2,
225 REUSABLE_AFTER_RELEASE_MESSAGE = 3,
226 REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN = 4,
227 REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN = 5,
228 REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN = 6
229};
230
231typedef std::set<BuilderReuseTestSelector> TestSelector;
232
Austin Schuh272c6132020-11-14 16:37:52 -0800233template<class DestBuilder, class SrcBuilder> struct BuilderReuseTests {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700234 static void builder_reusable_after_release_test(TestSelector selector) {
Austin Schuh272c6132020-11-14 16:37:52 -0800235 if (!selector.count(REUSABLE_AFTER_RELEASE)) { return; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700236
237 DestBuilder fbb;
238 std::vector<flatbuffers::DetachedBuffer> buffers;
239 for (int i = 0; i < 5; ++i) {
240 auto root_offset1 = populate1(fbb);
241 fbb.Finish(root_offset1);
242 buffers.push_back(fbb.Release());
Austin Schuh272c6132020-11-14 16:37:52 -0800243 TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700244 }
245 }
246
247 static void builder_reusable_after_releaseraw_test(TestSelector selector) {
Austin Schuh272c6132020-11-14 16:37:52 -0800248 if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { return; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700249
250 DestBuilder fbb;
251 for (int i = 0; i < 5; ++i) {
252 auto root_offset1 = populate1(fbb);
253 fbb.Finish(root_offset1);
254 size_t size, offset;
255 uint8_t *buf = release_raw_base(fbb, size, offset);
Austin Schuh272c6132020-11-14 16:37:52 -0800256 TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700257 free_raw(fbb, buf);
258 }
259 }
260
Austin Schuh272c6132020-11-14 16:37:52 -0800261 static void builder_reusable_after_release_and_move_assign_test(
262 TestSelector selector) {
263 if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) { return; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700264
265 DestBuilder dst;
266 std::vector<flatbuffers::DetachedBuffer> buffers;
267 for (int i = 0; i < 5; ++i) {
268 auto root_offset1 = populate1(dst);
269 dst.Finish(root_offset1);
270 buffers.push_back(dst.Release());
Austin Schuh272c6132020-11-14 16:37:52 -0800271 TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700272 SrcBuilder src;
273 dst = std::move(src);
274 TEST_EQ_FUNC(src.GetSize(), 0);
275 }
276 }
277
Austin Schuh272c6132020-11-14 16:37:52 -0800278 static void builder_reusable_after_releaseraw_and_move_assign_test(
279 TestSelector selector) {
280 if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) { return; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700281
282 DestBuilder dst;
283 for (int i = 0; i < 5; ++i) {
284 auto root_offset1 = populate1(dst);
285 dst.Finish(root_offset1);
286 size_t size, offset;
287 uint8_t *buf = release_raw_base(dst, size, offset);
Austin Schuh272c6132020-11-14 16:37:52 -0800288 TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700289 free_raw(dst, buf);
290 SrcBuilder src;
291 dst = std::move(src);
292 TEST_EQ_FUNC(src.GetSize(), 0);
293 }
294 }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700295
296 static void run_tests(TestSelector selector) {
297 builder_reusable_after_release_test(selector);
298 builder_reusable_after_releaseraw_test(selector);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700299 builder_reusable_after_release_and_move_assign_test(selector);
300 builder_reusable_after_releaseraw_and_move_assign_test(selector);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700301 }
302};
303
Austin Schuh272c6132020-11-14 16:37:52 -0800304#endif // TEST_BUILDER_H