Skip to content

Commit cba818f

Browse files
committed
Best-effort attempt to preserve log files in e2e tests
- Tests are tagged with "supports-graceful-termination" so bazel sends a SIGTERM. Bazel still sends a SIGKILL after 5 seconds in this case - TestContext.SetUp installs a signal handler that cancels the test on receiving a SIGINT or SIGTERM - TestContext instances are reused between test runs to preserve the cancelled state - TearDown() is called in a `defer` statement which still runs when the test panics due to Go's `-timeout` flag which is used by bazel. - Commands in TestContext.TearDown are run using context.TODO to escape the possibly-cancelled test context Bug: b/493728561
1 parent 75e592d commit cba818f

20 files changed

Lines changed: 82 additions & 45 deletions

File tree

e2etests/cvd/bugreport_tests/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,6 @@ go_test(
4141
"exclusive",
4242
"external",
4343
"no-sandbox",
44+
"supports-graceful-termination",
4445
],
4546
)

e2etests/cvd/bugreport_tests/main_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
func TestTakeBugreport(t *testing.T) {
2424
c := e2etests.TestContext{}
2525
c.SetUp(t)
26+
defer c.TearDown()
2627

2728
if err := c.CVDFetch(e2etests.FetchArgs{
2829
DefaultBuildBranch: "aosp-android-latest-release",
@@ -37,6 +38,4 @@ func TestTakeBugreport(t *testing.T) {
3738
if _, err := c.RunCmd("cvd", "host_bugreport"); err != nil {
3839
t.Fatal(err)
3940
}
40-
41-
c.TearDown()
4241
}

e2etests/cvd/common/common.go

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package e2etests
1818

1919
import (
2020
"bytes"
21+
"context"
2122
"encoding/xml"
2223
"errors"
2324
"fmt"
@@ -26,9 +27,11 @@ import (
2627
"log"
2728
"os"
2829
"os/exec"
30+
"os/signal"
2931
"path"
3032
"path/filepath"
3133
"strings"
34+
"syscall"
3235
"testing"
3336

3437
"github.com/bazelbuild/rules_go/go/runfiles"
@@ -68,11 +71,13 @@ type TestContext struct {
6871
// registered cleanup functions are invoked.
6972
cleanups []func()
7073
teardownCalled bool
74+
75+
context context.Context
76+
cancelled bool
7177
}
7278

73-
// Runs the given command with the given set of envvars overrided.
74-
func (tc *TestContext) RunCmdWithEnv(command []string, envvars map[string]string) (string, error) {
75-
cmd := exec.CommandContext(tc.t.Context(), command[0], command[1:]...)
79+
func runCmdWithContextEnv(ctx context.Context, command []string, envvars map[string]string) (string, error) {
80+
cmd := exec.CommandContext(ctx, command[0], command[1:]...)
7681

7782
cmdOutputBuf := bytes.Buffer{}
7883
cmdWriter := io.MultiWriter(&cmdOutputBuf, log.Writer())
@@ -84,7 +89,7 @@ func (tc *TestContext) RunCmdWithEnv(command []string, envvars map[string]string
8489
envvarPairs = append(envvarPairs, fmt.Sprintf("%s=%s", k, v))
8590
}
8691
cmd.Env = os.Environ()
87-
cmd.Env = append(cmd.Env, envvarPairs...)
92+
cmd.Env = append(cmd.Env, envvarPairs...)
8893

8994
log.Printf("Running `%s %s`\n", strings.Join(envvarPairs, " "), strings.Join(command, " "))
9095
err := cmd.Run()
@@ -95,6 +100,11 @@ func (tc *TestContext) RunCmdWithEnv(command []string, envvars map[string]string
95100
return cmdOutputBuf.String(), nil
96101
}
97102

103+
// Runs the given command with the given set of envvars overrided.
104+
func (tc *TestContext) RunCmdWithEnv(command []string, envvars map[string]string) (string, error) {
105+
return runCmdWithContextEnv(tc.context, command, envvars)
106+
}
107+
98108
// Waits for a device to be available via adb.
99109
func (tc *TestContext) RunAdbWaitForDevice() error {
100110
adbCommand := []string{
@@ -283,6 +293,8 @@ func (tc *TestContext) CVDLoad(load LoadArgs) error {
283293
func (tc *TestContext) SetUp(t *testing.T) {
284294
tc.t = t
285295
tc.teardownCalled = false
296+
cancellableContext, cancel := context.WithCancel(t.Context())
297+
tc.context = cancellableContext
286298

287299
log.Printf("Initializing %s test...", tc.t.Name())
288300

@@ -314,6 +326,21 @@ func (tc *TestContext) SetUp(t *testing.T) {
314326

315327
log.Printf("Initialized %s test!", tc.t.Name())
316328

329+
sigChan := make(chan os.Signal, 10)
330+
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
331+
332+
go func() {
333+
for sig := range sigChan {
334+
t.Errorf("Received signal '%s'", sig.String())
335+
tc.cancelled = true
336+
cancel()
337+
}
338+
}()
339+
340+
if tc.cancelled {
341+
t.Fatalf("Previous test was cancelled")
342+
}
343+
317344
tc.t.Cleanup(func() {
318345
if !tc.teardownCalled {
319346
tc.t.Fatalf("Test %s forgot to call TearDown().", tc.t.Name())
@@ -373,7 +400,7 @@ func (tc *TestContext) TearDown() {
373400
err := os.MkdirAll(outinstancedir, os.ModePerm)
374401
if err == nil {
375402
logdir := path.Join(instancedir, "logs")
376-
_, err := tc.RunCmd("cp", "-r", "--dereference", logdir, outinstancedir)
403+
_, err := runCmdWithContextEnv(context.TODO(), []string{"cp", "-r", "--dereference", logdir, outinstancedir}, map[string]string{})
377404
if err != nil {
378405
log.Printf("failed to copy %s to %s: %w", logdir, outinstancedir, err)
379406
}
@@ -387,7 +414,7 @@ func (tc *TestContext) TearDown() {
387414
}
388415
}
389416

390-
tc.RunCmd("cvd", "reset", "-y")
417+
runCmdWithContextEnv(context.TODO(), []string{"cvd", "reset", "-y"}, map[string]string{})
391418

392419
log.Printf("Finished cleaning up after test!")
393420
}
@@ -459,6 +486,7 @@ type XtsArgs struct {
459486
func RunXts(t *testing.T, cuttlefishArgs FetchAndCreateArgs, xtsArgs XtsArgs) {
460487
tc := TestContext{}
461488
tc.SetUp(t)
489+
defer tc.TearDown()
462490

463491
localXtsDir := findLocalXTS(cuttlefishArgs, xtsArgs)
464492
if localXtsDir != "" {
@@ -511,9 +539,9 @@ func RunXts(t *testing.T, cuttlefishArgs FetchAndCreateArgs, xtsArgs XtsArgs) {
511539
}
512540

513541
var xtsResult xtsResult
514-
if err := xml.Unmarshal([]byte(xtsResultsBytes), &xtsResult); err != nil {
542+
if err := xml.Unmarshal([]byte(xtsResultsBytes), &xtsResult); err != nil {
515543
t.Fatalf("failed to parse XTS XML results from %s: %w", xtsResultsPath, err)
516-
}
544+
}
517545

518546
for _, xtsModule := range(xtsResult.Modules) {
519547
for _, xtsTestCase := range(xtsModule.TestCases) {
@@ -529,6 +557,4 @@ func RunXts(t *testing.T, cuttlefishArgs FetchAndCreateArgs, xtsArgs XtsArgs) {
529557
}
530558
}
531559
log.Printf("Finished parsing XTS results!", err)
532-
533-
tc.TearDown()
534560
}

e2etests/cvd/cvd_create_tests/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ go_test(
2525
"exclusive",
2626
"external",
2727
"no-sandbox",
28+
"supports-graceful-termination",
2829
],
2930
)

e2etests/cvd/cvd_create_tests/main_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@ func TestCvdCreate(t *testing.T) {
3535
target: "aosp_cf_x86_64_only_phone-trunk_staging-userdebug",
3636
},
3737
}
38+
c := e2etests.TestContext{}
3839
for _, tc := range testcases {
3940
t.Run(fmt.Sprintf("BUILD=%s/%s", tc.branch, tc.target), func(t *testing.T) {
40-
c := e2etests.TestContext{}
4141
c.SetUp(t)
42+
defer c.TearDown()
4243

4344
if err := c.CVDFetch(e2etests.FetchArgs{
4445
DefaultBuildBranch: tc.branch,
@@ -51,7 +52,6 @@ func TestCvdCreate(t *testing.T) {
5152
t.Fatal(err)
5253
}
5354

54-
c.TearDown()
5555
})
5656
}
5757
}

e2etests/cvd/cvd_load_tests/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ go_test(
2525
"exclusive",
2626
"external",
2727
"no-sandbox",
28+
"supports-graceful-termination",
2829
],
2930
)

e2etests/cvd/cvd_load_tests/main_test.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,9 @@ func TestCvdLoad(t *testing.T) {
109109
}
110110
}`,
111111
},
112-
{
113-
name: "AospMainX64PhoneX2",
114-
loadconfig: `
112+
{
113+
name: "AospMainX64PhoneX2",
114+
loadconfig: `
115115
{
116116
"instances": [
117117
{
@@ -134,20 +134,20 @@ func TestCvdLoad(t *testing.T) {
134134
"host_package": "@ab\/aosp-android-latest-release\/aosp_cf_x86_64_only_phone-userdebug"
135135
}
136136
}`,
137-
},
137+
},
138138
}
139+
c := e2etests.TestContext{}
139140
for _, tc := range testcases {
140141
t.Run(fmt.Sprintf("BUILD=%s", tc.name), func(t *testing.T) {
141-
c := e2etests.TestContext{}
142-
c.SetUp(t)
143-
144-
if err := c.CVDLoad(e2etests.LoadArgs{
145-
LoadConfig: tc.loadconfig,
146-
}); err != nil {
147-
t.Fatal(err)
148-
}
142+
c.SetUp(t)
143+
defer c.TearDown()
149144

150-
c.TearDown()
145+
err := c.CVDLoad(e2etests.LoadArgs{
146+
LoadConfig: tc.loadconfig,
147+
});
148+
if err != nil {
149+
t.Fatal(err)
150+
}
151151
})
152152
}
153153
}

e2etests/cvd/display_tests/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ go_test(
2525
"exclusive",
2626
"external",
2727
"no-sandbox",
28+
"supports-graceful-termination",
2829
],
2930
)
3031

@@ -41,5 +42,6 @@ go_test(
4142
"exclusive",
4243
"external",
4344
"no-sandbox",
45+
"supports-graceful-termination",
4446
],
4547
)

e2etests/cvd/display_tests/main_test.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ import (
2020
"github.com/google/android-cuttlefish/e2etests/cvd/common"
2121
)
2222

23-
func TestAddDisplay(t *testing.T) {
24-
c := e2etests.TestContext{}
23+
func addDisplay(c e2etests.TestContext, t *testing.T) {
2524
c.SetUp(t)
25+
defer c.TearDown()
2626

2727
if err := c.CVDFetch(e2etests.FetchArgs{
2828
DefaultBuildBranch: "aosp-android-latest-release",
@@ -38,13 +38,11 @@ func TestAddDisplay(t *testing.T) {
3838
if _, err := c.RunCmd("cvd", "display", "add", "--display=width=500,height=500",); err != nil {
3939
t.Fatal(err)
4040
}
41-
42-
c.TearDown()
4341
}
4442

45-
func TestListDisplays(t *testing.T) {
46-
c := e2etests.TestContext{}
43+
func listDisplays(c e2etests.TestContext, t *testing.T) {
4744
c.SetUp(t)
45+
defer c.TearDown()
4846

4947
if err := c.CVDFetch(e2etests.FetchArgs{
5048
DefaultBuildBranch: "aosp-android-latest-release",
@@ -60,6 +58,10 @@ func TestListDisplays(t *testing.T) {
6058
if _, err := c.RunCmd("cvd", "display", "list",); err != nil {
6159
t.Fatal(err)
6260
}
61+
}
6362

64-
c.TearDown()
63+
func TestRunAll(t *testing.T) {
64+
c := e2etests.TestContext{}
65+
t.Run("AddDisplay", func(t *testing.T) { addDisplay(c, t) })
66+
t.Run("ListDisplays", func(t *testing.T) { listDisplays(c, t) })
6567
}

e2etests/cvd/env_tests/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ go_test(
2525
"exclusive",
2626
"external",
2727
"no-sandbox",
28+
"supports-graceful-termination",
2829
],
2930
)
3031

@@ -41,5 +42,6 @@ go_test(
4142
"exclusive",
4243
"external",
4344
"no-sandbox",
45+
"supports-graceful-termination",
4446
],
4547
)

0 commit comments

Comments
 (0)