blob: e2db3b4835b2c1365e8e96d97ed5e48c2f64ae63 [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package main
import (
"errors"
"io"
"strings"
"testing"
)
func TestIWYUArgOrder(t *testing.T) {
withIWYUTestContext(t, func(ctx *testContext) {
ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
if ctx.cmdCount == 2 {
if err := verifyArgOrder(cmd, "-checks=.*", mainCc, "--", "-resource-dir=.*", mainCc, "--some_arg"); err != nil {
return err
}
}
return nil
}
ctx.must(callCompiler(ctx, ctx.cfg,
ctx.newCommand(clangX86_64, mainCc, "--some_arg")))
if ctx.cmdCount < 2 {
t.Error("expected multiple calls.")
}
})
}
func TestIgnoreNonZeroExitCodeFromIWYU(t *testing.T) {
withIWYUTestContext(t, func(ctx *testContext) {
ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
if ctx.cmdCount == 2 {
return newExitCodeError(23)
}
return nil
}
ctx.must(callCompiler(ctx, ctx.cfg,
ctx.newCommand(clangX86_64, mainCc)))
stderr := ctx.stderrString()
if err := verifyNonInternalError(stderr, "include-what-you-use failed"); err != nil {
t.Error(err)
}
})
}
func TestReportGeneralErrorsFromIWYU(t *testing.T) {
withIWYUTestContext(t, func(ctx *testContext) {
ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
if ctx.cmdCount > 1 {
return errors.New("someerror")
}
return nil
}
stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg,
ctx.newCommand(clangX86_64, mainCc)))
if err := verifyInternalError(stderr); err != nil {
t.Fatal(err)
}
if !strings.Contains(stderr, "someerror") {
t.Errorf("unexpected error. Got: %s", stderr)
}
})
}
func TestUseIWYUBasedOnFileExtension(t *testing.T) {
withIWYUTestContext(t, func(ctx *testContext) {
testData := []struct {
args []string
iwyu bool
}{
{[]string{"main.cc"}, true},
{[]string{"main.cc"}, true},
{[]string{"main.C"}, true},
{[]string{"main.cxx"}, true},
{[]string{"main.c++"}, true},
{[]string{"main.xy"}, false},
{[]string{"-o", "main.cc"}, false},
{[]string{}, false},
}
for _, tt := range testData {
ctx.cmdCount = 0
ctx.must(callCompiler(ctx, ctx.cfg,
ctx.newCommand(clangX86_64, tt.args...)))
if ctx.cmdCount == 2 && !tt.iwyu {
t.Errorf("expected a call to iwyu but got none for args %s", tt.args)
}
if ctx.cmdCount == 1 && tt.iwyu {
t.Errorf("expected no call to iwyu but got one for args %s", tt.args)
}
}
})
}
func TestIWYUFiltersIWYUFlags(t *testing.T) {
withIWYUTestContext(t, func(ctx *testContext) {
addedFlag := "--some_iwyu_flag=flag"
ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
switch ctx.cmdCount {
case 1:
if err := verifyPath(cmd, "usr/bin/clang"); err != nil {
t.Error(err)
} else if err := verifyArgCount(cmd, 0, addedFlag); err != nil {
t.Error(err)
}
return nil
case 2:
if err := verifyPath(cmd, "usr/bin/include-what-you-use"); err != nil {
t.Error(err)
} else if verifyArgCount(cmd, 1, addedFlag); err != nil {
t.Error(err)
}
return nil
default:
return nil
}
}
cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangX86_64, mainCc, "-iwyu-flag="+addedFlag)))
if ctx.cmdCount < 2 {
t.Errorf("expected multiple calls.")
}
if err := verifyPath(cmd, "usr/bin/clang"); err != nil {
t.Error(err)
}
})
}
func withIWYUTestContext(t *testing.T, work func(ctx *testContext)) {
withTestContext(t, func(ctx *testContext) {
artifactDir := t.TempDir()
ctx.env = []string{"WITH_IWYU=1", "CROS_ARTIFACTS_TMP_DIR=" + artifactDir}
work(ctx)
})
}