blob: 3ce33a98724ef99de29f067adf4607289188ef94 [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001#include "flatbuffers/grpc.h"
2#include "monster_test_generated.h"
3#include "test_assert.h"
4#include "test_builder.h"
5
Austin Schuhe89fa2d2019-08-14 20:24:23 -07006using MyGame::Example::Any_NONE;
Austin Schuh272c6132020-11-14 16:37:52 -08007using MyGame::Example::CreateStat;
8using MyGame::Example::Vec3;
Austin Schuhe89fa2d2019-08-14 20:24:23 -07009
Austin Schuh272c6132020-11-14 16:37:52 -080010bool verify(flatbuffers::grpc::Message<Monster> &msg,
11 const std::string &expected_name, Color expected_color) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070012 const Monster *monster = msg.GetRoot();
Austin Schuh272c6132020-11-14 16:37:52 -080013 const auto name = monster->name()->str();
14 const auto color = monster->color();
15 TEST_EQ(name, expected_name);
16 TEST_EQ(color, expected_color);
17 return (name == expected_name) && (color == expected_color);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070018}
19
Austin Schuh272c6132020-11-14 16:37:52 -080020bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb,
21 const std::string &expected_name, Color expected_color) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070022 flatbuffers::grpc::Message<Monster> msg = mbb.ReleaseMessage<Monster>();
Austin Schuh272c6132020-11-14 16:37:52 -080023 return verify(msg, expected_name, expected_color);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070024}
25
Austin Schuh272c6132020-11-14 16:37:52 -080026void builder_move_assign_after_releaseraw_test(
27 flatbuffers::grpc::MessageBuilder dst) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070028 auto root_offset1 = populate1(dst);
29 dst.Finish(root_offset1);
30 size_t size, offset;
31 grpc_slice slice;
32 dst.ReleaseRaw(size, offset, slice);
33 flatbuffers::FlatBufferBuilder src;
34 auto root_offset2 = populate2(src);
35 src.Finish(root_offset2);
36 auto src_size = src.GetSize();
37 // Move into a released builder.
38 dst = std::move(src);
39 TEST_EQ(dst.GetSize(), src_size);
Austin Schuh272c6132020-11-14 16:37:52 -080040 TEST_ASSERT(release_n_verify(dst, m2_name(), m2_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -070041 TEST_EQ(src.GetSize(), 0);
42 grpc_slice_unref(slice);
43}
44
Austin Schuh272c6132020-11-14 16:37:52 -080045template<class SrcBuilder>
Austin Schuhe89fa2d2019-08-14 20:24:23 -070046struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
Austin Schuh272c6132020-11-14 16:37:52 -080047 static void builder_reusable_after_release_message_test(
48 TestSelector selector) {
49 if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) { return; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -070050
51 flatbuffers::grpc::MessageBuilder mb;
52 std::vector<flatbuffers::grpc::Message<Monster>> buffers;
53 for (int i = 0; i < 5; ++i) {
54 auto root_offset1 = populate1(mb);
55 mb.Finish(root_offset1);
56 buffers.push_back(mb.ReleaseMessage<Monster>());
Austin Schuh272c6132020-11-14 16:37:52 -080057 TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -070058 }
59 }
60
61 static void builder_reusable_after_release_test(TestSelector selector) {
Austin Schuh272c6132020-11-14 16:37:52 -080062 if (!selector.count(REUSABLE_AFTER_RELEASE)) { return; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -070063
Austin Schuh272c6132020-11-14 16:37:52 -080064 // FIXME: Populate-Release loop fails assert(GRPC_SLICE_IS_EMPTY(slice_)) in
65 // SliceAllocator::allocate in the second iteration.
Austin Schuhe89fa2d2019-08-14 20:24:23 -070066
67 flatbuffers::grpc::MessageBuilder mb;
68 std::vector<flatbuffers::DetachedBuffer> buffers;
69 for (int i = 0; i < 2; ++i) {
70 auto root_offset1 = populate1(mb);
71 mb.Finish(root_offset1);
72 buffers.push_back(mb.Release());
Austin Schuh272c6132020-11-14 16:37:52 -080073 TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -070074 }
75 }
76
77 static void builder_reusable_after_releaseraw_test(TestSelector selector) {
Austin Schuh272c6132020-11-14 16:37:52 -080078 if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { return; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -070079
80 flatbuffers::grpc::MessageBuilder mb;
81 for (int i = 0; i < 5; ++i) {
82 auto root_offset1 = populate1(mb);
83 mb.Finish(root_offset1);
84 size_t size, offset;
85 grpc_slice slice;
86 const uint8_t *buf = mb.ReleaseRaw(size, offset, slice);
Austin Schuh272c6132020-11-14 16:37:52 -080087 TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -070088 grpc_slice_unref(slice);
89 }
90 }
91
Austin Schuh272c6132020-11-14 16:37:52 -080092 static void builder_reusable_after_release_and_move_assign_test(
93 TestSelector selector) {
94 if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) { return; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -070095
Austin Schuh272c6132020-11-14 16:37:52 -080096 // FIXME: Release-move_assign loop fails assert(p ==
97 // GRPC_SLICE_START_PTR(slice_)) in DetachedBuffer destructor after all the
98 // iterations
Austin Schuhe89fa2d2019-08-14 20:24:23 -070099
100 flatbuffers::grpc::MessageBuilder dst;
101 std::vector<flatbuffers::DetachedBuffer> buffers;
102
103 for (int i = 0; i < 2; ++i) {
104 auto root_offset1 = populate1(dst);
105 dst.Finish(root_offset1);
106 buffers.push_back(dst.Release());
Austin Schuh272c6132020-11-14 16:37:52 -0800107 TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700108
109 // bring dst back to life.
110 SrcBuilder src;
111 dst = std::move(src);
112 TEST_EQ_FUNC(dst.GetSize(), 0);
113 TEST_EQ_FUNC(src.GetSize(), 0);
114 }
115 }
116
Austin Schuh272c6132020-11-14 16:37:52 -0800117 static void builder_reusable_after_release_message_and_move_assign_test(
118 TestSelector selector) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700119 if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN)) {
120 return;
121 }
122
123 flatbuffers::grpc::MessageBuilder dst;
124 std::vector<flatbuffers::grpc::Message<Monster>> buffers;
125
126 for (int i = 0; i < 5; ++i) {
127 auto root_offset1 = populate1(dst);
128 dst.Finish(root_offset1);
129 buffers.push_back(dst.ReleaseMessage<Monster>());
Austin Schuh272c6132020-11-14 16:37:52 -0800130 TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700131
132 // bring dst back to life.
133 SrcBuilder src;
134 dst = std::move(src);
135 TEST_EQ_FUNC(dst.GetSize(), 0);
136 TEST_EQ_FUNC(src.GetSize(), 0);
137 }
138 }
139
Austin Schuh272c6132020-11-14 16:37:52 -0800140 static void builder_reusable_after_releaseraw_and_move_assign_test(
141 TestSelector selector) {
142 if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) { return; }
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700143
144 flatbuffers::grpc::MessageBuilder dst;
145 for (int i = 0; i < 5; ++i) {
146 auto root_offset1 = populate1(dst);
147 dst.Finish(root_offset1);
148 size_t size, offset;
149 grpc_slice slice = grpc_empty_slice();
150 const uint8_t *buf = dst.ReleaseRaw(size, offset, slice);
Austin Schuh272c6132020-11-14 16:37:52 -0800151 TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700152 grpc_slice_unref(slice);
153
154 SrcBuilder src;
155 dst = std::move(src);
156 TEST_EQ_FUNC(dst.GetSize(), 0);
157 TEST_EQ_FUNC(src.GetSize(), 0);
158 }
159 }
160
161 static void run_tests(TestSelector selector) {
162 builder_reusable_after_release_test(selector);
163 builder_reusable_after_release_message_test(selector);
164 builder_reusable_after_releaseraw_test(selector);
165 builder_reusable_after_release_and_move_assign_test(selector);
166 builder_reusable_after_releaseraw_and_move_assign_test(selector);
167 builder_reusable_after_release_message_and_move_assign_test(selector);
168 }
169};
170
171void slice_allocator_tests() {
172 // move-construct no-delete test
173 {
174 size_t size = 2048;
175 flatbuffers::grpc::SliceAllocator sa1;
176 uint8_t *buf = sa1.allocate(size);
177 TEST_ASSERT_FUNC(buf != 0);
178 buf[0] = 100;
Austin Schuh272c6132020-11-14 16:37:52 -0800179 buf[size - 1] = 200;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700180 flatbuffers::grpc::SliceAllocator sa2(std::move(sa1));
181 // buf should not be deleted after move-construct
182 TEST_EQ_FUNC(buf[0], 100);
Austin Schuh272c6132020-11-14 16:37:52 -0800183 TEST_EQ_FUNC(buf[size - 1], 200);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700184 // buf is freed here
185 }
186
187 // move-assign test
188 {
189 flatbuffers::grpc::SliceAllocator sa1, sa2;
190 uint8_t *buf = sa1.allocate(2048);
191 sa1 = std::move(sa2);
192 // sa1 deletes previously allocated memory in move-assign.
193 // So buf is no longer usable here.
194 TEST_ASSERT_FUNC(buf != 0);
195 }
196}
197
Austin Schuh272c6132020-11-14 16:37:52 -0800198/// This function does not populate exactly the first half of the table. But it
199/// could.
200void populate_first_half(MyGame::Example::MonsterBuilder &wrapper,
201 flatbuffers::Offset<flatbuffers::String> name_offset) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700202 wrapper.add_name(name_offset);
Austin Schuh272c6132020-11-14 16:37:52 -0800203 wrapper.add_color(m1_color());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700204}
205
Austin Schuh272c6132020-11-14 16:37:52 -0800206/// This function does not populate exactly the second half of the table. But it
207/// could.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700208void populate_second_half(MyGame::Example::MonsterBuilder &wrapper) {
209 wrapper.add_hp(77);
210 wrapper.add_mana(88);
211 Vec3 vec3;
212 wrapper.add_pos(&vec3);
213}
214
Austin Schuh272c6132020-11-14 16:37:52 -0800215/// This function is a hack to update the FlatBufferBuilder reference (fbb_) in
216/// the MonsterBuilder object. This function will break if fbb_ is not the first
217/// member in MonsterBuilder. In that case, some offset must be added. This
218/// function is used exclusively for testing correctness of move operations
219/// between FlatBufferBuilders. If MonsterBuilder had a fbb_ pointer, this hack
220/// would be unnecessary. That involves a code-generator change though.
221void test_only_hack_update_fbb_reference(
222 MyGame::Example::MonsterBuilder &monsterBuilder,
223 flatbuffers::grpc::MessageBuilder &mb) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700224 *reinterpret_cast<flatbuffers::FlatBufferBuilder **>(&monsterBuilder) = &mb;
225}
226
Austin Schuh272c6132020-11-14 16:37:52 -0800227/// This test validates correctness of move conversion of FlatBufferBuilder to a
228/// MessageBuilder DURING a table construction. Half of the table is constructed
229/// using FlatBufferBuilder and the other half of the table is constructed using
230/// a MessageBuilder.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700231void builder_move_ctor_conversion_before_finish_half_n_half_table_test() {
Austin Schuh272c6132020-11-14 16:37:52 -0800232 for (size_t initial_size = 4; initial_size <= 2048; initial_size *= 2) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700233 flatbuffers::FlatBufferBuilder fbb(initial_size);
Austin Schuh272c6132020-11-14 16:37:52 -0800234 auto name_offset = fbb.CreateString(m1_name());
235 MyGame::Example::MonsterBuilder monsterBuilder(
236 fbb); // starts a table in FlatBufferBuilder
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700237 populate_first_half(monsterBuilder, name_offset);
238 flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
Austin Schuh272c6132020-11-14 16:37:52 -0800239 test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700240 populate_second_half(monsterBuilder);
Austin Schuh272c6132020-11-14 16:37:52 -0800241 mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder
242 TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700243 TEST_EQ_FUNC(fbb.GetSize(), 0);
244 }
245}
246
Austin Schuh272c6132020-11-14 16:37:52 -0800247/// This test populates a COMPLETE inner table before move conversion and later
248/// populates more members in the outer table.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700249void builder_move_ctor_conversion_before_finish_test() {
Austin Schuh272c6132020-11-14 16:37:52 -0800250 for (size_t initial_size = 1; initial_size <= 2048; initial_size += 1) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700251 flatbuffers::FlatBufferBuilder fbb(initial_size);
252 auto stat_offset = CreateStat(fbb, fbb.CreateString("SomeId"), 0, 0);
253 flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
Austin Schuh272c6132020-11-14 16:37:52 -0800254 auto monster_offset =
255 CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name()), 0,
256 m1_color(), Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700257 mb.Finish(monster_offset);
Austin Schuh272c6132020-11-14 16:37:52 -0800258 {
259 auto mon = flatbuffers::GetRoot<Monster>(mb.GetBufferPointer());
260 TEST_NOTNULL(mon);
261 TEST_NOTNULL(mon->name());
262 TEST_EQ_STR(mon->name()->c_str(), m1_name().c_str());
263 TEST_EQ(mon->color(), m1_color());
264 }
265 TEST_EQ(1, MyGame::Example::Color_Red);
266 TEST_EQ(1, m1_color());
267 TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700268 TEST_EQ_FUNC(fbb.GetSize(), 0);
269 }
270}
271
Austin Schuh272c6132020-11-14 16:37:52 -0800272/// This test validates correctness of move conversion of FlatBufferBuilder to a
273/// MessageBuilder DURING a table construction. Half of the table is constructed
274/// using FlatBufferBuilder and the other half of the table is constructed using
275/// a MessageBuilder.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700276void builder_move_assign_conversion_before_finish_half_n_half_table_test() {
277 flatbuffers::FlatBufferBuilder fbb;
278 flatbuffers::grpc::MessageBuilder mb;
279
Austin Schuh272c6132020-11-14 16:37:52 -0800280 for (int i = 0; i < 5; ++i) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700281 flatbuffers::FlatBufferBuilder fbb;
Austin Schuh272c6132020-11-14 16:37:52 -0800282 auto name_offset = fbb.CreateString(m1_name());
283 MyGame::Example::MonsterBuilder monsterBuilder(
284 fbb); // starts a table in FlatBufferBuilder
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700285 populate_first_half(monsterBuilder, name_offset);
286 mb = std::move(fbb);
Austin Schuh272c6132020-11-14 16:37:52 -0800287 test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700288 populate_second_half(monsterBuilder);
Austin Schuh272c6132020-11-14 16:37:52 -0800289 mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder
290 TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700291 TEST_EQ_FUNC(fbb.GetSize(), 0);
292 }
293}
294
Austin Schuh272c6132020-11-14 16:37:52 -0800295/// This test populates a COMPLETE inner table before move conversion and later
296/// populates more members in the outer table.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700297void builder_move_assign_conversion_before_finish_test() {
298 flatbuffers::FlatBufferBuilder fbb;
299 flatbuffers::grpc::MessageBuilder mb;
300
Austin Schuh272c6132020-11-14 16:37:52 -0800301 for (int i = 0; i < 5; ++i) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700302 auto stat_offset = CreateStat(fbb, fbb.CreateString("SomeId"), 0, 0);
303 mb = std::move(fbb);
Austin Schuh272c6132020-11-14 16:37:52 -0800304 auto monster_offset =
305 CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name()), 0,
306 m1_color(), Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700307 mb.Finish(monster_offset);
Austin Schuh272c6132020-11-14 16:37:52 -0800308 TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700309 TEST_EQ_FUNC(fbb.GetSize(), 0);
310 }
311}
312
Austin Schuh272c6132020-11-14 16:37:52 -0800313/// This test populates data, finishes the buffer, and does move conversion
314/// after.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700315void builder_move_ctor_conversion_after_finish_test() {
316 flatbuffers::FlatBufferBuilder fbb;
317 fbb.Finish(populate1(fbb));
318 flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
Austin Schuh272c6132020-11-14 16:37:52 -0800319 TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700320 TEST_EQ_FUNC(fbb.GetSize(), 0);
321}
322
Austin Schuh272c6132020-11-14 16:37:52 -0800323/// This test populates data, finishes the buffer, and does move conversion
324/// after.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700325void builder_move_assign_conversion_after_finish_test() {
326 flatbuffers::FlatBufferBuilder fbb;
327 flatbuffers::grpc::MessageBuilder mb;
328
Austin Schuh272c6132020-11-14 16:37:52 -0800329 for (int i = 0; i < 5; ++i) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700330 fbb.Finish(populate1(fbb));
331 mb = std::move(fbb);
Austin Schuh272c6132020-11-14 16:37:52 -0800332 TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700333 TEST_EQ_FUNC(fbb.GetSize(), 0);
334 }
335}
336
337void message_builder_tests() {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700338 using flatbuffers::FlatBufferBuilder;
Austin Schuh272c6132020-11-14 16:37:52 -0800339 using flatbuffers::grpc::MessageBuilder;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700340
341 slice_allocator_tests();
342
343#ifndef __APPLE__
344 builder_move_ctor_conversion_before_finish_half_n_half_table_test();
345 builder_move_assign_conversion_before_finish_half_n_half_table_test();
Austin Schuh272c6132020-11-14 16:37:52 -0800346#endif // __APPLE__
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700347 builder_move_ctor_conversion_before_finish_test();
348 builder_move_assign_conversion_before_finish_test();
349
350 builder_move_ctor_conversion_after_finish_test();
351 builder_move_assign_conversion_after_finish_test();
352
353 BuilderTests<MessageBuilder, MessageBuilder>::all_tests();
354 BuilderTests<MessageBuilder, FlatBufferBuilder>::all_tests();
355
356 BuilderReuseTestSelector tests[6] = {
Austin Schuh272c6132020-11-14 16:37:52 -0800357 // REUSABLE_AFTER_RELEASE, // Assertion failed:
358 // (GRPC_SLICE_IS_EMPTY(slice_))
359 // REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN, // Assertion failed: (p ==
360 // GRPC_SLICE_START_PTR(slice_)
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700361
Austin Schuh272c6132020-11-14 16:37:52 -0800362 REUSABLE_AFTER_RELEASE_RAW, REUSABLE_AFTER_RELEASE_MESSAGE,
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700363 REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN,
364 REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN
365 };
366
Austin Schuh272c6132020-11-14 16:37:52 -0800367 BuilderReuseTests<MessageBuilder, MessageBuilder>::run_tests(
368 TestSelector(tests, tests + 6));
369 BuilderReuseTests<MessageBuilder, FlatBufferBuilder>::run_tests(
370 TestSelector(tests, tests + 6));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700371}