blob: d80c9a055d2e84293c1feef837d7d6da3a76b130 [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 firmware
import (
"context"
"io/ioutil"
"os"
"time"
"chromiumos/tast/common/perf"
"chromiumos/tast/common/testexec"
"chromiumos/tast/shutil"
"chromiumos/tast/testing"
)
type params struct {
region string
deadline float64
}
func init() {
testing.AddTest(&testing.Test{
Func: FlashromPerf,
Desc: "Flashrom SPI flash E2E tests",
Contacts: []string{
"quasisec@chromium.org", // Test Author
"quasisec@chromium.org", // CrOS Flashrom Maintainer
"chromeos-firmware@google.com", // CrOS Firmware Developers
},
Attr: []string{"group:mainline", "informational"},
SoftwareDeps: []string{"flashrom"},
Params: []testing.Param{{
Val: params{
region: "", // empty str implies a full read.
deadline: 21000,
},
}, {
Name: "fmap",
Val: params{
region: "FMAP",
deadline: 850,
},
}, {
Name: "gbb",
Val: params{
region: "GBB",
deadline: 2700,
},
}, {
Name: "rw_vpd",
Val: params{
region: "RW_VPD",
deadline: 2300,
},
}, {
Name: "rw_elog",
Val: params{
region: "RW_ELOG",
deadline: 2300,
},
}, {
Name: "coreboot",
Val: params{
region: "COREBOOT",
deadline: 6000,
},
}},
})
}
// FlashromPerf runs the flashrom utility to verify various expected behaviour
// is maintained. The function times Flashrom total execution time for a
// complete probe and read of a given region of the SPI flash.
func FlashromPerf(ctx context.Context, s *testing.State) {
readTime := perf.Metric{
Name: "flashrom_region_read_time",
Unit: "ms",
Direction: perf.SmallerIsBetter,
}
p := s.Param().(params)
perf := perf.NewValues()
duration := testFlashromReadTime(ctx, s, p.region)
perf.Set(readTime, duration)
const lowerBound = 100 // sub-process execution should take some time.
if err := perf.Save(s.OutDir()); err != nil {
s.Error("Failed saving perf data: ", err)
}
if duration <= lowerBound || duration >= p.deadline {
s.Errorf("Flashrom execution outside time-bounds, %v < expected < %v ms, got = %v ms", lowerBound, p.deadline, duration)
}
}
func testFlashromReadTime(ctx context.Context, s *testing.State, region string) float64 {
flashromStart := time.Now()
opTempFile, err := ioutil.TempFile("", "dump_"+region+"_*.bin")
if err != nil {
s.Fatal("Failed creating temp file: ", err)
}
defer os.Remove(opTempFile.Name())
var cmd *testexec.Cmd
if len(region) > 0 {
cmd = testexec.CommandContext(ctx, "flashrom", "-i", region, "-r", opTempFile.Name())
} else { // full read is then assumed.
cmd = testexec.CommandContext(ctx, "flashrom", "-r", opTempFile.Name())
}
if _, err := cmd.Output(testexec.DumpLogOnError); err != nil {
s.Fatalf("%q failed: %v", shutil.EscapeSlice(cmd.Args), err)
}
flashromElapsed := time.Since(flashromStart)
return float64(flashromElapsed.Milliseconds())
}