1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 use flexbuffers::*;
16 #[cfg(not(miri))] // slow.
17 use quickcheck::QuickCheck;
18
19 #[test]
20 #[cfg(not(miri))] // slow.
qc_reader_no_crash()21 fn qc_reader_no_crash() {
22 fn no_crash(xs: Vec<u8>) -> bool {
23 let r = Reader::get_root(xs.as_ref());
24 r.is_err() || r.is_ok()
25 }
26 QuickCheck::new()
27 .min_tests_passed(10_000_000)
28 .quicktest(no_crash as fn(Vec<u8>) -> bool)
29 .unwrap();
30
31 no_crash(vec![0, 10 << 2 | 2, 0]);
32 }
33 #[test]
as_num()34 fn as_num() {
35 let mut fxb = Builder::default();
36 let mut m = fxb.start_map();
37 m.push("a", &[-1i8, -2, -3, -4]);
38 m.push("b", 250i64);
39 m.push("c", 5000u16);
40 m.end_map();
41
42 let r = Reader::get_root(fxb.view()).unwrap();
43 assert_eq!(r.as_i8(), 3); // length.
44 assert_eq!(r.as_i16(), 3);
45 assert_eq!(r.as_i32(), 3);
46 assert_eq!(r.as_i64(), 3);
47 assert_eq!(r.as_u8(), 3);
48 assert_eq!(r.as_u16(), 3);
49 assert_eq!(r.as_u32(), 3);
50 assert_eq!(r.as_u64(), 3);
51 assert_eq!(r.as_f32(), 3.0);
52 assert_eq!(r.as_f64(), 3.0);
53
54 let m = r.as_map();
55 let a = m.index("a").unwrap();
56 assert_eq!(a.as_f32(), 4.0); // length.
57 assert_eq!(a.as_f64(), 4.0); // length.
58 assert_eq!(a.as_vector().idx(0).as_i8(), -1);
59 assert_eq!(a.as_vector().idx(1).as_i16(), -2);
60 assert_eq!(a.as_vector().idx(2).as_i32(), -3);
61 assert_eq!(a.as_vector().idx(3).as_i64(), -4);
62
63 let b = m.index("b").unwrap();
64 assert_eq!(b.as_u8(), 250);
65 assert_eq!(b.as_u16(), 250);
66 assert_eq!(b.as_u32(), 250);
67 assert_eq!(b.as_u64(), 250);
68 assert_eq!(b.as_i8(), 0); // overflow
69 assert_eq!(b.as_i16(), 250);
70 assert_eq!(b.as_i32(), 250);
71 assert_eq!(b.as_i64(), 250);
72
73 let c = m.index("c").unwrap();
74 assert_eq!(c.as_i64(), 5000);
75 assert_eq!(c.as_u64(), 5000);
76 assert_eq!(c.as_f32(), 5000.0);
77 assert_eq!(c.as_u8(), 0); // overflow
78 assert_eq!(c.as_u16(), 5000);
79 assert_eq!(c.as_u32(), 5000);
80 assert_eq!(c.as_u64(), 5000);
81 assert_eq!(c.as_i8(), 0); // overflow
82 assert_eq!(c.as_i16(), 5000);
83 assert_eq!(c.as_i32(), 5000);
84 assert_eq!(c.as_i64(), 5000);
85 }
86 #[test]
string_as_num()87 fn string_as_num() {
88 let mut fxb = Builder::default();
89 let mut v = fxb.start_vector();
90 v.push("3.1415");
91 v.push("9.001e3");
92 v.push("42");
93 v.end_vector();
94 let r = Reader::get_root(fxb.view()).unwrap();
95
96 let v0 = r.as_vector().idx(0);
97 assert_eq!(v0.as_f64(), 3.1415);
98 assert_eq!(v0.as_f32(), 3.1415);
99 assert_eq!(v0.as_u8(), 0);
100 assert_eq!(v0.as_u16(), 0);
101 assert_eq!(v0.as_u32(), 0);
102 assert_eq!(v0.as_u64(), 0);
103 assert_eq!(v0.as_i8(), 0);
104 assert_eq!(v0.as_i16(), 0);
105 assert_eq!(v0.as_i32(), 0);
106 assert_eq!(v0.as_i64(), 0);
107
108 let v1 = r.as_vector().idx(1);
109 assert_eq!(v1.as_f64(), 9001.0);
110 assert_eq!(v1.as_f32(), 9001.0);
111 assert_eq!(v1.as_u8(), 0);
112 assert_eq!(v1.as_u16(), 0);
113 assert_eq!(v1.as_u32(), 0);
114 assert_eq!(v1.as_u64(), 0);
115 assert_eq!(v1.as_i8(), 0);
116 assert_eq!(v1.as_i16(), 0);
117 assert_eq!(v1.as_i32(), 0);
118 assert_eq!(v1.as_i64(), 0);
119 assert_eq!(v1.as_i32(), 0);
120
121 let v2 = r.as_vector().idx(2);
122 assert_eq!(v2.as_f64(), 42.0);
123 assert_eq!(v2.as_f32(), 42.0);
124 assert_eq!(v2.as_u8(), 42);
125 assert_eq!(v2.as_u16(), 42);
126 assert_eq!(v2.as_u32(), 42);
127 assert_eq!(v2.as_u64(), 42);
128 assert_eq!(v2.as_i8(), 42);
129 assert_eq!(v2.as_i16(), 42);
130 assert_eq!(v2.as_i32(), 42);
131 assert_eq!(v2.as_i64(), 42);
132 assert_eq!(v2.as_i32(), 42);
133 }
134 #[test]
null_reader()135 fn null_reader() {
136 let n = Reader::<&[u8]>::default();
137 assert_eq!(n.as_i8(), 0);
138 assert_eq!(n.as_i16(), 0);
139 assert_eq!(n.as_i32(), 0);
140 assert_eq!(n.as_i64(), 0);
141 assert_eq!(n.as_u8(), 0);
142 assert_eq!(n.as_u16(), 0);
143 assert_eq!(n.as_u32(), 0);
144 assert_eq!(n.as_u64(), 0);
145 assert_eq!(n.as_f32(), 0.0);
146 assert_eq!(n.as_f64(), 0.0);
147 assert!(n.get_i64().is_err());
148 assert!(n.get_u64().is_err());
149 assert!(n.get_f64().is_err());
150 assert!(n.as_vector().is_empty());
151 assert!(n.as_map().is_empty());
152 assert_eq!(n.as_vector().idx(1).flexbuffer_type(), FlexBufferType::Null);
153 assert_eq!(n.as_map().idx("1").flexbuffer_type(), FlexBufferType::Null);
154 }
155 #[test]
get_root_deref_oob()156 fn get_root_deref_oob() {
157 let s = &[
158 4, // Deref out of bounds
159 (FlexBufferType::Vector as u8) << 2 | BitWidth::W8 as u8,
160 1,
161 ];
162 assert!(Reader::get_root(s.as_ref()).is_err());
163 }
164 #[test]
get_root_deref_u64()165 fn get_root_deref_u64() {
166 let s = &[
167 0,
168 0,
169 (FlexBufferType::IndirectUInt as u8) << 2 | BitWidth::W64 as u8,
170 1,
171 ];
172 // The risk of crashing is reading 8 bytes from index 0.
173 assert_eq!(Reader::get_root(s.as_ref()).unwrap().as_u64(), 0);
174 }
175
176 /// Verifies that the clone operation is shallow / zero copy.
177 #[test]
clone_is_shallow()178 fn clone_is_shallow() {
179 let mut fxb = Builder::default();
180 let mut m = fxb.start_map();
181 m.push("a", &[-1i8, -2, -3, -4]);
182 m.push("b", 250i64);
183 m.push("c", 5000u16);
184 m.end_map();
185
186 let r = Reader::get_root(fxb.view()).unwrap();
187
188 let r2 = r.clone();
189
190 assert_eq!(r.buffer().as_ptr(), r2.buffer().as_ptr());
191 }
192
193 #[test]
194 #[should_panic]
build_map_panic_on_repeated_key()195 fn build_map_panic_on_repeated_key() {
196 let mut b = Builder::default();
197 let mut m = b.start_map();
198 m.push("foo", 5u8);
199 m.push("foo", 6u8);
200 m.end_map();
201 }
202 #[test]
203 #[should_panic]
build_map_panic_on_internal_null()204 fn build_map_panic_on_internal_null() {
205 let mut b = Builder::default();
206 let mut m = b.start_map();
207 m.push("foo\0", 5u8);
208 m.end_map();
209 }
210