1 /*
2 *
3 * Copyright 2018 Google Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 extern crate quickcheck;
19
20 extern crate flatbuffers;
21
22 #[path = "../../monster_test_generated.rs"]
23 mod monster_test_generated;
24 pub use monster_test_generated::my_game;
25
26 // Include simple random number generator to ensure results will be the
27 // same across platforms.
28 // http://en.wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator
29 struct LCG(u64);
30 impl LCG {
new() -> Self31 fn new() -> Self {
32 LCG { 0: 48271 }
33 }
next(&mut self) -> u6434 fn next(&mut self) -> u64 {
35 let old = self.0;
36 self.0 = (self.0 * 279470273u64) % 4294967291u64;
37 old
38 }
reset(&mut self)39 fn reset(&mut self) {
40 self.0 = 48271
41 }
42 }
43
44 // test helper macro to return an error if two expressions are not equal
45 macro_rules! check_eq {
46 ($field_call:expr, $want:expr) => (
47 if $field_call == $want {
48 Ok(())
49 } else {
50 Err(stringify!($field_call))
51 }
52 )
53 }
54
55 #[test]
macro_check_eq()56 fn macro_check_eq() {
57 assert!(check_eq!(1, 1).is_ok());
58 assert!(check_eq!(1, 2).is_err());
59 }
60
61 // test helper macro to return an error if two expressions are equal
62 macro_rules! check_is_some {
63 ($field_call:expr) => (
64 if $field_call.is_some() {
65 Ok(())
66 } else {
67 Err(stringify!($field_call))
68 }
69 )
70 }
71
72 #[test]
macro_check_is_some()73 fn macro_check_is_some() {
74 let some: Option<usize> = Some(0);
75 let none: Option<usize> = None;
76 assert!(check_is_some!(some).is_ok());
77 assert!(check_is_some!(none).is_err());
78 }
79
80
create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder)81 fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder) {
82 let mon = {
83 let s0 = builder.create_string("test1");
84 let s1 = builder.create_string("test2");
85 let fred_name = builder.create_string("Fred");
86
87 // can't inline creation of this Vec3 because we refer to it by reference, so it must live
88 // long enough to be used by MonsterArgs.
89 let pos = my_game::example::Vec3::new(1.0, 2.0, 3.0, 3.0, my_game::example::Color::Green, &my_game::example::Test::new(5i16, 6i8));
90
91 let args = my_game::example::MonsterArgs{
92 hp: 80,
93 mana: 150,
94 name: Some(builder.create_string("MyMonster")),
95 pos: Some(&pos),
96 test_type: my_game::example::Any::Monster,
97 test: Some(my_game::example::Monster::create(builder, &my_game::example::MonsterArgs{
98 name: Some(fred_name),
99 ..Default::default()
100 }).as_union_value()),
101 inventory: Some(builder.create_vector_direct(&[0u8, 1, 2, 3, 4][..])),
102 test4: Some(builder.create_vector_direct(&[my_game::example::Test::new(10, 20),
103 my_game::example::Test::new(30, 40)])),
104 testarrayofstring: Some(builder.create_vector(&[s0, s1])),
105 ..Default::default()
106 };
107 my_game::example::Monster::create(builder, &args)
108 };
109 my_game::example::finish_monster_buffer(builder, mon);
110 }
111
create_serialized_example_with_library_code(builder: &mut flatbuffers::FlatBufferBuilder)112 fn create_serialized_example_with_library_code(builder: &mut flatbuffers::FlatBufferBuilder) {
113 let nested_union_mon = {
114 let name = builder.create_string("Fred");
115 let table_start = builder.start_table();
116 builder.push_slot_always(my_game::example::Monster::VT_NAME, name);
117 builder.end_table(table_start)
118 };
119 let pos = my_game::example::Vec3::new(1.0, 2.0, 3.0, 3.0, my_game::example::Color::Green, &my_game::example::Test::new(5i16, 6i8));
120 let inv = builder.create_vector(&[0u8, 1, 2, 3, 4]);
121
122 let test4 = builder.create_vector(&[my_game::example::Test::new(10, 20),
123 my_game::example::Test::new(30, 40)][..]);
124
125 let name = builder.create_string("MyMonster");
126 let testarrayofstring = builder.create_vector_of_strings(&["test1", "test2"][..]);
127
128 // begin building
129
130 let table_start = builder.start_table();
131 builder.push_slot(my_game::example::Monster::VT_HP, 80i16, 100);
132 builder.push_slot_always(my_game::example::Monster::VT_NAME, name);
133 builder.push_slot_always(my_game::example::Monster::VT_POS, &pos);
134 builder.push_slot(my_game::example::Monster::VT_TEST_TYPE, my_game::example::Any::Monster, my_game::example::Any::NONE);
135 builder.push_slot_always(my_game::example::Monster::VT_TEST, nested_union_mon);
136 builder.push_slot_always(my_game::example::Monster::VT_INVENTORY, inv);
137 builder.push_slot_always(my_game::example::Monster::VT_TEST4, test4);
138 builder.push_slot_always(my_game::example::Monster::VT_TESTARRAYOFSTRING, testarrayofstring);
139 let root = builder.end_table(table_start);
140 builder.finish(root, Some(my_game::example::MONSTER_IDENTIFIER));
141 }
142
serialized_example_is_accessible_and_correct(bytes: &[u8], identifier_required: bool, size_prefixed: bool) -> Result<(), &'static str>143 fn serialized_example_is_accessible_and_correct(bytes: &[u8], identifier_required: bool, size_prefixed: bool) -> Result<(), &'static str> {
144
145 if identifier_required {
146 let correct = if size_prefixed {
147 my_game::example::monster_size_prefixed_buffer_has_identifier(bytes)
148 } else {
149 my_game::example::monster_buffer_has_identifier(bytes)
150 };
151 check_eq!(correct, true)?;
152 }
153
154 let m = if size_prefixed {
155 my_game::example::get_size_prefixed_root_as_monster(bytes)
156 } else {
157 my_game::example::get_root_as_monster(bytes)
158 };
159
160 check_eq!(m.hp(), 80)?;
161 check_eq!(m.mana(), 150)?;
162 check_eq!(m.name(), "MyMonster")?;
163
164 let pos = m.pos().unwrap();
165 check_eq!(pos.x(), 1.0f32)?;
166 check_eq!(pos.y(), 2.0f32)?;
167 check_eq!(pos.z(), 3.0f32)?;
168 check_eq!(pos.test1(), 3.0f64)?;
169 check_eq!(pos.test2(), my_game::example::Color::Green)?;
170
171 let pos_test3 = pos.test3();
172 check_eq!(pos_test3.a(), 5i16)?;
173 check_eq!(pos_test3.b(), 6i8)?;
174
175 check_eq!(m.test_type(), my_game::example::Any::Monster)?;
176 check_is_some!(m.test())?;
177 let table2 = m.test().unwrap();
178 let monster2 = my_game::example::Monster::init_from_table(table2);
179
180 check_eq!(monster2.name(), "Fred")?;
181
182 check_is_some!(m.inventory())?;
183 let inv = m.inventory().unwrap();
184 check_eq!(inv.len(), 5)?;
185 check_eq!(inv.iter().sum::<u8>(), 10u8)?;
186
187 check_is_some!(m.test4())?;
188 let test4 = m.test4().unwrap();
189 check_eq!(test4.len(), 2)?;
190 check_eq!(test4[0].a() as i32 + test4[0].b() as i32 +
191 test4[1].a() as i32 + test4[1].b() as i32, 100)?;
192
193 check_is_some!(m.testarrayofstring())?;
194 let testarrayofstring = m.testarrayofstring().unwrap();
195 check_eq!(testarrayofstring.len(), 2)?;
196 check_eq!(testarrayofstring.get(0), "test1")?;
197 check_eq!(testarrayofstring.get(1), "test2")?;
198
199 Ok(())
200 }
201
202 // Disabled due to Windows CI limitations.
203 // #[test]
204 // fn builder_initializes_with_maximum_buffer_size() {
205 // flatbuffers::FlatBufferBuilder::new_with_capacity(flatbuffers::FLATBUFFERS_MAX_BUFFER_SIZE);
206 // }
207
208 #[should_panic]
209 #[test]
builder_abort_with_greater_than_maximum_buffer_size()210 fn builder_abort_with_greater_than_maximum_buffer_size() {
211 flatbuffers::FlatBufferBuilder::new_with_capacity(flatbuffers::FLATBUFFERS_MAX_BUFFER_SIZE+1);
212 }
213
214 #[test]
builder_collapses_into_vec()215 fn builder_collapses_into_vec() {
216 let mut b = flatbuffers::FlatBufferBuilder::new();
217 create_serialized_example_with_generated_code(&mut b);
218 let (backing_buf, head) = b.collapse();
219 serialized_example_is_accessible_and_correct(&backing_buf[head..], true, false).unwrap();
220 }
221
222 #[cfg(test)]
223 mod generated_constants {
224 extern crate flatbuffers;
225 use super::my_game;
226
227 #[test]
monster_identifier()228 fn monster_identifier() {
229 assert_eq!("MONS", my_game::example::MONSTER_IDENTIFIER);
230 }
231
232 #[test]
monster_file_extension()233 fn monster_file_extension() {
234 assert_eq!("mon", my_game::example::MONSTER_EXTENSION);
235 }
236 }
237
238 #[cfg(test)]
239 mod lifetime_correctness {
240 extern crate flatbuffers;
241
242 use std::mem;
243
244 use super::my_game;
245 use super::load_file;
246
247 #[test]
table_get_field_from_static_buffer_1()248 fn table_get_field_from_static_buffer_1() {
249 let buf = load_file("../monsterdata_test.mon").expect("missing monsterdata_test.mon");
250 // create 'static slice
251 let slice: &[u8] = &buf;
252 let slice: &'static [u8] = unsafe { mem::transmute(slice) };
253 // make sure values retrieved from the 'static buffer are themselves 'static
254 let monster: my_game::example::Monster<'static> = my_game::example::get_root_as_monster(slice);
255 // this line should compile:
256 let name: Option<&'static str> = monster._tab.get::<flatbuffers::ForwardsUOffset<&str>>(my_game::example::Monster::VT_NAME, None);
257 assert_eq!(name, Some("MyMonster"));
258 }
259
260 #[test]
table_get_field_from_static_buffer_2()261 fn table_get_field_from_static_buffer_2() {
262 static DATA: [u8; 4] = [0, 0, 0, 0]; // some binary data
263 let table: flatbuffers::Table<'static> = flatbuffers::Table::new(&DATA, 0);
264 // this line should compile:
265 table.get::<&'static str>(0, None);
266 }
267
268 #[test]
table_object_self_lifetime_in_closure()269 fn table_object_self_lifetime_in_closure() {
270 // This test is designed to ensure that lifetimes for temporary intermediate tables aren't inflated beyond where the need to be.
271 let buf = load_file("../monsterdata_test.mon").expect("missing monsterdata_test.mon");
272 let monster = my_game::example::get_root_as_monster(&buf);
273 let enemy: Option<my_game::example::Monster> = monster.enemy();
274 // This line won't compile if "self" is required to live for the lifetime of buf above as the borrow disappears at the end of the closure.
275 let enemy_of_my_enemy = enemy.map(|e| {
276 // enemy (the Option) is consumed, and the enum's value is taken as a temporary (e) at the start of the closure
277 let name = e.name();
278 // ... the temporary dies here, so for this to compile name's lifetime must not be tied to the temporary
279 name
280 // If this test fails the error would be "`e` dropped here while still borrowed"
281 });
282 assert_eq!(enemy_of_my_enemy, Some("Fred"));
283 }
284 }
285
286 #[cfg(test)]
287 mod roundtrip_generated_code {
288 extern crate flatbuffers;
289
290 use super::my_game;
291
build_mon<'a, 'b>(builder: &'a mut flatbuffers::FlatBufferBuilder, args: &'b my_game::example::MonsterArgs) -> my_game::example::Monster<'a>292 fn build_mon<'a, 'b>(builder: &'a mut flatbuffers::FlatBufferBuilder, args: &'b my_game::example::MonsterArgs) -> my_game::example::Monster<'a> {
293 let mon = my_game::example::Monster::create(builder, &args);
294 my_game::example::finish_monster_buffer(builder, mon);
295 my_game::example::get_root_as_monster(builder.finished_data())
296 }
297
298 #[test]
scalar_store()299 fn scalar_store() {
300 let mut b = flatbuffers::FlatBufferBuilder::new();
301 let name = b.create_string("foo");
302 let m = build_mon(&mut b, &my_game::example::MonsterArgs{hp: 123, name: Some(name), ..Default::default()});
303 assert_eq!(m.hp(), 123);
304 }
305 #[test]
scalar_default()306 fn scalar_default() {
307 let mut b = flatbuffers::FlatBufferBuilder::new();
308 let name = b.create_string("foo");
309 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
310 assert_eq!(m.hp(), 100);
311 }
312 #[test]
string_store()313 fn string_store() {
314 let mut b = flatbuffers::FlatBufferBuilder::new();
315 let name = b.create_string("foobar");
316 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
317 assert_eq!(m.name(), "foobar");
318 }
319 #[test]
struct_store()320 fn struct_store() {
321 let mut b = flatbuffers::FlatBufferBuilder::new();
322 let name = b.create_string("foo");
323 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
324 name: Some(name),
325 pos: Some(&my_game::example::Vec3::new(1.0, 2.0, 3.0, 4.0,
326 my_game::example::Color::Green,
327 &my_game::example::Test::new(98, 99))),
328 ..Default::default()
329 });
330 assert_eq!(m.pos(), Some(&my_game::example::Vec3::new(1.0, 2.0, 3.0, 4.0,
331 my_game::example::Color::Green,
332 &my_game::example::Test::new(98, 99))));
333 }
334 #[test]
struct_default()335 fn struct_default() {
336 let mut b = flatbuffers::FlatBufferBuilder::new();
337 let name = b.create_string("foo");
338 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
339 assert_eq!(m.pos(), None);
340 }
341 #[test]
enum_store()342 fn enum_store() {
343 let mut b = flatbuffers::FlatBufferBuilder::new();
344 let name = b.create_string("foo");
345 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), color: my_game::example::Color::Red, ..Default::default()});
346 assert_eq!(m.color(), my_game::example::Color::Red);
347 }
348 #[test]
enum_default()349 fn enum_default() {
350 let mut b = flatbuffers::FlatBufferBuilder::new();
351 let name = b.create_string("foo");
352 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
353 assert_eq!(m.color(), my_game::example::Color::Blue);
354 }
355 #[test]
union_store()356 fn union_store() {
357 let b = &mut flatbuffers::FlatBufferBuilder::new();
358 {
359 let name_inner = b.create_string("foo");
360 let name_outer = b.create_string("bar");
361
362 let inner = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
363 name: Some(name_inner),
364 ..Default::default()
365 });
366 let outer = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
367 name: Some(name_outer),
368 test_type: my_game::example::Any::Monster,
369 test: Some(inner.as_union_value()),
370 ..Default::default()
371 });
372 my_game::example::finish_monster_buffer(b, outer);
373 }
374
375 let mon = my_game::example::get_root_as_monster(b.finished_data());
376 assert_eq!(mon.name(), "bar");
377 assert_eq!(mon.test_type(), my_game::example::Any::Monster);
378 assert_eq!(my_game::example::Monster::init_from_table(mon.test().unwrap()).name(),
379 "foo");
380 assert_eq!(mon.test_as_monster().unwrap().name(), "foo");
381 assert_eq!(mon.test_as_test_simple_table_with_enum(), None);
382 assert_eq!(mon.test_as_my_game_example_2_monster(), None);
383 }
384 #[test]
union_default()385 fn union_default() {
386 let mut b = flatbuffers::FlatBufferBuilder::new();
387 let name = b.create_string("foo");
388 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
389 assert_eq!(m.test_type(), my_game::example::Any::NONE);
390 assert_eq!(m.test(), None);
391 }
392 #[test]
table_full_namespace_store()393 fn table_full_namespace_store() {
394 let b = &mut flatbuffers::FlatBufferBuilder::new();
395 {
396 let name_inner = b.create_string("foo");
397 let name_outer = b.create_string("bar");
398
399 let inner = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
400 name: Some(name_inner),
401 ..Default::default()
402 });
403 let outer = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
404 name: Some(name_outer),
405 enemy: Some(inner),
406 ..Default::default()
407 });
408 my_game::example::finish_monster_buffer(b, outer);
409 }
410
411 let mon = my_game::example::get_root_as_monster(b.finished_data());
412 assert_eq!(mon.name(), "bar");
413 assert_eq!(mon.enemy().unwrap().name(), "foo");
414 }
415 #[test]
table_full_namespace_default()416 fn table_full_namespace_default() {
417 let mut b = flatbuffers::FlatBufferBuilder::new();
418 let name = b.create_string("foo");
419 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
420 assert_eq!(m.enemy(), None);
421 }
422 #[test]
table_store()423 fn table_store() {
424 let b = &mut flatbuffers::FlatBufferBuilder::new();
425 {
426 let id_inner = b.create_string("foo");
427 let name_outer = b.create_string("bar");
428
429 let inner = my_game::example::Stat::create(b, &my_game::example::StatArgs{
430 id: Some(id_inner),
431 ..Default::default()
432 });
433 let outer = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
434 name: Some(name_outer),
435 testempty: Some(inner),
436 ..Default::default()
437 });
438 my_game::example::finish_monster_buffer(b, outer);
439 }
440
441 let mon = my_game::example::get_root_as_monster(b.finished_data());
442 assert_eq!(mon.name(), "bar");
443 assert_eq!(mon.testempty().unwrap().id(), Some("foo"));
444 }
445 #[test]
table_default()446 fn table_default() {
447 let mut b = flatbuffers::FlatBufferBuilder::new();
448 let name = b.create_string("foo");
449 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
450 assert_eq!(m.testempty(), None);
451 }
452 #[test]
nested_flatbuffer_store()453 fn nested_flatbuffer_store() {
454 let b0 = {
455 let mut b0 = flatbuffers::FlatBufferBuilder::new();
456 let args = my_game::example::MonsterArgs{
457 hp: 123,
458 name: Some(b0.create_string("foobar")),
459 ..Default::default()
460 };
461 let mon = my_game::example::Monster::create(&mut b0, &args);
462 my_game::example::finish_monster_buffer(&mut b0, mon);
463 b0
464 };
465
466 let b1 = {
467 let mut b1 = flatbuffers::FlatBufferBuilder::new();
468 let args = my_game::example::MonsterArgs{
469 testnestedflatbuffer: Some(b1.create_vector(b0.finished_data())),
470 name: Some(b1.create_string("foo")),
471 ..Default::default()
472 };
473 let mon = my_game::example::Monster::create(&mut b1, &args);
474 my_game::example::finish_monster_buffer(&mut b1, mon);
475 b1
476 };
477
478 let m = my_game::example::get_root_as_monster(b1.finished_data());
479
480 assert!(m.testnestedflatbuffer().is_some());
481 assert_eq!(m.testnestedflatbuffer().unwrap(), b0.finished_data());
482
483 let m2_a = my_game::example::get_root_as_monster(m.testnestedflatbuffer().unwrap());
484 assert_eq!(m2_a.hp(), 123);
485 assert_eq!(m2_a.name(), "foobar");
486
487 assert!(m.testnestedflatbuffer_nested_flatbuffer().is_some());
488 let m2_b = m.testnestedflatbuffer_nested_flatbuffer().unwrap();
489
490 assert_eq!(m2_b.hp(), 123);
491 assert_eq!(m2_b.name(), "foobar");
492 }
493 #[test]
nested_flatbuffer_default()494 fn nested_flatbuffer_default() {
495 let mut b = flatbuffers::FlatBufferBuilder::new();
496 let name = b.create_string("foo");
497 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
498 assert!(m.testnestedflatbuffer().is_none());
499 }
500 #[test]
vector_of_string_store_helper_build()501 fn vector_of_string_store_helper_build() {
502 let mut b = flatbuffers::FlatBufferBuilder::new();
503 let v = b.create_vector_of_strings(&["foobar", "baz"]);
504 let name = b.create_string("foo");
505 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
506 name: Some(name),
507 testarrayofstring: Some(v), ..Default::default()});
508 assert_eq!(m.testarrayofstring().unwrap().len(), 2);
509 assert_eq!(m.testarrayofstring().unwrap().get(0), "foobar");
510 assert_eq!(m.testarrayofstring().unwrap().get(1), "baz");
511 }
512 #[test]
vector_of_string_store_manual_build()513 fn vector_of_string_store_manual_build() {
514 let mut b = flatbuffers::FlatBufferBuilder::new();
515 let s0 = b.create_string("foobar");
516 let s1 = b.create_string("baz");
517 let v = b.create_vector(&[s0, s1]);
518 let name = b.create_string("foo");
519 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
520 name: Some(name),
521 testarrayofstring: Some(v), ..Default::default()});
522 assert_eq!(m.testarrayofstring().unwrap().len(), 2);
523 assert_eq!(m.testarrayofstring().unwrap().get(0), "foobar");
524 assert_eq!(m.testarrayofstring().unwrap().get(1), "baz");
525 }
526 #[test]
vector_of_ubyte_store()527 fn vector_of_ubyte_store() {
528 let mut b = flatbuffers::FlatBufferBuilder::new();
529 let v = b.create_vector(&[123u8, 234u8][..]);
530 let name = b.create_string("foo");
531 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
532 name: Some(name),
533 inventory: Some(v), ..Default::default()});
534 assert_eq!(m.inventory().unwrap(), &[123, 234][..]);
535 }
536 #[test]
vector_of_bool_store()537 fn vector_of_bool_store() {
538 let mut b = flatbuffers::FlatBufferBuilder::new();
539 let v = b.create_vector(&[false, true, false, true][..]);
540 let name = b.create_string("foo");
541 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
542 name: Some(name),
543 testarrayofbools: Some(v), ..Default::default()});
544 assert_eq!(m.testarrayofbools().unwrap(), &[false, true, false, true][..]);
545 }
546 #[test]
vector_of_f64_store()547 fn vector_of_f64_store() {
548 let mut b = flatbuffers::FlatBufferBuilder::new();
549 let v = b.create_vector(&[3.14159265359f64][..]);
550 let name = b.create_string("foo");
551 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
552 name: Some(name),
553 vector_of_doubles: Some(v), ..Default::default()});
554 assert_eq!(m.vector_of_doubles().unwrap().len(), 1);
555 assert_eq!(m.vector_of_doubles().unwrap().get(0), 3.14159265359f64);
556 }
557 #[test]
vector_of_struct_store()558 fn vector_of_struct_store() {
559 let mut b = flatbuffers::FlatBufferBuilder::new();
560 let v = b.create_vector(&[my_game::example::Test::new(127, -128), my_game::example::Test::new(3, 123)][..]);
561 let name = b.create_string("foo");
562 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
563 name: Some(name),
564 test4: Some(v), ..Default::default()});
565 assert_eq!(m.test4().unwrap(), &[my_game::example::Test::new(127, -128), my_game::example::Test::new(3, 123)][..]);
566 }
567 #[test]
vector_of_struct_store_with_type_inference()568 fn vector_of_struct_store_with_type_inference() {
569 let mut b = flatbuffers::FlatBufferBuilder::new();
570 let v = b.create_vector(&[my_game::example::Test::new(127, -128),
571 my_game::example::Test::new(3, 123),
572 my_game::example::Test::new(100, 101)]);
573 let name = b.create_string("foo");
574 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
575 name: Some(name),
576 test4: Some(v), ..Default::default()});
577 assert_eq!(m.test4().unwrap(), &[my_game::example::Test::new(127, -128), my_game::example::Test::new(3, 123), my_game::example::Test::new(100, 101)][..]);
578 }
579 // TODO(rw) this passes, but I don't want to change the monster test schema right now
580 // #[test]
581 // fn vector_of_enum_store() {
582 // let mut b = flatbuffers::FlatBufferBuilder::new();
583 // let v = b.create_vector::<my_game::example::Color>(&[my_game::example::Color::Red, my_game::example::Color::Green][..]);
584 // let name = b.create_string("foo");
585 // let m = build_mon(&mut b, &my_game::example::MonsterArgs{
586 // name: Some(name),
587 // vector_of_enum: Some(v), ..Default::default()});
588 // assert_eq!(m.vector_of_enum().unwrap().len(), 2);
589 // assert_eq!(m.vector_of_enum().unwrap().get(0), my_game::example::Color::Red);
590 // assert_eq!(m.vector_of_enum().unwrap().get(1), my_game::example::Color::Green);
591 // }
592 #[test]
vector_of_table_store()593 fn vector_of_table_store() {
594 let b = &mut flatbuffers::FlatBufferBuilder::new();
595 let t0 = {
596 let name = b.create_string("foo");
597 let args = my_game::example::MonsterArgs{hp: 55, name: Some(name), ..Default::default()};
598 my_game::example::Monster::create(b, &args)
599 };
600 let t1 = {
601 let name = b.create_string("bar");
602 let args = my_game::example::MonsterArgs{name: Some(name), ..Default::default()};
603 my_game::example::Monster::create(b, &args)
604 };
605 let v = b.create_vector(&[t0, t1][..]);
606 let name = b.create_string("foo");
607 let m = build_mon(b, &my_game::example::MonsterArgs{
608 name: Some(name),
609 testarrayoftables: Some(v), ..Default::default()});
610 assert_eq!(m.testarrayoftables().unwrap().len(), 2);
611 assert_eq!(m.testarrayoftables().unwrap().get(0).hp(), 55);
612 assert_eq!(m.testarrayoftables().unwrap().get(0).name(), "foo");
613 assert_eq!(m.testarrayoftables().unwrap().get(1).hp(), 100);
614 assert_eq!(m.testarrayoftables().unwrap().get(1).name(), "bar");
615 }
616 }
617
618 #[cfg(test)]
619 mod generated_code_alignment_and_padding {
620 extern crate flatbuffers;
621 use super::my_game;
622
623 #[test]
enum_color_is_1_byte()624 fn enum_color_is_1_byte() {
625 assert_eq!(1, ::std::mem::size_of::<my_game::example::Color>());
626 }
627
628 #[test]
enum_color_is_aligned_to_1()629 fn enum_color_is_aligned_to_1() {
630 assert_eq!(1, ::std::mem::align_of::<my_game::example::Color>());
631 }
632
633 #[test]
union_any_is_1_byte()634 fn union_any_is_1_byte() {
635 assert_eq!(1, ::std::mem::size_of::<my_game::example::Any>());
636 }
637
638 #[test]
union_any_is_aligned_to_1()639 fn union_any_is_aligned_to_1() {
640 assert_eq!(1, ::std::mem::align_of::<my_game::example::Any>());
641 }
642
643 #[test]
struct_test_is_4_bytes()644 fn struct_test_is_4_bytes() {
645 assert_eq!(4, ::std::mem::size_of::<my_game::example::Test>());
646 }
647
648 #[test]
struct_test_is_aligned_to_2()649 fn struct_test_is_aligned_to_2() {
650 assert_eq!(2, ::std::mem::align_of::<my_game::example::Test>());
651 }
652
653 #[test]
struct_vec3_is_32_bytes()654 fn struct_vec3_is_32_bytes() {
655 assert_eq!(32, ::std::mem::size_of::<my_game::example::Vec3>());
656 }
657
658 #[test]
struct_vec3_is_aligned_to_8()659 fn struct_vec3_is_aligned_to_8() {
660 assert_eq!(8, ::std::mem::align_of::<my_game::example::Vec3>());
661 }
662
663 #[test]
struct_vec3_is_written_with_correct_alignment_in_table()664 fn struct_vec3_is_written_with_correct_alignment_in_table() {
665 let b = &mut flatbuffers::FlatBufferBuilder::new();
666 {
667 let name = b.create_string("foo");
668 let mon = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
669 name: Some(name),
670 pos: Some(&my_game::example::Vec3::new(1.0, 2.0, 3.0, 4.0,
671 my_game::example::Color::Green,
672 &my_game::example::Test::new(98, 99))),
673 ..Default::default()});
674 my_game::example::finish_monster_buffer(b, mon);
675 }
676 let buf = b.finished_data();
677 let mon = my_game::example::get_root_as_monster(buf);
678 let vec3 = mon.pos().unwrap();
679
680 let start_ptr = buf.as_ptr() as usize;
681 let vec3_ptr = vec3 as *const my_game::example::Vec3 as usize;
682
683 assert!(vec3_ptr > start_ptr);
684 let aln = ::std::mem::align_of::<my_game::example::Vec3>();
685 assert_eq!((vec3_ptr - start_ptr) % aln, 0);
686 }
687
688 #[test]
struct_ability_is_8_bytes()689 fn struct_ability_is_8_bytes() {
690 assert_eq!(8, ::std::mem::size_of::<my_game::example::Ability>());
691 }
692
693 #[test]
struct_ability_is_aligned_to_4()694 fn struct_ability_is_aligned_to_4() {
695 assert_eq!(4, ::std::mem::align_of::<my_game::example::Ability>());
696 }
697
698 #[test]
struct_ability_is_written_with_correct_alignment_in_table_vector()699 fn struct_ability_is_written_with_correct_alignment_in_table_vector() {
700 let b = &mut flatbuffers::FlatBufferBuilder::new();
701 {
702 let name = b.create_string("foo");
703 let v = b.create_vector(&[my_game::example::Ability::new(1, 2),
704 my_game::example::Ability::new(3, 4),
705 my_game::example::Ability::new(5, 6)]);
706 let mon = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
707 name: Some(name),
708 testarrayofsortedstruct: Some(v),
709 ..Default::default()});
710 my_game::example::finish_monster_buffer(b, mon);
711 }
712 let buf = b.finished_data();
713 let mon = my_game::example::get_root_as_monster(buf);
714 let abilities = mon.testarrayofsortedstruct().unwrap();
715
716 let start_ptr = buf.as_ptr() as usize;
717 for a in abilities.iter() {
718 let a_ptr = a as *const my_game::example::Ability as usize;
719 assert!(a_ptr > start_ptr);
720 let aln = ::std::mem::align_of::<my_game::example::Ability>();
721 assert_eq!((a_ptr - start_ptr) % aln, 0);
722 }
723 }
724 }
725
726 #[cfg(test)]
727 mod roundtrip_byteswap {
728 extern crate quickcheck;
729 extern crate flatbuffers;
730
731 const N: u64 = 10000;
732
palindrome_32(x: f32) -> bool733 fn palindrome_32(x: f32) -> bool {
734 x == f32::from_bits(x.to_bits().swap_bytes())
735 }
palindrome_64(x: f64) -> bool736 fn palindrome_64(x: f64) -> bool {
737 x == f64::from_bits(x.to_bits().swap_bytes())
738 }
739
prop_f32(x: f32)740 fn prop_f32(x: f32) {
741 use flatbuffers::byte_swap_f32;
742
743 let there = byte_swap_f32(x);
744
745 let back_again = byte_swap_f32(there);
746
747 if !palindrome_32(x) {
748 assert!(x != there);
749 }
750
751 assert_eq!(x, back_again);
752 }
753
prop_f64(x: f64)754 fn prop_f64(x: f64) {
755 use flatbuffers::byte_swap_f64;
756
757 let there = byte_swap_f64(x);
758 let back_again = byte_swap_f64(there);
759
760 if !palindrome_64(x) {
761 assert!(x != there);
762 }
763
764 assert_eq!(x, back_again);
765 }
766
767 #[test]
fuzz_f32()768 fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_f32 as fn(f32)); }
769 #[test]
fuzz_f64()770 fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_f64 as fn(f64)); }
771 }
772
773 #[cfg(test)]
774 mod roundtrip_vectors {
775
776 #[cfg(test)]
777 mod scalar {
778 extern crate quickcheck;
779 extern crate flatbuffers;
780
781 const N: u64 = 20;
782
prop<T: PartialEq + ::std::fmt::Debug + Copy + flatbuffers::EndianScalar + flatbuffers::Push>(xs: Vec<T>)783 fn prop<T: PartialEq + ::std::fmt::Debug + Copy + flatbuffers::EndianScalar + flatbuffers::Push>(xs: Vec<T>) {
784 use flatbuffers::Follow;
785
786 let mut b = flatbuffers::FlatBufferBuilder::new();
787 b.start_vector::<T>(xs.len());
788 for i in (0..xs.len()).rev() {
789 b.push::<T>(xs[i]);
790 }
791 let vecend = b.end_vector::<T>(xs.len());
792 b.finish_minimal(vecend);
793
794 let buf = b.finished_data();
795
796 let got = <flatbuffers::ForwardsUOffset<&[T]>>::follow(buf, 0);
797 assert_eq!(got, &xs[..]);
798 }
799
800 #[test]
easy_u8()801 fn easy_u8() {
802 prop::<u8>(vec![]);
803 prop::<u8>(vec![1u8]);
804 prop::<u8>(vec![1u8, 2u8]);
805 prop::<u8>(vec![1u8, 2u8, 3u8]);
806 prop::<u8>(vec![1u8, 2u8, 3u8, 4u8]);
807 }
808
809 #[test]
fuzz_bool()810 fn fuzz_bool() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<bool> as fn(Vec<_>)); }
811 #[test]
fuzz_u8()812 fn fuzz_u8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u8> as fn(Vec<_>)); }
813 #[test]
fuzz_i8()814 fn fuzz_i8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i8> as fn(Vec<_>)); }
815 #[test]
fuzz_u16()816 fn fuzz_u16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u16> as fn(Vec<_>)); }
817 #[test]
fuzz_i16()818 fn fuzz_i16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i16> as fn(Vec<_>)); }
819 #[test]
fuzz_u32()820 fn fuzz_u32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u32> as fn(Vec<_>)); }
821 #[test]
fuzz_i32()822 fn fuzz_i32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i32> as fn(Vec<_>)); }
823 #[test]
fuzz_u64()824 fn fuzz_u64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u64> as fn(Vec<_>)); }
825 #[test]
fuzz_i64()826 fn fuzz_i64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i64> as fn(Vec<_>)); }
827 #[test]
fuzz_f32()828 fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<f32> as fn(Vec<_>)); }
829 #[test]
fuzz_f64()830 fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<f64> as fn(Vec<_>)); }
831 }
832
833 #[cfg(test)]
834 mod create_vector_direct {
835 extern crate quickcheck;
836 extern crate flatbuffers;
837
838 const N: u64 = 20;
839
840 // This uses a macro because lifetimes for the trait-bounded function get too
841 // complicated.
842 macro_rules! impl_prop {
843 ($test_name:ident, $fn_name:ident, $ty:ident) => (
844 fn $fn_name(xs: Vec<$ty>) {
845 use flatbuffers::Follow;
846
847 let mut b = flatbuffers::FlatBufferBuilder::new();
848 b.create_vector_direct(&xs[..]);
849 let buf = b.unfinished_data();
850
851 let got = <flatbuffers::Vector<$ty>>::follow(&buf[..], 0).safe_slice();
852 assert_eq!(got, &xs[..]);
853 }
854 #[test]
855 fn $test_name() { quickcheck::QuickCheck::new().max_tests(N).quickcheck($fn_name as fn(Vec<_>)); }
856 )
857 }
858
859 impl_prop!(test_bool, prop_bool, bool);
860 impl_prop!(test_u8, prop_u8, u8);
861 impl_prop!(test_i8, prop_i8, i8);
862
863 #[cfg(test)]
864 #[cfg(target_endian = "little")]
865 mod host_is_le {
866 const N: u64 = 20;
867 use super::flatbuffers;
868 use super::quickcheck;
869 impl_prop!(test_u16, prop_u16, u16);
870 impl_prop!(test_u32, prop_u32, u32);
871 impl_prop!(test_u64, prop_u64, u64);
872 impl_prop!(test_i16, prop_i16, i16);
873 impl_prop!(test_i32, prop_i32, i32);
874 impl_prop!(test_i64, prop_i64, i64);
875 impl_prop!(test_f32, prop_f32, f32);
876 impl_prop!(test_f64, prop_f64, f64);
877 }
878 }
879
880 #[cfg(test)]
881 mod string_manual_build {
882 extern crate quickcheck;
883 extern crate flatbuffers;
884
prop(xs: Vec<String>)885 fn prop(xs: Vec<String>) {
886 use flatbuffers::Follow;
887
888 let mut b = flatbuffers::FlatBufferBuilder::new();
889 let mut offsets = Vec::new();
890 for s in xs.iter().rev() {
891 offsets.push(b.create_string(s.as_str()));
892 }
893
894 b.start_vector::<flatbuffers::WIPOffset<&str>>(xs.len());
895 for &i in offsets.iter() {
896 b.push(i);
897 }
898 let vecend = b.end_vector::<flatbuffers::WIPOffset<&str>>(xs.len());
899
900 b.finish_minimal(vecend);
901
902 let buf = b.finished_data();
903 let got = <flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&str>>>>::follow(buf, 0);
904
905 assert_eq!(got.len(), xs.len());
906 for i in 0..xs.len() {
907 assert_eq!(got.get(i), &xs[i][..]);
908 }
909 }
910
911 #[test]
fuzz()912 fn fuzz() {
913 quickcheck::QuickCheck::new().max_tests(20).quickcheck(prop as fn(Vec<_>));
914 }
915 }
916
917 #[cfg(test)]
918 mod string_helper_build {
919 extern crate quickcheck;
920 extern crate flatbuffers;
921
prop(input: Vec<String>)922 fn prop(input: Vec<String>) {
923 let xs: Vec<&str> = input.iter().map(|s: &String| &s[..]).collect();
924
925 use flatbuffers::Follow;
926
927 let mut b = flatbuffers::FlatBufferBuilder::new();
928 let vecend = b.create_vector_of_strings(&xs[..]);
929
930 b.finish_minimal(vecend);
931
932 let buf = b.finished_data();
933 let got = <flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&str>>>>::follow(buf, 0);
934
935 assert_eq!(got.len(), xs.len());
936 for i in 0..xs.len() {
937 assert_eq!(got.get(i), &xs[i][..]);
938 }
939 }
940
941 #[test]
fuzz()942 fn fuzz() {
943 quickcheck::QuickCheck::new().max_tests(100).quickcheck(prop as fn(Vec<_>));
944 }
945 }
946
947 #[cfg(test)]
948 mod ubyte {
949 extern crate quickcheck;
950 extern crate flatbuffers;
951
952 #[test]
fuzz_manual_build()953 fn fuzz_manual_build() {
954 fn prop(vec: Vec<u8>) {
955 let xs = &vec[..];
956
957 let mut b1 = flatbuffers::FlatBufferBuilder::new();
958 b1.start_vector::<u8>(xs.len());
959
960 for i in (0..xs.len()).rev() {
961 b1.push(xs[i]);
962 }
963 b1.end_vector::<u8>(xs.len());
964
965 let mut b2 = flatbuffers::FlatBufferBuilder::new();
966 b2.create_vector(xs);
967 assert_eq!(b1.unfinished_data(), b2.unfinished_data());
968 }
969 quickcheck::QuickCheck::new().max_tests(100).quickcheck(prop as fn(Vec<_>));
970 }
971 }
972 }
973
974 #[cfg(test)]
975 mod framing_format {
976 extern crate flatbuffers;
977
978 use super::my_game;
979
980 #[test]
test_size_prefixed_buffer()981 fn test_size_prefixed_buffer() {
982 // Create size prefixed buffer.
983 let mut b = flatbuffers::FlatBufferBuilder::new();
984 let args = &my_game::example::MonsterArgs{
985 mana: 200,
986 hp: 300,
987 name: Some(b.create_string("bob")),
988 ..Default::default()
989 };
990 let mon = my_game::example::Monster::create(&mut b, &args);
991 b.finish_size_prefixed(mon, None);
992
993 // Access it.
994 let buf = b.finished_data();
995 let m = flatbuffers::get_size_prefixed_root::<my_game::example::Monster>(buf);
996 assert_eq!(m.mana(), 200);
997 assert_eq!(m.hp(), 300);
998 assert_eq!(m.name(), "bob");
999 }
1000 }
1001
1002 #[cfg(test)]
1003 mod roundtrip_table {
1004 use std::collections::HashMap;
1005
1006 extern crate flatbuffers;
1007 extern crate quickcheck;
1008
1009 use super::LCG;
1010
1011 #[test]
table_of_mixed_scalars_fuzz()1012 fn table_of_mixed_scalars_fuzz() {
1013 // Values we're testing against: chosen to ensure no bits get chopped
1014 // off anywhere, and also be different from eachother.
1015 let bool_val: bool = true;
1016 let char_val: i8 = -127; // 0x81
1017 let uchar_val: u8 = 0xFF;
1018 let short_val: i16 = -32222; // 0x8222;
1019 let ushort_val: u16 = 0xFEEE;
1020 let int_val: i32 = unsafe { ::std::mem::transmute(0x83333333u32) };
1021 let uint_val: u32 = 0xFDDDDDDD;
1022 let long_val: i64 = unsafe { ::std::mem::transmute(0x8444444444444444u64) }; // TODO: byte literal?
1023 let ulong_val: u64 = 0xFCCCCCCCCCCCCCCCu64;
1024 let float_val: f32 = 3.14159;
1025 let double_val: f64 = 3.14159265359;
1026
1027 let test_value_types_max: isize = 11;
1028 let max_fields_per_object: flatbuffers::VOffsetT = 100;
1029 let num_fuzz_objects: isize = 1000; // The higher, the more thorough :)
1030
1031 let mut builder = flatbuffers::FlatBufferBuilder::new();
1032 let mut lcg = LCG::new();
1033
1034 let mut objects: Vec<flatbuffers::UOffsetT> = vec![0; num_fuzz_objects as usize];
1035
1036 // Generate num_fuzz_objects random objects each consisting of
1037 // fields_per_object fields, each of a random type.
1038 for i in 0..(num_fuzz_objects as usize) {
1039 let fields_per_object = (lcg.next() % (max_fields_per_object as u64)) as flatbuffers::VOffsetT;
1040 let start = builder.start_table();
1041
1042 for j in 0..fields_per_object {
1043 let choice = lcg.next() % (test_value_types_max as u64);
1044
1045 let f = flatbuffers::field_index_to_field_offset(j);
1046
1047 match choice {
1048 0 => {builder.push_slot::<bool>(f, bool_val, false);}
1049 1 => {builder.push_slot::<i8>(f, char_val, 0);}
1050 2 => {builder.push_slot::<u8>(f, uchar_val, 0);}
1051 3 => {builder.push_slot::<i16>(f, short_val, 0);}
1052 4 => {builder.push_slot::<u16>(f, ushort_val, 0);}
1053 5 => {builder.push_slot::<i32>(f, int_val, 0);}
1054 6 => {builder.push_slot::<u32>(f, uint_val, 0);}
1055 7 => {builder.push_slot::<i64>(f, long_val, 0);}
1056 8 => {builder.push_slot::<u64>(f, ulong_val, 0);}
1057 9 => {builder.push_slot::<f32>(f, float_val, 0.0);}
1058 10 => {builder.push_slot::<f64>(f, double_val, 0.0);}
1059 _ => { panic!("unknown choice: {}", choice); }
1060 }
1061 }
1062 objects[i] = builder.end_table(start).value();
1063 }
1064
1065 // Do some bookkeeping to generate stats on fuzzes:
1066 let mut stats: HashMap<u64, u64> = HashMap::new();
1067 let mut values_generated: u64 = 0;
1068
1069 // Embrace PRNG determinism:
1070 lcg.reset();
1071
1072 // Test that all objects we generated are readable and return the
1073 // expected values. We generate random objects in the same order
1074 // so this is deterministic:
1075 for i in 0..(num_fuzz_objects as usize) {
1076 let table = {
1077 let buf = builder.unfinished_data();
1078 let loc = buf.len() as flatbuffers::UOffsetT - objects[i];
1079 flatbuffers::Table::new(buf, loc as usize)
1080 };
1081
1082 let fields_per_object = (lcg.next() % (max_fields_per_object as u64)) as flatbuffers::VOffsetT;
1083 for j in 0..fields_per_object {
1084 let choice = lcg.next() % (test_value_types_max as u64);
1085
1086 *stats.entry(choice).or_insert(0) += 1;
1087 values_generated += 1;
1088
1089 let f = flatbuffers::field_index_to_field_offset(j);
1090
1091 match choice {
1092 0 => { assert_eq!(bool_val, table.get::<bool>(f, Some(false)).unwrap()); }
1093 1 => { assert_eq!(char_val, table.get::<i8>(f, Some(0)).unwrap()); }
1094 2 => { assert_eq!(uchar_val, table.get::<u8>(f, Some(0)).unwrap()); }
1095 3 => { assert_eq!(short_val, table.get::<i16>(f, Some(0)).unwrap()); }
1096 4 => { assert_eq!(ushort_val, table.get::<u16>(f, Some(0)).unwrap()); }
1097 5 => { assert_eq!(int_val, table.get::<i32>(f, Some(0)).unwrap()); }
1098 6 => { assert_eq!(uint_val, table.get::<u32>(f, Some(0)).unwrap()); }
1099 7 => { assert_eq!(long_val, table.get::<i64>(f, Some(0)).unwrap()); }
1100 8 => { assert_eq!(ulong_val, table.get::<u64>(f, Some(0)).unwrap()); }
1101 9 => { assert_eq!(float_val, table.get::<f32>(f, Some(0.0)).unwrap()); }
1102 10 => { assert_eq!(double_val, table.get::<f64>(f, Some(0.0)).unwrap()); }
1103 _ => { panic!("unknown choice: {}", choice); }
1104 }
1105 }
1106 }
1107
1108 // Assert that we tested all the fuzz cases enough:
1109 let min_tests_per_choice = 1000;
1110 assert!(values_generated > 0);
1111 assert!(min_tests_per_choice > 0);
1112 for i in 0..test_value_types_max as u64 {
1113 assert!(stats[&i] >= min_tests_per_choice,
1114 format!("inadequately-tested fuzz case: {}", i));
1115 }
1116 }
1117
1118 #[test]
table_of_byte_strings_fuzz()1119 fn table_of_byte_strings_fuzz() {
1120 fn prop(vec: Vec<Vec<u8>>) {
1121 use flatbuffers::field_index_to_field_offset as fi2fo;
1122 use flatbuffers::Follow;
1123
1124 let xs = &vec[..];
1125
1126 // build
1127 let mut b = flatbuffers::FlatBufferBuilder::new();
1128 let str_offsets: Vec<flatbuffers::WIPOffset<_>> = xs.iter().map(|s| b.create_byte_string(&s[..])).collect();
1129 let table_start = b.start_table();
1130
1131 for i in 0..xs.len() {
1132 b.push_slot_always(fi2fo(i as flatbuffers::VOffsetT), str_offsets[i]);
1133 }
1134 let root = b.end_table(table_start);
1135 b.finish_minimal(root);
1136
1137 // use
1138 let buf = b.finished_data();
1139 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(buf, 0);
1140
1141 for i in 0..xs.len() {
1142 let v = tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(i as flatbuffers::VOffsetT), None);
1143 assert_eq!(v, Some(&xs[i][..]));
1144 }
1145 }
1146 prop(vec![vec![1,2,3]]);
1147
1148 let n = 20;
1149 quickcheck::QuickCheck::new().max_tests(n).quickcheck(prop as fn(Vec<_>));
1150 }
1151
1152 #[test]
fuzz_table_of_strings()1153 fn fuzz_table_of_strings() {
1154 fn prop(vec: Vec<String>) {
1155 use flatbuffers::field_index_to_field_offset as fi2fo;
1156 use flatbuffers::Follow;
1157
1158 let xs = &vec[..];
1159
1160 // build
1161 let mut b = flatbuffers::FlatBufferBuilder::new();
1162 let str_offsets: Vec<flatbuffers::WIPOffset<_>> = xs.iter().map(|s| b.create_string(&s[..])).collect();
1163 let table_start = b.start_table();
1164
1165 for i in 0..xs.len() {
1166 b.push_slot_always(fi2fo(i as flatbuffers::VOffsetT), str_offsets[i]);
1167 }
1168 let root = b.end_table(table_start);
1169 b.finish_minimal(root);
1170
1171 // use
1172 let buf = b.finished_data();
1173 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(buf, 0);
1174
1175 for i in 0..xs.len() {
1176 let v = tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(i as flatbuffers::VOffsetT), None);
1177 assert_eq!(v, Some(&xs[i][..]));
1178 }
1179 }
1180 let n = 20;
1181 quickcheck::QuickCheck::new().max_tests(n).quickcheck(prop as fn(Vec<String>));
1182 }
1183
1184 mod table_of_vectors_of_scalars {
1185 extern crate flatbuffers;
1186 extern crate quickcheck;
1187
1188 const N: u64 = 20;
1189
prop<'a, T: flatbuffers::Follow<'a> + 'a + flatbuffers::EndianScalar + flatbuffers::Push + ::std::fmt::Debug>(vecs: Vec<Vec<T>>)1190 fn prop<'a, T: flatbuffers::Follow<'a> + 'a + flatbuffers::EndianScalar + flatbuffers::Push + ::std::fmt::Debug>(vecs: Vec<Vec<T>>) {
1191 use flatbuffers::field_index_to_field_offset as fi2fo;
1192 use flatbuffers::Follow;
1193
1194 // build
1195 let mut b = flatbuffers::FlatBufferBuilder::new();
1196 let mut offs = vec![];
1197 for vec in &vecs {
1198 b.start_vector::<T>(vec.len());
1199
1200 let xs = &vec[..];
1201 for i in (0..xs.len()).rev() {
1202 b.push::<T>(xs[i]);
1203 }
1204 let vecend = b.end_vector::<T>(xs.len());
1205 offs.push(vecend);
1206 }
1207
1208 let table_start = b.start_table();
1209
1210 for i in 0..vecs.len() {
1211 b.push_slot_always(fi2fo(i as flatbuffers::VOffsetT), offs[i]);
1212 }
1213 let root = b.end_table(table_start);
1214 b.finish_minimal(root);
1215
1216 // use
1217 let buf = b.finished_data();
1218 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(buf, 0);
1219
1220 for i in 0..vecs.len() {
1221 let got = tab.get::<flatbuffers::ForwardsUOffset<&[T]>>(fi2fo(i as flatbuffers::VOffsetT), None);
1222 assert!(got.is_some());
1223 let got2 = got.unwrap();
1224 assert_eq!(&vecs[i][..], got2);
1225 }
1226 }
1227
1228 #[test]
fuzz_bool()1229 fn fuzz_bool() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<bool>>)); }
1230
1231 #[test]
fuzz_u8()1232 fn fuzz_u8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u8>>)); }
1233 #[test]
fuzz_u16()1234 fn fuzz_u16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u16>>)); }
1235 #[test]
fuzz_u32()1236 fn fuzz_u32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u32>>)); }
1237 #[test]
fuzz_u64()1238 fn fuzz_u64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u64>>)); }
1239
1240 #[test]
fuzz_i8()1241 fn fuzz_i8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u8>>)); }
1242 #[test]
fuzz_i16()1243 fn fuzz_i16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u16>>)); }
1244 #[test]
fuzz_i32()1245 fn fuzz_i32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u32>>)); }
1246 #[test]
fuzz_i64()1247 fn fuzz_i64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u64>>)); }
1248
1249 #[test]
fuzz_f32()1250 fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<f32>>)); }
1251 #[test]
fuzz_f64()1252 fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<f64>>)); }
1253 }
1254 }
1255
1256 #[cfg(test)]
1257 mod roundtrip_scalars {
1258 extern crate flatbuffers;
1259 extern crate quickcheck;
1260
1261 const N: u64 = 1000;
1262
prop<T: PartialEq + ::std::fmt::Debug + Copy + flatbuffers::EndianScalar>(x: T)1263 fn prop<T: PartialEq + ::std::fmt::Debug + Copy + flatbuffers::EndianScalar>(x: T) {
1264 let mut buf = vec![0u8; ::std::mem::size_of::<T>()];
1265 flatbuffers::emplace_scalar(&mut buf[..], x);
1266 let y = flatbuffers::read_scalar(&buf[..]);
1267 assert_eq!(x, y);
1268 }
1269
1270 #[test]
fuzz_bool()1271 fn fuzz_bool() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<bool> as fn(_)); }
1272 #[test]
fuzz_u8()1273 fn fuzz_u8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u8> as fn(_)); }
1274 #[test]
fuzz_i8()1275 fn fuzz_i8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i8> as fn(_)); }
1276
1277 #[test]
fuzz_u16()1278 fn fuzz_u16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u16> as fn(_)); }
1279 #[test]
fuzz_i16()1280 fn fuzz_i16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i16> as fn(_)); }
1281
1282 #[test]
fuzz_u32()1283 fn fuzz_u32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u32> as fn(_)); }
1284 #[test]
fuzz_i32()1285 fn fuzz_i32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i32> as fn(_)); }
1286
1287 #[test]
fuzz_u64()1288 fn fuzz_u64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u64> as fn(_)); }
1289 #[test]
fuzz_i64()1290 fn fuzz_i64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i64> as fn(_)); }
1291
1292 #[test]
fuzz_f32()1293 fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<f32> as fn(_)); }
1294 #[test]
fuzz_f64()1295 fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<f64> as fn(_)); }
1296 }
1297
1298 #[cfg(test)]
1299 mod roundtrip_push_follow_scalars {
1300 extern crate flatbuffers;
1301 extern crate quickcheck;
1302
1303 use flatbuffers::Push;
1304
1305 const N: u64 = 1000;
1306
1307 // This uses a macro because lifetimes for a trait-bounded function get too
1308 // complicated.
1309 macro_rules! impl_prop {
1310 ($fn_name:ident, $ty:ident) => (
1311 fn $fn_name(x: $ty) {
1312 let mut buf = vec![0u8; ::std::mem::size_of::<$ty>()];
1313 x.push(&mut buf[..], &[][..]);
1314 let fs: flatbuffers::FollowStart<$ty> = flatbuffers::FollowStart::new();
1315 assert_eq!(fs.self_follow(&buf[..], 0), x);
1316 }
1317 )
1318 }
1319
1320 impl_prop!(prop_bool, bool);
1321 impl_prop!(prop_u8, u8);
1322 impl_prop!(prop_i8, i8);
1323 impl_prop!(prop_u16, u16);
1324 impl_prop!(prop_i16, i16);
1325 impl_prop!(prop_u32, u32);
1326 impl_prop!(prop_i32, i32);
1327 impl_prop!(prop_u64, u64);
1328 impl_prop!(prop_i64, i64);
1329 impl_prop!(prop_f32, f32);
1330 impl_prop!(prop_f64, f64);
1331
1332 #[test]
fuzz_bool()1333 fn fuzz_bool() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_bool as fn(bool)); }
1334 #[test]
fuzz_u8()1335 fn fuzz_u8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_u8 as fn(u8)); }
1336 #[test]
fuzz_i8()1337 fn fuzz_i8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_i8 as fn(i8)); }
1338 #[test]
fuzz_u16()1339 fn fuzz_u16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_u16 as fn(u16)); }
1340 #[test]
fuzz_i16()1341 fn fuzz_i16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_i16 as fn(i16)); }
1342 #[test]
fuzz_u32()1343 fn fuzz_u32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_u32 as fn(u32)); }
1344 #[test]
fuzz_i32()1345 fn fuzz_i32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_i32 as fn(i32)); }
1346 #[test]
fuzz_u64()1347 fn fuzz_u64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_u64 as fn(u64)); }
1348 #[test]
fuzz_i64()1349 fn fuzz_i64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_i64 as fn(i64)); }
1350 #[test]
fuzz_f32()1351 fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_f32 as fn(f32)); }
1352 #[test]
fuzz_f64()1353 fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_f64 as fn(f64)); }
1354 }
1355
1356
1357 #[cfg(test)]
1358 mod write_and_read_examples {
1359 extern crate flatbuffers;
1360
1361 use super::create_serialized_example_with_library_code;
1362 use super::create_serialized_example_with_generated_code;
1363 use super::serialized_example_is_accessible_and_correct;
1364
1365 #[test]
generated_code_creates_correct_example()1366 fn generated_code_creates_correct_example() {
1367 let b = &mut flatbuffers::FlatBufferBuilder::new();
1368 create_serialized_example_with_generated_code(b);
1369 let buf = b.finished_data();
1370 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1371 }
1372
1373 #[test]
generated_code_creates_correct_example_repeatedly_with_reset()1374 fn generated_code_creates_correct_example_repeatedly_with_reset() {
1375 let b = &mut flatbuffers::FlatBufferBuilder::new();
1376 for _ in 0..100 {
1377 create_serialized_example_with_generated_code(b);
1378 {
1379 let buf = b.finished_data();
1380 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1381 }
1382 b.reset();
1383 }
1384 }
1385
1386 #[test]
library_code_creates_correct_example()1387 fn library_code_creates_correct_example() {
1388 let b = &mut flatbuffers::FlatBufferBuilder::new();
1389 create_serialized_example_with_library_code(b);
1390 let buf = b.finished_data();
1391 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1392 }
1393
1394 #[test]
library_code_creates_correct_example_repeatedly_with_reset()1395 fn library_code_creates_correct_example_repeatedly_with_reset() {
1396 let b = &mut flatbuffers::FlatBufferBuilder::new();
1397 for _ in 0..100 {
1398 create_serialized_example_with_library_code(b);
1399 {
1400 let buf = b.finished_data();
1401 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1402 }
1403 b.reset();
1404 }
1405 }
1406 }
1407
1408 #[cfg(test)]
1409 mod read_examples_from_other_language_ports {
1410 extern crate flatbuffers;
1411
1412 use super::load_file;
1413 use super::serialized_example_is_accessible_and_correct;
1414
1415 #[test]
gold_cpp_example_data_is_accessible_and_correct()1416 fn gold_cpp_example_data_is_accessible_and_correct() {
1417 let buf = load_file("../monsterdata_test.mon").expect("missing monsterdata_test.mon");
1418 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1419 }
1420 #[test]
java_wire_example_data_is_accessible_and_correct()1421 fn java_wire_example_data_is_accessible_and_correct() {
1422 let buf = load_file("../monsterdata_java_wire.mon");
1423 if buf.is_err() {
1424 println!("skipping java wire test because it is not present");
1425 return;
1426 }
1427 let buf = buf.unwrap();
1428 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1429 }
1430 #[test]
java_wire_size_prefixed_example_data_is_accessible_and_correct()1431 fn java_wire_size_prefixed_example_data_is_accessible_and_correct() {
1432 let buf = load_file("../monsterdata_java_wire_sp.mon");
1433 if buf.is_err() {
1434 println!("skipping java wire test because it is not present");
1435 return;
1436 }
1437 let buf = buf.unwrap();
1438 serialized_example_is_accessible_and_correct(&buf[..], true, true).unwrap();
1439 }
1440 }
1441
1442 #[cfg(test)]
1443 mod generated_code_asserts {
1444 extern crate flatbuffers;
1445
1446 use super::my_game;
1447
1448 #[test]
1449 #[should_panic]
monster_builder_fails_when_name_is_missing()1450 fn monster_builder_fails_when_name_is_missing() {
1451 let b = &mut flatbuffers::FlatBufferBuilder::new();
1452 my_game::example::Monster::create(b, &my_game::example::MonsterArgs{..Default::default()});
1453 }
1454 }
1455
1456 #[cfg(test)]
1457 mod generated_key_comparisons {
1458 extern crate flatbuffers;
1459
1460 use super::my_game;
1461
1462 #[test]
struct_ability_key_compare_less_than()1463 fn struct_ability_key_compare_less_than() {
1464 let a = my_game::example::Ability::new(1, 2);
1465 let b = my_game::example::Ability::new(2, 1);
1466 let c = my_game::example::Ability::new(3, 3);
1467
1468 assert_eq!(a.key_compare_less_than(&a), false);
1469 assert_eq!(b.key_compare_less_than(&b), false);
1470 assert_eq!(c.key_compare_less_than(&c), false);
1471
1472 assert_eq!(a.key_compare_less_than(&b), true);
1473 assert_eq!(a.key_compare_less_than(&c), true);
1474
1475 assert_eq!(b.key_compare_less_than(&a), false);
1476 assert_eq!(b.key_compare_less_than(&c), true);
1477
1478 assert_eq!(c.key_compare_less_than(&a), false);
1479 assert_eq!(c.key_compare_less_than(&b), false);
1480 }
1481
1482 #[test]
struct_key_compare_with_value()1483 fn struct_key_compare_with_value() {
1484 let a = my_game::example::Ability::new(1, 2);
1485
1486 assert_eq!(a.key_compare_with_value(0), ::std::cmp::Ordering::Greater);
1487 assert_eq!(a.key_compare_with_value(1), ::std::cmp::Ordering::Equal);
1488 assert_eq!(a.key_compare_with_value(2), ::std::cmp::Ordering::Less);
1489 }
1490
1491 #[test]
struct_key_compare_less_than()1492 fn struct_key_compare_less_than() {
1493 let a = my_game::example::Ability::new(1, 2);
1494 let b = my_game::example::Ability::new(2, 1);
1495 let c = my_game::example::Ability::new(3, 3);
1496
1497 assert_eq!(a.key_compare_less_than(&a), false);
1498 assert_eq!(b.key_compare_less_than(&b), false);
1499 assert_eq!(c.key_compare_less_than(&c), false);
1500
1501 assert_eq!(a.key_compare_less_than(&b), true);
1502 assert_eq!(a.key_compare_less_than(&c), true);
1503
1504 assert_eq!(b.key_compare_less_than(&a), false);
1505 assert_eq!(b.key_compare_less_than(&c), true);
1506
1507 assert_eq!(c.key_compare_less_than(&a), false);
1508 assert_eq!(c.key_compare_less_than(&b), false);
1509 }
1510
1511 #[test]
table_key_compare_with_value()1512 fn table_key_compare_with_value() {
1513 // setup
1514 let builder = &mut flatbuffers::FlatBufferBuilder::new();
1515 super::create_serialized_example_with_library_code(builder);
1516 let buf = builder.finished_data();
1517 let a = my_game::example::get_root_as_monster(buf);
1518
1519 // preconditions
1520 assert_eq!(a.name(), "MyMonster");
1521
1522 assert_eq!(a.key_compare_with_value("AAA"), ::std::cmp::Ordering::Greater);
1523 assert_eq!(a.key_compare_with_value("MyMonster"), ::std::cmp::Ordering::Equal);
1524 assert_eq!(a.key_compare_with_value("ZZZ"), ::std::cmp::Ordering::Less);
1525 }
1526
1527 #[test]
table_key_compare_less_than()1528 fn table_key_compare_less_than() {
1529 // setup
1530 let builder = &mut flatbuffers::FlatBufferBuilder::new();
1531 super::create_serialized_example_with_library_code(builder);
1532 let buf = builder.finished_data();
1533 let a = my_game::example::get_root_as_monster(buf);
1534 let b = a.test_as_monster().unwrap();
1535
1536 // preconditions
1537 assert_eq!(a.name(), "MyMonster");
1538 assert_eq!(b.name(), "Fred");
1539
1540 assert_eq!(a.key_compare_less_than(&a), false);
1541 assert_eq!(a.key_compare_less_than(&b), false);
1542
1543 assert_eq!(b.key_compare_less_than(&a), true);
1544 assert_eq!(b.key_compare_less_than(&b), false);
1545 }
1546 }
1547
1548 #[cfg(test)]
1549 mod included_schema_generated_code {
1550 extern crate flatbuffers;
1551
1552 //extern crate rust_usage_test;
1553
1554 // TODO(rw): make generated sub-namespace files importable
1555 //#[test]
1556 //fn namespace_test_mod_is_importable() {
1557 // use rust_usage_test::namespace_test;
1558 //}
1559 //#[test]
1560 //fn namespace_test1_mod_is_importable() {
1561 // use rust_usage_test::namespace_test::namespace_test1_generated;
1562 //}
1563 //#[test]
1564 //fn namespace_test2_mod_is_importable() {
1565 // use rust_usage_test::namespace_test::namespace_test2_generated;
1566 //}
1567 }
1568
1569 #[cfg(test)]
1570 mod builder_asserts {
1571 extern crate flatbuffers;
1572
1573 #[test]
1574 #[should_panic]
end_table_should_panic_when_not_in_table()1575 fn end_table_should_panic_when_not_in_table() {
1576 let mut b = flatbuffers::FlatBufferBuilder::new();
1577 b.end_table(flatbuffers::WIPOffset::new(0));
1578 }
1579
1580 #[test]
1581 #[should_panic]
create_string_should_panic_when_in_table()1582 fn create_string_should_panic_when_in_table() {
1583 let mut b = flatbuffers::FlatBufferBuilder::new();
1584 b.start_table();
1585 b.create_string("foo");
1586 }
1587
1588 #[test]
1589 #[should_panic]
create_byte_string_should_panic_when_in_table()1590 fn create_byte_string_should_panic_when_in_table() {
1591 let mut b = flatbuffers::FlatBufferBuilder::new();
1592 b.start_table();
1593 b.create_byte_string(b"foo");
1594 }
1595
1596 #[test]
1597 #[should_panic]
push_struct_slot_should_panic_when_not_in_table()1598 fn push_struct_slot_should_panic_when_not_in_table() {
1599 #[derive(Copy, Clone, Debug, PartialEq)]
1600 #[repr(C, packed)]
1601 struct foo { }
1602 impl<'b> flatbuffers::Push for &'b foo {
1603 type Output = foo;
1604 fn push<'a>(&'a self, _dst: &'a mut [u8], _rest: &'a [u8]) { }
1605 }
1606 let mut b = flatbuffers::FlatBufferBuilder::new();
1607 b.push_slot_always(0, &foo{});
1608 }
1609
1610 #[test]
1611 #[should_panic]
finished_bytes_should_panic_when_table_is_not_finished()1612 fn finished_bytes_should_panic_when_table_is_not_finished() {
1613 let mut b = flatbuffers::FlatBufferBuilder::new();
1614 b.start_table();
1615 b.finished_data();
1616 }
1617
1618 #[test]
1619 #[should_panic]
required_panics_when_field_not_set()1620 fn required_panics_when_field_not_set() {
1621 let mut b = flatbuffers::FlatBufferBuilder::new();
1622 let start = b.start_table();
1623 let o = b.end_table(start);
1624 b.required(o, 4 /* byte offset to first field */, "test field");
1625 }
1626 }
1627
1628 #[cfg(test)]
1629 mod follow_impls {
1630 extern crate flatbuffers;
1631 use flatbuffers::Follow;
1632 use flatbuffers::field_index_to_field_offset as fi2fo;
1633
1634 #[test]
to_u8()1635 fn to_u8() {
1636 let vec: Vec<u8> = vec![255, 3];
1637 let fs: flatbuffers::FollowStart<u8> = flatbuffers::FollowStart::new();
1638 assert_eq!(fs.self_follow(&vec[..], 1), 3);
1639 }
1640
1641 #[test]
to_u16()1642 fn to_u16() {
1643 let vec: Vec<u8> = vec![255, 255, 3, 4];
1644 let fs: flatbuffers::FollowStart<u16> = flatbuffers::FollowStart::new();
1645 assert_eq!(fs.self_follow(&vec[..], 2), 1027);
1646 }
1647
1648 #[test]
to_f32()1649 fn to_f32() {
1650 let vec: Vec<u8> = vec![255, 255, 255, 255, /* start of value */ 208, 15, 73, 64];
1651 let fs: flatbuffers::FollowStart<f32> = flatbuffers::FollowStart::new();
1652 assert_eq!(fs.self_follow(&vec[..], 4), 3.14159);
1653 }
1654
1655 #[test]
to_string()1656 fn to_string() {
1657 let vec: Vec<u8> = vec![255,255,255,255, 3, 0, 0, 0, 'f' as u8, 'o' as u8, 'o' as u8, 0];
1658 let off: flatbuffers::FollowStart<&str> = flatbuffers::FollowStart::new();
1659 assert_eq!(off.self_follow(&vec[..], 4), "foo");
1660 }
1661
1662 #[test]
to_byte_slice()1663 fn to_byte_slice() {
1664 let vec: Vec<u8> = vec![255, 255, 255, 255, 4, 0, 0, 0, 1, 2, 3, 4];
1665 let off: flatbuffers::FollowStart<&[u8]> = flatbuffers::FollowStart::new();
1666 assert_eq!(off.self_follow(&vec[..], 4), &[1, 2, 3, 4][..]);
1667 }
1668
1669 #[test]
to_byte_vector()1670 fn to_byte_vector() {
1671 let vec: Vec<u8> = vec![255, 255, 255, 255, 4, 0, 0, 0, 1, 2, 3, 4];
1672 let off: flatbuffers::FollowStart<flatbuffers::Vector<u8>> = flatbuffers::FollowStart::new();
1673 assert_eq!(off.self_follow(&vec[..], 4).safe_slice(), &[1, 2, 3, 4][..]);
1674 }
1675
1676 #[test]
to_byte_string_zero_teriminated()1677 fn to_byte_string_zero_teriminated() {
1678 let vec: Vec<u8> = vec![255, 255, 255, 255, 3, 0, 0, 0, 1, 2, 3, 0];
1679 let off: flatbuffers::FollowStart<&[u8]> = flatbuffers::FollowStart::new();
1680 assert_eq!(off.self_follow(&vec[..], 4), &[1, 2, 3][..]);
1681 }
1682
1683 #[cfg(target_endian = "little")]
1684 #[test]
to_slice_of_u16()1685 fn to_slice_of_u16() {
1686 let vec: Vec<u8> = vec![255, 255, 255, 255, 2, 0, 0, 0, 1, 2, 3, 4];
1687 let off: flatbuffers::FollowStart<&[u16]> = flatbuffers::FollowStart::new();
1688 assert_eq!(off.self_follow(&vec[..], 4), &vec![513, 1027][..]);
1689 }
1690
1691 #[test]
to_vector_of_u16()1692 fn to_vector_of_u16() {
1693 let vec: Vec<u8> = vec![255, 255, 255, 255, 2, 0, 0, 0, 1, 2, 3, 4];
1694 let off: flatbuffers::FollowStart<flatbuffers::Vector<u16>> = flatbuffers::FollowStart::new();
1695 assert_eq!(off.self_follow(&vec[..], 4).len(), 2);
1696 assert_eq!(off.self_follow(&vec[..], 4).get(0), 513);
1697 assert_eq!(off.self_follow(&vec[..], 4).get(1), 1027);
1698 }
1699
1700 #[test]
to_struct()1701 fn to_struct() {
1702 #[derive(Copy, Clone, Debug, PartialEq)]
1703 #[repr(C, packed)]
1704 struct FooStruct {
1705 a: i8,
1706 b: u8,
1707 c: i16,
1708 }
1709 impl<'a> flatbuffers::Follow<'a> for &'a FooStruct {
1710 type Inner = &'a FooStruct;
1711 #[inline(always)]
1712 fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
1713 flatbuffers::follow_cast_ref::<FooStruct>(buf, loc)
1714 }
1715 }
1716
1717 let vec: Vec<u8> = vec![255, 255, 255, 255, 1, 2, 3, 4];
1718 let off: flatbuffers::FollowStart<&FooStruct> = flatbuffers::FollowStart::new();
1719 assert_eq!(*off.self_follow(&vec[..], 4), FooStruct{a: 1, b: 2, c: 1027});
1720 }
1721
1722 #[test]
to_vector_of_offset_to_string_elements()1723 fn to_vector_of_offset_to_string_elements() {
1724 let buf: Vec<u8> = vec![/* vec len */ 1, 0, 0, 0, /* offset to string */ 4, 0, 0, 0, /* str length */ 3, 0, 0, 0, 'f' as u8, 'o' as u8, 'o' as u8, 0];
1725 let s: flatbuffers::FollowStart<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&str>>> = flatbuffers::FollowStart::new();
1726 assert_eq!(s.self_follow(&buf[..], 0).len(), 1);
1727 assert_eq!(s.self_follow(&buf[..], 0).get(0), "foo");
1728 }
1729
1730 #[test]
to_slice_of_struct_elements()1731 fn to_slice_of_struct_elements() {
1732 #[derive(Copy, Clone, Debug, PartialEq)]
1733 #[repr(C, packed)]
1734 struct FooStruct {
1735 a: i8,
1736 b: u8,
1737 c: i16,
1738 }
1739 impl flatbuffers::SafeSliceAccess for FooStruct {}
1740 impl<'a> flatbuffers::Follow<'a> for FooStruct {
1741 type Inner = &'a FooStruct;
1742 #[inline(always)]
1743 fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
1744 flatbuffers::follow_cast_ref::<FooStruct>(buf, loc)
1745 }
1746 }
1747
1748 let buf: Vec<u8> = vec![1, 0, 0, 0, /* struct data */ 1, 2, 3, 4];
1749 let fs: flatbuffers::FollowStart<flatbuffers::Vector<FooStruct>> = flatbuffers::FollowStart::new();
1750 assert_eq!(fs.self_follow(&buf[..], 0).safe_slice(), &vec![FooStruct{a: 1, b: 2, c: 1027}][..]);
1751 }
1752
1753 #[test]
to_vector_of_struct_elements()1754 fn to_vector_of_struct_elements() {
1755 #[derive(Copy, Clone, Debug, PartialEq)]
1756 #[repr(C, packed)]
1757 struct FooStruct {
1758 a: i8,
1759 b: u8,
1760 c: i16,
1761 }
1762 impl<'a> flatbuffers::Follow<'a> for FooStruct {
1763 type Inner = &'a FooStruct;
1764 #[inline(always)]
1765 fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
1766 flatbuffers::follow_cast_ref::<FooStruct>(buf, loc)
1767 }
1768 }
1769
1770 let buf: Vec<u8> = vec![1, 0, 0, 0, /* struct data */ 1, 2, 3, 4];
1771 let fs: flatbuffers::FollowStart<flatbuffers::Vector<FooStruct>> = flatbuffers::FollowStart::new();
1772 assert_eq!(fs.self_follow(&buf[..], 0).len(), 1);
1773 assert_eq!(fs.self_follow(&buf[..], 0).get(0), &FooStruct{a: 1, b: 2, c: 1027});
1774 }
1775
1776 #[test]
to_root_to_empty_table()1777 fn to_root_to_empty_table() {
1778 let buf: Vec<u8> = vec![
1779 12, 0, 0, 0, // offset to root table
1780 // enter vtable
1781 4, 0, // vtable len
1782 0, 0, // inline size
1783 255, 255, 255, 255, // canary
1784 // enter table
1785 8, 0, 0, 0, // vtable location
1786 ];
1787 let fs: flatbuffers::FollowStart<flatbuffers::ForwardsUOffset<flatbuffers::Table>> = flatbuffers::FollowStart::new();
1788 assert_eq!(fs.self_follow(&buf[..], 0), flatbuffers::Table::new(&buf[..], 12));
1789 }
1790
1791 #[test]
to_root_table_get_slot_scalar_u8()1792 fn to_root_table_get_slot_scalar_u8() {
1793 let buf: Vec<u8> = vec![
1794 14, 0, 0, 0, // offset to root table
1795 // enter vtable
1796 6, 0, // vtable len
1797 2, 0, // inline size
1798 5, 0, // value loc
1799 255, 255, 255, 255, // canary
1800 // enter table
1801 10, 0, 0, 0, // vtable location
1802 0, 99 // value (with padding)
1803 ];
1804 let fs: flatbuffers::FollowStart<flatbuffers::ForwardsUOffset<flatbuffers::Table>> = flatbuffers::FollowStart::new();
1805 let tab = fs.self_follow(&buf[..], 0);
1806 assert_eq!(tab.get::<u8>(fi2fo(0), Some(123)), Some(99));
1807 }
1808
1809 #[test]
to_root_to_table_get_slot_scalar_u8_default_via_vtable_len()1810 fn to_root_to_table_get_slot_scalar_u8_default_via_vtable_len() {
1811 let buf: Vec<u8> = vec![
1812 12, 0, 0, 0, // offset to root table
1813 // enter vtable
1814 4, 0, // vtable len
1815 2, 0, // inline size
1816 255, 255, 255, 255, // canary
1817 // enter table
1818 8, 0, 0, 0, // vtable location
1819 ];
1820 let fs: flatbuffers::FollowStart<flatbuffers::ForwardsUOffset<flatbuffers::Table>> = flatbuffers::FollowStart::new();
1821 let tab = fs.self_follow(&buf[..], 0);
1822 assert_eq!(tab.get::<u8>(fi2fo(0), Some(123)), Some(123));
1823 }
1824
1825 #[test]
to_root_to_table_get_slot_scalar_u8_default_via_vtable_zero()1826 fn to_root_to_table_get_slot_scalar_u8_default_via_vtable_zero() {
1827 let buf: Vec<u8> = vec![
1828 14, 0, 0, 0, // offset to root table
1829 // enter vtable
1830 6, 0, // vtable len
1831 2, 0, // inline size
1832 0, 0, // zero means use the default value
1833 255, 255, 255, 255, // canary
1834 // enter table
1835 10, 0, 0, 0, // vtable location
1836 ];
1837 let fs: flatbuffers::FollowStart<flatbuffers::ForwardsUOffset<flatbuffers::Table>> = flatbuffers::FollowStart::new();
1838 let tab = fs.self_follow(&buf[..], 0);
1839 assert_eq!(tab.get::<u8>(fi2fo(0), Some(123)), Some(123));
1840 }
1841
1842 #[test]
to_root_to_table_get_slot_string_multiple_types()1843 fn to_root_to_table_get_slot_string_multiple_types() {
1844 let buf: Vec<u8> = vec![
1845 14, 0, 0, 0, // offset to root table
1846 // enter vtable
1847 6, 0, // vtable len
1848 2, 0, // inline size
1849 4, 0, // value loc
1850 255, 255, 255, 255, // canary
1851 // enter table
1852 10, 0, 0, 0, // vtable location
1853 8, 0, 0, 0, // offset to string
1854 // leave table
1855 255, 255, 255, 255, // canary
1856 // enter string
1857 3, 0, 0, 0, 109, 111, 111, 0 // string length and contents
1858 ];
1859 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(&buf[..], 0);
1860 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(0), None), Some("moo"));
1861 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(0), None), Some(&vec![109, 111, 111][..]));
1862 let v = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(0), None).unwrap();
1863 assert_eq!(v.len(), 3);
1864 assert_eq!(v.get(0), 109);
1865 assert_eq!(v.get(1), 111);
1866 assert_eq!(v.get(2), 111);
1867 }
1868
1869 #[test]
to_root_to_table_get_slot_string_multiple_types_default_via_vtable_len()1870 fn to_root_to_table_get_slot_string_multiple_types_default_via_vtable_len() {
1871 let buf: Vec<u8> = vec![
1872 12, 0, 0, 0, // offset to root table
1873 // enter vtable
1874 4, 0, // vtable len
1875 4, 0, // table inline len
1876 255, 255, 255, 255, // canary
1877 // enter table
1878 8, 0, 0, 0, // vtable location
1879 ];
1880 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(&buf[..], 0);
1881 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(0), Some("abc")), Some("abc"));
1882 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..]));
1883
1884 let default_vec_buf: Vec<u8> = vec![3, 0, 0, 0, 70, 71, 72, 0];
1885 let default_vec = flatbuffers::Vector::new(&default_vec_buf[..], 0);
1886 let v = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(0), Some(default_vec)).unwrap();
1887 assert_eq!(v.len(), 3);
1888 assert_eq!(v.get(0), 70);
1889 assert_eq!(v.get(1), 71);
1890 assert_eq!(v.get(2), 72);
1891 }
1892
1893 #[test]
to_root_to_table_get_slot_string_multiple_types_default_via_vtable_zero()1894 fn to_root_to_table_get_slot_string_multiple_types_default_via_vtable_zero() {
1895 let buf: Vec<u8> = vec![
1896 14, 0, 0, 0, // offset to root table
1897 // enter vtable
1898 6, 0, // vtable len
1899 2, 0, // inline size
1900 0, 0, // value loc
1901 255, 255, 255, 255, // canary
1902 // enter table
1903 10, 0, 0, 0, // vtable location
1904 ];
1905 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(&buf[..], 0);
1906 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(0), Some("abc")), Some("abc"));
1907 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..]));
1908
1909 let default_vec_buf: Vec<u8> = vec![3, 0, 0, 0, 70, 71, 72, 0];
1910 let default_vec = flatbuffers::Vector::new(&default_vec_buf[..], 0);
1911 let v = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(0), Some(default_vec)).unwrap();
1912 assert_eq!(v.len(), 3);
1913 assert_eq!(v.get(0), 70);
1914 assert_eq!(v.get(1), 71);
1915 assert_eq!(v.get(2), 72);
1916 }
1917 }
1918
1919 #[cfg(test)]
1920 mod push_impls {
1921 extern crate flatbuffers;
1922
1923 use super::my_game;
1924
check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8])1925 fn check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8]) {
1926 let got = b.unfinished_data();
1927 assert_eq!(want, got);
1928 }
1929
1930 #[test]
push_u8()1931 fn push_u8() {
1932 let mut b = flatbuffers::FlatBufferBuilder::new();
1933 b.push(123u8);
1934 check(&b, &[123]);
1935 }
1936
1937 #[test]
push_u64()1938 fn push_u64() {
1939 let mut b = flatbuffers::FlatBufferBuilder::new();
1940 b.push(0x12345678);
1941 check(&b, &[0x78, 0x56, 0x34, 0x12]);
1942 }
1943
1944 #[test]
push_f64()1945 fn push_f64() {
1946 let mut b = flatbuffers::FlatBufferBuilder::new();
1947 b.push(3.14159265359f64);
1948 check(&b, &[234, 46, 68, 84, 251, 33, 9, 64]);
1949 }
1950
1951 #[test]
push_generated_struct()1952 fn push_generated_struct() {
1953 let mut b = flatbuffers::FlatBufferBuilder::new();
1954 b.push(my_game::example::Test::new(10, 20));
1955 check(&b, &[10, 0, 20, 0]);
1956 }
1957
1958 #[test]
push_u8_vector_with_offset_with_alignment()1959 fn push_u8_vector_with_offset_with_alignment() {
1960 let mut b = flatbuffers::FlatBufferBuilder::new();
1961 let off = b.create_vector(&[1u8, 2, 3, 4, 5, 6, 7, 8, 9][..]);
1962 b.push(off);
1963 check(&b, &[/* loc */ 4, 0, 0, 0, /* len */ 9, 0, 0, 0, /* val */ 1, 2, 3, 4, 5, 6, 7, 8, 9, /* padding */ 0, 0, 0]);
1964 }
1965
1966 #[test]
push_u8_u16_alignment()1967 fn push_u8_u16_alignment() {
1968 let mut b = flatbuffers::FlatBufferBuilder::new();
1969 b.push(1u8);
1970 b.push(2u16);
1971 check(&b, &[2, 0, 0, 1]);
1972 }
1973
1974 #[test]
push_u8_u32_alignment()1975 fn push_u8_u32_alignment() {
1976 let mut b = flatbuffers::FlatBufferBuilder::new();
1977 b.push(1u8);
1978 b.push(2u32);
1979 check(&b, &[2, 0, 0, 0, 0, 0, 0, 1]);
1980 }
1981
1982 #[test]
push_u8_u64_alignment()1983 fn push_u8_u64_alignment() {
1984 let mut b = flatbuffers::FlatBufferBuilder::new();
1985 b.push(1u8);
1986 b.push(2u64);
1987 check(&b, &[2, 0, 0, 0,
1988 0, 0, 0, 0,
1989 0, 0, 0, 0,
1990 0, 0, 0, 1]);
1991 }
1992 }
1993
1994 #[cfg(test)]
1995 mod vtable_deduplication {
1996 extern crate flatbuffers;
1997 use flatbuffers::field_index_to_field_offset as fi2fo;
1998
check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8])1999 fn check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8]) {
2000 let got = b.unfinished_data();
2001 assert_eq!(want, got);
2002 }
2003
2004 #[test]
one_empty_table()2005 fn one_empty_table() {
2006 let mut b = flatbuffers::FlatBufferBuilder::new();
2007 let start0 = b.start_table();
2008 b.end_table(start0);
2009 check(&b, &[
2010 4, 0, // vtable size in bytes
2011 4, 0, // object inline data in bytes
2012
2013 4, 0, 0, 0, // backwards offset to vtable
2014 ]);
2015 }
2016
2017 #[test]
two_empty_tables_are_deduplicated()2018 fn two_empty_tables_are_deduplicated() {
2019 let mut b = flatbuffers::FlatBufferBuilder::new();
2020 let start0 = b.start_table();
2021 b.end_table(start0);
2022 let start1 = b.start_table();
2023 b.end_table(start1);
2024 check(&b, &[
2025 252, 255, 255, 255, // forwards offset to vtable
2026
2027 4, 0, // vtable size in bytes
2028 4, 0, // object inline data in bytes
2029
2030 4, 0, 0, 0, // backwards offset to vtable
2031 ]);
2032 }
2033
2034 #[test]
two_tables_with_two_conveniently_sized_inline_elements_are_deduplicated()2035 fn two_tables_with_two_conveniently_sized_inline_elements_are_deduplicated() {
2036 let mut b = flatbuffers::FlatBufferBuilder::new();
2037 let start0 = b.start_table();
2038 b.push_slot::<u64>(fi2fo(0), 100, 0);
2039 b.push_slot::<u32>(fi2fo(1), 101, 0);
2040 b.end_table(start0);
2041 let start1 = b.start_table();
2042 b.push_slot::<u64>(fi2fo(0), 200, 0);
2043 b.push_slot::<u32>(fi2fo(1), 201, 0);
2044 b.end_table(start1);
2045 check(&b, &[
2046 240, 255, 255, 255, // forwards offset to vtable
2047
2048 201, 0, 0, 0, // value #1
2049 200, 0, 0, 0, 0, 0, 0, 0, // value #0
2050
2051 8, 0, // vtable size in bytes
2052 16, 0, // object inline data in bytes
2053 8, 0, // offset in object for value #0
2054 4, 0, // offset in object for value #1
2055
2056 8, 0, 0, 0, // backwards offset to vtable
2057 101, 0, 0, 0, // value #1
2058 100, 0, 0, 0, 0, 0, 0, 0 // value #0
2059 ]);
2060 }
2061
2062 #[test]
many_identical_tables_use_few_vtables()2063 fn many_identical_tables_use_few_vtables() {
2064 let mut b = flatbuffers::FlatBufferBuilder::new();
2065 for _ in 0..1000 {
2066 let start = b.start_table();
2067 b.push_slot::<u8>(fi2fo(0), 100, 0);
2068 b.push_slot::<u32>(fi2fo(1), 101, 0);
2069 b.end_table(start);
2070 }
2071 assert!(b.num_written_vtables() <= 10);
2072 }
2073 }
2074
2075 #[cfg(test)]
2076 mod byte_layouts {
2077 extern crate flatbuffers;
2078 use flatbuffers::field_index_to_field_offset as fi2fo;
2079
check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8])2080 fn check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8]) {
2081 let got = b.unfinished_data();
2082 assert_eq!(want, got);
2083 }
2084
2085 #[test]
layout_01_basic_numbers()2086 fn layout_01_basic_numbers() {
2087 let mut b = flatbuffers::FlatBufferBuilder::new();
2088 b.push(true);
2089 check(&b, &[1]);
2090 b.push(-127i8);
2091 check(&b, &[129, 1]);
2092 b.push(255u8);
2093 check(&b, &[255, 129, 1]);
2094 b.push(-32222i16);
2095 check(&b, &[0x22, 0x82, 0, 255, 129, 1]); // first pad
2096 b.push(0xFEEEu16);
2097 check(&b, &[0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]); // no pad this time
2098 b.push(-53687092i32);
2099 check(&b, &[204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]);
2100 b.push(0x98765432u32);
2101 check(&b, &[0x32, 0x54, 0x76, 0x98, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]);
2102 }
2103
2104 #[test]
layout_01b_bigger_numbers()2105 fn layout_01b_bigger_numbers() {
2106 let mut b = flatbuffers::FlatBufferBuilder::new();
2107 b.push(0x1122334455667788u64);
2108 check(&b, &[0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]);
2109 }
2110
2111 #[test]
layout_02_1xbyte_vector()2112 fn layout_02_1xbyte_vector() {
2113 let mut b = flatbuffers::FlatBufferBuilder::new();
2114 check(&b, &[]);
2115 b.start_vector::<u8>(1);
2116 check(&b, &[0, 0, 0]); // align to 4bytes
2117 b.push(1u8);
2118 check(&b, &[1, 0, 0, 0]);
2119 b.end_vector::<u8>(1);
2120 check(&b, &[1, 0, 0, 0, 1, 0, 0, 0]); // padding
2121 }
2122
2123 #[test]
layout_03_2xbyte_vector()2124 fn layout_03_2xbyte_vector() {
2125 let mut b = flatbuffers::FlatBufferBuilder::new();
2126 b.start_vector::<u8>(2);
2127 check(&b, &[0, 0]); // align to 4bytes
2128 b.push(1u8);
2129 check(&b, &[1, 0, 0]);
2130 b.push(2u8);
2131 check(&b, &[2, 1, 0, 0]);
2132 b.end_vector::<u8>(2);
2133 check(&b, &[2, 0, 0, 0, 2, 1, 0, 0]); // padding
2134 }
2135
2136 #[test]
layout_03b_11xbyte_vector_matches_builder_size()2137 fn layout_03b_11xbyte_vector_matches_builder_size() {
2138 let mut b = flatbuffers::FlatBufferBuilder::new_with_capacity(12);
2139 b.start_vector::<u8>(8);
2140
2141 let mut gold = vec![0u8; 0];
2142 check(&b, &gold[..]);
2143
2144 for i in 1u8..=8 {
2145 b.push(i);
2146 gold.insert(0, i);
2147 check(&b, &gold[..]);
2148 }
2149 b.end_vector::<u8>(8);
2150 let want = vec![8u8, 0, 0, 0, 8, 7, 6, 5, 4, 3, 2, 1];
2151 check(&b, &want[..]);
2152 }
2153 #[test]
layout_04_1xuint16_vector()2154 fn layout_04_1xuint16_vector() {
2155 let mut b = flatbuffers::FlatBufferBuilder::new();
2156 b.start_vector::<u16>(1);
2157 check(&b, &[0, 0]); // align to 4bytes
2158 b.push(1u16);
2159 check(&b, &[1, 0, 0, 0]);
2160 b.end_vector::<u16>(1);
2161 check(&b, &[1, 0, 0, 0, 1, 0, 0, 0]); // padding
2162 }
2163
2164 #[test]
layout_05_2xuint16_vector()2165 fn layout_05_2xuint16_vector() {
2166 let mut b = flatbuffers::FlatBufferBuilder::new();
2167 let _off = b.start_vector::<u16>(2);
2168 check(&b, &[]); // align to 4bytes
2169 b.push(0xABCDu16);
2170 check(&b, &[0xCD, 0xAB]);
2171 b.push(0xDCBAu16);
2172 check(&b, &[0xBA, 0xDC, 0xCD, 0xAB]);
2173 b.end_vector::<u16>(2);
2174 check(&b, &[2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB]);
2175 }
2176
2177 #[test]
layout_06_create_string()2178 fn layout_06_create_string() {
2179 let mut b = flatbuffers::FlatBufferBuilder::new();
2180 let off0 = b.create_string("foo");
2181 assert_eq!(8, off0.value());
2182 check(&b, b"\x03\x00\x00\x00foo\x00"); // 0-terminated, no pad
2183 let off1 = b.create_string("moop");
2184 assert_eq!(20, off1.value());
2185 check(&b, b"\x04\x00\x00\x00moop\x00\x00\x00\x00\
2186 \x03\x00\x00\x00foo\x00"); // 0-terminated, 3-byte pad
2187 }
2188
2189 #[test]
layout_06b_create_string_unicode()2190 fn layout_06b_create_string_unicode() {
2191 let mut b = flatbuffers::FlatBufferBuilder::new();
2192 // These characters are chinese from blog.golang.org/strings
2193 // We use escape codes here so that editors without unicode support
2194 // aren't bothered:
2195 let uni_str = "\u{65e5}\u{672c}\u{8a9e}";
2196 let off0 = b.create_string(uni_str);
2197 assert_eq!(16, off0.value());
2198 check(&b, &[9, 0, 0, 0, 230, 151, 165, 230, 156, 172, 232, 170, 158, 0, // null-terminated, 2-byte pad
2199 0, 0]);
2200 }
2201
2202 #[test]
layout_06c_create_byte_string()2203 fn layout_06c_create_byte_string() {
2204 let mut b = flatbuffers::FlatBufferBuilder::new();
2205 let off0 = b.create_byte_string(b"foo");
2206 assert_eq!(8, off0.value());
2207 check(&b, b"\x03\x00\x00\x00foo\x00"); // 0-terminated, no pad
2208 let off1 = b.create_byte_string(b"moop");
2209 assert_eq!(20, off1.value());
2210 check(&b, b"\x04\x00\x00\x00moop\x00\x00\x00\x00\
2211 \x03\x00\x00\x00foo\x00"); // 0-terminated, 3-byte pad
2212 }
2213
2214 #[test]
layout_07_empty_vtable()2215 fn layout_07_empty_vtable() {
2216 let mut b = flatbuffers::FlatBufferBuilder::new();
2217 let off0 = b.start_table();
2218 check(&b, &[]);
2219 b.end_table(off0);
2220 check(&b, &[4, 0, // vtable length
2221 4, 0, // length of table including vtable offset
2222 4, 0, 0, 0]); // offset for start of vtable
2223 }
2224
2225 #[test]
layout_08_vtable_with_one_true_bool()2226 fn layout_08_vtable_with_one_true_bool() {
2227 let mut b = flatbuffers::FlatBufferBuilder::new();
2228 check(&b, &[]);
2229 let off0 = b.start_table();
2230 assert_eq!(0, off0.value());
2231 check(&b, &[]);
2232 b.push_slot(fi2fo(0), true, false);
2233 check(&b, &[1]);
2234 let off1 = b.end_table(off0);
2235 assert_eq!(8, off1.value());
2236 check(&b, &[
2237 6, 0, // vtable bytes
2238 8, 0, // length of object including vtable offset
2239 7, 0, // start of bool value
2240 6, 0, 0, 0, // offset for start of vtable (int32)
2241 0, 0, 0, // padded to 4 bytes
2242 1, // bool value
2243 ]);
2244 }
2245
2246 #[test]
layout_09_vtable_with_one_default_bool()2247 fn layout_09_vtable_with_one_default_bool() {
2248 let mut b = flatbuffers::FlatBufferBuilder::new();
2249 check(&b, &[]);
2250 let off = b.start_table();
2251 check(&b, &[]);
2252 b.push_slot(fi2fo(0), false, false);
2253 b.end_table(off);
2254 check(&b, &[
2255 4, 0, // vtable bytes
2256 4, 0, // end of object from here
2257 // entry 1 is zero and not stored.
2258 4, 0, 0, 0, // offset for start of vtable (int32)
2259 ]);
2260 }
2261
2262 #[test]
layout_10_vtable_with_one_int16()2263 fn layout_10_vtable_with_one_int16() {
2264 let mut b = flatbuffers::FlatBufferBuilder::new();
2265 check(&b, &[]);
2266 let off = b.start_table();
2267 b.push_slot(fi2fo(0), 0x789Ai16, 0);
2268 b.end_table(off);
2269 check(&b, &[
2270 6, 0, // vtable bytes
2271 8, 0, // end of object from here
2272 6, 0, // offset to value
2273 6, 0, 0, 0, // offset for start of vtable (int32)
2274 0, 0, // padding to 4 bytes
2275 0x9A, 0x78,
2276 ]);
2277 }
2278
2279 #[test]
layout_11_vtable_with_two_int16()2280 fn layout_11_vtable_with_two_int16() {
2281 let mut b = flatbuffers::FlatBufferBuilder::new();
2282 let off = b.start_table();
2283 b.push_slot(fi2fo(0), 0x3456i16, 0);
2284 b.push_slot(fi2fo(1), 0x789Ai16, 0);
2285 b.end_table(off);
2286 check(&b, &[
2287 8, 0, // vtable bytes
2288 8, 0, // end of object from here
2289 6, 0, // offset to value 0
2290 4, 0, // offset to value 1
2291 8, 0, 0, 0, // offset for start of vtable (int32)
2292 0x9A, 0x78, // value 1
2293 0x56, 0x34, // value 0
2294 ]);
2295 }
2296
2297 #[test]
layout_12_vtable_with_int16_and_bool()2298 fn layout_12_vtable_with_int16_and_bool() {
2299 let mut b = flatbuffers::FlatBufferBuilder::new();
2300 let off = b.start_table();
2301 b.push_slot(fi2fo(0), 0x3456i16, 0);
2302 b.push_slot(fi2fo(1), true, false);
2303 b.end_table(off);
2304 check(&b, &[
2305 8, 0, // vtable bytes
2306 8, 0, // end of object from here
2307 6, 0, // offset to value 0
2308 5, 0, // offset to value 1
2309 8, 0, 0, 0, // offset for start of vtable (int32)
2310 0, // padding
2311 1, // value 1
2312 0x56, 0x34, // value 0
2313 ]);
2314 }
2315
2316 #[test]
layout_12b_vtable_with_empty_vector()2317 fn layout_12b_vtable_with_empty_vector() {
2318 let mut b = flatbuffers::FlatBufferBuilder::new();
2319 b.start_vector::<u8>(0);
2320 let vecend = b.end_vector::<u8>(0);
2321 let off = b.start_table();
2322 b.push_slot_always(fi2fo(0), vecend);
2323 b.end_table(off);
2324 check(&b, &[
2325 6, 0, // vtable bytes
2326 8, 0,
2327 4, 0, // offset to vector offset
2328 6, 0, 0, 0, // offset for start of vtable (int32)
2329 4, 0, 0, 0,
2330 0, 0, 0, 0, // length of vector (not in struct)
2331 ]);
2332 }
2333
2334 #[test]
layout_12c_vtable_with_empty_vector_of_byte_and_some_scalars()2335 fn layout_12c_vtable_with_empty_vector_of_byte_and_some_scalars() {
2336 let mut b = flatbuffers::FlatBufferBuilder::new();
2337 b.start_vector::<u8>(0);
2338 let vecend = b.end_vector::<u8>(0);
2339 let off = b.start_table();
2340 b.push_slot::<i16>(fi2fo(0), 55i16, 0);
2341 b.push_slot_always::<flatbuffers::WIPOffset<_>>(fi2fo(1), vecend);
2342 b.end_table(off);
2343 check(&b, &[
2344 8, 0, // vtable bytes
2345 12, 0,
2346 10, 0, // offset to value 0
2347 4, 0, // offset to vector offset
2348 8, 0, 0, 0, // vtable loc
2349 8, 0, 0, 0, // value 1
2350 0, 0, 55, 0, // value 0
2351
2352 0, 0, 0, 0, // length of vector (not in struct)
2353 ]);
2354 }
2355 #[test]
layout_13_vtable_with_1_int16_and_2_vector_of_i16()2356 fn layout_13_vtable_with_1_int16_and_2_vector_of_i16() {
2357 let mut b = flatbuffers::FlatBufferBuilder::new();
2358 b.start_vector::<i16>(2);
2359 b.push(0x1234i16);
2360 b.push(0x5678i16);
2361 let vecend = b.end_vector::<i16>(2);
2362 let off = b.start_table();
2363 b.push_slot_always(fi2fo(1), vecend);
2364 b.push_slot(fi2fo(0), 55i16, 0);
2365 b.end_table(off);
2366 check(&b, &[
2367 8, 0, // vtable bytes
2368 12, 0, // length of object
2369 6, 0, // start of value 0 from end of vtable
2370 8, 0, // start of value 1 from end of buffer
2371 8, 0, 0, 0, // offset for start of vtable (int32)
2372 0, 0, // padding
2373 55, 0, // value 0
2374 4, 0, 0, 0, // vector position from here
2375 2, 0, 0, 0, // length of vector (uint32)
2376 0x78, 0x56, // vector value 1
2377 0x34, 0x12, // vector value 0
2378 ]);
2379 }
2380 #[test]
layout_14_vtable_with_1_struct_of_int8_and_int16_and_int32()2381 fn layout_14_vtable_with_1_struct_of_int8_and_int16_and_int32() {
2382 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
2383 #[repr(C, packed)]
2384 struct foo {
2385 a: i32,
2386 _pad0: [u8; 2],
2387 b: i16,
2388 _pad1: [u8; 3],
2389 c: i8,
2390 _pad2: [u8; 4],
2391 }
2392 assert_eq!(::std::mem::size_of::<foo>(), 16);
2393 impl<'b> flatbuffers::Push for &'b foo {
2394 type Output = foo;
2395 fn push<'a>(&'a self, dst: &'a mut [u8], _rest: &'a [u8]) {
2396 let src = unsafe {
2397 ::std::slice::from_raw_parts(*self as *const foo as *const u8, ::std::mem::size_of::<foo>())
2398 };
2399 dst.copy_from_slice(src);
2400 }
2401 }
2402
2403 let mut b = flatbuffers::FlatBufferBuilder::new();
2404 let off = b.start_table();
2405 let x = foo{a: 0x12345678i32.to_le(), _pad0: [0,0], b: 0x1234i16.to_le(), _pad1: [0, 0, 0], c: 0x12i8.to_le(), _pad2: [0, 0, 0, 0]};
2406 b.push_slot_always(fi2fo(0), &x);
2407 b.end_table(off);
2408 check(&b, &[
2409 6, 0, // vtable bytes
2410 20, 0, // end of object from here
2411 4, 0, // start of struct from here
2412 6, 0, 0, 0, // offset for start of vtable (int32)
2413
2414 0x78, 0x56, 0x34, 0x12, // value a
2415 0, 0, // padding
2416 0x34, 0x12, // value b
2417 0, 0, 0, // padding
2418 0x12, // value c
2419 0, 0, 0, 0, // padding
2420 ]);
2421 }
2422 #[test]
layout_15_vtable_with_1_vector_of_4_int8()2423 fn layout_15_vtable_with_1_vector_of_4_int8() {
2424 let mut b = flatbuffers::FlatBufferBuilder::new();
2425 b.start_vector::<i8>(4);
2426 b.push(33i8);
2427 b.push(44i8);
2428 b.push(55i8);
2429 b.push(66i8);
2430 let vecend = b.end_vector::<i8>(4);
2431 let off = b.start_table();
2432 b.push_slot_always(fi2fo(0), vecend);
2433 b.end_table(off);
2434 check(&b, &[
2435 6, 0, // vtable bytes
2436 8, 0,
2437 4, 0, // offset of vector offset
2438 6, 0, 0, 0, // offset for start of vtable (int32)
2439 4, 0, 0, 0, // vector start offset
2440
2441 4, 0, 0, 0, // vector length
2442 66, // vector value 1,1
2443 55, // vector value 1,0
2444 44, // vector value 0,1
2445 33, // vector value 0,0
2446 ]);
2447 }
2448
2449 #[test]
layout_16_table_with_some_elements()2450 fn layout_16_table_with_some_elements() {
2451 let mut b = flatbuffers::FlatBufferBuilder::new();
2452 let off = b.start_table();
2453 b.push_slot(fi2fo(0), 33i8, 0);
2454 b.push_slot(fi2fo(1), 66i16, 0);
2455 let off2 = b.end_table(off);
2456 b.finish_minimal(off2);
2457
2458 check(&b, &[
2459 12, 0, 0, 0, // root of table: points to vtable offset
2460
2461 8, 0, // vtable bytes
2462 8, 0, // end of object from here
2463 7, 0, // start of value 0
2464 4, 0, // start of value 1
2465
2466 8, 0, 0, 0, // offset for start of vtable (int32)
2467
2468 66, 0, // value 1
2469 0, // padding
2470 33, // value 0
2471 ]);
2472 }
2473
2474 #[test]
layout_17_one_unfinished_table_and_one_finished_table()2475 fn layout_17_one_unfinished_table_and_one_finished_table() {
2476 let mut b = flatbuffers::FlatBufferBuilder::new();
2477 {
2478 let off = b.start_table();
2479 b.push_slot(fi2fo(0), 33i8, 0);
2480 b.push_slot(fi2fo(1), 44i8, 0);
2481 b.end_table(off);
2482 }
2483
2484 {
2485 let off = b.start_table();
2486 b.push_slot(fi2fo(0), 55i8, 0);
2487 b.push_slot(fi2fo(1), 66i8, 0);
2488 b.push_slot(fi2fo(2), 77i8, 0);
2489 let off2 = b.end_table(off);
2490 b.finish_minimal(off2);
2491 }
2492
2493 check(&b, &[
2494 16, 0, 0, 0, // root of table: points to object
2495 0, 0, // padding
2496
2497 10, 0, // vtable bytes
2498 8, 0, // size of object
2499 7, 0, // start of value 0
2500 6, 0, // start of value 1
2501 5, 0, // start of value 2
2502 10, 0, 0, 0, // offset for start of vtable (int32)
2503 0, // padding
2504 77, // value 2
2505 66, // value 1
2506 55, // value 0
2507
2508 //12, 0, 0, 0, // root of table: points to object
2509
2510 8, 0, // vtable bytes
2511 8, 0, // size of object
2512 7, 0, // start of value 0
2513 6, 0, // start of value 1
2514 8, 0, 0, 0, // offset for start of vtable (int32)
2515 0, 0, // padding
2516 44, // value 1
2517 33, // value 0
2518 ]);
2519 }
2520
2521 #[test]
layout_18_a_bunch_of_bools()2522 fn layout_18_a_bunch_of_bools() {
2523 let mut b = flatbuffers::FlatBufferBuilder::new();
2524 let off = b.start_table();
2525 b.push_slot(fi2fo(0), true, false);
2526 b.push_slot(fi2fo(1), true, false);
2527 b.push_slot(fi2fo(2), true, false);
2528 b.push_slot(fi2fo(3), true, false);
2529 b.push_slot(fi2fo(4), true, false);
2530 b.push_slot(fi2fo(5), true, false);
2531 b.push_slot(fi2fo(6), true, false);
2532 b.push_slot(fi2fo(7), true, false);
2533 let off2 = b.end_table(off);
2534 b.finish_minimal(off2);
2535
2536 check(&b, &[
2537 24, 0, 0, 0, // root of table: points to vtable offset
2538
2539 20, 0, // vtable bytes
2540 12, 0, // size of object
2541 11, 0, // start of value 0
2542 10, 0, // start of value 1
2543 9, 0, // start of value 2
2544 8, 0, // start of value 3
2545 7, 0, // start of value 4
2546 6, 0, // start of value 5
2547 5, 0, // start of value 6
2548 4, 0, // start of value 7
2549 20, 0, 0, 0, // vtable offset
2550
2551 1, // value 7
2552 1, // value 6
2553 1, // value 5
2554 1, // value 4
2555 1, // value 3
2556 1, // value 2
2557 1, // value 1
2558 1, // value 0
2559 ]);
2560 }
2561
2562 #[test]
layout_19_three_bools()2563 fn layout_19_three_bools() {
2564 let mut b = flatbuffers::FlatBufferBuilder::new();
2565 let off = b.start_table();
2566 b.push_slot(fi2fo(0), true, false);
2567 b.push_slot(fi2fo(1), true, false);
2568 b.push_slot(fi2fo(2), true, false);
2569 let off2 = b.end_table(off);
2570 b.finish_minimal(off2);
2571
2572 check(&b, &[
2573 16, 0, 0, 0, // root of table: points to vtable offset
2574
2575 0, 0, // padding
2576
2577 10, 0, // vtable bytes
2578 8, 0, // size of object
2579 7, 0, // start of value 0
2580 6, 0, // start of value 1
2581 5, 0, // start of value 2
2582 10, 0, 0, 0, // vtable offset from here
2583
2584 0, // padding
2585 1, // value 2
2586 1, // value 1
2587 1, // value 0
2588 ]);
2589 }
2590
2591 #[test]
layout_20_some_floats()2592 fn layout_20_some_floats() {
2593 let mut b = flatbuffers::FlatBufferBuilder::new();
2594 let off = b.start_table();
2595 b.push_slot(fi2fo(0), 1.0f32, 0.0);
2596 b.end_table(off);
2597
2598 check(&b, &[
2599 6, 0, // vtable bytes
2600 8, 0, // size of object
2601 4, 0, // start of value 0
2602 6, 0, 0, 0, // vtable offset
2603
2604 0, 0, 128, 63, // value 0
2605 ]);
2606 }
2607
2608 #[test]
layout_21_vtable_defaults()2609 fn layout_21_vtable_defaults() {
2610 let mut b = flatbuffers::FlatBufferBuilder::new();
2611 let off = b.start_table();
2612 b.push_slot::<i8>(fi2fo(0), 1, 1);
2613 b.push_slot::<i8>(fi2fo(1), 3, 2);
2614 b.push_slot::<i8>(fi2fo(2), 3, 3);
2615 b.end_table(off);
2616 check(&b, &[
2617 8, 0, // vtable size in bytes
2618 8, 0, // object inline data in bytes
2619 0, 0, // entry 1/3: 0 => default
2620 7, 0, // entry 2/3: 7 => table start + 7 bytes
2621 // entry 3/3: not present => default
2622 8, 0, 0, 0,
2623 0, 0, 0,
2624 3,
2625 ]);
2626 }
2627
2628 #[test]
layout_22_root()2629 fn layout_22_root() {
2630 let mut b = flatbuffers::FlatBufferBuilder::new();
2631 let off = b.start_table();
2632 // skipped: b.push_slot_scalar::<i16>(0, 1, 1);
2633 b.push_slot::<i16>(fi2fo(1), 3, 2);
2634 b.push_slot::<i16>(fi2fo(2), 3, 3);
2635 let table_end = b.end_table(off);
2636 b.finish_minimal(table_end);
2637 check(&b, &[
2638 12, 0, 0, 0, // root
2639
2640 8, 0, // vtable size in bytes
2641 8, 0, // object inline data in bytes
2642 0, 0, // entry 1/3: 0 => default
2643 6, 0, // entry 2/3: 6 => table start + 6 bytes
2644 // entry 3/3: not present => default
2645 8, 0, 0, 0, // size of table data in bytes
2646 0, 0, // padding
2647 3, 0, // value 2/3
2648 ]);
2649 }
2650 #[test]
layout_23_varied_slots_and_root()2651 fn layout_23_varied_slots_and_root() {
2652 let mut b = flatbuffers::FlatBufferBuilder::new();
2653 let off = b.start_table();
2654 b.push_slot::<i16>(fi2fo(0), 1, 0);
2655 b.push_slot::<u8>(fi2fo(1), 2, 0);
2656 b.push_slot::<f32>(fi2fo(2), 3.0, 0.0);
2657 let table_end = b.end_table(off);
2658 b.finish_minimal(table_end);
2659 check(&b, &[
2660 16, 0, 0, 0, // root
2661 0, 0, // padding
2662 10, 0, // vtable bytes
2663 12, 0, // object inline data size
2664 10, 0, // offset to value #1 (i16)
2665 9, 0, // offset to value #2 (u8)
2666 4, 0, // offset to value #3 (f32)
2667 10, 0, // offset to vtable
2668 0, 0, // padding
2669 0, 0, 64, 64, // value #3 => 3.0 (float32)
2670 0, 2, // value #1 => 2 (u8)
2671 1, 0, // value #0 => 1 (int16)
2672 ]);
2673 }
2674 }
2675
2676 // this is not technically a test, but we want to always keep this generated
2677 // file up-to-date, and the simplest way to do that is to make sure that when
2678 // tests are run, the file is generated.
2679 #[test]
write_example_wire_data_to_file()2680 fn write_example_wire_data_to_file() {
2681 let b = &mut flatbuffers::FlatBufferBuilder::new();
2682 create_serialized_example_with_generated_code(b);
2683
2684 use ::std::io::Write;
2685 let mut f = std::fs::File::create("../monsterdata_rust_wire.mon").unwrap();
2686 f.write_all(b.finished_data()).unwrap();
2687 }
2688
load_file(filename: &str) -> Result<Vec<u8>, std::io::Error>2689 fn load_file(filename: &str) -> Result<Vec<u8>, std::io::Error> {
2690 use std::io::Read;
2691 let mut f = std::fs::File::open(filename)?;
2692 let mut buf = Vec::new();
2693 f.read_to_end(&mut buf)?;
2694 Ok(buf)
2695 }
2696