blob: 144ab4411abd1b4b2a3e4d383eff3b3c1fdb7221 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package graphics
import (
"bufio"
"context"
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"time"
"chromiumos/tast/common/testexec"
"chromiumos/tast/local/upstart"
"chromiumos/tast/testing"
)
// igtTest is used to describe the config used to run each test.
type igtTest struct {
exe string // The test executable name.
}
// resultSummary is a summary of results from an igt test log.
type resultSummary struct {
passed int // number of passed subtests
failed int // number of failed subtests
skipped int // number of skipped subtests
}
var subtestResultRegex = regexp.MustCompile("^Subtest .*: ([A-Z]+)")
func init() {
testing.AddTest(&testing.Test{
Func: IGT,
Desc: "Verifies igt-gpu-tools test binaries run successfully",
Contacts: []string{
"ddavenport@chromium.org",
"chromeos-gfx@google.com",
"chromeos-gfx-display@google.com",
"markyacoub@google.com",
},
SoftwareDeps: []string{"drm_atomic", "igt", "no_qemu"},
Params: []testing.Param{{
Name: "drm_import_export",
Val: igtTest{
exe: "drm_import_export",
},
Timeout: 5 * time.Minute,
}, {
Name: "drm_mm",
Val: igtTest{
exe: "drm_mm",
},
Timeout: 5 * time.Minute,
}, {
Name: "drm_read",
Val: igtTest{
exe: "drm_read",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_addfb_basic",
Val: igtTest{
exe: "kms_addfb_basic",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_atomic",
Val: igtTest{
exe: "kms_atomic",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_atomic_interruptible",
Val: igtTest{
exe: "kms_atomic_interruptible",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_atomic_transition",
Val: igtTest{
exe: "kms_atomic_transition",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_big_fb",
Val: igtTest{
exe: "kms_big_fb",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_busy",
Val: igtTest{
exe: "kms_busy",
},
Timeout: 15 * time.Minute,
}, {
Name: "kms_color",
Val: igtTest{
exe: "kms_color",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_concurrent",
Val: igtTest{
exe: "kms_concurrent",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_content_protection",
Val: igtTest{
exe: "kms_content_protection",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_crtc_background_color",
Val: igtTest{
exe: "kms_crtc_background_color",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_cursor_crc",
Val: igtTest{
exe: "kms_cursor_crc",
},
Timeout: 15 * time.Minute,
}, {
Name: "kms_cursor_legacy",
Val: igtTest{
exe: "kms_cursor_legacy",
},
Timeout: 20 * time.Minute,
}, {
Name: "kms_dp_aux_dev",
Val: igtTest{
exe: "kms_dp_aux_dev",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_dp_dsc",
Val: igtTest{
exe: "kms_dp_dsc",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_draw_crc",
Val: igtTest{
exe: "kms_draw_crc",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_flip",
Val: igtTest{
exe: "kms_flip",
},
Timeout: 30 * time.Minute,
}, {
Name: "kms_flip_event_leak",
Val: igtTest{
exe: "kms_flip_event_leak",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_frontbuffer_tracking",
Val: igtTest{
exe: "kms_frontbuffer_tracking",
},
Timeout: 25 * time.Minute,
}, {
Name: "kms_getfb",
Val: igtTest{
exe: "kms_getfb",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_hdmi_inject",
Val: igtTest{
exe: "kms_hdmi_inject",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_hdr",
Val: igtTest{
exe: "kms_hdr",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_invalid_dotclock",
Val: igtTest{
exe: "kms_invalid_dotclock",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_multipipe_modeset",
Val: igtTest{
exe: "kms_multipipe_modeset",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_panel_fitting",
Val: igtTest{
exe: "kms_panel_fitting",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_pipe_crc_basic",
Val: igtTest{
exe: "kms_pipe_crc_basic",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_plane",
Val: igtTest{
exe: "kms_plane",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_plane_alpha_blend",
Val: igtTest{
exe: "kms_plane_alpha_blend",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_plane_cursor",
Val: igtTest{
exe: "kms_plane_cursor",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_plane_lowres",
Val: igtTest{
exe: "kms_plane_lowres",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_plane_multiple",
Val: igtTest{
exe: "kms_plane_multiple",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_plane_scaling",
Val: igtTest{
exe: "kms_plane_scaling",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_prime",
Val: igtTest{
exe: "kms_prime",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_prop_blob",
Val: igtTest{
exe: "kms_prop_blob",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_properties",
Val: igtTest{
exe: "kms_properties",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_psr",
Val: igtTest{
exe: "kms_psr",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_psr2_su",
Val: igtTest{
exe: "kms_psr2_su",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_rmfb",
Val: igtTest{
exe: "kms_rmfb",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_rotation_crc",
Val: igtTest{
exe: "kms_rotation_crc",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_selftest",
Val: igtTest{
exe: "kms_selftest",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_setmode",
Val: igtTest{
exe: "kms_setmode",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_sysfs_edid_timing",
Val: igtTest{
exe: "kms_sysfs_edid_timing",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_universal_plane",
Val: igtTest{
exe: "kms_universal_plane",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_vblank",
Val: igtTest{
exe: "kms_vblank",
},
Timeout: 5 * time.Minute,
}, {
Name: "kms_vrr",
Val: igtTest{
exe: "kms_vrr",
},
Timeout: 5 * time.Minute,
}, {
Name: "sw_sync",
Val: igtTest{
exe: "sw_sync",
},
Timeout: 5 * time.Minute,
}, {
Name: "testdisplay",
Val: igtTest{
exe: "testdisplay",
},
Timeout: 5 * time.Minute,
}, {
Name: "vgem_basic",
Val: igtTest{
exe: "vgem_basic",
},
Timeout: 5 * time.Minute,
}, {
Name: "vgem_slow",
Val: igtTest{
exe: "vgem_slow",
},
Timeout: 5 * time.Minute,
}},
Attr: []string{"group:graphics", "graphics_perbuild"},
Fixture: "graphicsNoChrome",
})
}
func summarizeLog(f *os.File) resultSummary {
var r resultSummary
scanner := bufio.NewScanner(f)
for scanner.Scan() {
if m := subtestResultRegex.FindStringSubmatch(scanner.Text()); m != nil {
switch m[1] {
case "SKIP":
r.skipped++
case "FAIL":
r.failed++
case "SUCCESS":
r.passed++
}
}
}
return r
}
func IGT(ctx context.Context, s *testing.State) {
testOpt := s.Param().(igtTest)
f, err := os.Create(filepath.Join(s.OutDir(), filepath.Base(testOpt.exe)+".txt"))
if err != nil {
s.Fatal("Failed to create a log file: ", err)
}
defer f.Close()
exePath := filepath.Join("/usr/local/libexec/igt-gpu-tools", testOpt.exe)
cmd := testexec.CommandContext(ctx, exePath)
cmd.Stdout = f
cmd.Stderr = f
// Tests such as kms_flip requires Suspend and Wake-up which is achieved using the RTC wake-up alarm.
// tlsdated is holding /dev/rtc so IGT fails to take the lock and set a wake up alarm. Hence, it
// is required to stop the tlsdated before running the IGT test.
if err := upstart.StopJob(ctx, "tlsdated"); err != nil {
s.Fatal("Failed to stop tlsdated: ", err)
}
err = cmd.Run()
exitErr, isExitErr := err.(*exec.ExitError)
// Reset the file to the beginning so the log can be read out again.
f.Seek(0, 0)
results := summarizeLog(f)
summary := fmt.Sprintf("Ran %d subtests with %d failures and %d skipped",
results.passed+results.failed, results.failed, results.skipped)
if results.passed+results.failed+results.skipped == 0 {
// TODO(markyacoub): Many tests have igt_require_intel(), which automatically skips
// everything on other platforms. Mark the test as PASS for now until there are no more
// platform specific dependencies
s.Log("Entire test was skipped - No subtests were run")
// In the case of running multiple subtests which all happen to be skipped, igt_exitcode is 0,
// but the final exit code will be 77.
} else if results.passed+results.failed == 0 && isExitErr && exitErr.ExitCode() == 77 {
s.Log("____________________________________________________")
s.Logf("ALL %d subtests were SKIPPED: %s", results.skipped, err.Error())
s.Log("----------------------------------------------------")
} else if err != nil {
s.Errorf("Error running %s: %v", exePath, err)
s.Error(summary)
} else {
s.Log(summary)
}
}