1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use std::ffi::{CStr, CString};
15 use std::os::raw::{c_char, c_double, c_int};
16 use std::ptr::*;
17 use ylong_json::*;
18 
19 const RFC7159_EXAMPLE1: &str = r#"
20 {
21     "Image": {
22         "Width":  800,
23         "Height": 600,
24         "Title":  "View from 15th Floor",
25         "Thumbnail": {
26             "Url":    "http://www.example.com/image/481989943",
27             "Height": 125,
28             "Width":  100
29         },
30         "Animated" : false,
31         "IDs": [116, 943, 234, 38793]
32     }
33 }
34 "#;
35 
36 macro_rules! test_json {
37     ($json: expr) => {{
38         let target = str_to_c_char("Image");
39         let image = ylong_json_get_object_item($json, target);
40         let _ = CString::from_raw(target);
41 
42         assert_eq!(ylong_json_is_object(image), 1);
43 
44         let target = str_to_c_char("Width");
45         let width = ylong_json_get_object_item(image, target);
46         let _ = CString::from_raw(target);
47         let mut ptr: c_double = 0f64;
48         assert_eq!(
49             ylong_json_get_double_value_from_number(width, &mut ptr as *mut c_double),
50             1
51         );
52         assert_eq!(ptr, 800f64);
53 
54         let target = str_to_c_char("Height");
55         let height = ylong_json_get_object_item(image, target);
56         let _ = CString::from_raw(target);
57         let mut ptr: c_double = 0f64;
58         assert_eq!(
59             ylong_json_get_double_value_from_number(height, &mut ptr as *mut c_double),
60             1
61         );
62         assert_eq!(ptr, 600f64);
63 
64         let target = str_to_c_char("Title");
65         let title = ylong_json_get_object_item(image, target);
66         let _ = CString::from_raw(target);
67         let mut ptr: *mut c_char = null_mut::<c_char>();
68         assert_eq!(
69             ylong_json_get_value_from_string(title, &mut ptr as *mut *mut c_char),
70             1
71         );
72         assert_eq!(
73             CStr::from_ptr(ptr).to_str().unwrap(),
74             "View from 15th Floor"
75         );
76 
77         let target = str_to_c_char("Thumbnail");
78         let thumbnail = ylong_json_get_object_item(image, target);
79         let _ = CString::from_raw(target);
80         assert_eq!(ylong_json_is_object(thumbnail), 1);
81 
82         let target = str_to_c_char("Url");
83         let url = ylong_json_get_object_item(thumbnail, target);
84         let _ = CString::from_raw(target);
85         let mut ptr: *mut c_char = null_mut::<c_char>();
86         assert_eq!(
87             ylong_json_get_value_from_string(url, &mut ptr as *mut *mut c_char),
88             1
89         );
90         assert_eq!(
91             CStr::from_ptr(ptr).to_str().unwrap(),
92             "http://www.example.com/image/481989943"
93         );
94 
95         let target = str_to_c_char("Height");
96         let height = ylong_json_get_object_item(thumbnail, target);
97         let _ = CString::from_raw(target);
98         let mut ptr: c_double = 0f64;
99         assert_eq!(
100             ylong_json_get_double_value_from_number(height, &mut ptr as *mut c_double),
101             1
102         );
103         assert_eq!(ptr, 125f64);
104 
105         let target = str_to_c_char("Width");
106         let width = ylong_json_get_object_item(thumbnail, target);
107         let _ = CString::from_raw(target);
108         let mut ptr: c_double = 0f64;
109         assert_eq!(
110             ylong_json_get_double_value_from_number(width, &mut ptr as *mut c_double),
111             1
112         );
113         assert_eq!(ptr, 100f64);
114 
115         let target = str_to_c_char("Animated");
116         let animated = ylong_json_get_object_item(image, target);
117         let _ = CString::from_raw(target);
118         let mut ptr: c_int = 0;
119         assert_eq!(
120             ylong_json_get_value_from_bool(animated, &mut ptr as *mut c_int),
121             1
122         );
123         assert_eq!(ptr, 0);
124 
125         let target = str_to_c_char("IDs");
126         let ids = ylong_json_get_object_item(image, target);
127         let _ = CString::from_raw(target);
128 
129         assert_eq!(ylong_json_is_array(ids), 1);
130 
131         let item = ylong_json_get_array_item(ids, 0);
132         let mut ptr = 0f64;
133         assert_eq!(
134             ylong_json_get_double_value_from_number(item, &mut ptr as *mut c_double),
135             1
136         );
137         assert_eq!(ptr, 116f64);
138 
139         let item = ylong_json_get_array_item(ids, 1);
140         let mut ptr = 0f64;
141         assert_eq!(
142             ylong_json_get_double_value_from_number(item, &mut ptr as *mut c_double),
143             1
144         );
145         assert_eq!(ptr, 943f64);
146 
147         let item = ylong_json_get_array_item(ids, 2);
148         let mut ptr = 0f64;
149         assert_eq!(
150             ylong_json_get_double_value_from_number(item, &mut ptr as *mut c_double),
151             1
152         );
153         assert_eq!(ptr, 234f64);
154 
155         let item = ylong_json_get_array_item(ids, 3);
156         let mut ptr = 0f64;
157         assert_eq!(
158             ylong_json_get_double_value_from_number(item, &mut ptr as *mut c_double),
159             1
160         );
161         assert_eq!(ptr, 38793f64);
162     }};
163 }
164 
165 #[test]
sdv_adapter_test()166 fn sdv_adapter_test() {
167     unsafe {
168         sdv_adapter_parse_and_print();
169         sdv_adapter_parse_memory_check();
170     }
171 }
172 
str_to_c_char(str: &str) -> *mut c_char173 unsafe fn str_to_c_char(str: &str) -> *mut c_char {
174     CString::from_vec_unchecked(str.as_bytes().to_vec()).into_raw()
175 }
176 
sdv_adapter_parse_and_print()177 unsafe fn sdv_adapter_parse_and_print() {
178     let text = str_to_c_char(RFC7159_EXAMPLE1);
179 
180     let msg = null_mut::<c_char>();
181     let mut json = Some(ylong_json_parse(
182         text,
183         &msg as *const *mut c_char as *mut *mut c_char,
184     ));
185 
186     for _ in 0..1000 {
187         let curr = json.take().unwrap();
188 
189         let curr_str = ylong_json_print_unformatted(curr);
190 
191         let msg = null_mut::<c_char>();
192         let new = ylong_json_parse(curr_str, &msg as *const *mut c_char as *mut *mut c_char);
193 
194         let _ = CString::from_raw(curr_str);
195 
196         test_json!(new);
197 
198         json = Some(new);
199         ylong_json_delete(curr);
200     }
201 
202     ylong_json_delete(json.take().unwrap());
203 
204     // 析构 text
205     let _ = CString::from_raw(text);
206 }
207 
sdv_adapter_parse_memory_check()208 unsafe fn sdv_adapter_parse_memory_check() {
209     const TEXT: &str = r#"
210 {
211     "null": null,
212     "true": true,
213     "false": false,
214     "number": 3.14,
215     "string": "Hello World!",
216     "array": [1, 2, 3],
217     "object": {
218         "key1": 1,
219         "key2": 2,
220         "key3": 3
221     }
222 }
223 "#;
224 
225     let text = str_to_c_char(TEXT);
226     let msg = null_mut::<c_char>();
227     let json = ylong_json_parse(text, &msg as *const *mut c_char as *mut *mut c_char);
228     let _ = Box::from_raw(text);
229 
230     assert!(msg.is_null());
231     let result = ylong_json_print_unformatted(json);
232     ylong_json_free_string(result);
233 
234     let duplicate = ylong_json_duplicate(json, 1);
235     ylong_json_delete(duplicate);
236 
237     let null = ylong_json_create_null();
238     ylong_json_delete(null);
239 
240     let index = str_to_c_char("string");
241     let string = ylong_json_get_object_item(json, index);
242     let content = null_mut::<c_char>();
243     ylong_json_get_value_from_string(string, &content as *const *mut c_char as *mut *mut c_char);
244     let _ = Box::from_raw(index);
245 
246     let null = ylong_json_create_null();
247     let index = str_to_c_char("123");
248     ylong_json_add_item_to_object(json, index, null);
249 
250     let content = str_to_c_char("aaaa");
251     let string = ylong_json_create_string(content);
252     ylong_json_replace_object_item_by_index(json, index, string);
253     let _ = Box::from_raw(content);
254 
255     let removed = ylong_json_remove_object_item_by_index(json, index);
256     ylong_json_delete(removed);
257     let _ = Box::from_raw(index);
258 
259     extern "C" fn func(_value: *mut YlongJson) {}
260     ylong_json_for_each_object_item(json, func);
261 
262     ylong_json_delete(json);
263 }
264