blob: d0770fdcdba4e6754eb29456a5647f898f97a0cd [file] [log] [blame]
// Copyright 2019 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 arc
import (
"context"
"io/ioutil"
"strconv"
"strings"
"time"
"chromiumos/tast/errors"
"chromiumos/tast/local/arc"
"chromiumos/tast/local/chrome"
"chromiumos/tast/local/chrome/ash"
"chromiumos/tast/testing"
)
func init() {
testing.AddTest(&testing.Test{
Func: Cgroups,
Desc: "Checks that foreground/background status of ARC applications reflects properly in cgroup limits",
Contacts: []string{"sonnyrao@chromium.org", "arc-eng@google.com"},
Attr: []string{"group:mainline", "informational"},
SoftwareDeps: []string{"chrome"},
Timeout: 4 * time.Minute,
Params: []testing.Param{{
ExtraSoftwareDeps: []string{"android_p"},
Val: "/sys/fs/cgroup/cpu/session_manager_containers/cpu.shares",
}, {
Name: "vm",
ExtraSoftwareDeps: []string{"android_vm"},
Val: "/sys/fs/cgroup/cpu/vms/arc/cpu.shares",
}},
})
}
// See platform2/login_manager/session_manager_impl.cc for defintion of these constants.
const (
// cpuSharesARCBackground is the value for cpu.shares when ARC has nothing in the foreground.
cpuSharesARCBackground = 64
// cpuSharesARCForeground is the value of cpu.shares when ARC is in the foreground.
cpuSharesARCForeground = 1024
)
// cpuCgroupShares retrieves the current value for cpu.shares for the container.
func cpuCgroupShares(path string) (int, error) {
// Read from a file that indicates the relative amount of CPU this cgroup gets when there's contention.
b, err := ioutil.ReadFile(path)
if err != nil {
return 0, err
}
shares, err := strconv.Atoi(strings.TrimSpace(string(b)))
if err != nil {
return 0, errors.Wrapf(err, "bad integer: %q", b)
}
return shares, nil
}
func Cgroups(ctx context.Context, s *testing.State) {
// Path to cpu.shares.
path := s.Param().(string)
const pkgName = "com.android.settings"
cr, err := chrome.New(ctx, chrome.ARCEnabled(), chrome.RestrictARCCPU())
if err != nil {
s.Fatal("Failed to connect to Chrome: ", err)
}
defer cr.Close(ctx)
a, err := arc.New(ctx, s.OutDir())
if err != nil {
s.Fatal("Failed to start ARC: ", err)
}
defer a.Close(ctx)
tconn, err := cr.TestAPIConn(ctx)
if err != nil {
s.Fatal("Failed to create Test API connection: ", err)
}
defer tconn.Close()
// TODO(sonnyrao): Try to figure out how to use the app launcher to do this.
act, err := arc.NewActivity(a, pkgName, ".Settings")
if err != nil {
s.Fatal("Failed to create new activity: ", err)
}
defer act.Close()
if err := act.Start(ctx, tconn); err != nil {
s.Fatal("Failed start Settings activity: ", err)
}
if _, err := ash.SetARCAppWindowState(ctx, tconn, act.PackageName(), ash.WMEventMaximize); err != nil {
s.Fatal("Failed to maximize the activity: ", err)
}
if err := ash.WaitForARCAppWindowState(ctx, tconn, act.PackageName(), ash.WindowStateMaximized); err != nil {
s.Fatal("Failed to wait for activity to enter Maximized state: ", err)
}
// Check shares after ARC window is up and in the foreground.
share, err := cpuCgroupShares(path)
if err != nil {
s.Fatal("Failed to get ARC CPU shares value: ", err)
}
// TODO(sonnyrao): try to show and then hide the apps shelf and verify the shares value stays as expected.
if share != cpuSharesARCForeground {
s.Fatal("Unexpected ARC CPU shares value foreground: ", share)
}
// Minimize ARC window and ensure we go back to background shares.
if _, err := ash.SetARCAppWindowState(ctx, tconn, act.PackageName(), ash.WMEventMinimize); err != nil {
s.Fatal("Failed to set window state to Minimized: ", err)
}
if err := ash.WaitForARCAppWindowState(ctx, tconn, act.PackageName(), ash.WindowStateMinimized); err != nil {
s.Fatal("Failed to wait for activity to become Minimized: ", err)
}
// TODO(b/152733335): Fix and remove this in ARCVM.
if path == "/sys/fs/cgroup/cpu/session_manager_containers/cpu.shares" {
if err := testing.Poll(ctx, func(ctx context.Context) error {
share, err = cpuCgroupShares(path)
if err != nil {
return testing.PollBreak(err)
}
if share != cpuSharesARCBackground {
return errors.Errorf("unexpected ARC CPU shares: got %d, want %d", share, cpuSharesARCBackground)
}
return nil
}, &testing.PollOptions{Timeout: 15 * time.Second}); err != nil {
s.Error("Failed to verify cpu.shares after minimize: ", err)
}
}
}