blob: 5d880373ae3d60e6ee77c04b43f5f778c878c77e [file]
// Copyright 2022 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 arcappgameperf
import (
"context"
"time"
"chromiumos/tast/common/action"
"chromiumos/tast/common/android/ui"
"chromiumos/tast/common/perf"
"chromiumos/tast/errors"
"chromiumos/tast/local/bundles/cros/arcappgameperf/fixtures"
"chromiumos/tast/local/bundles/cros/arcappgameperf/testutil"
"chromiumos/tast/local/chrome/uiauto"
"chromiumos/tast/local/uidetection"
"chromiumos/tast/testing"
"chromiumos/tast/testing/hwdep"
)
func init() {
testing.AddTest(&testing.Test{
Func: AmongusGpuBenchmark,
LacrosStatus: testing.LacrosVariantUnknown,
Desc: "Creates a local game for Among Us and records performance metrics",
Contacts: []string{"pjlee@google.com", "davidwelling@google.com", "arc-engprod@google.com"},
Attr: []string{"group:crosbolt", "crosbolt_nightly"},
SoftwareDeps: []string{"chrome"},
Data: []string{"amongus-dob-ok-button.png", "amongus-in-game-settings-button.png", "amongus-announcements-close-button.png"},
HardwareDeps: hwdep.D(hwdep.Model(testutil.ModelsToTest()...)),
Fixture: fixtures.ARCAppGamePerfFixture,
Params: []testing.Param{
{
ExtraSoftwareDeps: []string{"android_p"},
}, {
// The hardware dependency for the "vm" subtest and the entire "vm_zork" subtest
// are put in place to prevent this test from being run on 4GB zork devices with
// zork-arc-r, which have been shown to have memory issues with this test (b/224785022).
// TODO(b/224785022): Remove this hardware dependency as well as the "vm_zork" subtest once
// a fix for 4GB zork-arc-r devices for this test has been found and implemented, or the
// "MinMemoryForPlatforms" hardware dependency is merged.
Name: "vm",
ExtraSoftwareDeps: []string{"android_vm"},
ExtraHardwareDeps: hwdep.D(hwdep.SkipOnPlatform("zork")),
}, {
Name: "vm_zork",
ExtraSoftwareDeps: []string{"android_vm"},
ExtraHardwareDeps: hwdep.D(hwdep.Platform("zork"), hwdep.MinMemory(5000)),
}},
Timeout: 20 * time.Minute,
VarDeps: []string{"arcappgameperf.username", "arcappgameperf.password"},
})
}
func AmongusGpuBenchmark(ctx context.Context, s *testing.State) {
const (
appPkgName = "com.innersloth.spacemafia"
appActivity = ".EosUnityPlayerActivity"
// The inputs rendered by Among Us are not immediately active after being clicked
// so wait a moment for the engine to make the input active before interacting with it.
waitForActiveInputTime = time.Second * 5
// Stores how long the game should be benchmarked.
gameBenchmarkTime = time.Minute * 1
// The amount of time that the test should wait for the optional play games
// prompts which need to be closed.
playGamesClosePromptTimeout = time.Second * 45
)
testutil.PerformTest(ctx, s, appPkgName, appActivity, func(params testutil.TestParams) error {
// No need to poll for game launched.
uda := uidetection.NewDefault(params.TestConn).WithOptions(uidetection.Retries(3)).WithTimeout(time.Minute).WithScreenshotStrategy(uidetection.ImmediateScreenshot)
if err := uiauto.Combine("Tap through optional screens",
// Identify and click through optional screens (e.g. download, terms, D.O.B., "play offline").
// Click through optional screen for downloading data.
action.IfSuccessThen(
uda.WaitUntilExists(uidetection.TextBlock([]string{"Accept"})),
uda.WithScreenshotStrategy(uidetection.ImmediateScreenshot).Tap(uidetection.TextBlock([]string{"Accept"})),
),
// Click through optional screen for EULA, allowing extended time for slow downloads.
action.IfSuccessThen(
uda.WithTimeout(time.Minute*5).WaitUntilExists(uidetection.TextBlock([]string{"Understand"})),
uda.Tap(uidetection.TextBlock([]string{"Understand"})),
),
// Click through date of birth screen.
// TODO(b/220912392): Icon detection coordinates inconsistent with that of word/text detection.
action.IfSuccessThen(
uda.WaitUntilExists(uidetection.CustomIcon(s.DataPath("amongus-dob-ok-button.png"))),
uda.Tap(uidetection.Word("OK").Nth(1)),
),
// Click through game mode, with the "offline" option.
action.IfSuccessThen(
uda.WaitUntilExists(uidetection.TextBlock([]string{"Offline"})),
uda.Tap(uidetection.TextBlock([]string{"Offline"})),
),
// Google Play Games may pop-up after this. It could contain a 'Cancel' or 'Not now' prompt.
action.IfSuccessThen(
uda.WithTimeout(playGamesClosePromptTimeout).WaitUntilExists(uidetection.Word("CANCEL")),
uda.Tap(uidetection.Word("CANCEL")),
),
action.IfSuccessThen(
testutil.WaitForExists(params.Device.Object(ui.Text("Not now"), ui.ClassName("android.widget.Button")), playGamesClosePromptTimeout),
testutil.Click(params.Device.Object(ui.Text("Not now"), ui.ClassName("android.widget.Button"))),
),
// Identify and click "x" button to close announcements pop-up.
action.IfSuccessThen(
uda.WaitUntilExists(uidetection.CustomIcon(s.DataPath("amongus-announcements-close-button.png"))),
uda.Tap(uidetection.CustomIcon(s.DataPath("amongus-announcements-close-button.png"))),
),
// Poll created menu loaded (wait until "LOCAL" appears).
uda.WaitUntilExists(uidetection.Word("LOCAL")),
)(ctx); err != nil {
return errors.Wrap(err, "menu not loaded")
}
if err := uiauto.Combine("Load GPU Benchmark",
// Identify and click "Local".
uda.Tap(uidetection.Word("LOCAL")),
// Identify and click "Create Game".
action.Sleep(waitForActiveInputTime),
uda.Tap(uidetection.TextBlock([]string{"Create", "Game"})),
// A failure to join a created session will be retried twice before being skipped.
action.IfSuccessThen(
uda.WithTimeout(playGamesClosePromptTimeout).WaitUntilExists(uidetection.Word("Failed")),
uiauto.Retry(2, uiauto.Combine("Close announcements and click 'Create game' again",
uda.Tap(uidetection.CustomIcon(s.DataPath("amongus-announcements-close-button.png"))),
uda.Tap(uidetection.TextBlock([]string{"Create", "Game"})),
uda.WaitUntilExists(uidetection.CustomIcon(s.DataPath("amongus-in-game-settings-button.png"))),
)),
),
// Poll created game loaded (wait until settings button appears).
uda.WaitUntilExists(uidetection.CustomIcon(s.DataPath("amongus-in-game-settings-button.png"))),
)(ctx); err != nil {
return errors.Wrap(err, "failed to finish test")
}
// Leave the mini-game running for while recording metrics.
if err := testutil.StartBenchmarking(ctx, params); err != nil {
return errors.Wrap(err, "failed to start benchmarking")
}
if err := testing.Sleep(ctx, gameBenchmarkTime); err != nil {
return errors.Wrap(err, "failed sleep for sample")
}
r, err := testutil.StopBenchmarking(ctx, params)
if err != nil {
return errors.Wrap(err, "failed to stop benchmarking")
}
// Save the test results.
fullTestTime := time.Now().Sub(params.ActivityStartTime)
perfValues := perf.NewValues()
perfValues.Set(testutil.TestTimePerfMetric(), fullTestTime.Seconds())
perfValues.Set(testutil.FpsPerfMetric(), r.FPS)
perfValues.Set(testutil.CommitDeviationPerfMetric(), r.CommitDeviation)
perfValues.Set(testutil.RenderQualityPerfMetric(), r.RenderQuality*100.0)
if err := perfValues.Save(s.OutDir()); err != nil {
s.Fatal("Failed saving perf data: ", err)
}
return nil
})
}