1 #[cfg(test)] 2 mod tests { 3 4 use std::io::Read; 5 6 use crate::parser::*; 7 use nom::error::VerboseError; 8 use nom::Err; 9 10 #[test] test_parse_array()11 fn test_parse_array() { 12 // Test case 1: Valid input 13 let input = r#"[ "value1", "value2", "value3" ]"#; 14 let expected_output = Ok(("", vec!["value1".into(), "value2".into(), "value3".into()])); 15 assert_eq!(parse_array(input), expected_output); 16 17 // Test case 2: Empty array 18 let input = r#"[]"#; 19 let expected_output = Ok(("", vec![])); 20 assert_eq!(parse_array(input), expected_output); 21 22 // Test case 3: Array with whitespace 23 let input = r#"[ "value1" , "value2" , "value3" ]"#; 24 let expected_output = Ok(("", vec!["value1".into(), "value2".into(), "value3".into()])); 25 assert_eq!(parse_array(input), expected_output); 26 27 // Test case 4: Array with empty values 28 let input = r#"[ "", "", "" ]"#; 29 let expected_output = Ok(("", vec!["".into(), "".into(), "".into()])); 30 assert_eq!(parse_array(input), expected_output); 31 32 // Test case 5: Invalid input - missing closing bracket 33 let input = r#"[ "value1", "value2", "value3""#; 34 assert!(parse_array(input).is_err()); 35 36 // Test case 5: Invalid input - missing opening bracket 37 let input = r#""value1", "value2", "value3" ]"#; 38 assert!(parse_array(input).is_err()); 39 40 // Test case 6: Array with trailing comma is not an error 41 let input = r#"[ "value1", "value2", "value3", ]"#; 42 let expected_output = Ok(("", vec!["value1".into(), "value2".into(), "value3".into()])); 43 assert_eq!(parse_array(input), expected_output); 44 } 45 #[test] test_parse_entry()46 fn test_parse_entry() { 47 // Test case 1: Valid input 48 let input = r#"key: "value""#; 49 let expected_output = Ok(("", ("key".to_string(), Value::String("value".to_string())))); 50 assert_eq!(parse_module_entry(input), expected_output); 51 52 // Test case 2: Valid input with whitespace 53 let input = r#" key : "value" "#; 54 let expected_output = Ok(("", ("key".to_string(), Value::String("value".to_string())))); 55 assert_eq!(parse_module_entry(input), expected_output); 56 57 // Test case 3: Valid input with array value 58 let input = r#"key: [ "value1", "value2", "value3" ]"#; 59 let expected_output = Ok(( 60 "", 61 ( 62 "key".to_string(), 63 Value::Array(vec!["value1".into(), "value2".into(), "value3".into()]), 64 ), 65 )); 66 assert_eq!(parse_module_entry(input), expected_output); 67 68 // Test case 4: Invalid input - missing colon 69 let input = r#"key "value""#; 70 assert!(parse_module_entry(input).is_err()); 71 72 // Test case 5: Invalid input - missing value 73 let input = r#"key:"#; 74 assert!(parse_module_entry(input).is_err()); 75 76 // Test case 6: Invalid input - missing key 77 let input = r#":"value""#; 78 assert!(parse_module_entry(input).is_err()); 79 80 // Test case 7: Invalid input - missing key and value 81 let input = r#":"#; 82 assert!(parse_module_entry(input).is_err()); 83 } 84 #[test] test_parse_module()85 fn test_parse_module() { 86 let input = r#" 87 module_name { 88 key1: "value1", 89 key2: true, 90 key3: [ "value2", "value3" ], 91 } 92 "#; 93 94 let expected_output = Module { 95 typ: "module_name".to_string(), 96 entries: vec![ 97 ("key1".to_string(), Value::String("value1".to_string())), 98 ("key2".to_string(), Value::Boolean(true)), 99 ( 100 "key3".to_string(), 101 Value::Array(vec!["value2".into(), "value3".into()]), 102 ), 103 ] 104 .into_iter() 105 .collect(), 106 }; 107 108 assert_eq!(parse_module(input), Ok(("", expected_output))); 109 } 110 #[test] test_parse_blueprint()111 fn test_parse_blueprint() { 112 let input = r#" 113 module_name { 114 key1: "value1", 115 key2: true, 116 key3: [ "value2", "value3" ], 117 } 118 module_name2 { 119 key1: "value1", 120 key2: true, 121 key3: [ "value2", "value3" ], 122 }"#; 123 let output = BluePrint::parse(input).unwrap(); 124 assert_eq!(output.modules.len(), 2); 125 assert_eq!(output.modules[0].typ, "module_name"); 126 assert_eq!(output.modules[1].typ, "module_name2"); 127 let mut keys = output.modules[0] 128 .entries 129 .keys() 130 .map(|x| x.to_owned()) 131 .collect::<Vec<_>>(); 132 keys.sort(); 133 assert_eq!( 134 keys, 135 vec!["key1".to_string(), "key2".to_string(), "key3".to_string()] 136 ); 137 } 138 #[test] test_nested_dict()139 fn test_nested_dict() { 140 let input = r#" 141 rust_test_host { 142 name: "ss", 143 srcs: ["src/ss.rs"], 144 test_options: { 145 unit_test: true, 146 }, 147 } "#; 148 let output: Result<(&str, Module), Err<VerboseError<&str>>> = parse_module(input); 149 assert!(output.is_ok()); 150 } 151 152 #[test] test_comment()153 fn test_comment() { 154 let input = r#" 155 rust_test_host { 156 // name: "ss", 157 // 158 srcs: ["src/ss.rs"], 159 test_options: { 160 unit_test: true, 161 }, 162 } "#; 163 let output = parse_module(input); 164 display_error(input, &output); 165 assert!(output.is_ok()); 166 } 167 #[test] test_all_comment()168 fn test_all_comment() { 169 let input = r#"/* 170 rust_test_host { 171 // name: "ss", 172 // 173 srcs: ["src/ss.rs"], 174 test_options: { 175 unit_test: true, 176 }, 177 } 178 */"#; 179 let output = BluePrint::parse(input); 180 if output.is_err() { 181 println!("Error: {}", output.unwrap_err()); 182 panic!("Error in parsing"); 183 } 184 } 185 186 #[test] test_issue_1()187 fn test_issue_1() { 188 let input = r#" 189 aidl_interface { 190 name: "android.hardware.tetheroffload", 191 vendor_available: true, 192 srcs: ["android/hardware/tetheroffload/*.aidl"], 193 stability: "vintf", 194 backend: { 195 cpp: { 196 enabled: false, 197 }, 198 java: { 199 sdk_version: "module_current", 200 apex_available: [ 201 "com.android.tethering", 202 ], 203 min_sdk_version: "30", 204 enabled: true, 205 }, 206 ndk: { 207 apps_enabled: false, 208 }, 209 }, 210 versions_with_info: [ 211 { 212 version: "1", 213 imports: [], 214 }, 215 ], 216 frozen: true, 217 218 } 219 "#; 220 let output = parse_module(input); 221 display_error(input, &output); 222 assert!(output.is_ok()); 223 } 224 #[test] test_issue_2()225 fn test_issue_2() { 226 let input = r#" 227 aidl_interface { 228 name: "android.hardw\"are.tetheroffload", 229 } 230 "#; 231 let output = parse_module(input); 232 display_error(input, &output); 233 assert!(output.is_ok()); 234 } 235 #[test] test_module_second_form()236 fn test_module_second_form() { 237 let input = r#" 238 aidl_interface(name = "android.hardware.tetheroffload") 239 "#; 240 let output = parse_module(input); 241 display_error(input, &output); 242 assert!(output.is_ok()); 243 } display_error<T>(input: &str, output: &Result<(&str, T), Err<VerboseError<&str>>>) -> ()244 fn display_error<T>(input: &str, output: &Result<(&str, T), Err<VerboseError<&str>>>) -> () { 245 if let Err(e) = output { 246 println!("Error: {}", format_err(input, e.clone())); 247 } 248 } 249 #[test] test_expr()250 fn test_expr() { 251 let input = r#""abc" + "def""#; 252 let output = parse_expr(input); 253 display_error(input, &output); 254 assert!(output.is_ok()); 255 assert!(output.as_ref().unwrap().0.is_empty()); 256 assert!(output.unwrap().1 == Value::String("abcdef".to_string())); 257 } 258 #[test] test_expr_array()259 fn test_expr_array() { 260 let input = r#"["abc", "def"] + [ "ghi" ]"#; 261 let output = parse_expr(input); 262 display_error(input, &output); 263 assert!(output.is_ok()); 264 assert!(output.as_ref().unwrap().0.is_empty()); 265 assert!(output.unwrap().1 == Value::Array(vec!["abc".into(), "def".into(), "ghi".into()])); 266 } 267 #[test] test_expr_ident()268 fn test_expr_ident() { 269 let input = r#"ident + [ "ghi" ]"#; 270 let output = parse_expr(input); 271 display_error(input, &output); 272 assert!(output.is_ok()); 273 assert!(output.as_ref().unwrap().0.is_empty()); 274 assert!( 275 output.unwrap().1 276 == Value::ConcatExpr([ 277 Value::Ident("ident".to_string()), 278 Value::Array(["ghi".into()].into()) 279 ].into()) 280 ); 281 } 282 #[test] test_expr_value()283 fn test_expr_value() { 284 let input = r#"123"#; 285 let output = parse_expr(input); 286 display_error(input, &output); 287 assert!(output.is_ok()); 288 assert!(output.as_ref().unwrap().0.is_empty()); 289 assert!( 290 output.unwrap().1 291 == Value::Integer(123)); 292 } 293 // found in platform_testing/tests/health/scenarios/tests/Android.bp 294 #[test] test_complicated_concat()295 fn test_complicated_concat() { 296 let input = r#""out_dir=$$(dirname $(out)) && assets_dir=\"assets\" " + 297 "&& mkdir -p $$out_dir/$$assets_dir && src_protos=($(locations assets/*.textpb)) " + 298 "&& for file in $${src_protos[@]} ; do fname=$$(basename $$file) " + 299 "&& if ! ($(location aprotoc) --encode=longevity.profile.Configuration " + 300 "$(location :profile-proto-def) < $$file > " + 301 "$$out_dir/$$assets_dir/$${fname//.textpb/.pb}) ; then " + 302 "echo \"\x1b[0;31mFailed to parse profile $$file. See above for errors.\x1b[0m\" " + 303 "&& exit 1 ; fi ; done && jar cf $(out) -C $$(dirname $(out)) $$assets_dir""#; 304 let output = parse_expr(input); 305 display_error(input, &output); 306 assert!(output.is_ok()); 307 assert!(output.as_ref().unwrap().0.is_empty()); 308 309 } 310 #[test] test_linecomment_wo_eol()311 fn test_linecomment_wo_eol() { 312 let input = r#"// foo"#; 313 let output = BluePrint::parse(input); 314 assert!(output.is_ok()); 315 316 } 317 #[test] test_defines_extends()318 fn test_defines_extends(){ 319 let input = r#" 320 var = ["a", "b"] 321 var2 = 12 322 var += ["c"] 323 var2 += 1 324 var3 = "abc" 325 var3 += "def" 326 "#; 327 let output = BluePrint::parse(input); 328 assert!(output.is_ok()); 329 let bp = output.unwrap(); 330 assert_eq!(bp.variables.get("var").unwrap(), &Value::Array(vec!["a".into(), "b".into(), "c".into()])); 331 assert_eq!(bp.variables.get("var2").unwrap(), &Value::Integer(13)); 332 assert_eq!(bp.variables.get("var3").unwrap(), &Value::String("abcdef".to_string())); 333 } 334 335 #[test] test_defines_extends_error()336 fn test_defines_extends_error(){ 337 let input = r#" 338 var = ["a", "b"] 339 var2 = 12 340 var += 1 341 var2 += "a" 342 "#; 343 let output = BluePrint::parse(input); 344 println!("Error: {}", output.unwrap_err()); 345 // assert!(output.is_err()); 346 } 347 #[test] test_function()348 fn test_function() { 349 let input = r#"method("ss")"#; 350 let output = parse_expr(input); 351 display_error(input, &output); 352 assert!(output.is_ok()); 353 assert_eq!(output.unwrap().1, Value::Function(Function { 354 name: "method".to_string(), 355 args: vec![Value::String("ss".to_string())] 356 })); 357 358 } 359 #[test] test_aosp_db()360 fn test_aosp_db() { 361 // generate tarball from aosp tree 362 // fd -g Android.bp | tar cJf ../rs-bp/src/test_db.tar.xz -T - 363 let data = include_bytes!("test_db.tar.xz"); 364 let mut archive = tar::Archive::new(liblzma::read::XzDecoder::new(&data[..])); 365 let mut count = 0; 366 let mut bytes = 0; 367 let mut num_errors = 0; 368 let mut all_bp = Vec::new(); 369 // first decompress in memory to avoid disk IO for measuring performance 370 for entry in archive.entries().unwrap() { 371 let entry = entry.unwrap(); 372 let mut entry_data = std::io::BufReader::new(entry); 373 let mut contents = String::new(); 374 entry_data.read_to_string(&mut contents).unwrap(); 375 bytes += contents.len(); 376 all_bp.push((format!("{:?}", entry_data.into_inner().path().unwrap()), contents)); 377 } 378 let now = std::time::Instant::now(); 379 for (path, contents) in all_bp { 380 let output = BluePrint::parse(&contents); 381 if output.is_err() { 382 println!("Error for file: {:?}", path); 383 println!("File content: {}", contents); 384 println!("Error: {}", output.unwrap_err()); 385 num_errors += 1; 386 } 387 count += 1; 388 } 389 let elapsed = now.elapsed().as_secs_f32(); 390 println!("{} files ({} bytes) parsed in {:.3}s {}MB/s", count, bytes, elapsed, bytes as f32 / elapsed / 1024.0 / 1024.0); 391 assert_eq!(num_errors, 0); 392 } 393 } 394