blob: 48d16658d00c061c7e605c60637d8664c5fdfb13 [file] [log] [blame]
// Copyright 2022 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"
"strings"
"github.com/golang/protobuf/ptypes/empty"
"go.chromium.org/tast-tests/cros/common/servo"
"go.chromium.org/tast-tests/cros/common/testexec"
"go.chromium.org/tast-tests/cros/services/cros/camera"
"go.chromium.org/tast/core/rpc"
"go.chromium.org/tast/core/testing"
"go.chromium.org/tast/core/testing/hwdep"
)
func init() {
testing.AddTest(&testing.Test{
Func: CCAUIMultiCameraSuspendResume,
LacrosStatus: testing.LacrosVariantUnneeded,
Desc: "Functionality of multi-camera after suspend-resume scenario",
Contacts: []string{"chromeos-camera-eng@google.com", "intel.chrome.automation.team@intel.com", "ambalavanan.m.m@intel.com"},
BugComponent: "b:978428", // ChromeOS > Platform > Technologies > Camera > App & Framework
Vars: []string{"servo"},
SoftwareDeps: []string{"chrome"},
ServiceDeps: []string{"tast.cros.camera.CCAService"},
HardwareDeps: hwdep.D(hwdep.X86()),
Attr: []string{"group:intel-sleep"},
Params: []testing.Param{
{
Name: "user_facing_photo",
Val: &camera.CameraTestRequest{Mode: camera.CameraMode_PHOTO, Facing: camera.Facing_FACING_FRONT},
},
{
Name: "env_facing_photo",
Val: &camera.CameraTestRequest{Mode: camera.CameraMode_PHOTO, Facing: camera.Facing_FACING_BACK},
},
{
Name: "user_facing_video",
Val: &camera.CameraTestRequest{Mode: camera.CameraMode_VIDEO, Facing: camera.Facing_FACING_FRONT},
},
{
Name: "env_facing_video",
Val: &camera.CameraTestRequest{Mode: camera.CameraMode_VIDEO, Facing: camera.Facing_FACING_BACK},
},
},
})
}
func CCAUIMultiCameraSuspendResume(ctx context.Context, s *testing.State) {
const (
slpS0Cmd = "cat /sys/kernel/debug/pmc_core/slp_s0_residency_usec"
pkgCstateCmd = "cat /sys/kernel/debug/pmc_core/package_cstate_show"
)
// Set up Servo in remote tests.
dut := s.DUT()
testRequest := s.Param().(*camera.CameraTestRequest)
servoSpec, _ := s.Var("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(ctx)
// Connect to RPC.
cl, err := rpc.Dial(ctx, dut, s.RPCHint())
if err != nil {
s.Fatal("Failed to connect to the RPC service on the DUT: ", err)
}
defer cl.Close(ctx)
cr := camera.NewCCAServiceClient(cl.Conn)
if _, err := cr.NewChrome(ctx, &empty.Empty{}); err != nil {
s.Fatal("Failed to start Chrome: ", err)
}
defer cr.CloseChrome(ctx, &empty.Empty{})
_, err = cr.OpenCamera(ctx, testRequest)
if err != nil {
s.Fatal("Failed to open the camera: ", err)
}
defer cr.CloseCamera(ctx, &empty.Empty{})
if testRequest.Mode == camera.CameraMode_PHOTO {
_, err := cr.TakePicture(ctx, &empty.Empty{})
if err != nil {
s.Fatal("Failed to take picture: ", err)
}
} else if testRequest.Mode == camera.CameraMode_VIDEO {
_, err := cr.RecordVideo(ctx, &empty.Empty{})
if err != nil {
s.Fatal("Failed to record video: ", err)
}
}
cmdOutput := func(cmd string) string {
out, err := dut.Conn().CommandContext(ctx, "bash", "-c", cmd).Output(testexec.DumpLogOnError)
if err != nil {
s.Fatalf("Failed to execute command %q: %v", cmd, err)
}
return strings.Trim(string(out), "\n")
}
// SLP output before lid close.
slpBeforeSuspend := cmdOutput(slpS0Cmd)
pkgCBeforeSuspend := cmdOutput(pkgCstateCmd)
c10PkgPattern := regexp.MustCompile(`C10 : ([A-Za-z0-9]+)`)
matchSetPre := (c10PkgPattern).FindStringSubmatch(pkgCBeforeSuspend)
if matchSetPre == nil {
s.Fatal("Failed to match pre PkgCstate value: ", pkgCBeforeSuspend)
}
pkgCStateBeforeSuspend := matchSetPre[1]
s.Log("Closing lid")
if err := pxy.Servo().SetString(ctx, "lid_open", "no"); err != nil {
s.Fatal("Failed to close lid: ", err)
}
if err := dut.WaitUnreachable(ctx); err != nil {
s.Fatal("Failed to wait DUT to become unreachable: ", err)
}
s.Log("Opening lid")
if err := pxy.Servo().SetString(ctx, "lid_open", "yes"); err != nil {
s.Fatal("Failed to open lid: ", err)
}
if err := dut.WaitConnect(ctx); err != nil {
s.Fatal("Failed to wake up DUT: ", err)
}
slpAfterSuspend := cmdOutput(slpS0Cmd)
if slpBeforeSuspend == slpAfterSuspend {
s.Fatalf("Failed SLP counter value must be different than the value %q noted most recently %q", slpBeforeSuspend, slpAfterSuspend)
}
if slpAfterSuspend == "0" {
s.Fatal("Failed SLP counter value must be non-zero, noted is: ", slpAfterSuspend)
}
pkgCAfterSuspend := cmdOutput(pkgCstateCmd)
matchSetPost := (c10PkgPattern).FindStringSubmatch(pkgCAfterSuspend)
if matchSetPost == nil {
s.Fatal("Failed to match post PkgCstate value: ", pkgCAfterSuspend)
}
pkgCStateAfterSuspend := matchSetPost[1]
if pkgCStateBeforeSuspend == pkgCStateAfterSuspend {
s.Fatalf("Failed Package C10 value %q must be different than value noted earlier %q", pkgCStateBeforeSuspend, pkgCStateAfterSuspend)
}
if pkgCStateAfterSuspend == "0x0" || pkgCStateAfterSuspend == "0" {
s.Fatal("Failed Package C10 should be non-zero")
}
cl, err = rpc.Dial(ctx, dut, s.RPCHint())
if err != nil {
s.Fatal("Failed to connect to the RPC service on the DUT: ", err)
}
defer cl.Close(ctx)
cr = camera.NewCCAServiceClient(cl.Conn)
if _, err := cr.ReuseChrome(ctx, &empty.Empty{}); err != nil {
s.Fatal("Failed to reconnect to the Chrome session: ", err)
}
s.Log("Check Camera is active after suspend resume")
testResponse, err := cr.CheckCameraExists(ctx, &empty.Empty{})
if err != nil {
s.Fatal("Failed to check for active camera: ", err)
}
// Check test result.
switch testResponse.Result {
case camera.TestResult_TEST_RESULT_PASSED:
s.Log("Remote test passed")
case camera.TestResult_TEST_RESULT_FAILED:
s.Error("Remote test failed with error message:", testResponse.Error)
case camera.TestResult_TEST_RESULT_UNSET:
s.Error("Remote test result is unset")
}
defer func() {
s.Log("Opening lid")
if err := pxy.Servo().SetString(ctx, "lid_open", "yes"); err != nil {
s.Fatal("Failed to open lid: ", err)
}
}()
}