aboutsummaryrefslogtreecommitdiff
path: root/compiler_wrapper/testutil_test.go
diff options
context:
space:
mode:
authorTobias Bosch <tbosch@google.com>2019-06-10 15:50:33 -0700
committerTobias Bosch <tbosch@google.com>2019-06-20 15:41:37 +0000
commitef8f969c8ea2498c2a8aa701cb2e83833339f9a8 (patch)
treea3c988999263f4e43ec561908b452093ad169b53 /compiler_wrapper/testutil_test.go
parent87d457dfc5ae0a7631917523eb3c62751453e4bb (diff)
downloadtoolchain-utils-ef8f969c8ea2498c2a8aa701cb2e83833339f9a8.tar.gz
Initial version of a go version of the compiler wrapper.
Still calls the old wrapper if one of the following flags is given: - Xclang-path - clang-syntax - env WITH_TIDY - env FORCE_DISABLE_WERROR - env GETRUSAGE - env BISECT_STAGE BUG=chromium:773875 TEST=Unit tests that also verify the produced command against the TEST=existing compiler wrapper. Change-Id: I1e0a720ce9f485d8015deefb2682f2cb760d82e4 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/1652057 Reviewed-by: Manoj Gupta <manojgupta@chromium.org> Reviewed-by: Tobias Bosch <tbosch@google.com> Reviewed-by: George Burgess <gbiv@chromium.org> Tested-by: Tobias Bosch <tbosch@google.com> Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
Diffstat (limited to 'compiler_wrapper/testutil_test.go')
-rw-r--r--compiler_wrapper/testutil_test.go193
1 files changed, 193 insertions, 0 deletions
diff --git a/compiler_wrapper/testutil_test.go b/compiler_wrapper/testutil_test.go
new file mode 100644
index 00000000..5ebe0084
--- /dev/null
+++ b/compiler_wrapper/testutil_test.go
@@ -0,0 +1,193 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "regexp"
+ "strings"
+ "testing"
+)
+
+var crosRootDirFlag = flag.String("crosroot", "", "root dir of the chrome os toolchain")
+
+const mainCc = "main.cc"
+const clangX86_64 = "./x86_64-cros-linux-gnu-clang"
+const gccX86_64 = "./x86_64-cros-linux-gnu-gcc"
+const gccX86_64Eabi = "./x86_64-cros-linux-eabi-gcc"
+const gccArmV7 = "./armv7m-cros-linux-gnu-gcc"
+const gccArmV7Eabi = "./armv7m-cros-linux-eabi-gcc"
+const gccArmV8 = "./armv8m-cros-linux-gnu-gcc"
+const gccArmV8Eabi = "./armv8m-cros-linux-eabi-gcc"
+
+const oldHardenedWrapperPathForTest = "/usr/x86_64-pc-linux-gnu/x86_64-cros-linux-gnu/gcc-bin/4.9.x/sysroot_wrapper.hardened"
+const oldNonHardenedWrapperPathForTest = "/usr/x86_64-pc-linux-gnu/arm-none-eabi/gcc-bin/4.9.x/sysroot_wrapper"
+
+type testContext struct {
+ t *testing.T
+ tempDir string
+ env []string
+ cfg *config
+}
+
+func withTestContext(t *testing.T, work func(ctx *testContext)) {
+ t.Parallel()
+ tempDir, err := ioutil.TempDir("", "compiler_wrapper")
+ if err != nil {
+ t.Fatalf("Unable to create the temp dir. Error: %s", err)
+ }
+ defer os.RemoveAll(tempDir)
+
+ ctx := testContext{
+ t: t,
+ tempDir: tempDir,
+ env: nil,
+ cfg: &config{
+ oldWrapperPath: "FilledLater",
+ overrideOldWrapperConfig: true,
+ },
+ }
+ // Note: It's ok to use the hardened wrapper here, as we replace its config
+ // on each run.
+ ctx.setOldWrapperPath(oldHardenedWrapperPathForTest)
+
+ work(&ctx)
+}
+
+var _ env = (*testContext)(nil)
+
+func (ctx *testContext) getenv(key string) string {
+ for i := len(ctx.env) - 1; i >= 0; i-- {
+ entry := ctx.env[i]
+ if strings.HasPrefix(entry, key+"=") {
+ return entry[len(key)+1:]
+ }
+ }
+ return ""
+}
+
+func (ctx *testContext) environ() []string {
+ return ctx.env
+}
+
+func (ctx *testContext) getwd() string {
+ return ctx.tempDir
+}
+
+func (ctx *testContext) must(cmd *command, err error) *command {
+ if err != nil {
+ ctx.t.Fatalf("Expected no error, but got %s", err)
+ }
+ return cmd
+}
+
+func (ctx *testContext) setOldWrapperPath(chrootPath string) {
+ if *crosRootDirFlag != "" {
+ ctx.cfg.oldWrapperPath = filepath.Join(*crosRootDirFlag, chrootPath)
+ } else {
+ ctx.cfg.oldWrapperPath = ""
+ }
+}
+
+func (ctx *testContext) newCommand(path string, args ...string) *command {
+ // Create an empty wrapper at the given path.
+ // Needed as we are resolving symlinks which stats the wrapper file.
+ ctx.writeFile(path, "")
+ return &command{
+ path: path,
+ args: args,
+ }
+}
+
+func (ctx *testContext) writeFile(fullFileName string, fileContent string) {
+ if !filepath.IsAbs(fullFileName) {
+ fullFileName = filepath.Join(ctx.tempDir, fullFileName)
+ }
+ if err := os.MkdirAll(filepath.Dir(fullFileName), 0777); err != nil {
+ ctx.t.Fatal(err)
+ }
+ if err := ioutil.WriteFile(fullFileName, []byte(fileContent), 0777); err != nil {
+ ctx.t.Fatal(err)
+ }
+}
+
+func (ctx *testContext) symlink(oldname string, newname string) {
+ if err := os.MkdirAll(filepath.Dir(newname), 0777); err != nil {
+ ctx.t.Fatal(err)
+ }
+ if err := os.Symlink(oldname, newname); err != nil {
+ ctx.t.Fatal(err)
+ }
+}
+
+func verifyPath(cmd *command, expectedRegex string) error {
+ compiledRegex := regexp.MustCompile(matchFullString(expectedRegex))
+ if !compiledRegex.MatchString(cmd.path) {
+ return fmt.Errorf("path does not match %s. Actual %s", expectedRegex, cmd.path)
+ }
+ return nil
+}
+
+func verifyArgCount(cmd *command, expectedCount int, expectedRegex string) error {
+ compiledRegex := regexp.MustCompile(matchFullString(expectedRegex))
+ count := 0
+ for _, arg := range cmd.args {
+ if compiledRegex.MatchString(arg) {
+ count++
+ }
+ }
+ if count != expectedCount {
+ return fmt.Errorf("expected %d matches for arg %s. All args: %s",
+ expectedCount, expectedRegex, cmd.args)
+ }
+ return nil
+}
+
+func verifyArgOrder(cmd *command, expectedRegexes ...string) error {
+ compiledRegexes := []*regexp.Regexp{}
+ for _, regex := range expectedRegexes {
+ compiledRegexes = append(compiledRegexes, regexp.MustCompile(matchFullString(regex)))
+ }
+ expectedArgIndex := 0
+ for _, arg := range cmd.args {
+ if expectedArgIndex == len(compiledRegexes) {
+ break
+ } else if compiledRegexes[expectedArgIndex].MatchString(arg) {
+ expectedArgIndex++
+ }
+ }
+ if expectedArgIndex != len(expectedRegexes) {
+ return fmt.Errorf("expected args %s in order. All args: %s",
+ expectedRegexes, cmd.args)
+ }
+ return nil
+}
+
+func verifyEnvUpdate(cmd *command, expectedRegex string) error {
+ compiledRegex := regexp.MustCompile(matchFullString(expectedRegex))
+ for _, update := range cmd.envUpdates {
+ if compiledRegex.MatchString(update) {
+ return nil
+ }
+ }
+ return fmt.Errorf("expected at least one match for env update %s. All env updates: %s",
+ expectedRegex, cmd.envUpdates)
+}
+
+func verifyNoEnvUpdate(cmd *command, expectedRegex string) error {
+ compiledRegex := regexp.MustCompile(matchFullString(expectedRegex))
+ updates := cmd.envUpdates
+ for _, update := range updates {
+ if compiledRegex.MatchString(update) {
+ return fmt.Errorf("expected no match for env update %s. All env updates: %s",
+ expectedRegex, cmd.envUpdates)
+ }
+ }
+ return nil
+}
+
+func matchFullString(regex string) string {
+ return "^" + regex + "$"
+}