blob: 13d79bc4a07d10d73295bc1deb502b46aabb02bd [file] [log] [blame]
// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package intel
import (
"context"
"regexp"
"time"
"github.com/golang/protobuf/ptypes/empty"
"go.chromium.org/tast-tests/cros/common/servo"
"go.chromium.org/tast-tests/cros/remote/powercontrol"
"go.chromium.org/tast-tests/cros/remote/tabletmode"
"go.chromium.org/tast-tests/cros/services/cros/security"
"go.chromium.org/tast/core/ctxutil"
"go.chromium.org/tast/core/errors"
"go.chromium.org/tast/core/rpc"
"go.chromium.org/tast/core/ssh/linuxssh"
"go.chromium.org/tast/core/testing"
"go.chromium.org/tast/core/testing/hwdep"
)
func init() {
testing.AddTest(&testing.Test{
Func: DUTWakeOnPowerButtonTabletMode,
LacrosStatus: testing.LacrosVariantUnneeded,
Desc: "Verifies waking DUT from S0ix using power button press in tabletmode",
BugComponent: "b:157291", // ChromeOS > External > Intel
Contacts: []string{"intel.chrome.automation.team@intel.com", "pathan.jilani@intel.com"},
SoftwareDeps: []string{"chrome"},
ServiceDeps: []string{"tast.cros.security.BootLockboxService"},
HardwareDeps: hwdep.D(hwdep.ChromeEC(), hwdep.FormFactor(hwdep.Convertible, hwdep.Detachable)),
Attr: []string{"group:intel-convertible"},
VarDeps: []string{"servo"},
Timeout: 10 * time.Minute,
})
}
func DUTWakeOnPowerButtonTabletMode(ctx context.Context, s *testing.State) {
ctxForCleanUp := ctx
ctx, cancel := ctxutil.Shorten(ctx, 2*time.Minute)
defer cancel()
dut := s.DUT()
servoSpec := s.RequiredVar("servo")
pxy, err := servo.NewProxy(ctx, servoSpec, dut.KeyFile(), dut.KeyDir())
if err != nil {
s.Fatal("Failed to connect to servo: ", err)
}
defer pxy.Close(ctxForCleanUp)
var reC10Package = regexp.MustCompile(`C10 : ([A-Za-z0-9]+)`)
const (
slpS0File = "/sys/kernel/debug/pmc_core/slp_s0_residency_usec"
pkgCstateFile = "/sys/kernel/debug/pmc_core/package_cstate_show"
)
tmc := &tabletmode.ConvertibleModeControl{}
if err := tmc.InitControl(ctx, dut); err != nil {
s.Fatal("Failed to init TabletModeControl: ", err)
}
defer func(ctx context.Context) {
testing.ContextLog(ctx, "Resetting tabletmode")
if err := tmc.Reset(ctx); err != nil {
s.Fatal("Failed to restore tabletmode to the original settings: ", err)
}
}(ctxForCleanUp)
testing.ContextLog(ctx, "Put DUT into tablet mode")
if err := tmc.ForceTabletMode(ctx); err != nil {
s.Fatal("Failed to set DUT into tablet mode: ", err)
}
cl, err := rpc.Dial(ctx, s.DUT(), s.RPCHint())
if err != nil {
s.Fatal("Failed to connect to the RPC service on the DUT: ", err)
}
defer cl.Close(ctxForCleanUp)
client := security.NewBootLockboxServiceClient(cl.Conn)
if _, err := client.NewChromeLogin(ctx, &empty.Empty{}); err != nil {
s.Fatal("Failed to start Chrome: ", err)
}
defer client.CloseChrome(ctxForCleanUp, &empty.Empty{})
defer func(ctx context.Context) {
testing.ContextLog(ctx, "Performing cleanup")
if !dut.Connected(ctx) {
if err := powercontrol.PowerOntoDUT(ctx, pxy, dut); err != nil {
s.Fatal("Failed to power on DUT at cleanup: ", err)
}
}
}(ctxForCleanUp)
slpOpSetPre, err := linuxssh.ReadFile(ctx, dut.Conn(), slpS0File)
if err != nil {
s.Fatal("Failed to get initial slp s0 value: ", err)
}
pkgOpSetOutput, err := linuxssh.ReadFile(ctx, dut.Conn(), pkgCstateFile)
if err != nil {
s.Fatal("Failed to get initial PkgCstate value: ", err)
}
matchSetPre := reC10Package.FindStringSubmatch(string(pkgOpSetOutput))
if matchSetPre == nil {
s.Fatal("Failed to match pre PkgCstate value: ", string(pkgOpSetOutput))
}
pkgOpSetPre := matchSetPre[1]
suspendCtx, cancel := context.WithTimeout(ctx, 20*time.Second)
defer cancel()
if err := dut.Conn().CommandContext(suspendCtx, "powerd_dbus_suspend").Run(); err != nil && !errors.Is(err, context.DeadlineExceeded) {
s.Fatal("Failed to power off DUT: ", err)
}
sdCtx, cancel := context.WithTimeout(ctx, 20*time.Second)
defer cancel()
if err := dut.WaitUnreachable(sdCtx); err != nil {
s.Fatal("Failed to wait for unreachable: ", err)
}
if err := powercontrol.PowerOnDutWithRetry(ctx, pxy, dut); err != nil {
s.Fatal("Failed to power on DUT after suspend: ", err)
}
slpOpSetPost, err := linuxssh.ReadFile(ctx, dut.Conn(), slpS0File)
if err != nil {
s.Fatal("Failed to get slp s0 value after DUT suspend-resume: ", err)
}
if string(slpOpSetPre) == string(slpOpSetPost) {
s.Errorf("Failed SLP counter value must be different than the value %q noted most recently %q", string(slpOpSetPre), string(slpOpSetPost))
}
if string(slpOpSetPost) == "0" {
s.Error("Failed SLP counter value must be non-zero, noted is: ", slpOpSetPost)
}
pkgOpSetPostOutput, err := linuxssh.ReadFile(ctx, dut.Conn(), pkgCstateFile)
if err != nil {
s.Fatal("Failed to get PkgCstate value after DUT suspend-resume: ", err)
}
matchSetPost := reC10Package.FindStringSubmatch(string(pkgOpSetPostOutput))
if matchSetPost == nil {
s.Fatal("Failed to match post PkgCstate value: ", string(pkgOpSetPostOutput))
}
pkgOpSetPost := matchSetPost[1]
if pkgOpSetPre == pkgOpSetPost {
s.Errorf("Failed Package C10 value %q must be different than value noted earlier %q", pkgOpSetPre, pkgOpSetPost)
}
if pkgOpSetPost == "0x0" || pkgOpSetPost == "0" {
s.Error("Failed Package C10 should be non-zero")
}
}