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