1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 use anyhow::Result;
18 use fbthrift::simplejson_protocol::{deserialize, serialize};
19 use fbthrift::{simplejson_protocol::SimpleJsonProtocolDeserializer, Deserialize};
20 use fbthrift_test_if::{
21 Basic, Containers, En, MainStruct, MainStructNoBinary, Small, SubStruct, Un, UnOne,
22 };
23 use std::collections::BTreeMap;
24 use std::io::Cursor;
25
26 #[test]
test_large_roundtrip() -> Result<()>27 fn test_large_roundtrip() -> Result<()> {
28 // Build the big struct
29 let mut m = BTreeMap::new();
30 m.insert("m1".to_string(), 1);
31 m.insert("m2".to_string(), 2);
32
33 let sub = SubStruct {
34 ..Default::default()
35 };
36
37 let u = Un::un1(UnOne {
38 one: 1,
39 ..Default::default()
40 });
41 let e = En::TWO;
42
43 let mut int_keys = BTreeMap::new();
44 int_keys.insert(42, 43);
45 int_keys.insert(44, 45);
46
47 let r = MainStruct {
48 foo: "foo".to_string(),
49 m,
50 bar: "test".to_string(),
51 s: sub,
52 l: vec![
53 Small {
54 num: 1,
55 two: 2,
56 ..Default::default()
57 },
58 Small {
59 num: 2,
60 two: 3,
61 ..Default::default()
62 },
63 ],
64 u,
65 e,
66 int_keys,
67 opt: None,
68 ..Default::default()
69 };
70
71 // serialize it and assert that it serializes correctly
72 let s = String::from_utf8(serialize(&r).to_vec()).unwrap();
73
74 // Note that default optionals are there
75 // but non-default optionals are not there
76 // That is an artifact on how the serialize trait works
77 let expected_string = r#"{
78 "foo":"foo",
79 "m":{"m1":1,"m2":2},
80 "bar":"test",
81 "s":{"optDef":"IAMOPT","req_def":"IAMREQ","bin":""},
82 "l":[{"num":1,"two":2},{"num":2,"two":3}],
83 "u":{"un1":{"one":1}},
84 "e":2,
85 "int_keys":{"42":43,"44":45}
86 }"#
87 .replace(" ", "")
88 .replace("\n", "");
89 assert_eq!(expected_string, s);
90
91 // It at least needs to be valid json, the serialize then
92 // deserialize and compare will come in the next diff
93 let v: serde_json::Result<serde_json::Value> = serde_json::from_str(&s);
94 assert!(v.is_ok());
95
96 // Assert that deserialize builts the exact same struct
97 assert_eq!(r, deserialize(s).unwrap());
98
99 Ok(())
100 }
101
102 #[test]
test_struct_key() -> Result<()>103 fn test_struct_key() -> Result<()> {
104 // See the `structKey` test in cpp_compat_test
105
106 let mut h = std::collections::BTreeMap::new();
107 h.insert(
108 Small {
109 ..Default::default()
110 },
111 1,
112 );
113 let sub = SubStruct {
114 key_map: Some(h),
115 // In rust we need to specify optionals with defaults as None
116 // instead of relying on ..Default::default()
117 optDef: None,
118 ..Default::default()
119 };
120
121 let s = String::from_utf8(serialize(&sub).to_vec()).unwrap();
122 let expected_string = r#"{
123 "req_def":"IAMREQ",
124 "key_map":{{"num":0,"two":0}:1},
125 "bin":""
126 }"#
127 .replace(" ", "")
128 .replace("\n", "");
129 assert_eq!(expected_string, s);
130
131 // It's definitely not JSON...
132 let v: serde_json::Result<serde_json::Value> = serde_json::from_str(&s);
133 assert!(v.is_err());
134
135 // ...but it needs to deserialize
136 assert_eq!(sub, deserialize(&s).unwrap());
137
138 // ...though not to serde_json::Value.
139 if let Ok(wat) = deserialize(&s) {
140 let _: serde_json::Value = wat;
141 panic!("map with struct keys is not supposed to deserialize to Value");
142 }
143
144 Ok(())
145 }
146
147 #[test]
test_weird_text() -> Result<()>148 fn test_weird_text() -> Result<()> {
149 // See the `weirdText` test in cpp_compat_test
150
151 let mut sub = SubStruct {
152 optDef: Some("stuff\twith\nescape\\characters'...\"lots{of}fun</xml>".to_string()),
153 bin: "1234".as_bytes().to_vec(),
154 ..Default::default()
155 };
156
157 let s = String::from_utf8(serialize(&sub).to_vec()).unwrap();
158 let expected_string = r#"{
159 "optDef":"stuff\twith\nescape\\characters'...\"lots{of}fun</xml>",
160 "req_def":"IAMREQ",
161 "bin":"MTIzNA"
162 }"#
163 .replace(" ", "")
164 .replace("\n", "");
165 assert_eq!(expected_string, s);
166 // Make sure its equal
167 assert_eq!(sub, deserialize(s).unwrap());
168
169 // Unicode escaping
170 sub.optDef = Some("UNICODE\u{1F60A}UH OH".to_string());
171
172 let s = String::from_utf8(serialize(&sub).to_vec()).unwrap();
173 let expected_string = r#"{
174 "optDef":"UNICODEUH OH",
175 "req_def":"IAMREQ",
176 "bin":"MTIzNA"
177 }"#
178 // Double-space to deal with "tabs"
179 .replace(" ", "")
180 .replace("\n", "");
181 assert_eq!(expected_string, s);
182 // Make sure its equal
183 assert_eq!(sub, deserialize(s).unwrap());
184
185 Ok(())
186 }
187
188 #[test]
test_skip_complex() -> Result<()>189 fn test_skip_complex() -> Result<()> {
190 // See the `skipComplex` test in cpp_compat_test
191
192 let sub = SubStruct {
193 optDef: Some("thing".to_string()),
194 bin: "1234".as_bytes().to_vec(),
195 ..Default::default()
196 };
197
198 let input = r#"{
199 "optDef":"thing",
200 "req_def":"IAMREQ",
201 "bin":"MTIzNA",
202 "extra":[1,{"thing":"thing2"}],
203 "extra_map":{"thing":null,"thing2":2},
204 "extra_bool":true
205 }"#
206 .replace(" ", "")
207 .replace("\n", "");
208 // Make sure everything is skipped properly
209 assert_eq!(sub, deserialize(input).unwrap());
210
211 Ok(())
212 }
213
214 #[test]
test_need_commas() -> Result<()>215 fn test_need_commas() -> Result<()> {
216 // See the `needCommas` test in cpp_compat_test
217
218 // Note the missing commas
219
220 let input = r#"{
221 "num":1
222 "two":2
223 }"#
224 .replace(" ", "")
225 .replace("\n", "");
226 assert!(deserialize::<Small, _, _>(input).is_err());
227
228 // even when skipping
229 let input2 = r#"{
230 "num":1,
231 "two":2,
232 "extra_map":{"thing":null,"thing2":2}
233 "extra_bool":true
234 }"#
235 .replace(" ", "")
236 .replace("\n", "");
237 assert!(deserialize::<Small, _, _>(input2).is_err());
238
239 Ok(())
240 }
241
242 #[test]
test_need_commas_containers() -> Result<()>243 fn test_need_commas_containers() -> Result<()> {
244 // See the `needCommasContainers` test in cpp_compat_test
245
246 let goodinput = r#"{
247 "m":{"m1":"m1","m2":"m2"}
248 }"#;
249 // Note the missing comma
250 let badinput = r#"{
251 "m":{"m1":"m1""m2":"m2"}
252 }"#;
253 assert!(deserialize::<Containers, _, _>(goodinput).is_ok());
254 assert!(deserialize::<Containers, _, _>(badinput).is_err());
255
256 let goodinput2 = r#"{
257 "l":["l1","l2"]
258 }"#;
259 // Note the missing comma
260 let badinput2 = r#"{
261 "l":["l1""l2"]
262 }"#;
263 assert!(deserialize::<Containers, _, _>(goodinput2).is_ok());
264 assert!(deserialize::<Containers, _, _>(badinput2).is_err());
265
266 Ok(())
267 }
268
269 #[test]
test_null_stuff() -> Result<()>270 fn test_null_stuff() -> Result<()> {
271 // See the `nullStuff` test in cpp_compat_test
272
273 let sub = SubStruct {
274 optDef: None,
275 bin: "1234".as_bytes().to_vec(),
276 ..Default::default()
277 };
278
279 let input = r#"{
280 "optDef":null,
281 "req_def":"IAMREQ",
282 "bin":"MTIzNA"
283 }"#
284 .replace(" ", "")
285 .replace("\n", "");
286 // Make sure everything is skipped properly
287 assert_eq!(sub, deserialize(input).unwrap());
288
289 Ok(())
290 }
291
292 #[test]
infinite_spaces() -> Result<()>293 fn infinite_spaces() -> Result<()> {
294 let mut m = BTreeMap::new();
295 m.insert("m1".to_string(), 1);
296 m.insert("m2".to_string(), 2);
297
298 let sub = SubStruct {
299 ..Default::default()
300 };
301
302 let u = Un::un1(UnOne {
303 one: 1,
304 ..Default::default()
305 });
306 let e = En::TWO;
307
308 let mut int_keys = BTreeMap::new();
309 int_keys.insert(42, 43);
310 int_keys.insert(44, 45);
311
312 let r = MainStruct {
313 foo: "foo".to_string(),
314 m,
315 bar: "test".to_string(),
316 s: sub,
317 l: vec![
318 Small {
319 num: 1,
320 two: 2,
321 ..Default::default()
322 },
323 Small {
324 num: 2,
325 two: 3,
326 ..Default::default()
327 },
328 ],
329 u,
330 e,
331 int_keys,
332 opt: None,
333 ..Default::default()
334 };
335
336 let input = r#"{
337 "foo" : "foo" ,
338 "m" : { "m1" : 1 , "m2" : 2 } ,
339 "bar":"test",
340 "s":{"optDef": "IAMOPT" ,"req_def": "IAMREQ","bin": "" },
341 "l":[{"num":1,"two":2},{"num" :2 ," two" : 3 } ],
342 "u":{"un1":{"one": 1 } },
343 "e": 2 ,
344 "int_keys" :{"42" : 43, "44":45}
345 }"#;
346
347 // Assert that deserialize builts the exact same struct
348 assert_eq!(r, deserialize(input).unwrap());
349
350 Ok(())
351 }
352
353 #[test]
test_bool() -> Result<()>354 fn test_bool() -> Result<()> {
355 let b = Basic {
356 b: true,
357 b2: false,
358 ..Default::default()
359 };
360 // serialize it and assert that it serializes correctly
361 let s = String::from_utf8(serialize(&b).to_vec()).unwrap();
362
363 // Assert that deserialize builts the exact same struct
364 assert_eq!(b, deserialize(s).unwrap());
365
366 Ok(())
367 }
368
369 #[test]
test_serde_compat() -> Result<()>370 fn test_serde_compat() -> Result<()> {
371 // Build the big struct
372 let mut m = BTreeMap::new();
373 m.insert("m1".to_string(), 1);
374 m.insert("m2".to_string(), 2);
375
376 let u = Un::un1(UnOne {
377 one: 1,
378 ..Default::default()
379 });
380 let e = En::TWO;
381
382 let mut int_keys = BTreeMap::new();
383 int_keys.insert(42, 43);
384 int_keys.insert(44, 45);
385
386 let r = MainStructNoBinary {
387 foo: "foo".to_string(),
388 m,
389 bar: "test".to_string(),
390 l: vec![
391 Small {
392 num: 1,
393 two: 2,
394 ..Default::default()
395 },
396 Small {
397 num: 2,
398 two: 3,
399 ..Default::default()
400 },
401 ],
402 u,
403 e,
404 int_keys,
405 opt: None,
406 ..Default::default()
407 };
408
409 let fbthrift_s = String::from_utf8(serialize(&r).to_vec()).unwrap();
410 // We aren't going to get full compat, but at least make it so fbthrift
411 // can deserialize
412 // what serde has written out
413 let serde_s = serde_json::to_string(&r).unwrap();
414
415 // but passing between them should work
416 assert_eq!(r, serde_json::from_str(&fbthrift_s).unwrap());
417 assert_eq!(r, deserialize(&serde_s).unwrap());
418 Ok(())
419 }
420
421 #[test]
test_multiple_deser() -> Result<()>422 fn test_multiple_deser() -> Result<()> {
423 // Tests that we don't too eagerly advance the buffer
424 let b1 = Basic {
425 b: true,
426 b2: false,
427 ..Default::default()
428 };
429 let b2 = Basic {
430 b: true,
431 b2: true,
432 ..Default::default()
433 };
434 // serialize it and assert that it serializes correctly
435 let s1 = String::from_utf8(serialize(&b1).to_vec()).unwrap();
436 let s2 = String::from_utf8(serialize(&b2).to_vec()).unwrap();
437 let to_check = format!("{} {}", s1, s2);
438
439 let mut deserializer = SimpleJsonProtocolDeserializer::new(Cursor::new(to_check.as_bytes()));
440 // Assert that deserialize builts the exact same struct
441 assert_eq!(b1, Basic::read(&mut deserializer)?);
442 assert_eq!(b2, Basic::read(&mut deserializer)?);
443
444 Ok(())
445 }
446
447 #[test]
test_not_enough() -> Result<()>448 fn test_not_enough() -> Result<()> {
449 // Tests that we can deserialize until
450 // we run out, and don't panic
451 let b1 = Basic {
452 b: true,
453 b2: false,
454 ..Default::default()
455 };
456 let b2 = Basic {
457 b: true,
458 b2: true,
459 ..Default::default()
460 };
461 // serialize it and assert that it serializes correctly
462 let s1 = String::from_utf8(serialize(&b1).to_vec()).unwrap();
463 let s2 = String::from_utf8(serialize(&b2).to_vec()).unwrap();
464 let to_check = format!("{} {}", s1, s2);
465
466 let mut deserializer = SimpleJsonProtocolDeserializer::new(Cursor::new(
467 // 6 should cover the } and a `true` value
468 &to_check.as_bytes()[..to_check.as_bytes().len() - 6],
469 ));
470 // Assert that deserialize builts the exact same struct
471 assert_eq!(b1, Basic::read(&mut deserializer)?);
472 assert!(Basic::read(&mut deserializer).is_err());
473
474 Ok(())
475 }
476
477 #[test]
test_unknown_union() -> Result<()>478 fn test_unknown_union() -> Result<()> {
479 // See unknownUnion
480
481 // Build the empty union
482 let u = Un::default();
483
484 let s = String::from_utf8(serialize(&u).to_vec()).unwrap();
485 let expected_string = "{}";
486 assert_eq!(expected_string, s);
487
488 // Assert that deserialize builts the exact same struct
489 assert_eq!(u, deserialize(s).unwrap());
490
491 // ...
492 // extra weirdness
493 // Build an explicit unknown
494 let explicit_unknown = Un::UnknownField(100);
495 let s2 = String::from_utf8(serialize(&explicit_unknown).to_vec()).unwrap();
496 let expected_string = "{}";
497 assert_eq!(expected_string, s2);
498
499 // Deserializes to the default -1 case, this matches the other
500 // protocols behavior
501 assert_eq!(u, deserialize(s2).unwrap());
502
503 // backwards compat test
504 let old_output = r#"{
505 "UnknownField":-1
506 }"#
507 .replace(" ", "")
508 .replace("\n", "");
509
510 assert_eq!(u, deserialize(old_output).unwrap());
511
512 Ok(())
513 }
514