blob: f50be78b0d4796ca4d2c7f019e7c46f214970760 [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"
"regexp"
"strings"
"time"
"chromiumos/tast/common/firmware/ti50"
"chromiumos/tast/remote/firmware/ti50/fixture"
"chromiumos/tast/testing"
)
const timeLimit = 2 * time.Minute
func init() {
testing.AddTest(&testing.Test{
Func: Ti50SystemTestImage,
Desc: "Ti50 system test",
Timeout: 20 * time.Minute,
Contacts: []string{
"ecgh@chromium.org",
"ti50-core@google.com",
},
Attr: []string{"group:firmware"},
Fixture: fixture.SystemTestAuto,
})
}
func Ti50SystemTestImage(ctx context.Context, s *testing.State) {
f := s.FixtValue().(*fixture.Value)
board, err := f.DevBoard(ctx, 10000, time.Second)
if err != nil {
s.Fatal("Could not get board: ", err)
}
err = board.Open(ctx)
if err != nil {
s.Fatal("Open console port: ", err)
}
if err = board.Reset(ctx); err != nil {
s.Fatal("Failed to reset: ", err)
}
s.Log("Kernel tests:")
checkTestResults(ctx, s, board, "KERNEL")
s.Log("App tests:")
checkTestResults(ctx, s, board, "APP")
}
func checkTestResults(ctx context.Context, s *testing.State, board ti50.DevBoard, sectionName string) {
_, err := board.ReadSerialSubmatch(ctx, regexp.MustCompile("##"+regexp.QuoteMeta(sectionName)+" TESTS START"))
if err != nil {
s.Fatal("Failed to read section start: ", err)
}
endMarker := "##" + regexp.QuoteMeta(sectionName) + " TESTS END"
re := regexp.MustCompile("(" + endMarker + `|##TEST (SKIP|START) (\S+)\s)`)
for {
m, err := board.ReadSerialSubmatch(ctx, re)
if err != nil {
s.Fatal("Failed to read next test: ", err)
}
match := string(m[0])
if match == endMarker {
return
}
start := string(m[2])
testName := string(m[3])
result := "Skip"
if start != "SKIP" {
result = waitForTest(ctx, s, board, testName)
}
if result == "Fail" {
s.Errorf("%s test failed", testName)
}
}
}
func waitForTest(ctx context.Context, s *testing.State, board ti50.DevBoard, testName string) string {
lineRe := regexp.MustCompile(`.*[\r\n]+`)
slowCryptoRe := regexp.MustCompile("Long running SW crypto operation")
resultRe := regexp.MustCompile("##TEST RESULT " + regexp.QuoteMeta(testName) + `: (\S+)`)
testTime := time.Now()
var line string
lineTime := time.Now()
timeLimit := timeLimit
var elapsedTime time.Duration
for ; elapsedTime < timeLimit; elapsedTime = time.Since(testTime) {
m, err := board.ReadSerialSubmatch(ctx, lineRe)
if err != nil {
// Tests might be silent for several seconds, so just
// try the read again.
continue
}
delay := time.Since(lineTime)
if delay > 10*time.Second {
s.Logf("(%q took %v)", line, delay.Round(time.Second))
}
lineTime = time.Now()
line = strings.TrimSpace(string(m[0]))
if m := resultRe.FindStringSubmatch(line); m != nil {
result := m[1]
s.Logf("%s: %s (%v)", testName, result, elapsedTime.Round(time.Second))
return result
}
if slowCryptoRe.MatchString(line) {
timeLimit += 10 * time.Minute
s.Log("(Waiting for slow crypto.)")
}
}
s.Logf("Still waiting for test %s after %v, giving up", testName, elapsedTime.Round(time.Second))
delay := time.Since(lineTime)
s.Logf("Waited %v at %q", delay.Round(time.Second), line)
s.Fatalf("%s test failed to finish in time", testName)
return ""
}