blob: 8232ccdf19a76eda64dd4aae435dd631e832f1f0 [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 lacros implements a library used for utilities and communication with lacros-chrome on ChromeOS.
package lacros
import (
"context"
"chromiumos/tast/errors"
"chromiumos/tast/local/chrome"
"chromiumos/tast/local/chrome/ui/quicksettings"
"chromiumos/tast/local/lacros/launcher"
"chromiumos/tast/local/media/cpu"
"chromiumos/tast/local/power"
"chromiumos/tast/local/power/setup"
)
// CleanupCallback is a callback that should be deferred to clean up test resources.
type CleanupCallback func(context.Context) error
func noCleanup(context.Context) error { return nil }
// CombineCleanup combines two CleanupCallbacks so they are executed in the same order
// that they would be if they had been deferred.
func CombineCleanup(ctx context.Context, existing, new func(context.Context) error, msg string) CleanupCallback {
return func(context.Context) error {
if err := new(ctx); err != nil {
existing(ctx)
return errors.Wrap(err, msg)
}
return existing(ctx)
}
}
// SetupPerfTest sets up a stable environment for a lacros performance test.
// The returned CleanupCallback should be deferred to be executed upon test completion.
func SetupPerfTest(ctx context.Context, tconn *chrome.TestConn, name string) (retCleanup CleanupCallback, retErr error) {
// Set-up environment to be more consistent:
sup, supCleanup := setup.New(name)
cleanup := CombineCleanup(ctx, noCleanup, supCleanup, "failed to clean up perf test")
defer func() {
if retErr != nil {
cleanup(ctx)
}
}()
sup.Add(setup.PowerTest(ctx, tconn, setup.PowerTestOptions{Wifi: setup.DoNotChangeWifiInterfaces, NightLight: setup.DisableNightLight}))
if err := sup.Check(ctx); err != nil {
return nil, errors.Wrap(err, "failed to setup GpuCUJ power test environment")
}
if err := quicksettings.ToggleSetting(ctx, tconn, quicksettings.SettingPodDoNotDisturb, true); err != nil {
return nil, errors.Wrap(err, "failed to disable notifications")
}
cleanup = CombineCleanup(ctx, cleanup, func(ctx context.Context) error {
return quicksettings.ToggleSetting(ctx, tconn, quicksettings.SettingPodDoNotDisturb, false)
}, "failed to re-enable notifications")
return cleanup, nil
}
func waitForStableEnvironment(ctx context.Context) error {
// Wait for CPU to cool down.
if _, err := power.WaitUntilCPUCoolDown(ctx, power.DefaultCoolDownConfig(power.CoolDownPreserveUI)); err != nil {
return errors.Wrap(err, "failed to wait for CPU to cool down")
}
// Wait for quiescent state.
if err := cpu.WaitUntilIdle(ctx); err != nil {
return errors.Wrap(err, "failed waiting for CPU to become idle")
}
return nil
}
// SetupCrosTestWithPage opens a cros-chrome page after waiting for a stable environment (CPU temperature, etc).
func SetupCrosTestWithPage(ctx context.Context, f launcher.FixtData, url string) (*chrome.Conn, CleanupCallback, error) {
if err := waitForStableEnvironment(ctx); err != nil {
return nil, nil, err
}
conn, err := f.Chrome.NewConn(ctx, url)
if err != nil {
return nil, nil, errors.Wrap(err, "failed to open new tab")
}
return conn, func(ctx context.Context) error {
conn.CloseTarget(ctx)
conn.Close()
return nil
}, nil
}
// SetupLacrosTestWithPage opens a lacros-chrome page after waiting for a stable environment (CPU temperature, etc).
// TODO(crbug.com/1127165): Remove the artifactPath argument when we can use Data in fixtures.
func SetupLacrosTestWithPage(ctx context.Context, f launcher.FixtData, artifactPath, url string) (
retConn *chrome.Conn, retTConn *chrome.TestConn, retL *launcher.LacrosChrome, retCleanup CleanupCallback, retErr error) {
// Launch lacros-chrome with about:blank loaded first - we don't want to include startup cost.
l, err := launcher.LaunchLacrosChrome(ctx, f, artifactPath)
if err != nil {
return nil, nil, nil, nil, errors.Wrap(err, "failed to launch lacros-chrome")
}
cleanup := func(ctx context.Context) error {
l.Close(ctx)
return nil
}
defer func() {
if retErr != nil {
cleanup(ctx)
}
}()
ltconn, err := l.TestAPIConn(ctx)
if err != nil {
return nil, nil, nil, nil, errors.Wrap(err, "failed to connect to test API")
}
if err := waitForStableEnvironment(ctx); err != nil {
return nil, nil, nil, nil, err
}
conn, err := l.NewConn(ctx, url)
if err != nil {
return nil, nil, nil, nil, errors.Wrap(err, "failed to open new tab")
}
cleanup = CombineCleanup(ctx, cleanup, func(ctx context.Context) error {
conn.CloseTarget(ctx)
conn.Close()
return nil
}, "")
// Close the initial "about:blank" tab present at startup.
if err := CloseAboutBlank(ctx, f.TestAPIConn, l.Devsess, 0); err != nil {
return nil, nil, nil, nil, errors.Wrap(err, "failed to close about:blank tab")
}
return conn, ltconn, l, cleanup, nil
}