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, 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.test_timeout = test_timeout 40 self.logger = logger 41 42 def print_error(self, message): 43 RED = '\033[0;31m' 44 NO_COLOR = '\033[0m' 45 print(RED + message + NO_COLOR) 46 self.logger.update_status_fail(message) 47 48 def logged_system(self, cmd): 49 print("Running '{}'".format(cmd)) 50 return os.system(cmd) 51 52 def run(self): 53 if self.logged_system(self.powerup) != 0: 54 self.logger.update_status_fail("powerup failed") 55 return 1 56 57 boot_detected = False 58 self.logger.create_job_phase("boot") 59 for line in self.ser.lines(timeout=5 * 60, phase="bootloader"): 60 if re.search("Booting Linux", line): 61 boot_detected = True 62 break 63 64 if not boot_detected: 65 self.print_error( 66 "Something wrong; couldn't detect the boot start up sequence") 67 return 1 68 69 self.logger.create_job_phase("test") 70 for line in self.ser.lines(timeout=self.test_timeout, phase="test"): 71 if re.search("---. end Kernel panic", line): 72 self.logger.update_status_fail("kernel panic") 73 return 1 74 75 # Binning memory problems 76 if re.search("binner overflow mem", line): 77 self.print_error("Memory overflow in the binner; GPU hang") 78 return 1 79 80 if re.search("nouveau 57000000.gpu: bus: MMIO read of 00000000 FAULT at 137000", line): 81 self.print_error("nouveau jetson boot bug, abandoning run.") 82 return 1 83 84 # network fail on tk1 85 if re.search("NETDEV WATCHDOG:.* transmit queue 0 timed out", line): 86 self.print_error("nouveau jetson tk1 network fail, abandoning run.") 87 return 1 88 89 result = re.search("hwci: mesa: (\S*)", line) 90 if result: 91 if result.group(1) == "pass": 92 self.logger.update_dut_job("status", "pass") 93 return 0 94 else: 95 self.logger.update_status_fail("test fail") 96 return 1 97 98 self.print_error( 99 "Reached the end of the CPU serial log without finding a result") 100 return 1 101 102 103def main(): 104 parser = argparse.ArgumentParser() 105 parser.add_argument('--dev', type=str, 106 help='Serial device to monitor', required=True) 107 parser.add_argument('--powerup', type=str, 108 help='shell command for rebooting', required=True) 109 parser.add_argument('--powerdown', type=str, 110 help='shell command for powering off', required=True) 111 parser.add_argument( 112 '--test-timeout', type=int, help='Test phase timeout (minutes)', required=True) 113 args = parser.parse_args() 114 115 logger = CustomLogger("job_detail.json") 116 logger.update_dut_time("start", None) 117 poe = PoERun(args, args.test_timeout * 60, logger) 118 retval = poe.run() 119 120 poe.logged_system(args.powerdown) 121 logger.update_dut_time("end", None) 122 123 sys.exit(retval) 124 125 126if __name__ == '__main__': 127 main() 128