Skip to content

Commit dd184f1

Browse files
committed
qemu.go, harness.go: Add go routine to handle badness
After the tests are complete this go routine verifies contents of console.txt and journal.txt through the use of CheckConsole. Ref: #3788
1 parent 77118ab commit dd184f1

File tree

3 files changed

+110
-46
lines changed

3 files changed

+110
-46
lines changed

mantle/cmd/kola/testiso.go

Lines changed: 72 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -675,59 +675,85 @@ func awaitCompletion(ctx context.Context, inst *platform.QemuInstance, outdir st
675675
err = platform.ErrInitramfsEmergency
676676
}
677677
}
678+
}()
679+
go func() {
680+
err := inst.Wait()
681+
// only one Wait() gets process data, so also manually check for signal
682+
plog.Debugf("qemu exited err=%v", err)
683+
if err == nil && inst.Signaled() {
684+
err = errors.New("process killed")
685+
}
678686
if err != nil {
679-
errchan <- err
687+
errchan <- errors.Wrapf(err, "QEMU unexpectedly exited while awaiting completion")
680688
}
689+
time.Sleep(1 * time.Minute)
690+
errchan <- fmt.Errorf("QEMU exited; timed out waiting for completion")
681691
}()
682-
}
683-
go func() {
684-
err := inst.Wait()
685-
// only one Wait() gets process data, so also manually check for signal
686-
plog.Debugf("qemu exited err=%v", err)
687-
if err == nil && inst.Signaled() {
688-
err = errors.New("process killed")
689-
}
690-
if err != nil {
691-
errchan <- errors.Wrapf(err, "QEMU unexpectedly exited while awaiting completion")
692-
}
693-
time.Sleep(1 * time.Minute)
694-
errchan <- fmt.Errorf("QEMU exited; timed out waiting for completion")
695-
}()
696-
go func() {
697-
r := bufio.NewReader(qchan)
698-
for _, exp := range expected {
699-
l, err := r.ReadString('\n')
700-
if err != nil {
701-
if err == io.EOF {
702-
// this may be from QEMU getting killed or exiting; wait a bit
703-
// to give a chance for .Wait() above to feed the channel with a
704-
// better error
705-
time.Sleep(1 * time.Second)
706-
errchan <- fmt.Errorf("Got EOF from completion channel, %s expected", exp)
707-
} else {
708-
errchan <- errors.Wrapf(err, "reading from completion channel")
692+
go func() {
693+
r := bufio.NewReader(qchan)
694+
for _, exp := range expected {
695+
l, err := r.ReadString('\n')
696+
if err != nil {
697+
if err == io.EOF {
698+
// this may be from QEMU getting killed or exiting; wait a bit
699+
// to give a chance for .Wait() above to feed the channel with a
700+
// better error
701+
time.Sleep(1 * time.Second)
702+
errchan <- fmt.Errorf("Got EOF from completion channel, %s expected", exp)
703+
} else {
704+
errchan <- errors.Wrapf(err, "reading from completion channel")
705+
}
706+
return
707+
}
708+
line := strings.TrimSpace(l)
709+
if line != exp {
710+
errchan <- fmt.Errorf("Unexpected string from completion channel: %s expected: %s", line, exp)
711+
return
709712
}
710-
return
713+
plog.Debugf("Matched expected message %s", exp)
711714
}
712-
line := strings.TrimSpace(l)
713-
if line != exp {
714-
errchan <- fmt.Errorf("Unexpected string from completion channel: %s expected: %s", line, exp)
715-
return
715+
plog.Debugf("Matched all expected messages")
716+
// OK!
717+
errchan <- nil
718+
}()
719+
go func() {
720+
//check for error when switching boot order
721+
if booterrchan != nil {
722+
if err := <-booterrchan; err != nil {
723+
errchan <- err
724+
}
716725
}
717-
plog.Debugf("Matched expected message %s", exp)
718-
}
719-
plog.Debugf("Matched all expected messages")
720-
// OK!
721-
errchan <- nil
722-
}()
723-
go func() {
724-
//check for error when switching boot order
725-
if booterrchan != nil {
726-
if err := <-booterrchan; err != nil {
727-
errchan <- err
726+
}()
727+
go func() {
728+
err := <-errchan
729+
if err == nil {
730+
// No error so far, check the console and journal files
731+
files := []string{filepath.Join(outdir, "console.txt"), filepath.Join(outdir, "journal.txt")}
732+
for _, file := range files {
733+
// Read the contents of the file
734+
fileContent, err := inst.ReadFile(file)
735+
if err != nil {
736+
fmt.Printf("error reading file %s: %v\n", file, err)
737+
return
738+
}
739+
// Check for badness with CheckConsole
740+
warnOnly, badlines := kola.CheckConsole([]byte(fileContent), nil)
741+
if len(badlines) > 0 {
742+
err = fmt.Errorf("errors found in console file: %v", badlines)
743+
for _, badline := range badlines {
744+
if err != nil {
745+
fmt.Printf("badness detected in console file: %v\n", badline)
746+
}
747+
}
748+
errchan <- err
749+
} else if warnOnly {
750+
fmt.Println("warnings found in console file")
751+
continue
752+
}
753+
}
728754
}
729-
}
730-
}()
755+
}()
756+
}
731757
err := <-errchan
732758
return time.Since(start), err
733759
}

mantle/kola/harness.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,6 +1917,27 @@ func ScpKolet(machines []platform.Machine) error {
19171917
return fmt.Errorf("Unable to locate kolet binary for %s", mArch)
19181918
}
19191919

1920+
// CheckConsoleText checks console output for badness
1921+
func CheckConsoleText(consoleOutput []byte) (bool, []string) {
1922+
var badlines []string
1923+
warnOnly := true
1924+
for _, check := range consoleChecks {
1925+
match := check.match.FindSubmatch(consoleOutput)
1926+
if match != nil {
1927+
badline := check.desc
1928+
if len(match) > 1 {
1929+
// include first subexpression
1930+
badline += fmt.Sprintf(" (%s)", match[1])
1931+
}
1932+
badlines = append(badlines, badline)
1933+
if !check.warnOnly {
1934+
warnOnly = false
1935+
}
1936+
}
1937+
}
1938+
return warnOnly, badlines
1939+
}
1940+
19201941
// CheckConsole checks some console output for badness and returns short
19211942
// descriptions of any bad lines it finds along with a boolean
19221943
// indicating if the configuration has the bad lines marked as
@@ -1926,6 +1947,12 @@ func ScpKolet(machines []platform.Machine) error {
19261947
func CheckConsole(output []byte, t *register.Test) (bool, []string) {
19271948
var badlines []string
19281949
warnOnly, allowRerunSuccess := true, true
1950+
// Check for badness using CheckConsoleText
1951+
addWarnOnly, addBadlines := CheckConsoleText(output)
1952+
if !addWarnOnly {
1953+
warnOnly = false
1954+
}
1955+
badlines = append(badlines, addBadlines...)
19291956
for _, check := range consoleChecks {
19301957
if check.skipFlag != nil && t != nil && t.HasFlag(*check.skipFlag) {
19311958
continue

mantle/platform/qemu.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,17 @@ func (inst *QemuInstance) WaitIgnitionError(ctx context.Context) (string, error)
255255
return r.String(), nil
256256
}
257257

258+
// Read file, output contents and return error if reading fails
259+
func (inst *QemuInstance) ReadFile(filename string) (string, error) {
260+
data, err := os.ReadFile(filename)
261+
errchan := make(chan error)
262+
if err != nil {
263+
errchan <- err
264+
return "", err
265+
}
266+
return string(data), nil
267+
}
268+
258269
// WaitAll wraps the process exit as well as WaitIgnitionError,
259270
// returning an error if either fail.
260271
func (inst *QemuInstance) WaitAll(ctx context.Context) error {

0 commit comments

Comments
 (0)