252 lines
8.0 KiB
Go
252 lines
8.0 KiB
Go
// Copyright 2019 The Chromium OS Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
package main
|
|
|
|
import (
|
|
"os"
|
|
"path"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestCommandlineFlagParsing(t *testing.T) {
|
|
withTestContext(t, func(ctx *testContext) {
|
|
type testCase struct {
|
|
extraFlags []string
|
|
// If this is nonempty, expectedValue is ignored. Otherwise, expectedValue
|
|
// has the expected value for the flag, and expectedCommand has the expected
|
|
// (extra) flags in the builder after filtering.
|
|
expectedError string
|
|
expectedValue string
|
|
expectedExtraFlags []string
|
|
}
|
|
|
|
const flagName = "--flag"
|
|
testCases := []testCase{
|
|
{
|
|
extraFlags: nil,
|
|
expectedError: errNoSuchCmdlineArg.Error(),
|
|
},
|
|
{
|
|
extraFlags: []string{flagName + "a"},
|
|
expectedError: errNoSuchCmdlineArg.Error(),
|
|
},
|
|
{
|
|
extraFlags: []string{flagName},
|
|
expectedError: "flag \"" + flagName + "\" requires a value",
|
|
},
|
|
{
|
|
extraFlags: []string{flagName, "foo"},
|
|
expectedValue: "foo",
|
|
expectedExtraFlags: nil,
|
|
},
|
|
{
|
|
extraFlags: []string{flagName + "=foo"},
|
|
expectedValue: "foo",
|
|
expectedExtraFlags: nil,
|
|
},
|
|
{
|
|
extraFlags: []string{flagName + "="},
|
|
expectedValue: "",
|
|
expectedExtraFlags: nil,
|
|
},
|
|
{
|
|
extraFlags: []string{flagName + "=foo", flagName + "=bar"},
|
|
expectedValue: "foo",
|
|
expectedExtraFlags: []string{flagName + "=bar"},
|
|
},
|
|
}
|
|
|
|
for _, testCase := range testCases {
|
|
cmd := ctx.newCommand(gccX86_64, testCase.extraFlags...)
|
|
builder, err := newCommandBuilder(ctx, ctx.cfg, cmd)
|
|
if err != nil {
|
|
t.Fatalf("Failed creating a command builder: %v", err)
|
|
}
|
|
|
|
flagValue, err := removeOneUserCmdlineFlagWithValue(builder, flagName)
|
|
if err != nil {
|
|
if testCase.expectedError == "" {
|
|
t.Errorf("given extra flags %q, got unexpected error removing %q: %v", testCase.extraFlags, flagName, err)
|
|
continue
|
|
}
|
|
|
|
if e := err.Error(); e != testCase.expectedError {
|
|
t.Errorf("given extra flags %q, got error %q; wanted %q", testCase.extraFlags, e, testCase.expectedError)
|
|
}
|
|
continue
|
|
}
|
|
|
|
if testCase.expectedError != "" {
|
|
t.Errorf("given extra flags %q, got no error, but expected %q", testCase.extraFlags, testCase.expectedError)
|
|
continue
|
|
}
|
|
|
|
if flagValue != testCase.expectedValue {
|
|
t.Errorf("given extra flags %q, got value %q, but expected %q", testCase.extraFlags, flagValue, testCase.expectedValue)
|
|
}
|
|
|
|
currentFlags := []string{}
|
|
// Chop off the first arg, which should just be the compiler
|
|
for _, a := range builder.args {
|
|
currentFlags = append(currentFlags, a.value)
|
|
}
|
|
|
|
sameFlags := (len(currentFlags) == 0 && len(testCase.expectedExtraFlags) == 0) || reflect.DeepEqual(currentFlags, testCase.expectedExtraFlags)
|
|
if !sameFlags {
|
|
t.Errorf("given extra flags %q, got post-removal flags %q, but expected %q", testCase.extraFlags, currentFlags, testCase.expectedExtraFlags)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestCallGomaccIfEnvIsGivenAndValid(t *testing.T) {
|
|
withGomaccTestContext(t, func(ctx *testContext, gomaPath string) {
|
|
ctx.env = []string{"GOMACC_PATH=" + gomaPath}
|
|
cmd := ctx.must(callCompiler(ctx, ctx.cfg,
|
|
ctx.newCommand(gccX86_64, mainCc)))
|
|
if err := verifyPath(cmd, gomaPath); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := verifyArgOrder(cmd, gccX86_64+".real", mainCc); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestOmitGomaccIfEnvIsGivenButInvalid(t *testing.T) {
|
|
withGomaccTestContext(t, func(ctx *testContext, gomaPath string) {
|
|
if err := os.Remove(gomaPath); err != nil {
|
|
t.Fatalf("failed removing fake goma file at %q: %v", gomaPath, err)
|
|
}
|
|
|
|
ctx.env = []string{"GOMACC_PATH=" + gomaPath}
|
|
cmd := ctx.must(callCompiler(ctx, ctx.cfg,
|
|
ctx.newCommand(gccX86_64, mainCc)))
|
|
if err := verifyPath(cmd, gccX86_64+".real"); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestCallGomaccIfArgIsGivenAndValid(t *testing.T) {
|
|
withGomaccTestContext(t, func(ctx *testContext, gomaPath string) {
|
|
cmd := ctx.must(callCompiler(ctx, ctx.cfg,
|
|
ctx.newCommand(gccX86_64, mainCc, "--gomacc-path", gomaPath)))
|
|
if err := verifyPath(cmd, gomaPath); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := verifyArgCount(cmd, 0, "--gomacc-path"); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := verifyArgCount(cmd, 0, gomaPath); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := verifyArgOrder(cmd, gccX86_64+".real", mainCc); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestOmitGomaccIfArgIsGivenButInvalid(t *testing.T) {
|
|
withGomaccTestContext(t, func(ctx *testContext, gomaPath string) {
|
|
if err := os.Remove(gomaPath); err != nil {
|
|
t.Fatalf("failed removing fake goma file at %q: %v", gomaPath, err)
|
|
}
|
|
|
|
cmd := ctx.must(callCompiler(ctx, ctx.cfg,
|
|
ctx.newCommand(gccX86_64, mainCc, "--gomacc-path", gomaPath)))
|
|
if err := verifyPath(cmd, gccX86_64+".real"); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestErrorOnGomaccArgWithoutValue(t *testing.T) {
|
|
withTestContext(t, func(ctx *testContext) {
|
|
stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg,
|
|
ctx.newCommand(gccX86_64, mainCc, "--gomacc-path")))
|
|
if err := verifyNonInternalError(stderr, "flag \"--gomacc-path\" requires a value"); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestOmitGomaccByDefault(t *testing.T) {
|
|
withTestContext(t, func(ctx *testContext) {
|
|
cmd := ctx.must(callCompiler(ctx, ctx.cfg,
|
|
ctx.newCommand(gccX86_64, mainCc)))
|
|
if err := verifyPath(cmd, gccX86_64+".real"); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func withGomaccTestContext(t *testing.T, f func(*testContext, string)) {
|
|
withTestContext(t, func(ctx *testContext) {
|
|
gomaPath := path.Join(ctx.tempDir, "gomacc")
|
|
// Create a file so the gomacc path is valid.
|
|
ctx.writeFile(gomaPath, "")
|
|
f(ctx, gomaPath)
|
|
})
|
|
}
|
|
|
|
func TestRewrapperDefersToTheWrapperProperly(t *testing.T) {
|
|
withTestContext(t, func(ctx *testContext) {
|
|
cmd := ctx.must(callCompiler(ctx, ctx.cfg,
|
|
ctx.newCommand(gccX86_64, mainCc, "--rewrapper-path", "/rewrapper", "--rewrapper-cfg", "/some-cfg", "some", "other", "args")))
|
|
if err := verifyPath(cmd, "/rewrapper"); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := verifyArgOrder(cmd, "-cfg", "/some-cfg", gccX86_64+".real", mainCc, "some", "other", "args"); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestRewrapperCfgMustBePrsentIfRewrapperPathIs(t *testing.T) {
|
|
withGomaccTestContext(t, func(ctx *testContext, gomaPath string) {
|
|
stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg,
|
|
ctx.newCommand(gccX86_64, mainCc, "--rewrapper-path", "/rewrapper")))
|
|
if err := verifyNonInternalError(stderr, "--rewrapper-cfg must be specified if --rewrapper-path is"); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestRewrapperPathMustBePrsentIfRewrapperCfgIs(t *testing.T) {
|
|
withGomaccTestContext(t, func(ctx *testContext, gomaPath string) {
|
|
stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg,
|
|
ctx.newCommand(gccX86_64, mainCc, "--rewrapper-cfg", "/some-cfg")))
|
|
if err := verifyNonInternalError(stderr, "--rewrapper-path must be specified if --rewrapper-cfg is"); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestRewrapperAndGomaAreMutuallyExclusive(t *testing.T) {
|
|
withGomaccTestContext(t, func(ctx *testContext, gomaPath string) {
|
|
stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg,
|
|
ctx.newCommand(gccX86_64, mainCc, "--rewrapper-path", "/rewrapper", "--rewrapper-cfg", "/some-cfg", "--gomacc-path", gomaPath)))
|
|
if err := verifyNonInternalError(stderr, "rewrapper and gomacc are mutually exclusive"); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestRewrapperBlocksGomaInheritanceFromEnv(t *testing.T) {
|
|
withGomaccTestContext(t, func(ctx *testContext, gomaPath string) {
|
|
ctx.env = []string{"GOMACC_PATH=" + gomaPath}
|
|
cmd := ctx.must(callCompiler(ctx, ctx.cfg,
|
|
ctx.newCommand(gccX86_64, mainCc, "--rewrapper-path", "/rewrapper", "--rewrapper-cfg", "/some-cfg")))
|
|
if err := verifyPath(cmd, "/rewrapper"); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if err := verifyArgOrder(cmd, "-cfg", "/some-cfg", gccX86_64+".real", mainCc); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
}
|