blob: 818f7fdb33e1e280bfc8508442f8fedca47e230e [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"
"strings"
"time"
"chromiumos/tast/common/testexec"
"chromiumos/tast/testing"
"chromiumos/tast/testing/hwdep"
)
// 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]+)")
var gpuAmd = []string{"zork", "grunt"}
var gpuQcom = []string{"strongbad", "trogdor"}
var gpuMtk = []string{"kukui", "jacuzzi"}
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"},
Attr: []string{"group:graphics", "graphics_igt"},
Fixture: "chromeGraphicsIgt",
Params: []testing.Param{{
Name: "drm_import_export",
Val: igtTest{
exe: "drm_import_export",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "drm_mm",
Val: igtTest{
exe: "drm_mm",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "drm_read",
Val: igtTest{
exe: "drm_read",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_addfb_basic",
Val: igtTest{
exe: "kms_addfb_basic",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_atomic",
Val: igtTest{
exe: "kms_atomic",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_perbuild"},
}, {
Name: "kms_atomic_interruptible",
Val: igtTest{
exe: "kms_atomic_interruptible",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_perbuild"},
}, {
Name: "kms_atomic_transition",
Val: igtTest{
exe: "kms_atomic_transition",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(gpuQcom...)),
}, {
Name: "kms_atomic_transition_unstable",
Val: igtTest{
exe: "kms_atomic_transition",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(gpuQcom...)),
}, {
Name: "kms_color",
Val: igtTest{
exe: "kms_color",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(gpuMtk...)),
}, {
Name: "kms_color_unstable",
Val: igtTest{
exe: "kms_color",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(gpuMtk...)),
}, {
Name: "kms_concurrent",
Val: igtTest{
exe: "kms_concurrent",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(gpuMtk...)),
}, {
Name: "kms_concurrent_unstable",
Val: igtTest{
exe: "kms_concurrent",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(gpuMtk...)),
}, {
Name: "kms_content_protection",
Val: igtTest{
exe: "kms_content_protection",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_cursor_crc",
Val: igtTest{
exe: "kms_cursor_crc",
},
Timeout: 15 * time.Minute,
ExtraAttr: []string{"graphics_weekly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(gpuAmd...)),
}, {
Name: "kms_cursor_crc_unstable",
Val: igtTest{
exe: "kms_cursor_crc",
},
Timeout: 15 * time.Minute,
ExtraAttr: []string{"graphics_weekly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(gpuAmd...)),
}, {
Name: "kms_cursor_legacy",
Val: igtTest{
exe: "kms_cursor_legacy",
},
Timeout: 20 * time.Minute,
ExtraAttr: []string{"graphics_weekly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(append(gpuAmd, gpuQcom...)...)),
}, {
Name: "kms_cursor_legacy_unstable",
Val: igtTest{
exe: "kms_cursor_legacy",
},
Timeout: 20 * time.Minute,
ExtraAttr: []string{"graphics_weekly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(append(gpuAmd, gpuQcom...)...)),
}, {
Name: "kms_dp_aux_dev",
Val: igtTest{
exe: "kms_dp_aux_dev",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_dp_dsc",
Val: igtTest{
exe: "kms_dp_dsc",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_flip",
Val: igtTest{
exe: "kms_flip",
},
Timeout: 30 * time.Minute,
ExtraAttr: []string{"graphics_weekly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(append(append(gpuAmd, gpuQcom...), gpuMtk...)...)),
}, {
Name: "kms_flip_unstable",
Val: igtTest{
exe: "kms_flip",
},
Timeout: 30 * time.Minute,
ExtraAttr: []string{"graphics_weekly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(append(append(gpuAmd, gpuQcom...), gpuMtk...)...)),
}, {
Name: "kms_flip_event_leak",
Val: igtTest{
exe: "kms_flip_event_leak",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_getfb",
Val: igtTest{
exe: "kms_getfb",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_hdmi_inject",
Val: igtTest{
exe: "kms_hdmi_inject",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_hdr",
Val: igtTest{
exe: "kms_hdr",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_multipipe_modeset",
Val: igtTest{
exe: "kms_multipipe_modeset",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_panel_fitting",
Val: igtTest{
exe: "kms_panel_fitting",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(append(gpuAmd, gpuQcom...)...)),
}, {
Name: "kms_panel_fitting_unstable",
Val: igtTest{
exe: "kms_panel_fitting",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(append(gpuAmd, gpuQcom...)...)),
}, {
Name: "kms_pipe_crc_basic",
Val: igtTest{
exe: "kms_pipe_crc_basic",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_plane",
Val: igtTest{
exe: "kms_plane",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(append(gpuAmd, gpuQcom...)...)),
}, {
Name: "kms_plane_unstable",
Val: igtTest{
exe: "kms_plane",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(append(gpuAmd, gpuQcom...)...)),
}, {
Name: "kms_plane_alpha_blend",
Val: igtTest{
exe: "kms_plane_alpha_blend",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(append(gpuAmd, gpuQcom...)...)),
}, {
Name: "kms_plane_alpha_blend_unstable",
Val: igtTest{
exe: "kms_plane_alpha_blend",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(append(gpuAmd, gpuQcom...)...)),
}, {
Name: "kms_plane_cursor",
Val: igtTest{
exe: "kms_plane_cursor",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(append(append(gpuAmd, gpuQcom...), gpuMtk...)...)),
}, {
Name: "kms_plane_cursor_unstable",
Val: igtTest{
exe: "kms_plane_cursor",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(append(append(gpuAmd, gpuQcom...), gpuMtk...)...)),
}, {
Name: "kms_plane_lowres",
Val: igtTest{
exe: "kms_plane_lowres",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_plane_multiple",
Val: igtTest{
exe: "kms_plane_multiple",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(append(gpuAmd, gpuQcom...)...)),
}, {
Name: "kms_plane_multiple_unstable",
Val: igtTest{
exe: "kms_plane_multiple",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(append(gpuAmd, gpuQcom...)...)),
}, {
Name: "kms_plane_scaling",
Val: igtTest{
exe: "kms_plane_scaling",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(append(gpuAmd, gpuQcom...)...)),
}, {
Name: "kms_plane_scaling_unstable",
Val: igtTest{
exe: "kms_plane_scaling",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(append(gpuAmd, gpuQcom...)...)),
}, {
Name: "kms_prime",
Val: igtTest{
exe: "kms_prime",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(gpuAmd...)),
}, {
Name: "kms_prime_unstable",
Val: igtTest{
exe: "kms_prime",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(gpuAmd...)),
}, {
Name: "kms_prop_blob",
Val: igtTest{
exe: "kms_prop_blob",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_properties",
Val: igtTest{
exe: "kms_properties",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform(gpuMtk...)),
}, {
Name: "kms_properties_unstable",
Val: igtTest{
exe: "kms_properties",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform(gpuMtk...)),
}, {
Name: "kms_rmfb",
Val: igtTest{
exe: "kms_rmfb",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_rotation_crc",
Val: igtTest{
exe: "kms_rotation_crc",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_selftest",
Val: igtTest{
exe: "kms_selftest",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_setmode",
Val: igtTest{
exe: "kms_setmode",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_sysfs_edid_timing",
Val: igtTest{
exe: "kms_sysfs_edid_timing",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_universal_plane",
Val: igtTest{
exe: "kms_universal_plane",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "kms_vblank",
Val: igtTest{
exe: "kms_vblank",
},
Timeout: 15 * time.Minute,
ExtraAttr: []string{"graphics_weekly"},
}, {
Name: "kms_vrr",
Val: igtTest{
exe: "kms_vrr",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "sw_sync",
Val: igtTest{
exe: "sw_sync",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "testdisplay",
Val: igtTest{
exe: "testdisplay",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "vgem_basic",
Val: igtTest{
exe: "vgem_basic",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "vgem_slow",
Val: igtTest{
exe: "vgem_slow",
},
Timeout: 5 * time.Minute,
ExtraAttr: []string{"graphics_nightly"},
}, {
Name: "template",
Val: igtTest{
exe: "template",
},
Timeout: 1 * time.Minute,
ExtraAttr: []string{"group:mainline"},
}},
})
}
func summarizeLog(f *os.File) (r resultSummary, failedSubtests []string) {
scanner := bufio.NewScanner(f)
for scanner.Scan() {
if m := subtestResultRegex.FindStringSubmatch(scanner.Text()); m != nil {
subtestName := m[1]
result := m[2]
switch result {
case "SKIP":
r.skipped++
case "FAIL":
r.failed++
failedSubtests = append(failedSubtests, subtestName)
case "SUCCESS":
r.passed++
}
}
}
return r, failedSubtests
}
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
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, failedSubtests := 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 len(failedSubtests) > 0 {
s.Logf("Error running %s: %v", exePath, err)
s.Log(summary)
s.Log("Failed subtests: ", failedSubtests)
failedSubtestsMessage := ""
if len(failedSubtests) <= 3 {
failedSubtestsMessage = strings.Join(failedSubtests, " ")
} else {
failedSubtestsMessage = failedSubtests[0] + " ... " + failedSubtests[len(failedSubtests)-1]
}
s.Errorf("%s Pass:%d Fail:%d (%s)", testOpt.exe, results.passed, results.failed, failedSubtestsMessage)
} else {
s.Log(summary)
}
}