1*760c253cSXin Li// Copyright 2019 The ChromiumOS Authors 2*760c253cSXin Li// Use of this source code is governed by a BSD-style license that can be 3*760c253cSXin Li// found in the LICENSE file. 4*760c253cSXin Li 5*760c253cSXin Lipackage main 6*760c253cSXin Li 7*760c253cSXin Liimport ( 8*760c253cSXin Li "encoding/json" 9*760c253cSXin Li "errors" 10*760c253cSXin Li "fmt" 11*760c253cSXin Li "io" 12*760c253cSXin Li "io/ioutil" 13*760c253cSXin Li "os" 14*760c253cSXin Li "path/filepath" 15*760c253cSXin Li "regexp" 16*760c253cSXin Li "strings" 17*760c253cSXin Li "testing" 18*760c253cSXin Li) 19*760c253cSXin Li 20*760c253cSXin Lifunc TestForwardStdOutAndStdErrAndExitCodeFromLogRusage(t *testing.T) { 21*760c253cSXin Li withLogRusageTestContext(t, func(ctx *testContext) { 22*760c253cSXin Li ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 23*760c253cSXin Li fmt.Fprint(stdout, "somemessage") 24*760c253cSXin Li fmt.Fprint(stderr, "someerror") 25*760c253cSXin Li return newExitCodeError(23) 26*760c253cSXin Li } 27*760c253cSXin Li exitCode := callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc)) 28*760c253cSXin Li if exitCode != 23 { 29*760c253cSXin Li t.Errorf("unexpected exit code. Got: %d", exitCode) 30*760c253cSXin Li } 31*760c253cSXin Li if ctx.stdoutString() != "somemessage" { 32*760c253cSXin Li t.Errorf("stdout was not forwarded. Got: %s", ctx.stdoutString()) 33*760c253cSXin Li } 34*760c253cSXin Li if ctx.stderrString() != "someerror" { 35*760c253cSXin Li t.Errorf("stderr was not forwarded. Got: %s", ctx.stderrString()) 36*760c253cSXin Li } 37*760c253cSXin Li }) 38*760c253cSXin Li} 39*760c253cSXin Li 40*760c253cSXin Lifunc TestForwardStdinFromLogRusage(t *testing.T) { 41*760c253cSXin Li withLogRusageTestContext(t, func(ctx *testContext) { 42*760c253cSXin Li ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 43*760c253cSXin Li // Note: This is called for the clang syntax call as well as for 44*760c253cSXin Li // the gcc call, and we assert that stdin is cloned and forwarded 45*760c253cSXin Li // to both. 46*760c253cSXin Li stdinStr := ctx.readAllString(stdin) 47*760c253cSXin Li if stdinStr != "someinput" { 48*760c253cSXin Li return fmt.Errorf("unexpected stdin. Got: %s", stdinStr) 49*760c253cSXin Li } 50*760c253cSXin Li return nil 51*760c253cSXin Li } 52*760c253cSXin Li io.WriteString(&ctx.stdinBuffer, "someinput") 53*760c253cSXin Li ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangX86_64, "-", mainCc))) 54*760c253cSXin Li }) 55*760c253cSXin Li} 56*760c253cSXin Li 57*760c253cSXin Lifunc TestReportGeneralErrorsFromLogRusage(t *testing.T) { 58*760c253cSXin Li withLogRusageTestContext(t, func(ctx *testContext) { 59*760c253cSXin Li ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 60*760c253cSXin Li return errors.New("someerror") 61*760c253cSXin Li } 62*760c253cSXin Li stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg, 63*760c253cSXin Li ctx.newCommand(gccX86_64, mainCc))) 64*760c253cSXin Li if err := verifyInternalError(stderr); err != nil { 65*760c253cSXin Li t.Fatal(err) 66*760c253cSXin Li } 67*760c253cSXin Li if !strings.Contains(stderr, "someerror") { 68*760c253cSXin Li t.Errorf("unexpected error. Got: %s", stderr) 69*760c253cSXin Li } 70*760c253cSXin Li }) 71*760c253cSXin Li} 72*760c253cSXin Li 73*760c253cSXin Lifunc TestCreateDirAndFileForLogRusage(t *testing.T) { 74*760c253cSXin Li withLogRusageTestContext(t, func(ctx *testContext) { 75*760c253cSXin Li logFileName := filepath.Join(ctx.tempDir, "somedir", "rusage.log") 76*760c253cSXin Li ctx.env = []string{"TOOLCHAIN_RUSAGE_OUTPUT=" + logFileName} 77*760c253cSXin Li ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) 78*760c253cSXin Li 79*760c253cSXin Li if _, err := os.Stat(logFileName); err != nil { 80*760c253cSXin Li t.Errorf("rusage log file does not exist: %s", err) 81*760c253cSXin Li } 82*760c253cSXin Li }) 83*760c253cSXin Li} 84*760c253cSXin Li 85*760c253cSXin Lifunc TestLogRusageFileContent(t *testing.T) { 86*760c253cSXin Li withLogRusageTestContext(t, func(ctx *testContext) { 87*760c253cSXin Li logFileName := filepath.Join(ctx.tempDir, "rusage.log") 88*760c253cSXin Li ctx.env = []string{"TOOLCHAIN_RUSAGE_OUTPUT=" + logFileName} 89*760c253cSXin Li ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) 90*760c253cSXin Li 91*760c253cSXin Li data, err := ioutil.ReadFile(logFileName) 92*760c253cSXin Li if err != nil { 93*760c253cSXin Li t.Errorf("could not read the rusage log file. Error: %s", err) 94*760c253cSXin Li } 95*760c253cSXin Li 96*760c253cSXin Li rlog := rusageLog{} 97*760c253cSXin Li 98*760c253cSXin Li if err := json.Unmarshal(data, &rlog); err != nil { 99*760c253cSXin Li t.Fatalf("rusage log could not be unmarshalled. Got: %s", data) 100*760c253cSXin Li } 101*760c253cSXin Li 102*760c253cSXin Li if rlog.Compiler != filepath.Join(ctx.tempDir, gccX86_64+".real") { 103*760c253cSXin Li t.Errorf("unexpected compiler path. Got: %s", rlog.Compiler) 104*760c253cSXin Li } 105*760c253cSXin Li if matched, _ := regexp.MatchString("--sysroot=.*", rlog.CompilerArgs[0]); !matched { 106*760c253cSXin Li t.Errorf("unexpected compiler args. Got: %s", rlog.CompilerArgs) 107*760c253cSXin Li } 108*760c253cSXin Li cwd, err := os.Getwd() 109*760c253cSXin Li if err != nil { 110*760c253cSXin Li t.Fatalf("Failed to get current working directory: %v", err) 111*760c253cSXin Li } 112*760c253cSXin Li if rlog.WorkingDirectory != cwd { 113*760c253cSXin Li t.Errorf("Unexpected working directory. Got: %q, Want: %q", rlog.WorkingDirectory, cwd) 114*760c253cSXin Li } 115*760c253cSXin Li }) 116*760c253cSXin Li} 117*760c253cSXin Li 118*760c253cSXin Lifunc TestLogRusageAppendsToFile(t *testing.T) { 119*760c253cSXin Li withLogRusageTestContext(t, func(ctx *testContext) { 120*760c253cSXin Li logFileName := filepath.Join(ctx.tempDir, "rusage.log") 121*760c253cSXin Li ctx.env = []string{"TOOLCHAIN_RUSAGE_OUTPUT=" + logFileName} 122*760c253cSXin Li 123*760c253cSXin Li ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) 124*760c253cSXin Li data, err := ioutil.ReadFile(logFileName) 125*760c253cSXin Li if err != nil { 126*760c253cSXin Li t.Errorf("could not read the rusage log file. Error: %s", err) 127*760c253cSXin Li } 128*760c253cSXin Li firstCallLines := strings.Split(string(data), "\n") 129*760c253cSXin Li if len(firstCallLines) != 2 { 130*760c253cSXin Li t.Errorf("unexpected number of lines. Got: %s", firstCallLines) 131*760c253cSXin Li } 132*760c253cSXin Li if firstCallLines[0] == "" { 133*760c253cSXin Li t.Error("first line was empty") 134*760c253cSXin Li } 135*760c253cSXin Li if firstCallLines[1] != "" { 136*760c253cSXin Li t.Errorf("second line was not empty. Got: %s", firstCallLines[1]) 137*760c253cSXin Li } 138*760c253cSXin Li 139*760c253cSXin Li ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) 140*760c253cSXin Li data, err = ioutil.ReadFile(logFileName) 141*760c253cSXin Li if err != nil { 142*760c253cSXin Li t.Errorf("could not read the rusage log file. Error: %s", err) 143*760c253cSXin Li } 144*760c253cSXin Li secondCallLines := strings.Split(string(data), "\n") 145*760c253cSXin Li if len(secondCallLines) != 3 { 146*760c253cSXin Li t.Errorf("unexpected number of lines. Got: %s", secondCallLines) 147*760c253cSXin Li } 148*760c253cSXin Li if secondCallLines[0] != firstCallLines[0] { 149*760c253cSXin Li t.Errorf("first line was changed. Got: %s", secondCallLines[0]) 150*760c253cSXin Li } 151*760c253cSXin Li if secondCallLines[1] == "" { 152*760c253cSXin Li t.Error("second line was empty") 153*760c253cSXin Li } 154*760c253cSXin Li if secondCallLines[2] != "" { 155*760c253cSXin Li t.Errorf("third line was not empty. Got: %s", secondCallLines[2]) 156*760c253cSXin Li } 157*760c253cSXin Li }) 158*760c253cSXin Li} 159*760c253cSXin Li 160*760c253cSXin Lifunc withLogRusageTestContext(t *testing.T, work func(ctx *testContext)) { 161*760c253cSXin Li withTestContext(t, func(ctx *testContext) { 162*760c253cSXin Li ctx.NoteTestWritesToUmask() 163*760c253cSXin Li 164*760c253cSXin Li ctx.env = []string{"TOOLCHAIN_RUSAGE_OUTPUT=" + filepath.Join(ctx.tempDir, "rusage.log")} 165*760c253cSXin Li work(ctx) 166*760c253cSXin Li }) 167*760c253cSXin Li} 168