1*760c253cSXin Li// Copyright 2021 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 Lipackage main 5*760c253cSXin Li 6*760c253cSXin Liimport ( 7*760c253cSXin Li "errors" 8*760c253cSXin Li "io" 9*760c253cSXin Li "testing" 10*760c253cSXin Li) 11*760c253cSXin Li 12*760c253cSXin Lifunc getErrorIndicatingKernelBug() error { 13*760c253cSXin Li return errors.New("waitid: errno 512") 14*760c253cSXin Li} 15*760c253cSXin Li 16*760c253cSXin Lifunc TestWrapperRetriesCompilationsOnApparentKernelBugsSurfacedInGo(t *testing.T) { 17*760c253cSXin Li withTestContext(t, func(ctx *testContext) { 18*760c253cSXin Li ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 19*760c253cSXin Li switch { 20*760c253cSXin Li case ctx.cmdCount < kernelBugRetryLimit: 21*760c253cSXin Li return getErrorIndicatingKernelBug() 22*760c253cSXin Li 23*760c253cSXin Li case ctx.cmdCount == kernelBugRetryLimit: 24*760c253cSXin Li return nil 25*760c253cSXin Li 26*760c253cSXin Li default: 27*760c253cSXin Li t.Fatalf("unexpected command: %#v", cmd) 28*760c253cSXin Li return nil 29*760c253cSXin Li } 30*760c253cSXin Li } 31*760c253cSXin Li ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) 32*760c253cSXin Li if ctx.cmdCount != kernelBugRetryLimit { 33*760c253cSXin Li t.Errorf("expected %d retries. Got: %d", kernelBugRetryLimit, ctx.cmdCount) 34*760c253cSXin Li } 35*760c253cSXin Li }) 36*760c253cSXin Li} 37*760c253cSXin Li 38*760c253cSXin Lifunc TestWrapperRetriesCompilationsOnApparentKernelBugsSurfacedInGCC(t *testing.T) { 39*760c253cSXin Li withTestContext(t, func(ctx *testContext) { 40*760c253cSXin Li ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 41*760c253cSXin Li if ctx.cmdCount >= kernelBugRetryLimit { 42*760c253cSXin Li return nil 43*760c253cSXin Li } 44*760c253cSXin Li _, err := io.WriteString(stderr, "fatal error: failed to get exit status: Unknown error 512") 45*760c253cSXin Li if err != nil { 46*760c253cSXin Li t.Fatalf("Failed writing to stdout: %v", err) 47*760c253cSXin Li } 48*760c253cSXin Li return newExitCodeError(1) 49*760c253cSXin Li } 50*760c253cSXin Li ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) 51*760c253cSXin Li if ctx.cmdCount != kernelBugRetryLimit { 52*760c253cSXin Li t.Errorf("expected %d retries. Got: %d", kernelBugRetryLimit, ctx.cmdCount) 53*760c253cSXin Li } 54*760c253cSXin Li }) 55*760c253cSXin Li} 56*760c253cSXin Li 57*760c253cSXin Lifunc TestWrapperOnlyRetriesCompilationAFiniteNumberOfTimes(t *testing.T) { 58*760c253cSXin Li withTestContext(t, func(ctx *testContext) { 59*760c253cSXin Li kernelBugErr := getErrorIndicatingKernelBug() 60*760c253cSXin Li ctx.cmdMock = func(cmd *command, stdin io.Reader, stdout io.Writer, stderr io.Writer) error { 61*760c253cSXin Li if ctx.cmdCount > kernelBugRetryLimit { 62*760c253cSXin Li t.Fatal("command count exceeded kernel bug retry limit; infinite loop?") 63*760c253cSXin Li } 64*760c253cSXin Li return kernelBugErr 65*760c253cSXin Li } 66*760c253cSXin Li stderr := ctx.mustFail(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) 67*760c253cSXin Li if err := verifyInternalError(stderr); err != nil { 68*760c253cSXin Li t.Errorf("Internal error wasn't reported: %v", err) 69*760c253cSXin Li } 70*760c253cSXin Li if ctx.cmdCount != kernelBugRetryLimit { 71*760c253cSXin Li t.Errorf("expected %d retries. Got: %d", kernelBugRetryLimit, ctx.cmdCount) 72*760c253cSXin Li } 73*760c253cSXin Li }) 74*760c253cSXin Li} 75