• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright © 2020 Igalia, S.L.
4#
5# Permission is hereby granted, free of charge, to any person obtaining a
6# copy of this software and associated documentation files (the "Software"),
7# to deal in the Software without restriction, including without limitation
8# the rights to use, copy, modify, merge, publish, distribute, sublicense,
9# and/or sell copies of the Software, and to permit persons to whom the
10# Software is furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice (including the next
13# paragraph) shall be included in all copies or substantial portions of the
14# Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22# IN THE SOFTWARE.
23
24import argparse
25import os
26import re
27import sys
28import threading
29
30from custom_logger import CustomLogger
31from serial_buffer import SerialBuffer
32
33class PoERun:
34    def __init__(self, args, boot_timeout, test_timeout, logger):
35        self.powerup = args.powerup
36        self.powerdown = args.powerdown
37        self.ser = SerialBuffer(
38            args.dev, "results/serial-output.txt", ": ")
39        self.boot_timeout = boot_timeout
40        self.test_timeout = test_timeout
41        self.logger = logger
42
43    def print_error(self, message):
44        RED = '\033[0;31m'
45        NO_COLOR = '\033[0m'
46        print(RED + message + NO_COLOR)
47        self.logger.update_status_fail(message)
48
49    def logged_system(self, cmd):
50        print("Running '{}'".format(cmd))
51        return os.system(cmd)
52
53    def run(self):
54        if self.logged_system(self.powerup) != 0:
55            self.logger.update_status_fail("powerup failed")
56            return 1
57
58        boot_detected = False
59        self.logger.create_job_phase("boot")
60        for line in self.ser.lines(timeout=self.boot_timeout, phase="bootloader"):
61            if re.search("Booting Linux", line):
62                boot_detected = True
63                break
64
65        if not boot_detected:
66            self.print_error(
67                "Something wrong; couldn't detect the boot start up sequence")
68            return 2
69
70        self.logger.create_job_phase("test")
71        for line in self.ser.lines(timeout=self.test_timeout, phase="test"):
72            if re.search("---. end Kernel panic", line):
73                self.logger.update_status_fail("kernel panic")
74                return 1
75
76            # Binning memory problems
77            if re.search("binner overflow mem", line):
78                self.print_error("Memory overflow in the binner; GPU hang")
79                return 1
80
81            if re.search("nouveau 57000000.gpu: bus: MMIO read of 00000000 FAULT at 137000", line):
82                self.print_error("nouveau jetson boot bug, abandoning run.")
83                return 1
84
85            # network fail on tk1
86            if re.search("NETDEV WATCHDOG:.* transmit queue 0 timed out", line):
87                self.print_error("nouveau jetson tk1 network fail, abandoning run.")
88                return 1
89
90            result = re.search(r"hwci: mesa: (\S*), exit_code: (\d+)", line)
91            if result:
92                status = result.group(1)
93                exit_code = int(result.group(2))
94
95                if status == "pass":
96                    self.logger.update_dut_job("status", "pass")
97                else:
98                    self.logger.update_status_fail("test fail")
99
100                self.logger.update_dut_job("exit_code", exit_code)
101                return exit_code
102
103        self.print_error(
104            "Reached the end of the CPU serial log without finding a result")
105        return 1
106
107
108def main():
109    parser = argparse.ArgumentParser()
110    parser.add_argument('--dev', type=str,
111                        help='Serial device to monitor', required=True)
112    parser.add_argument('--powerup', type=str,
113                        help='shell command for rebooting', required=True)
114    parser.add_argument('--powerdown', type=str,
115                        help='shell command for powering off', required=True)
116    parser.add_argument(
117        '--boot-timeout-seconds', type=int, help='Boot phase timeout (seconds)', required=True)
118    parser.add_argument(
119        '--test-timeout-minutes', type=int, help='Test phase timeout (minutes)', required=True)
120    args = parser.parse_args()
121
122    logger = CustomLogger("results/job_detail.json")
123    logger.update_dut_time("start", None)
124    poe = PoERun(args, args.boot_timeout_seconds, args.test_timeout_minutes * 60, logger)
125    retval = poe.run()
126
127    poe.logged_system(args.powerdown)
128    logger.update_dut_time("end", None)
129
130    sys.exit(retval)
131
132
133if __name__ == '__main__':
134    main()
135