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
27from serial_buffer import SerialBuffer
28import sys
29import threading
30
31class PoERun:
32    def __init__(self, args):
33        self.powerup = args.powerup
34        self.powerdown = args.powerdown
35        self.ser = SerialBuffer(args.dev, "results/serial-output.txt", "", args.timeout)
36
37    def print_error(self, message):
38        RED = '\033[0;31m'
39        NO_COLOR = '\033[0m'
40        print(RED + message + NO_COLOR)
41
42    def logged_system(self, cmd):
43        print("Running '{}'".format(cmd))
44        return os.system(cmd)
45
46    def run(self):
47        if self.logged_system(self.powerup) != 0:
48            return 1
49
50        boot_detected = False
51        for line in self.ser.lines():
52            if re.search("Booting Linux", line):
53                boot_detected = True
54                break
55
56        if not boot_detected:
57            self.print_error("Something wrong; couldn't detect the boot start up sequence")
58            return 2
59
60        for line in self.ser.lines():
61            if re.search("---. end Kernel panic", line):
62                return 1
63
64            # Binning memory problems
65            if re.search("binner overflow mem", line):
66                self.print_error("Memory overflow in the binner; GPU hang")
67                return 1
68
69            result = re.search("hwci: mesa: (\S*)", line)
70            if result:
71                if result.group(1) == "pass":
72                    return 0
73                else:
74                    return 1
75
76        self.print_error("Reached the end of the CPU serial log without finding a result")
77        return 2
78
79def main():
80    parser = argparse.ArgumentParser()
81    parser.add_argument('--dev', type=str, help='Serial device to monitor', required=True)
82    parser.add_argument('--powerup', type=str, help='shell command for rebooting', required=True)
83    parser.add_argument('--powerdown', type=str, help='shell command for powering off', required=True)
84    parser.add_argument('--timeout', type=int, default=60,
85                        help='time in seconds to wait for activity', required=False)
86    args = parser.parse_args()
87
88    poe = PoERun(args)
89    retval = poe.run()
90
91    poe.logged_system(args.powerdown)
92
93    sys.exit(retval)
94
95if __name__ == '__main__':
96    main()
97