1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
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 *     http://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 */
15extern crate key_enable;
16extern crate ylong_json;
17
18use std::thread;
19use ylong_json::JsonValue;
20use key_enable::cert_chain_utils::PemCollection;
21use key_enable::cert_path_utils::TrustCertPath;
22use key_enable::profile_utils::{UDID, get_udid, validate_bundle_and_distribution_type};
23
24
25// pem_cert_file
26const VALID_PEM_CERT: &str = "/data/test/tmp/valid_pem_cert.json";
27const NON_EXISTEND_PEM_CERT: &str = "/data/test/tmp/non_existent_cert_path.json";
28const INVALID_STRUCTURE_PEM_CERT: &str = "/data/test/tmp/invalid_structure_cert_path.json";
29const EMPTY_PEM_CERT: &str = "/data/test/tmp/empty_pem_cert.json";
30// cert_path_file
31const VALID_CERT_PATH: &str = "/data/test/tmp/valid_cert_path.json";
32const NON_EXISTEND_CERT_PATH: &str = "/data/test/tmp/non_existent_cert_path.json";
33const INVALID_STRUCTURE_CERT_PATH: &str = "/data/test/tmp/invalid_structure_cert_path.json";
34const EMPTY_CERT_PATH: &str = "/data/test/tmp/empty_cert_path.json";
35
36const ALLOWED_ROOT_CERT_MEMBER_NAMES: &[&str] = &[
37    "C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Root CA G2",
38    "C=CN, O=OpenHarmony, OU=OpenHarmony Team, CN=OpenHarmony Application Root CA",
39    "C=CN, O=Huawei, OU=Huawei CBG, CN=Huawei CBG Root CA G2 Test",
40];
41
42#[test]
43fn test_load_pem_cert_from_valid_json_file() {
44    // test is_debuggable true
45    let mut root_cert = PemCollection::new();
46    root_cert.load_pem_certs_from_json_file(VALID_PEM_CERT, ALLOWED_ROOT_CERT_MEMBER_NAMES);
47    assert_eq!(root_cert.pem_data.len(), 3);
48}
49
50#[test]
51fn test_invalid_pem_cert_file_path() {
52    let mut root_cert = PemCollection::new();
53    root_cert.load_pem_certs_from_json_file(NON_EXISTEND_PEM_CERT, ALLOWED_ROOT_CERT_MEMBER_NAMES);
54    assert!(root_cert.pem_data.is_empty());
55}
56
57#[test]
58fn test_invalid_pem_cert_json_structure() {
59    let mut root_cert = PemCollection::new();
60    root_cert
61        .load_pem_certs_from_json_file(INVALID_STRUCTURE_PEM_CERT, ALLOWED_ROOT_CERT_MEMBER_NAMES);
62    assert!(root_cert.pem_data.is_empty());
63}
64
65#[test]
66fn test_empty_pem_cert_json_file() {
67    let mut root_cert = PemCollection::new();
68    root_cert.load_pem_certs_from_json_file(EMPTY_PEM_CERT, ALLOWED_ROOT_CERT_MEMBER_NAMES);
69    assert!(root_cert.pem_data.is_empty());
70}
71
72#[test]
73fn test_successful_load_cert_path() {
74    let mut cert_paths = TrustCertPath::new();
75    cert_paths.load_cert_path_from_json_file(VALID_CERT_PATH);
76    assert_eq!(cert_paths.profile_signers.len(), 4);
77    assert_eq!(cert_paths.app_sources.len(), 6);
78}
79#[test]
80fn test_invalid_cert_path_file_path() {
81    let mut cert_paths = TrustCertPath::new();
82    cert_paths.load_cert_path_from_json_file(NON_EXISTEND_CERT_PATH);
83    assert!(
84        cert_paths.app_sources.is_empty(),
85        "Expected cert_paths.app_sources to be empty for an empty JSON file"
86    );
87}
88
89#[test]
90fn test_invalid_cert_path_json_structure() {
91    let mut cert_paths = TrustCertPath::new();
92    cert_paths.load_cert_path_from_json_file(INVALID_STRUCTURE_CERT_PATH);
93    assert!(
94        cert_paths.app_sources.is_empty(),
95        "Expected cert_paths.app_sources to be empty for an empty JSON file"
96    );
97}
98
99#[test]
100fn test_empty_cert_path_json_file() {
101    let mut cert_paths = TrustCertPath::new();
102    cert_paths.load_cert_path_from_json_file(EMPTY_CERT_PATH);
103    assert!(
104        cert_paths.app_sources.is_empty(),
105        "Expected cert_paths.app_sources to be empty for an empty JSON file"
106    );
107}
108
109#[test]
110fn test_parse_enterprise_profile() {
111    let profile_str = r#"
112    {
113        "version-name": "2.0.0",
114        "version-code": 2,
115        "app-distribution-type": "enterprise",
116        "uuid": "",
117        "validity": {
118            "not-before": 1,
119            "not-after": 2
120        },
121        "type": "release",
122        "bundle-info": {
123            "developer-id": "",
124            "distribution-certificate": "",
125            "bundle-name": "com.test.enterprise",
126            "apl": "normal",
127            "app-feature": "test_app",
128            "app-identifier": "123123"
129        },
130        "acls": {
131            "allowed-acls": [
132                ""
133            ]
134        },
135        "app-privilege-capabilities": [],
136        "permissions": {
137            "restricted-permissions": [
138                ""
139            ]
140        }
141    }
142    "#;
143    let profile_json =JsonValue::from_text(profile_str).unwrap();
144    let result = validate_bundle_and_distribution_type(&profile_json, true);
145    assert!(result.is_ok());
146}
147
148#[test]
149fn test_parse_enterprise_normal_profile() {
150    let profile_str = r#"
151    {
152        "version-name": "2.0.0",
153        "version-code": 2,
154        "app-distribution-type": "enterprise_normal",
155        "uuid": "",
156        "validity": {
157            "not-before": 1,
158            "not-after": 2
159        },
160        "type": "release",
161        "bundle-info": {
162            "developer-id": "",
163            "distribution-certificate": "",
164            "bundle-name": "com.test.enterprise_normal",
165            "apl": "normal",
166            "app-feature": "test_app",
167            "app-identifier": "123123"
168        },
169        "acls": {
170            "allowed-acls": [
171                ""
172            ]
173        },
174        "app-privilege-capabilities": [],
175        "permissions": {
176            "restricted-permissions": [
177                ""
178            ]
179        }
180    }
181    "#;
182    let profile_json =JsonValue::from_text(profile_str).unwrap();
183    let result = validate_bundle_and_distribution_type(&profile_json, true);
184    assert!(result.is_ok());
185}
186
187#[test]
188fn test_parse_enterprise_mdm_profile() {
189    let profile_str = r#"
190    {
191        "version-name": "2.0.0",
192        "version-code": 2,
193        "app-distribution-type": "enterprise_mdm",
194        "uuid": "",
195        "validity": {
196            "not-before": 1,
197            "not-after": 2
198        },
199        "type": "release",
200        "bundle-info": {
201            "developer-id": "",
202            "distribution-certificate": "",
203            "bundle-name": "com.test.enterprise_mdm",
204            "apl": "normal",
205            "app-feature": "test_app",
206            "app-identifier": "123123"
207        },
208        "acls": {
209            "allowed-acls": [
210                ""
211            ]
212        },
213        "app-privilege-capabilities": [],
214        "permissions": {
215            "restricted-permissions": [
216                ""
217            ]
218        }
219    }
220    "#;
221    let profile_json =JsonValue::from_text(profile_str).unwrap();
222    let result = validate_bundle_and_distribution_type(&profile_json, true);
223    assert!(result.is_ok());
224}
225
226#[test]
227fn test_parse_debug_profile() {
228    let profile_str = r#"
229    {
230        "version-name": "2.0.0",
231        "version-code": 2,
232        "app-distribution-type": "developer",
233        "uuid": "",
234        "validity": {
235            "not-before": 1,
236            "not-after": 2
237        },
238        "type": "debug",
239        "bundle-info": {
240            "developer-id": "",
241            "development-certificate": "",
242            "bundle-name": "com.test.developer",
243            "apl": "normal",
244            "app-feature": "test_app",
245            "app-identifier": "123123"
246        },
247        "acls": {
248            "allowed-acls": [
249                ""
250            ]
251        },
252        "app-privilege-capabilities": [],
253        "permissions": {
254            "restricted-permissions": [
255                ""
256            ]
257        },
258        "debug-info": {
259            "device-ids": [],
260            "device-id-type": "udid"
261        }
262    }
263    "#;
264    let udid = get_udid().expect("Failed to get UDID");
265    let mut profile_json =JsonValue::from_text(profile_str).unwrap();
266    profile_json["debug-info"]["device-ids"][0] = JsonValue::String(udid);
267    let result = validate_bundle_and_distribution_type(&profile_json, true);
268    assert!(result.is_ok());
269}
270
271#[test]
272fn test_parse_iternaltesting_profile() {
273    let profile_str = r#"
274    {
275        "version-name": "2.0.0",
276        "version-code": 2,
277        "app-distribution-type": "internaltesting",
278        "uuid": "",
279        "validity": {
280            "not-before": 1,
281            "not-after": 2
282        },
283        "type": "release",
284        "bundle-info": {
285            "developer-id": "",
286            "distribution-certificate": "",
287            "bundle-name": "com.test.internaltesting",
288            "apl": "normal",
289            "app-feature": "test_app",
290            "app-identifier": "123123"
291        },
292        "acls": {
293            "allowed-acls": [
294                ""
295            ]
296        },
297        "app-privilege-capabilities": [],
298        "permissions": {
299            "restricted-permissions": [
300                ""
301            ]
302        },
303        "debug-info": {
304            "device-ids": [],
305            "device-id-type": "udid"
306        }
307    }
308    "#;
309    let udid = get_udid().expect("Failed to get UDID");
310    let mut profile_json =JsonValue::from_text(profile_str).unwrap();
311    profile_json["debug-info"]["device-ids"][0] = JsonValue::String(udid);
312    let result = validate_bundle_and_distribution_type(&profile_json, true);
313    assert!(result.is_ok());
314}
315
316#[test]
317fn test_parse_invalid_profile() {
318    let no_type_profile = r#"
319    {
320        "version-name": "2.0.0",
321        "version-code": 2,
322        "app-distribution-type": "internaltesting",
323        "uuid": "",
324        "validity": {
325            "not-before": 1,
326            "not-after": 2
327        },
328        "bundle-info": {
329            "developer-id": "",
330            "distribution-certificate": "",
331            "bundle-name": "com.test.internaltesting",
332            "apl": "normal",
333            "app-feature": "test_app",
334            "app-identifier": "123123"
335        },
336        "acls": {
337            "allowed-acls": [
338                ""
339            ]
340        },
341        "app-privilege-capabilities": [],
342        "permissions": {
343            "restricted-permissions": [
344                ""
345            ]
346        },
347        "debug-info": {
348            "device-ids": [],
349            "device-id-type": "udid"
350        }
351    }
352    "#;
353    let no_distribution_profile = r#"
354    {
355        "version-name": "2.0.0",
356        "version-code": 2,
357        "uuid": "",
358        "validity": {
359            "not-before": 1,
360            "not-after": 2
361        },
362        "type": "release",
363        "bundle-info": {
364            "developer-id": "",
365            "distribution-certificate": "",
366            "bundle-name": "com.test.internaltesting",
367            "apl": "normal",
368            "app-feature": "test_app",
369            "app-identifier": "123123"
370        },
371        "acls": {
372            "allowed-acls": [
373                ""
374            ]
375        },
376        "app-privilege-capabilities": [],
377        "permissions": {
378            "restricted-permissions": [
379                ""
380            ]
381        },
382        "debug-info": {
383            "device-ids": [],
384            "device-id-type": "udid"
385        }
386    }
387    "#;
388    let no_debug_info_profile = r#"
389    {
390        "version-name": "2.0.0",
391        "version-code": 2,
392        "app-distribution-type": "internaltesting",
393        "uuid": "",
394        "validity": {
395            "not-before": 1,
396            "not-after": 2
397        },
398        "type": "release",
399        "bundle-info": {
400            "developer-id": "",
401            "distribution-certificate": "",
402            "bundle-name": "com.test.internaltesting",
403            "apl": "normal",
404            "app-feature": "test_app",
405            "app-identifier": "123123"
406        },
407        "acls": {
408            "allowed-acls": [
409                ""
410            ]
411        },
412        "app-privilege-capabilities": [],
413        "permissions": {
414            "restricted-permissions": [
415                ""
416            ]
417        }
418    }
419    "#;
420    let udid = get_udid().expect("Failed to get UDID");
421    let mut no_type_profile_json =JsonValue::from_text(no_type_profile).unwrap();
422    no_type_profile_json["debug-info"]["device-ids"][0] = JsonValue::String(udid.clone());
423    let result = validate_bundle_and_distribution_type(&no_type_profile_json, true);
424    assert!(result.is_err());
425
426    let mut no_distribution_profile_json =JsonValue::from_text(no_distribution_profile).unwrap();
427    no_distribution_profile_json["debug-info"]["device-ids"][0] = JsonValue::String(udid.clone());
428    let result = validate_bundle_and_distribution_type(&no_distribution_profile_json, true);
429    assert!(result.is_err());
430
431    let no_debug_info_profile_json =JsonValue::from_text(no_debug_info_profile).unwrap();
432    let result = validate_bundle_and_distribution_type(&no_debug_info_profile_json, true);
433    assert!(result.is_err());
434}
435
436#[test]
437fn test_get_udid_once() {
438    let udid_from_get = get_udid().expect("Failed to get UDID");
439    let udid_from_global = UDID.clone().expect("UDID is None");
440
441    assert_eq!(udid_from_get, udid_from_global);
442}
443
444#[test]
445fn test_get_udid_concurrent() {
446    let num_threads = 10;
447    let mut handles = vec![];
448
449    for _ in 0..num_threads {
450        let handle = thread::spawn(|| {
451            let udid = get_udid().expect("Failed to get UDID");
452            assert_eq!(udid, UDID.clone().expect("UDID is None"));
453        });
454        handles.push(handle);
455    }
456
457    for handle in handles {
458        handle.join().expect("Thread panicked");
459    }
460}