1// Copyright 2019 The Chromium OS Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5package main 6 7import ( 8 "fmt" 9 "path" 10 "path/filepath" 11 "strings" 12 "testing" 13) 14 15const crosHardenedGoldenDir = "testdata/cros_hardened_golden" 16const crosHardenedNoCCacheGoldenDir = "testdata/cros_hardened_noccache_golden" 17const crosHardenedLlvmNextGoldenDir = "testdata/cros_hardened_llvmnext_golden" 18 19func TestCrosHardenedConfig(t *testing.T) { 20 withTestContext(t, func(ctx *testContext) { 21 useLlvmNext := false 22 useCCache := true 23 cfg, err := getConfig("cros.hardened", useCCache, useLlvmNext, "123") 24 if err != nil { 25 t.Fatal(err) 26 } 27 ctx.updateConfig(cfg) 28 29 runGoldenRecords(ctx, crosHardenedGoldenDir, createSyswrapperGoldenInputs(ctx)) 30 }) 31} 32 33func TestCrosHardenedConfigWithoutCCache(t *testing.T) { 34 withTestContext(t, func(ctx *testContext) { 35 useLlvmNext := false 36 useCCache := false 37 cfg, err := getConfig("cros.hardened", useCCache, useLlvmNext, "123") 38 if err != nil { 39 t.Fatal(err) 40 } 41 ctx.updateConfig(cfg) 42 43 // Only run the subset of the sysroot wrapper tests that execute commands. 44 gomaPath := path.Join(ctx.tempDir, "gomacc") 45 ctx.writeFile(gomaPath, "") 46 gomaEnv := "GOMACC_PATH=" + gomaPath 47 runGoldenRecords(ctx, crosHardenedNoCCacheGoldenDir, []goldenFile{ 48 createGccPathGoldenInputs(ctx, gomaEnv), 49 createClangPathGoldenInputs(ctx, gomaEnv), 50 createClangSyntaxGoldenInputs(gomaEnv), 51 createBisectGoldenInputs(clangX86_64), 52 createForceDisableWErrorGoldenInputs(), 53 createClangTidyGoldenInputs(gomaEnv), 54 }) 55 }) 56} 57 58func TestCrosHardenedConfigWithLlvmNext(t *testing.T) { 59 withTestContext(t, func(ctx *testContext) { 60 useLlvmNext := true 61 useCCache := true 62 cfg, err := getConfig("cros.hardened", useCCache, useLlvmNext, "123") 63 if err != nil { 64 t.Fatal(err) 65 } 66 ctx.updateConfig(cfg) 67 68 // Only run the subset of the sysroot wrapper tests that execute commands. 69 gomaPath := path.Join(ctx.tempDir, "gomacc") 70 ctx.writeFile(gomaPath, "") 71 gomaEnv := "GOMACC_PATH=" + gomaPath 72 runGoldenRecords(ctx, crosHardenedLlvmNextGoldenDir, []goldenFile{ 73 createGccPathGoldenInputs(ctx, gomaEnv), 74 createClangPathGoldenInputs(ctx, gomaEnv), 75 createClangSyntaxGoldenInputs(gomaEnv), 76 createBisectGoldenInputs(clangX86_64), 77 createForceDisableWErrorGoldenInputs(), 78 createClangTidyGoldenInputs(gomaEnv), 79 }) 80 }) 81} 82 83func createSyswrapperGoldenInputs(ctx *testContext) []goldenFile { 84 gomaPath := path.Join(ctx.tempDir, "gomacc") 85 ctx.writeFile(gomaPath, "") 86 gomaEnv := "GOMACC_PATH=" + gomaPath 87 88 return []goldenFile{ 89 createGccPathGoldenInputs(ctx, gomaEnv), 90 createGoldenInputsForAllTargets("gcc", mainCc), 91 createSysrootWrapperCommonGoldenInputs("gcc", gomaEnv), 92 createSanitizerGoldenInputs("gcc"), 93 createGccArgsGoldenInputs(), 94 createClangSyntaxGoldenInputs(gomaEnv), 95 createClangPathGoldenInputs(ctx, gomaEnv), 96 createGoldenInputsForAllTargets("clang", mainCc), 97 createGoldenInputsForAllTargets("clang", "-ftrapv", mainCc), 98 createSysrootWrapperCommonGoldenInputs("clang", gomaEnv), 99 createSanitizerGoldenInputs("clang"), 100 createClangArgsGoldenInputs(), 101 createBisectGoldenInputs(clangX86_64), 102 createForceDisableWErrorGoldenInputs(), 103 createClangTidyGoldenInputs(gomaEnv), 104 } 105} 106 107func createGoldenInputsForAllTargets(compiler string, args ...string) goldenFile { 108 argsReplacer := strings.NewReplacer(".", "", "-", "") 109 return goldenFile{ 110 Name: fmt.Sprintf("%s_%s_target_specific.json", compiler, argsReplacer.Replace(strings.Join(args, "_"))), 111 Records: []goldenRecord{ 112 { 113 WrapperCmd: newGoldenCmd("./x86_64-cros-linux-gnu-"+compiler, args...), 114 Cmds: okResults, 115 }, 116 { 117 WrapperCmd: newGoldenCmd("./x86_64-cros-eabi-"+compiler, args...), 118 Cmds: okResults, 119 }, 120 { 121 WrapperCmd: newGoldenCmd("./x86_64-cros-win-gnu-"+compiler, args...), 122 Cmds: okResults, 123 }, 124 { 125 WrapperCmd: newGoldenCmd("./armv7m-cros-linux-gnu-"+compiler, args...), 126 Cmds: okResults, 127 }, 128 { 129 WrapperCmd: newGoldenCmd("./armv7m-cros-eabi-"+compiler, args...), 130 Cmds: okResults, 131 }, 132 { 133 WrapperCmd: newGoldenCmd("./armv7m-cros-win-gnu-"+compiler, args...), 134 Cmds: okResults, 135 }, 136 { 137 WrapperCmd: newGoldenCmd("./armv8m-cros-linux-gnu-"+compiler, args...), 138 Cmds: okResults, 139 }, 140 { 141 WrapperCmd: newGoldenCmd("./armv8m-cros-eabi-"+compiler, args...), 142 Cmds: okResults, 143 }, 144 { 145 WrapperCmd: newGoldenCmd("./armv8m-cros-win-gnu-"+compiler, args...), 146 Cmds: okResults, 147 }, 148 }, 149 } 150} 151 152func createBisectGoldenInputs(compiler string) goldenFile { 153 return goldenFile{ 154 Name: "bisect.json", 155 Records: []goldenRecord{ 156 { 157 WrapperCmd: newGoldenCmd(compiler, mainCc), 158 Env: []string{ 159 "BISECT_STAGE=someBisectStage", 160 "HOME=/user/home", 161 }, 162 Cmds: okResults, 163 }, 164 { 165 WrapperCmd: newGoldenCmd(compiler, mainCc), 166 Env: []string{ 167 "BISECT_STAGE=someBisectStage", 168 "BISECT_DIR=someBisectDir", 169 "HOME=/user/home", 170 }, 171 Cmds: okResults, 172 }, 173 { 174 WrapperCmd: newGoldenCmd(compiler, mainCc), 175 Env: []string{ 176 "BISECT_STAGE=someBisectStage", 177 "BISECT_DIR=someBisectDir", 178 "HOME=/user/home", 179 }, 180 Cmds: errorResults, 181 }, 182 }, 183 } 184} 185 186func createForceDisableWErrorGoldenInputs() goldenFile { 187 return goldenFile{ 188 Name: "force_disable_werror.json", 189 Records: []goldenRecord{ 190 { 191 WrapperCmd: newGoldenCmd(clangX86_64, mainCc), 192 Env: []string{"FORCE_DISABLE_WERROR=1"}, 193 Cmds: okResults, 194 }, 195 { 196 WrapperCmd: newGoldenCmd(clangX86_64, mainCc), 197 Env: []string{"FORCE_DISABLE_WERROR=1"}, 198 Cmds: []commandResult{ 199 { 200 Stderr: "-Werror originalerror", 201 ExitCode: 1, 202 }, 203 okResult, 204 }, 205 }, 206 { 207 WrapperCmd: newGoldenCmd(clangX86_64, mainCc), 208 Env: []string{"FORCE_DISABLE_WERROR=1"}, 209 Cmds: []commandResult{ 210 { 211 Stderr: "-Werror originalerror", 212 ExitCode: 1, 213 }, 214 errorResult, 215 }, 216 }, 217 }, 218 } 219} 220 221func createGccPathGoldenInputs(ctx *testContext, gomaEnv string) goldenFile { 222 deepPath := "./a/b/c/d/e/f/g/x86_64-cros-linux-gnu-gcc" 223 linkedDeepPath := "./symlinked/x86_64-cros-linux-gnu-gcc" 224 ctx.writeFile(filepath.Join(ctx.tempDir, "/pathenv/x86_64-cros-linux-gnu-gcc"), "") 225 ctx.symlink(deepPath, linkedDeepPath) 226 return goldenFile{ 227 Name: "gcc_path.json", 228 Records: []goldenRecord{ 229 { 230 WrapperCmd: newGoldenCmd("./x86_64-cros-linux-gnu-gcc", mainCc), 231 Cmds: okResults, 232 }, 233 { 234 WrapperCmd: newGoldenCmd("./x86_64-cros-linux-gnu-gcc", mainCc), 235 Cmds: errorResults, 236 }, 237 { 238 WrapperCmd: newGoldenCmd(filepath.Join(ctx.tempDir, "x86_64-cros-linux-gnu-gcc"), mainCc), 239 Cmds: okResults, 240 }, 241 { 242 WrapperCmd: newGoldenCmd(deepPath, mainCc), 243 Cmds: okResults, 244 }, 245 { 246 WrapperCmd: newGoldenCmd(linkedDeepPath, mainCc), 247 Cmds: okResults, 248 }, 249 { 250 Env: []string{"PATH=" + filepath.Join(ctx.tempDir, "/pathenv")}, 251 WrapperCmd: newGoldenCmd("x86_64-cros-linux-gnu-gcc", mainCc), 252 Cmds: okResults, 253 }, 254 }, 255 } 256} 257 258func createClangPathGoldenInputs(ctx *testContext, gomaEnv string) goldenFile { 259 deepPath := "./a/b/c/d/e/f/g/x86_64-cros-linux-gnu-clang" 260 linkedDeepPath := "./symlinked/x86_64-cros-linux-gnu-clang" 261 ctx.writeFile(filepath.Join(ctx.tempDir, "/pathenv/x86_64-cros-linux-gnu-clang"), "") 262 ctx.symlink(deepPath, linkedDeepPath) 263 return goldenFile{ 264 Name: "clang_path.json", 265 Records: []goldenRecord{ 266 { 267 WrapperCmd: newGoldenCmd("./x86_64-cros-linux-gnu-clang", mainCc), 268 Cmds: okResults, 269 }, 270 { 271 WrapperCmd: newGoldenCmd("./x86_64-cros-linux-gnu-clang", mainCc), 272 Cmds: errorResults, 273 }, 274 { 275 WrapperCmd: newGoldenCmd("./x86_64-cros-linux-gnu-clang++", mainCc), 276 Cmds: okResults, 277 }, 278 { 279 WrapperCmd: newGoldenCmd(clangX86_64, mainCc), 280 Env: []string{"CLANG=somepath/clang"}, 281 Cmds: okResults, 282 }, 283 { 284 WrapperCmd: newGoldenCmd(clangX86_64, "-Xclang-path=/somedir", mainCc), 285 Cmds: []commandResult{ 286 {Stdout: "someResourceDir"}, 287 okResult, 288 }, 289 }, 290 { 291 WrapperCmd: newGoldenCmd(clangX86_64, "-Xclang-path=/somedir", mainCc), 292 Env: []string{gomaEnv}, 293 Cmds: []commandResult{ 294 {Stdout: "someResourceDir"}, 295 okResult, 296 }, 297 }, 298 { 299 WrapperCmd: newGoldenCmd(clangX86_64, "-Xclang-path=/somedir", mainCc), 300 Cmds: []commandResult{ 301 {Stdout: "someResourceDir"}, 302 errorResult, 303 }, 304 }, 305 { 306 WrapperCmd: newGoldenCmd(filepath.Join(ctx.tempDir, "x86_64-cros-linux-gnu-clang"), mainCc), 307 Cmds: okResults, 308 }, 309 { 310 WrapperCmd: newGoldenCmd(deepPath, mainCc), 311 Cmds: okResults, 312 }, 313 { 314 WrapperCmd: newGoldenCmd(linkedDeepPath, mainCc), 315 Cmds: okResults, 316 }, 317 { 318 WrapperCmd: newGoldenCmd("somedir/x86_64-cros-linux-gnu-clang", mainCc), 319 Cmds: okResults, 320 }, 321 { 322 Env: []string{"PATH=" + filepath.Join(ctx.tempDir, "/pathenv")}, 323 WrapperCmd: newGoldenCmd("x86_64-cros-linux-gnu-clang", mainCc), 324 Cmds: okResults, 325 }, 326 }, 327 } 328} 329 330func createClangTidyGoldenInputs(gomaEnv string) goldenFile { 331 tidyEnv := "WITH_TIDY=1" 332 return goldenFile{ 333 Name: "clangtidy.json", 334 Records: []goldenRecord{ 335 { 336 WrapperCmd: newGoldenCmd(clangX86_64, mainCc), 337 Env: []string{tidyEnv}, 338 Cmds: []commandResult{ 339 {Stdout: "someResourceDir"}, 340 okResult, 341 okResult, 342 }, 343 }, 344 { 345 WrapperCmd: newGoldenCmd(clangX86_64, mainCc), 346 Env: []string{tidyEnv, gomaEnv}, 347 Cmds: []commandResult{ 348 {Stdout: "someResourceDir"}, 349 okResult, 350 okResult, 351 }, 352 }, 353 { 354 WrapperCmd: newGoldenCmd(clangX86_64, mainCc), 355 Env: []string{tidyEnv, gomaEnv}, 356 Cmds: []commandResult{ 357 {Stdout: "someResourceDir"}, 358 errorResult, 359 // TODO: we don't fail the compilation due to clang-tidy, as that 360 // is the behavior in the old wrapper. Consider changing this in 361 // the future. 362 okResult, 363 }, 364 }, 365 { 366 WrapperCmd: newGoldenCmd(clangX86_64, mainCc), 367 Env: []string{tidyEnv, gomaEnv}, 368 Cmds: []commandResult{ 369 {Stdout: "someResourceDir"}, 370 okResult, 371 errorResult, 372 }, 373 }, 374 }, 375 } 376} 377 378func createClangSyntaxGoldenInputs(gomaEnv string) goldenFile { 379 return goldenFile{ 380 Name: "gcc_clang_syntax.json", 381 Records: []goldenRecord{ 382 { 383 WrapperCmd: newGoldenCmd(gccX86_64, "-clang-syntax", mainCc), 384 Cmds: []commandResult{ 385 okResult, 386 okResult, 387 }, 388 }, 389 { 390 WrapperCmd: newGoldenCmd(gccX86_64, "-clang-syntax", mainCc), 391 Env: []string{gomaEnv}, 392 Cmds: []commandResult{ 393 okResult, 394 okResult, 395 }, 396 }, 397 { 398 WrapperCmd: newGoldenCmd(gccX86_64, "-clang-syntax", mainCc), 399 Cmds: errorResults, 400 }, 401 { 402 WrapperCmd: newGoldenCmd(gccX86_64, "-clang-syntax", mainCc), 403 Cmds: []commandResult{ 404 okResult, 405 errorResult, 406 }, 407 }, 408 }, 409 } 410} 411 412func createSysrootWrapperCommonGoldenInputs(compiler string, gomaEnv string) goldenFile { 413 // We are using a fixed target as all of the following args are target independent. 414 wrapperPath := "./x86_64-cros-linux-gnu-" + compiler 415 return goldenFile{ 416 Name: compiler + "_sysroot_wrapper_common.json", 417 Records: []goldenRecord{ 418 { 419 WrapperCmd: newGoldenCmd(gccX86_64, "-noccache", mainCc), 420 Cmds: okResults, 421 }, 422 { 423 WrapperCmd: newGoldenCmd(wrapperPath, mainCc), 424 Env: []string{"GOMACC_PATH=someNonExistingPath"}, 425 Cmds: okResults, 426 }, 427 { 428 WrapperCmd: newGoldenCmd(wrapperPath, mainCc), 429 Env: []string{gomaEnv}, 430 Cmds: okResults, 431 }, 432 { 433 WrapperCmd: newGoldenCmd(wrapperPath, "-nopie", mainCc), 434 Cmds: okResults, 435 }, 436 { 437 WrapperCmd: newGoldenCmd(wrapperPath, "-D__KERNEL__", mainCc), 438 Cmds: okResults, 439 }, 440 { 441 WrapperCmd: newGoldenCmd("./armv7a-cros-linux-gnueabihf-"+compiler, 442 "-D__KERNEL__", mainCc), 443 Cmds: okResults, 444 }, 445 { 446 WrapperCmd: newGoldenCmd(wrapperPath, "--sysroot=xyz", mainCc), 447 Cmds: okResults, 448 }, 449 }, 450 } 451} 452 453func createSanitizerGoldenInputs(compiler string) goldenFile { 454 // We are using a fixed target as all of the following args are target independent. 455 wrapperPath := "./x86_64-cros-linux-gnu-" + compiler 456 return goldenFile{ 457 Name: compiler + "_sanitizer_args.json", 458 Records: []goldenRecord{ 459 { 460 WrapperCmd: newGoldenCmd(wrapperPath, "-fsanitize=kernel-address", "-Wl,--no-undefined", mainCc), 461 Cmds: okResults, 462 }, 463 { 464 WrapperCmd: newGoldenCmd(wrapperPath, "-fsanitize=kernel-address", "-Wl,-z,defs", mainCc), 465 Cmds: okResults, 466 }, 467 { 468 WrapperCmd: newGoldenCmd(wrapperPath, "-fsanitize=kernel-address", "-D_FORTIFY_SOURCE=1", mainCc), 469 Cmds: okResults, 470 }, 471 { 472 WrapperCmd: newGoldenCmd(wrapperPath, "-fsanitize=kernel-address", "-D_FORTIFY_SOURCE=2", mainCc), 473 Cmds: okResults, 474 }, 475 { 476 WrapperCmd: newGoldenCmd(wrapperPath, "-fsanitize=fuzzer", mainCc), 477 Cmds: okResults, 478 }, 479 { 480 WrapperCmd: newGoldenCmd(wrapperPath, "-fsanitize=address", "-fprofile-instr-generate", mainCc), 481 Cmds: okResults, 482 }, 483 { 484 WrapperCmd: newGoldenCmd(wrapperPath, "-fsanitize=address", mainCc), 485 Cmds: okResults, 486 }, 487 { 488 WrapperCmd: newGoldenCmd(wrapperPath, "-fprofile-instr-generate", mainCc), 489 Cmds: okResults, 490 }, 491 }, 492 } 493} 494 495func createGccArgsGoldenInputs() goldenFile { 496 return goldenFile{ 497 Name: "gcc_specific_args.json", 498 Records: []goldenRecord{ 499 { 500 WrapperCmd: newGoldenCmd(gccX86_64, "-march=goldmont", mainCc), 501 Cmds: okResults, 502 }, 503 { 504 WrapperCmd: newGoldenCmd(gccX86_64, "-march=goldmont-plus", mainCc), 505 Cmds: okResults, 506 }, 507 { 508 WrapperCmd: newGoldenCmd(gccX86_64, "-march=skylake", mainCc), 509 Cmds: okResults, 510 }, 511 }, 512 } 513} 514 515func createClangArgsGoldenInputs() goldenFile { 516 return goldenFile{ 517 Name: "clang_specific_args.json", 518 Records: []goldenRecord{ 519 { 520 WrapperCmd: newGoldenCmd(clangX86_64, "-mno-movbe", "-pass-exit-codes", "-Wclobbered", "-Wno-psabi", "-Wlogical-op", 521 "-Wmissing-parameter-type", "-Wold-style-declaration", "-Woverride-init", "-Wunsafe-loop-optimizations", 522 "-Wstrict-aliasing=abc", "-finline-limit=abc", mainCc), 523 Cmds: okResults, 524 }, 525 { 526 WrapperCmd: newGoldenCmd(clangX86_64, "-Wno-error=cpp", mainCc), 527 Cmds: okResults, 528 }, 529 { 530 WrapperCmd: newGoldenCmd(clangX86_64, "-Wno-error=maybe-uninitialized", mainCc), 531 Cmds: okResults, 532 }, 533 { 534 WrapperCmd: newGoldenCmd(clangX86_64, "-Wno-error=unused-but-set-variable", mainCc), 535 Cmds: okResults, 536 }, 537 { 538 WrapperCmd: newGoldenCmd(clangX86_64, "-Wno-unused-but-set-variable", mainCc), 539 Cmds: okResults, 540 }, 541 { 542 WrapperCmd: newGoldenCmd(clangX86_64, "-Wunused-but-set-variable", mainCc), 543 Cmds: okResults, 544 }, 545 { 546 WrapperCmd: newGoldenCmd(clangX86_64, "-Xclang-only=-someflag", mainCc), 547 Cmds: okResults, 548 }, 549 }, 550 } 551} 552