blob: 8e36ee095c6fd5448a675ac0495aff4fc45240fd [file] [log] [blame]
// Copyright 2021 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 (
"bufio"
"context"
"os"
"path/filepath"
"regexp"
"strconv"
"time"
"github.com/shirou/gopsutil/mem"
"chromiumos/tast/common/testexec"
"chromiumos/tast/errors"
"chromiumos/tast/local/arc"
"chromiumos/tast/testing"
)
func init() {
testing.AddTest(&testing.Test{
Func: UreadaheadValidation,
Desc: "Validates that ARC ureadahead pack exists and looks valid",
Contacts: []string{"khmel@google.com",
"alanding@google.com",
"arc-performance@google.com"},
Attr: []string{"group:mainline", "informational", "group:arc-functional"},
SoftwareDeps: []string{"chrome"},
Params: []testing.Param{{
ExtraSoftwareDeps: []string{"android_p"},
}, {
Name: "vm",
ExtraSoftwareDeps: []string{"android_vm"},
}},
// Minimum acceptable.
Timeout: 4 * time.Minute,
})
}
// ureadaheadPackRequired returns true in case ureadahead is required for the current device.
func ureadaheadPackRequired(ctx context.Context, vmEnabled bool) (bool, error) {
// please see arc.DataCollector for description.
const minVMMemoryKB = 7500000
if !vmEnabled {
// For container ureadahead pack is always required.
return true, nil
}
m, err := mem.VirtualMemory()
if err != nil {
return false, errors.Wrap(err, "failed to get memory info")
}
return m.Total > uint64(minVMMemoryKB*1024), nil
}
func UreadaheadValidation(ctx context.Context, s *testing.State) {
const (
// normally generated ureadahead pack covers >350MB of data.
minAcceptableUreadaheadPackSizeKB = 300 * 1024
// name of ureadahead log.
ureadaheadLogName = "ureadahead.log"
)
vmEnabled, err := arc.VMEnabled()
if err != nil {
s.Fatal("Failed to get whether ARCVM is enabled: ", err)
}
packPath := ""
if vmEnabled {
// TODO(khmel): Add guest side validation.
packPath = "/opt/google/vms/android/ureadahead.pack"
} else {
packPath = "/opt/google/containers/android/ureadahead.pack"
}
if _, err := os.Stat(packPath); err != nil {
if !os.IsNotExist(err) {
s.Fatalf("Failed to check ureadahead pack exists %s: %v", packPath, err)
}
required, err := ureadaheadPackRequired(ctx, vmEnabled)
if err != nil {
s.Fatalf("Failed to check if ureadahead pack %s required: %v", packPath, err)
}
if required {
s.Fatalf("ureadahead pack %s does not exist but required", packPath)
}
testing.ContextLogf(ctx, "ureadahead pack %s does not exist and is not required", packPath)
return
}
logPath := filepath.Join(s.OutDir(), ureadaheadLogName)
cmd := testexec.CommandContext(ctx, "/sbin/ureadahead", "--dump", packPath)
logFile, err := os.Create(logPath)
if err != nil {
s.Fatal("Failed to create log file: ", err)
}
cmd.Stdout = logFile
// don't set cmd.Stderr, so it goes to default log buffer
// and DumpLogOnError can dump it.
err = cmd.Run(testexec.DumpLogOnError)
logFile.Close()
if err != nil {
s.Fatalf("Failed to get the ureadahead stats %s: %v", packPath, err)
}
re := regexp.MustCompile(`^(\d+) inode groups, (\d+) files, (\d+) blocks \((\d+) kB\)$`)
logFile, err = os.Open(logPath)
if err != nil {
s.Fatal("Failed to open log file: ", err)
}
defer logFile.Close()
scanner := bufio.NewScanner(logFile)
matchFound := false
sizeKB := -1
for scanner.Scan() {
str := scanner.Text()
result := re.FindStringSubmatch(str)
if result == nil {
continue
}
if matchFound {
s.Fatalf("More than 1 match found. Please check %q. Last match: %q", ureadaheadLogName, str)
}
// Parsing (\d+) group that represents number of Kb handled by this ureadahead pack
sizeKB, err = strconv.Atoi(result[4])
if err != nil {
s.Fatalf("Failed to parse group %q from %q: %v", result[4], str, err)
}
matchFound = true
}
if err := scanner.Err(); err != nil {
s.Fatalf("Failed to read log file %q: %v", ureadaheadLogName, err)
}
if !matchFound {
s.Fatalf("Failed to parse ureadahead pack dump. Please check %q", ureadaheadLogName)
}
if sizeKB < minAcceptableUreadaheadPackSizeKB {
s.Errorf("Pack size %d kB is too small. It is expected to be min %d kb", sizeKB, minAcceptableUreadaheadPackSizeKB)
}
}