1 // Copyright 2016 Google Inc. All rights reserved. 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 // 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 15 package main 16 17 import ( 18 "bytes" 19 "fmt" 20 "strings" 21 "testing" 22 23 "android/soong/bpfix/bpfix" 24 ) 25 26 var testCases = []struct { 27 desc string 28 in string 29 expected string 30 }{ 31 { 32 desc: "basic cc_library_shared with comments", 33 in: ` 34 # 35 # Copyright 36 # 37 38 # Module Comment 39 include $(CLEAR_VARS) 40 # Name Comment 41 LOCAL_MODULE := test 42 # Source comment 43 LOCAL_SRC_FILES_EXCLUDE := a.c 44 # Second source comment 45 LOCAL_SRC_FILES_EXCLUDE += b.c 46 include $(BUILD_SHARED_LIBRARY)`, 47 expected: ` 48 // 49 // Copyright 50 // 51 52 // Module Comment 53 cc_library_shared { 54 // Name Comment 55 name: "test", 56 // Source comment 57 exclude_srcs: ["a.c"] + ["b.c"], // Second source comment 58 59 }`, 60 }, 61 { 62 desc: "split local/global include_dirs (1)", 63 in: ` 64 include $(CLEAR_VARS) 65 LOCAL_C_INCLUDES := $(LOCAL_PATH) 66 include $(BUILD_SHARED_LIBRARY)`, 67 expected: ` 68 cc_library_shared { 69 local_include_dirs: ["."], 70 }`, 71 }, 72 { 73 desc: "split local/global include_dirs (2)", 74 in: ` 75 include $(CLEAR_VARS) 76 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include 77 include $(BUILD_SHARED_LIBRARY)`, 78 expected: ` 79 cc_library_shared { 80 local_include_dirs: ["include"], 81 }`, 82 }, 83 { 84 desc: "split local/global include_dirs (3)", 85 in: ` 86 include $(CLEAR_VARS) 87 LOCAL_C_INCLUDES := system/core/include 88 include $(BUILD_SHARED_LIBRARY)`, 89 expected: ` 90 cc_library_shared { 91 include_dirs: ["system/core/include"], 92 }`, 93 }, 94 { 95 desc: "split local/global include_dirs (4)", 96 in: ` 97 input := testing/include 98 include $(CLEAR_VARS) 99 # Comment 1 100 LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/include system/core/include $(input) 101 # Comment 2 102 LOCAL_C_INCLUDES += $(TOP)/system/core/include $(LOCAL_PATH)/test/include 103 # Comment 3 104 include $(BUILD_SHARED_LIBRARY)`, 105 expected: ` 106 input = ["testing/include"] 107 cc_library_shared { 108 // Comment 1 109 include_dirs: ["system/core/include"] + input + ["system/core/include"], // Comment 2 110 local_include_dirs: ["."] + ["include"] + ["test/include"], 111 // Comment 3 112 }`, 113 }, 114 { 115 desc: "LOCAL_MODULE_STEM", 116 in: ` 117 include $(CLEAR_VARS) 118 LOCAL_MODULE := libtest 119 LOCAL_MODULE_STEM := $(LOCAL_MODULE).so 120 include $(BUILD_SHARED_LIBRARY) 121 122 include $(CLEAR_VARS) 123 LOCAL_MODULE := libtest2 124 LOCAL_MODULE_STEM := testing.so 125 include $(BUILD_SHARED_LIBRARY) 126 `, 127 expected: ` 128 cc_library_shared { 129 name: "libtest", 130 suffix: ".so", 131 } 132 133 cc_library_shared { 134 name: "libtest2", 135 stem: "testing.so", 136 } 137 `, 138 }, 139 { 140 desc: "LOCAL_MODULE_HOST_OS", 141 in: ` 142 include $(CLEAR_VARS) 143 LOCAL_MODULE := libtest 144 LOCAL_MODULE_HOST_OS := linux darwin windows 145 include $(BUILD_SHARED_LIBRARY) 146 147 include $(CLEAR_VARS) 148 LOCAL_MODULE := libtest2 149 LOCAL_MODULE_HOST_OS := linux 150 include $(BUILD_SHARED_LIBRARY) 151 `, 152 expected: ` 153 cc_library_shared { 154 name: "libtest", 155 target: { 156 windows: { 157 enabled: true, 158 } 159 } 160 } 161 162 cc_library_shared { 163 name: "libtest2", 164 target: { 165 darwin: { 166 enabled: false, 167 } 168 } 169 } 170 `, 171 }, 172 { 173 desc: "LOCAL_RTTI_VALUE", 174 in: ` 175 include $(CLEAR_VARS) 176 LOCAL_MODULE := libtest 177 LOCAL_RTTI_FLAG := # Empty flag 178 include $(BUILD_SHARED_LIBRARY) 179 180 include $(CLEAR_VARS) 181 LOCAL_MODULE := libtest2 182 LOCAL_RTTI_FLAG := -frtti 183 include $(BUILD_SHARED_LIBRARY) 184 `, 185 expected: ` 186 cc_library_shared { 187 name: "libtest", 188 rtti: false, // Empty flag 189 } 190 191 cc_library_shared { 192 name: "libtest2", 193 rtti: true, 194 } 195 `, 196 }, 197 { 198 desc: "LOCAL_ARM_MODE", 199 in: ` 200 include $(CLEAR_VARS) 201 LOCAL_ARM_MODE := arm 202 include $(BUILD_SHARED_LIBRARY) 203 `, 204 expected: ` 205 cc_library_shared { 206 arch: { 207 arm: { 208 instruction_set: "arm", 209 }, 210 }, 211 } 212 `, 213 }, 214 { 215 desc: "_<OS> suffixes", 216 in: ` 217 include $(CLEAR_VARS) 218 LOCAL_SRC_FILES_darwin := darwin.c 219 LOCAL_SRC_FILES_linux := linux.c 220 LOCAL_SRC_FILES_windows := windows.c 221 include $(BUILD_SHARED_LIBRARY) 222 `, 223 expected: ` 224 cc_library_shared { 225 target: { 226 darwin: { 227 srcs: ["darwin.c"], 228 }, 229 linux_glibc: { 230 srcs: ["linux.c"], 231 }, 232 windows: { 233 srcs: ["windows.c"], 234 }, 235 }, 236 } 237 `, 238 }, 239 { 240 desc: "LOCAL_SANITIZE := never", 241 in: ` 242 include $(CLEAR_VARS) 243 LOCAL_SANITIZE := never 244 include $(BUILD_SHARED_LIBRARY) 245 `, 246 expected: ` 247 cc_library_shared { 248 sanitize: { 249 never: true, 250 }, 251 } 252 `, 253 }, 254 { 255 desc: "LOCAL_SANITIZE unknown parameter", 256 in: ` 257 include $(CLEAR_VARS) 258 LOCAL_SANITIZE := thread cfi asdf 259 LOCAL_SANITIZE_DIAG := cfi 260 LOCAL_SANITIZE_RECOVER := qwert 261 include $(BUILD_SHARED_LIBRARY) 262 `, 263 expected: ` 264 cc_library_shared { 265 sanitize: { 266 thread: true, 267 cfi: true, 268 misc_undefined: ["asdf"], 269 diag: { 270 cfi: true, 271 }, 272 recover: ["qwert"], 273 }, 274 } 275 `, 276 }, 277 { 278 desc: "LOCAL_SANITIZE_RECOVER", 279 in: ` 280 include $(CLEAR_VARS) 281 LOCAL_SANITIZE_RECOVER := shift-exponent 282 include $(BUILD_SHARED_LIBRARY) 283 `, 284 expected: ` 285 cc_library_shared { 286 sanitize: { 287 recover: ["shift-exponent"], 288 }, 289 } 290 `, 291 }, 292 { 293 desc: "version_script in LOCAL_LDFLAGS", 294 in: ` 295 include $(CLEAR_VARS) 296 LOCAL_LDFLAGS := -Wl,--link-opt -Wl,--version-script,$(LOCAL_PATH)/exported32.map 297 include $(BUILD_SHARED_LIBRARY) 298 `, 299 expected: ` 300 cc_library_shared { 301 ldflags: ["-Wl,--link-opt"], 302 version_script: "exported32.map", 303 } 304 `, 305 }, 306 { 307 desc: "Handle TOP", 308 in: ` 309 include $(CLEAR_VARS) 310 LOCAL_C_INCLUDES := $(TOP)/system/core/include $(TOP) 311 include $(BUILD_SHARED_LIBRARY) 312 `, 313 expected: ` 314 cc_library_shared { 315 include_dirs: ["system/core/include", "."], 316 } 317 `, 318 }, 319 { 320 desc: "Remove LOCAL_MODULE_TAGS optional", 321 in: ` 322 include $(CLEAR_VARS) 323 LOCAL_MODULE_TAGS := optional 324 include $(BUILD_SHARED_LIBRARY) 325 `, 326 327 expected: ` 328 cc_library_shared { 329 330 } 331 `, 332 }, 333 { 334 desc: "Keep LOCAL_MODULE_TAGS non-optional", 335 in: ` 336 include $(CLEAR_VARS) 337 LOCAL_MODULE_TAGS := debug 338 include $(BUILD_SHARED_LIBRARY) 339 `, 340 341 expected: ` 342 cc_library_shared { 343 tags: ["debug"], 344 } 345 `, 346 }, 347 348 { 349 desc: "Input containing escaped quotes", 350 in: ` 351 include $(CLEAR_VARS) 352 LOCAL_MODULE:= libsensorservice 353 LOCAL_CFLAGS:= -DLOG_TAG=\"-DDontEscapeMe\" 354 LOCAL_SRC_FILES := \"EscapeMe.cc\" 355 include $(BUILD_SHARED_LIBRARY) 356 `, 357 358 expected: ` 359 cc_library_shared { 360 name: "libsensorservice", 361 cflags: ["-DLOG_TAG=\"-DDontEscapeMe\""], 362 srcs: ["\\\"EscapeMe.cc\\\""], 363 } 364 `, 365 }, 366 { 367 368 desc: "Don't fail on missing CLEAR_VARS", 369 in: ` 370 LOCAL_MODULE := iAmAModule 371 include $(BUILD_SHARED_LIBRARY)`, 372 373 expected: ` 374 // ANDROIDMK TRANSLATION WARNING: No 'include $(CLEAR_VARS)' detected before first assignment; clearing vars now 375 cc_library_shared { 376 name: "iAmAModule", 377 378 }`, 379 }, 380 { 381 382 desc: "LOCAL_AIDL_INCLUDES", 383 in: ` 384 include $(CLEAR_VARS) 385 LOCAL_MODULE := iAmAModule 386 LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/src/main/java system/core 387 include $(BUILD_SHARED_LIBRARY)`, 388 389 expected: ` 390 cc_library_shared { 391 name: "iAmAModule", 392 aidl: { 393 include_dirs: ["system/core"], 394 local_include_dirs: ["src/main/java"], 395 } 396 }`, 397 }, 398 { 399 // the important part of this test case is that it confirms that androidmk doesn't 400 // panic in this case 401 desc: "multiple directives inside recipe", 402 in: ` 403 ifeq ($(a),true) 404 ifeq ($(b),false) 405 imABuildStatement: somefile 406 echo begin 407 endif # a==true 408 echo middle 409 endif # b==false 410 echo end 411 `, 412 expected: ` 413 // ANDROIDMK TRANSLATION ERROR: unsupported conditional 414 // ifeq ($(a),true) 415 416 // ANDROIDMK TRANSLATION ERROR: unsupported conditional 417 // ifeq ($(b),false) 418 419 // ANDROIDMK TRANSLATION ERROR: unsupported line 420 // rule: imABuildStatement: somefile 421 // echo begin 422 // # a==true 423 // echo middle 424 // # b==false 425 // echo end 426 // 427 // ANDROIDMK TRANSLATION ERROR: endif from unsupported contitional 428 // endif 429 // ANDROIDMK TRANSLATION ERROR: endif from unsupported contitional 430 // endif 431 `, 432 }, 433 { 434 desc: "ignore all-makefiles-under", 435 in: ` 436 include $(call all-makefiles-under,$(LOCAL_PATH)) 437 `, 438 expected: ``, 439 }, 440 { 441 desc: "proguard options for java library", 442 in: ` 443 include $(CLEAR_VARS) 444 # Empty 445 LOCAL_PROGUARD_ENABLED := 446 # Disabled 447 LOCAL_PROGUARD_ENABLED := disabled 448 # Full 449 LOCAL_PROGUARD_ENABLED := full 450 # Obfuscation and optimization 451 LOCAL_PROGUARD_ENABLED := obfuscation optimization 452 # Custom 453 LOCAL_PROGUARD_ENABLED := custom 454 include $(BUILD_JAVA_LIBRARY) 455 `, 456 expected: ` 457 java_library { 458 // Empty 459 460 // Disabled 461 optimize: { 462 enabled: false, 463 // Full 464 enabled: true, 465 // Obfuscation and optimization 466 obfuscate: true, 467 optimize: true, 468 enabled: true, 469 // Custom 470 no_aapt_flags: true, 471 enabled: true, 472 }, 473 } 474 `, 475 }, 476 { 477 desc: "errorprone options for java library", 478 in: ` 479 include $(CLEAR_VARS) 480 LOCAL_ERROR_PRONE_FLAGS := -Xep:AsyncCallableReturnsNull:ERROR -Xep:AsyncFunctionReturnsNull:ERROR 481 include $(BUILD_JAVA_LIBRARY) 482 `, 483 expected: ` 484 java_library { 485 errorprone: { 486 javacflags: [ 487 "-Xep:AsyncCallableReturnsNull:ERROR", 488 "-Xep:AsyncFunctionReturnsNull:ERROR", 489 ], 490 }, 491 } 492 `, 493 }, 494 { 495 desc: "java prebuilt", 496 in: ` 497 include $(CLEAR_VARS) 498 LOCAL_SRC_FILES := test.jar 499 LOCAL_MODULE_CLASS := JAVA_LIBRARIES 500 LOCAL_STATIC_ANDROID_LIBRARIES := 501 include $(BUILD_PREBUILT) 502 `, 503 expected: ` 504 java_import { 505 jars: ["test.jar"], 506 507 } 508 `, 509 }, 510 { 511 desc: "aar prebuilt", 512 in: ` 513 include $(CLEAR_VARS) 514 LOCAL_SRC_FILES := test.aar 515 LOCAL_MODULE_CLASS := JAVA_LIBRARIES 516 include $(BUILD_PREBUILT) 517 `, 518 expected: ` 519 android_library_import { 520 aars: ["test.aar"], 521 522 } 523 `, 524 }, 525 526 { 527 desc: "aar", 528 in: ` 529 include $(CLEAR_VARS) 530 LOCAL_SRC_FILES := test.java 531 LOCAL_RESOURCE_DIR := res 532 include $(BUILD_STATIC_JAVA_LIBRARY) 533 534 include $(CLEAR_VARS) 535 LOCAL_SRC_FILES := test.java 536 LOCAL_STATIC_LIBRARIES := foo 537 LOCAL_STATIC_ANDROID_LIBRARIES := bar 538 include $(BUILD_STATIC_JAVA_LIBRARY) 539 540 include $(CLEAR_VARS) 541 LOCAL_SRC_FILES := test.java 542 LOCAL_SHARED_LIBRARIES := foo 543 LOCAL_SHARED_ANDROID_LIBRARIES := bar 544 include $(BUILD_STATIC_JAVA_LIBRARY) 545 546 include $(CLEAR_VARS) 547 LOCAL_SRC_FILES := test.java 548 LOCAL_STATIC_ANDROID_LIBRARIES := 549 include $(BUILD_STATIC_JAVA_LIBRARY) 550 `, 551 expected: ` 552 android_library { 553 srcs: ["test.java"], 554 resource_dirs: ["res"], 555 } 556 557 android_library { 558 srcs: ["test.java"], 559 static_libs: [ 560 "foo", 561 "bar", 562 ], 563 } 564 565 android_library { 566 srcs: ["test.java"], 567 libs: [ 568 "foo", 569 "bar", 570 ], 571 } 572 573 java_library_static { 574 srcs: ["test.java"], 575 static_libs: [], 576 } 577 `, 578 }, 579 { 580 desc: "cc_library shared_libs", 581 in: ` 582 include $(CLEAR_VARS) 583 LOCAL_SHARED_LIBRARIES := libfoo 584 include $(BUILD_SHARED_LIBRARY) 585 `, 586 expected: ` 587 cc_library_shared { 588 shared_libs: ["libfoo"], 589 } 590 `, 591 }, 592 } 593 594 func TestEndToEnd(t *testing.T) { 595 for i, test := range testCases { 596 expected, err := bpfix.Reformat(test.expected) 597 if err != nil { 598 t.Error(err) 599 } 600 601 got, errs := convertFile(fmt.Sprintf("<testcase %d>", i), bytes.NewBufferString(test.in)) 602 if len(errs) > 0 { 603 t.Errorf("Unexpected errors: %q", errs) 604 continue 605 } 606 607 if got != expected { 608 t.Errorf("failed testcase '%s'\ninput:\n%s\n\nexpected:\n%s\ngot:\n%s\n", test.desc, strings.TrimSpace(test.in), expected, got) 609 } 610 } 611 } 612