• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![no_std]
2 
3 #[cfg(not(feature = "no_std"))]
4 extern crate std;
5 
6 extern crate alloc;
7 
8 extern crate array_init;
9 
10 #[allow(dead_code, unused_imports)]
11 #[path = "../../arrays_test/mod.rs"]
12 mod arrays_test_generated;
13 
14 use alloc::format;
15 use core::fmt::Debug;
16 
17 use crate::arrays_test_generated::my_game::example::*;
18 
19 extern crate quickcheck;
20 
21 use array_init::array_init;
22 use core::mem::size_of;
23 use quickcheck::{Arbitrary, Gen};
24 
create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder)25 fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder) {
26     let nested_struct1 = NestedStruct::new(
27         &[-1, 2],
28         TestEnum::A,
29         &[TestEnum::C, TestEnum::B],
30         &[0x1122334455667788, -0x1122334455667788],
31     );
32     let nested_struct2 = NestedStruct::new(
33         &[3, -4],
34         TestEnum::B,
35         &[TestEnum::B, TestEnum::A],
36         &[-0x1122334455667788, 0x1122334455667788],
37     );
38     let array_struct = ArrayStruct::new(
39         12.34,
40         &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
41         -127,
42         &[nested_struct1, nested_struct2],
43         1,
44         &[-0x8000000000000000, 0x7FFFFFFFFFFFFFFF],
45     );
46     // Test five makes sense when specified.
47     let ss = ArrayTable::create(
48         builder,
49         &ArrayTableArgs {
50             a: Some(&array_struct),
51         },
52     );
53     finish_array_table_buffer(builder, ss);
54 }
55 
serialized_example_is_accessible_and_correct( bytes: &[u8], identifier_required: bool, size_prefixed: bool, )56 fn serialized_example_is_accessible_and_correct(
57     bytes: &[u8],
58     identifier_required: bool,
59     size_prefixed: bool,
60 ) {
61     if identifier_required {
62         let correct = if size_prefixed {
63             array_table_size_prefixed_buffer_has_identifier(bytes)
64         } else {
65             array_table_buffer_has_identifier(bytes)
66         };
67 
68         assert_eq!(correct, true);
69     }
70 
71     let array_table = if size_prefixed {
72         size_prefixed_root_as_array_table(bytes).unwrap()
73     } else {
74         root_as_array_table(bytes).unwrap()
75     };
76 
77     let array_struct = array_table.a().unwrap();
78     assert_eq!(array_struct.a(), 12.34);
79     assert_eq!(array_struct.b().len(), 0xF);
80     assert_eq!(array_struct.b().iter().sum::<i32>(), 120);
81     assert_eq!(array_struct.c(), -127);
82 
83     assert_eq!(array_struct.d().len(), 2);
84     let nested_struct1 = array_struct.d().get(0);
85     assert_eq!(nested_struct1.a().len(), 2);
86     assert_eq!(nested_struct1.a().iter().sum::<i32>(), 1);
87     assert_eq!(nested_struct1.b(), TestEnum::A);
88     assert_eq!(nested_struct1.c().len(), 2);
89     assert_eq!(nested_struct1.c().get(0), TestEnum::C);
90     assert_eq!(nested_struct1.c().get(1), TestEnum::B);
91     assert_eq!(nested_struct1.d().len(), 2);
92     assert_eq!(
93         [nested_struct1.d().get(0), nested_struct1.d().get(1)],
94         [0x1122334455667788, -0x1122334455667788]
95     );
96     let nested_struct2 = array_struct.d().get(1);
97     assert_eq!(nested_struct2.a().len(), 2);
98     assert_eq!(nested_struct2.a().iter().sum::<i32>(), -1);
99     assert_eq!(nested_struct2.b(), TestEnum::B);
100     assert_eq!(nested_struct2.c().len(), 2);
101     assert_eq!(nested_struct2.c().get(0), TestEnum::B);
102     assert_eq!(nested_struct2.c().get(1), TestEnum::A);
103     assert_eq!(nested_struct2.d().len(), 2);
104     let arr: [i64; 2] = nested_struct2.d().into();
105     assert_eq!(
106         arr,
107         [-0x1122334455667788, 0x1122334455667788]
108     );
109 
110     assert_eq!(array_struct.e(), 1);
111     assert_eq!(array_struct.f().len(), 2);
112     assert_eq!(array_struct.f().get(0), -0x8000000000000000);
113     assert_eq!(array_struct.f().get(1), 0x7FFFFFFFFFFFFFFF);
114 }
115 
116 #[test]
generated_code_creates_correct_example()117 fn generated_code_creates_correct_example() {
118     let mut b = flatbuffers::FlatBufferBuilder::new();
119     create_serialized_example_with_generated_code(&mut b);
120     let buf = b.finished_data();
121     serialized_example_is_accessible_and_correct(&buf[..], true, false);
122 }
123 
124 #[test]
struct_netsted_struct_is_32_bytes()125 fn struct_netsted_struct_is_32_bytes() {
126     assert_eq!(32, ::core::mem::size_of::<NestedStruct>());
127 }
128 
129 #[test]
struct_array_struct_is_160_bytes()130 fn struct_array_struct_is_160_bytes() {
131     assert_eq!(160, ::core::mem::size_of::<ArrayStruct>());
132 }
133 
134 #[test]
test_object_api_reads_correctly()135 fn test_object_api_reads_correctly() {
136     let mut b = flatbuffers::FlatBufferBuilder::new();
137     create_serialized_example_with_generated_code(&mut b);
138 
139     let array_table = root_as_array_table(b.finished_data()).unwrap().unpack();
140 
141     let array_struct = array_table.a.unwrap();
142     assert_eq!(array_struct.a, 12.34);
143     assert_eq!(array_struct.b.len(), 0xF);
144     assert_eq!(array_struct.b.iter().sum::<i32>(), 120);
145     assert_eq!(array_struct.c, -127);
146 
147     assert_eq!(array_struct.d.len(), 2);
148     let nested_struct1 = &array_struct.d[0];
149     assert_eq!(nested_struct1.a.len(), 2);
150     assert_eq!(nested_struct1.a.iter().sum::<i32>(), 1);
151     assert_eq!(nested_struct1.b, TestEnum::A);
152     assert_eq!(nested_struct1.c.len(), 2);
153     assert_eq!(nested_struct1.c[0], TestEnum::C);
154     assert_eq!(nested_struct1.c[1], TestEnum::B);
155     assert_eq!(nested_struct1.d.len(), 2);
156     assert_eq!(nested_struct1.d, [0x1122334455667788, -0x1122334455667788]);
157     let nested_struct2 = &array_struct.d[1];
158     assert_eq!(nested_struct2.a.len(), 2);
159     assert_eq!(nested_struct2.a.iter().sum::<i32>(), -1);
160     assert_eq!(nested_struct2.b, TestEnum::B);
161     assert_eq!(nested_struct2.c.len(), 2);
162     assert_eq!(nested_struct2.c[0], TestEnum::B);
163     assert_eq!(nested_struct2.c[1], TestEnum::A);
164     assert_eq!(nested_struct2.d.len(), 2);
165     assert_eq!(nested_struct2.d, [-0x1122334455667788, 0x1122334455667788]);
166 
167     assert_eq!(array_struct.e, 1);
168     assert_eq!(array_struct.f.len(), 2);
169     assert_eq!(array_struct.f[0], -0x8000000000000000);
170     assert_eq!(array_struct.f[1], 0x7FFFFFFFFFFFFFFF);
171 }
172 
173 #[test]
object_api_defaults()174 fn object_api_defaults() {
175     use arrays_test_generated::my_game::example::*;
176 
177     assert_eq!(
178         NestedStructT::default(),
179         NestedStructT {
180             a: [0, 0],
181             b: TestEnum::default(),
182             c: [TestEnum::default(), TestEnum::default()],
183             d: [0, 0],
184         }
185     );
186 
187     assert_eq!(
188         ArrayStructT::default(),
189         ArrayStructT {
190             a: 0.0,
191             b: [0; 0xF],
192             c: 0,
193             d: [NestedStructT::default(), NestedStructT::default()],
194             e: 0,
195             f: [0, 0],
196         }
197     );
198 }
199 
200 #[test]
generated_code_debug_prints_correctly()201 fn generated_code_debug_prints_correctly() {
202     let b = &mut flatbuffers::FlatBufferBuilder::new();
203     create_serialized_example_with_generated_code(b);
204     let buf = b.finished_data();
205     let array_table = root_as_array_table(buf).unwrap();
206     assert_eq!(
207         format!("{:.5?}", &array_table),
208         "ArrayTable { a: Some(ArrayStruct { a: 12.34000, \
209          b: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], \
210          c: -127, d: [NestedStruct { a: [-1, 2], b: A, c: [C, B], \
211          d: [1234605616436508552, -1234605616436508552] }, \
212          NestedStruct { a: [3, -4], b: B, c: [B, A], d: [-1234605616436508552, 1234605616436508552] }], \
213          e: 1, f: [-9223372036854775808, 9223372036854775807] }) }"
214     );
215 }
216 
217 #[test]
218 #[should_panic]
assert_on_too_small_array_buf()219 fn assert_on_too_small_array_buf() {
220     let a = [0u8; 19];
221     unsafe { flatbuffers::Array::<i32, 5>::new(&a) };
222 }
223 
224 #[test]
225 #[should_panic]
assert_on_too_big_array_buf()226 fn assert_on_too_big_array_buf() {
227     let a = [0u8; 21];
228     unsafe { flatbuffers::Array::<i32, 5>::new(&a) };
229 }
230 
231 #[test]
232 #[cfg(target_endian = "little")]
verify_struct_array_alignment()233 fn verify_struct_array_alignment() {
234     let mut b = flatbuffers::FlatBufferBuilder::new();
235     create_serialized_example_with_generated_code(&mut b);
236     let buf = b.finished_data();
237     let array_table = root_as_array_table(buf).unwrap();
238     let array_struct = array_table.a().unwrap();
239     let struct_start_ptr = array_struct.0.as_ptr() as usize;
240     let b_start_ptr = array_struct.b().as_ptr() as usize;
241     let d_start_ptr = array_struct.d().as_ptr() as usize;
242     // The T type of b
243     let b_aln = ::core::mem::align_of::<i32>();
244     assert_eq!((b_start_ptr - struct_start_ptr) % b_aln, 0);
245     assert_eq!((d_start_ptr - b_start_ptr) % b_aln, 0);
246     assert_eq!((d_start_ptr - struct_start_ptr) % 8, 0);
247 }
248 
249 #[derive(Clone, Debug)]
250 struct FakeArray<T, const N: usize>([T; N]);
251 
252 impl<T: Arbitrary + Debug + PartialEq, const N: usize> Arbitrary for FakeArray<T, N> {
arbitrary<G: Gen>(g: &mut G) -> FakeArray<T, N>253     fn arbitrary<G: Gen>(g: &mut G) -> FakeArray<T, N> {
254         let x: [T; N] = array_init(|_| {
255             loop {
256                 let generated_scalar = T::arbitrary(g);
257                 // Verify that generated scalar is not Nan, which is not equals to itself,
258                 // therefore we can't use it to validate input == output
259                 if generated_scalar == generated_scalar { return generated_scalar; }
260             }
261         });
262         FakeArray { 0: x }
263     }
264 }
265 
266 #[cfg(test)]
267 mod array_fuzz {
268     #[cfg(not(miri))]  // slow.
269     extern crate quickcheck;
270     extern crate flatbuffers;
271 
272     use self::flatbuffers::{Follow, Push};
273     use super::*;
274 
275     const MAX_TESTS: u64 = 20;
276     const ARRAY_SIZE: usize = 29;
277 
278     // This uses a macro because lifetimes for the trait-bounded function get too
279     // complicated.
280     macro_rules! impl_prop {
281         ($test_name:ident, $fn_name:ident, $ty:ident) => (
282             fn $fn_name(xs: FakeArray<$ty, ARRAY_SIZE>) {
283                 let mut test_buf = [0 as u8; 1024];
284                 let arr: flatbuffers::Array<$ty, ARRAY_SIZE> =  unsafe {
285                     flatbuffers::emplace_scalar_array(&mut test_buf, 0, &xs.0);
286                     flatbuffers::Array::follow(&test_buf, 0)
287                 };
288                 let got: [$ty; ARRAY_SIZE] = arr.into();
289                 assert_eq!(got, xs.0);
290             }
291             #[test]
292             fn $test_name() {
293                 quickcheck::QuickCheck::new().max_tests(MAX_TESTS).quickcheck($fn_name as fn(FakeArray<$ty, ARRAY_SIZE>));
294             }
295         )
296     }
297 
298     impl_prop!(test_bool, prop_bool, bool);
299     impl_prop!(test_u8, prop_u8, u8);
300     impl_prop!(test_i8, prop_i8, i8);
301     impl_prop!(test_u16, prop_u16, u16);
302     impl_prop!(test_u32, prop_u32, u32);
303     impl_prop!(test_u64, prop_u64, u64);
304     impl_prop!(test_i16, prop_i16, i16);
305     impl_prop!(test_i32, prop_i32, i32);
306     impl_prop!(test_i64, prop_i64, i64);
307     impl_prop!(test_f32, prop_f32, f32);
308     impl_prop!(test_f64, prop_f64, f64);
309 
310     const NESTED_STRUCT_SIZE: usize = size_of::<NestedStruct>();
311 
312     #[derive(Clone, Debug, PartialEq)]
313     struct NestedStructWrapper(NestedStruct);
314 
315     impl Arbitrary for NestedStructWrapper {
arbitrary<G: Gen>(g: &mut G) -> NestedStructWrapper316         fn arbitrary<G: Gen>(g: &mut G) -> NestedStructWrapper {
317             let mut x = NestedStruct::default();
318             x.0 = FakeArray::<u8, NESTED_STRUCT_SIZE>::arbitrary(g).0;
319             NestedStructWrapper { 0: x }
320         }
321     }
322 
prop_struct(xs: FakeArray<NestedStructWrapper, ARRAY_SIZE>)323     fn prop_struct(xs: FakeArray<NestedStructWrapper, ARRAY_SIZE>) {
324         let mut test_buf = [0 as u8; 1024];
325         let native_struct_array: [&NestedStruct; ARRAY_SIZE] = array_init::from_iter(xs.0.iter().map(|x| &x.0)).unwrap();
326         for i in 0..ARRAY_SIZE {
327             let offset = i * NESTED_STRUCT_SIZE;
328             unsafe { native_struct_array[i].push(&mut test_buf[offset..offset + NESTED_STRUCT_SIZE], 0) };
329         }
330         let arr: flatbuffers::Array<NestedStruct, ARRAY_SIZE> = unsafe { flatbuffers::Array::follow(&test_buf, 0) };
331         let got: [&NestedStruct; ARRAY_SIZE] = arr.into();
332         assert_eq!(got, native_struct_array);
333     }
334 
335     #[test]
336     #[cfg(not(miri))]  // slow.
test_struct()337     fn test_struct() {
338         quickcheck::QuickCheck::new().max_tests(MAX_TESTS).quickcheck(prop_struct as fn(FakeArray<NestedStructWrapper, ARRAY_SIZE>));
339     }
340 }
341