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