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 "errors" 9 "fmt" 10 "io" 11 "path" 12 "strings" 13 "testing" 14) 15 16func TestCheckClangSyntaxByNestedCall(t *testing.T) { 17 withTestContext(t, func(ctx *testContext) { 18 ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 19 if ctx.cmdCount == 1 { 20 if err := verifyPath(cmd, "usr/bin/clang"); err != nil { 21 return err 22 } 23 if err := verifyArgOrder(cmd, mainCc, "-fsyntax-only", `-stdlib=libstdc\+\+`); err != nil { 24 return err 25 } 26 } 27 return nil 28 } 29 cmd := ctx.must(callCompiler(ctx, ctx.cfg, 30 ctx.newCommand(gccX86_64, "-clang-syntax", mainCc))) 31 if ctx.cmdCount != 2 { 32 t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount) 33 } 34 if err := verifyPath(cmd, gccX86_64+".real"); err != nil { 35 t.Error(err) 36 } 37 if err := verifyArgCount(cmd, 0, "-clang-syntax"); err != nil { 38 t.Error(err) 39 } 40 }) 41} 42 43func TestForwardStdOutAndStderrFromClangSyntaxCheck(t *testing.T) { 44 withTestContext(t, func(ctx *testContext) { 45 ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 46 if ctx.cmdCount == 1 { 47 fmt.Fprint(stdout, "somemessage") 48 fmt.Fprint(stderr, "someerror") 49 } 50 return nil 51 } 52 ctx.must(callCompiler(ctx, ctx.cfg, 53 ctx.newCommand(gccX86_64, "-clang-syntax", mainCc))) 54 if ctx.stdoutString() != "somemessage" { 55 t.Errorf("stdout was not forwarded. Got: %s", ctx.stdoutString()) 56 } 57 if ctx.stderrString() != "someerror" { 58 t.Errorf("stderr was not forwarded. Got: %s", ctx.stderrString()) 59 } 60 }) 61} 62 63func TestForwardStdinToClangSyntaxCheck(t *testing.T) { 64 withTestContext(t, func(ctx *testContext) { 65 ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 66 // Note: This is called for the clang syntax call as well as for 67 // the gcc call, and we assert that stdin is cloned and forwarded 68 // to both. 69 stdinStr := ctx.readAllString(stdin) 70 if stdinStr != "someinput" { 71 return fmt.Errorf("unexpected stdin. Got: %s", stdinStr) 72 } 73 return nil 74 } 75 io.WriteString(&ctx.stdinBuffer, "someinput") 76 ctx.must(callCompiler(ctx, ctx.cfg, 77 ctx.newCommand(gccX86_64, "-clang-syntax", "-", mainCc))) 78 }) 79} 80 81func TestForwardExitCodeFromClangSyntaxCheck(t *testing.T) { 82 withTestContext(t, func(ctx *testContext) { 83 ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 84 if ctx.cmdCount == 1 { 85 return newExitCodeError(23) 86 } 87 return nil 88 } 89 exitCode := callCompiler(ctx, ctx.cfg, 90 ctx.newCommand(gccX86_64, "-clang-syntax", mainCc)) 91 if exitCode != 23 { 92 t.Errorf("unexpected exit code. Got: %d", exitCode) 93 } 94 }) 95} 96 97func TestReportGeneralErrorsFromClangSyntaxCheck(t *testing.T) { 98 withTestContext(t, func(ctx *testContext) { 99 ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 100 if ctx.cmdCount == 1 { 101 return errors.New("someerror") 102 } 103 return nil 104 } 105 stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg, 106 ctx.newCommand(gccX86_64, "-clang-syntax", mainCc))) 107 if err := verifyInternalError(stderr); err != nil { 108 t.Fatal(err) 109 } 110 if !strings.Contains(stderr, "someerror") { 111 t.Errorf("unexpected error. Got: %s", stderr) 112 } 113 }) 114} 115 116func TestIgnoreClangSyntaxCheckWhenCallingClang(t *testing.T) { 117 withTestContext(t, func(ctx *testContext) { 118 ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 119 if ctx.cmdCount > 1 { 120 return fmt.Errorf("Unexpected call %#v", cmd) 121 } 122 return nil 123 } 124 cmd := ctx.must(callCompiler(ctx, ctx.cfg, 125 ctx.newCommand(clangX86_64, "-clang-syntax", mainCc))) 126 if err := verifyArgCount(cmd, 0, "-clang-syntax"); err != nil { 127 t.Error(err) 128 } 129 }) 130} 131 132func TestUseGomaForClangSyntaxCheck(t *testing.T) { 133 withTestContext(t, func(ctx *testContext) { 134 gomaPath := path.Join(ctx.tempDir, "gomacc") 135 // Create a file so the gomacc path is valid. 136 ctx.writeFile(gomaPath, "") 137 ctx.env = []string{"GOMACC_PATH=" + gomaPath} 138 ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 139 if ctx.cmdCount == 1 { 140 if err := verifyPath(cmd, gomaPath); err != nil { 141 return err 142 } 143 if err := verifyArgOrder(cmd, "usr/bin/clang", mainCc); err != nil { 144 return err 145 } 146 } 147 return nil 148 } 149 cmd := ctx.must(callCompiler(ctx, ctx.cfg, 150 ctx.newCommand(gccX86_64, "-clang-syntax", mainCc))) 151 if ctx.cmdCount != 2 { 152 t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount) 153 } 154 if err := verifyPath(cmd, gomaPath); err != nil { 155 t.Error(err) 156 } 157 }) 158} 159 160func TestPartiallyOmitCCacheForClangSyntaxCheck(t *testing.T) { 161 withTestContext(t, func(ctx *testContext) { 162 ctx.cfg.useCCache = true 163 ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 164 if ctx.cmdCount == 1 { 165 if err := verifyPath(cmd, "usr/bin/clang"); err != nil { 166 return err 167 } 168 } 169 return nil 170 } 171 cmd := ctx.must(callCompiler(ctx, ctx.cfg, 172 ctx.newCommand(gccX86_64, "-clang-syntax", mainCc))) 173 if ctx.cmdCount != 2 { 174 t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount) 175 } 176 if err := verifyPath(cmd, "/usr/bin/ccache"); err != nil { 177 t.Error(err) 178 } 179 }) 180} 181