• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging, os, re
6
7from autotest_lib.client.bin import utils
8from autotest_lib.client.common_lib import error
9from autotest_lib.server import test
10
11_KERN_WARNING = 4
12
13_WHITELIST_COMMON = [
14    r"used greatest stack depth: \d+ bytes left",
15    "Kernel-defined memdesc doesn't match the one from EFI!",
16    "Use a HIGHMEM enabled kernel.",
17   "GPT: Use GNU Parted to correct GPT errors.",
18    r"GPT:\d+ != \d+",
19    "GPT:Alternate GPT header not at the end of the disk.",
20    "GPT:Primary header thinks Alt. header is not at the end of the disk.",
21    r"GPT:partition_entry_array_crc32 values don't match: 0x[\da-f]+ !="
22    " 0x[\da-f]+",
23    r"Warning only \d+MB will be used.",
24    "\[drm:intel_init_bios\] \*ERROR\* VBT signature missing",
25    "i2c i2c-2: The new_device interface is still experimental and may change "
26    "in a near future",
27    "i915 0000:00:02.0: Invalid ROM contents",
28    "industrialio: module is from the staging directory, the quality is "
29    "unknown, you have been warned.",
30    "pnp 00:01: io resource \(0x164e-0x164f\) overlaps 0000:00:1c.0 "
31    "BAR 7 \(0x1000-0x1fff\), disabling",
32    r"sd \d:\d:\d:\d: \[sd[a-z]\] Assuming drive cache: write through",
33    "tsl[\da-z]+: module is from the staging directory, the quality is "
34    "unknown, you have been warned.",
35    "usb 1-2: unknown number of interfaces: 4",
36]
37
38_WHITELIST_TARGETS = {
39    'Alex' : [
40        r"CE: hpet increasing min_delta_ns to \d+ nsec",
41        r"Measured \d+ cycles TSC warp between CPUs, turning off TSC clock.",
42        "pci 0000:01:00.0: BAR 6: no parent found for of device "
43        "\[0xffff0000-0xffffffff]",
44        "tsl258x 2-0029: taos_get_lux data not valid",
45        "usb 1-2: config 1 has an invalid interface number: 1 but max is 0",
46        "usb 1-2: config 1 has no interface number 0",
47        ],
48    'Mario' : [
49        "chromeos_acpi: failed to retrieve MLST \(5\)",
50        r"btusb_[a-z]{4}_complete: hci\d urb [\da-f]+ failed to resubmit \(1\)",
51        ]
52}
53
54""" Interesting fields from meminfo that we want to log
55    If you add fields here, you must add them to the constraints
56    in the control file
57"""
58_meminfo_fields = { 'MemFree'   : 'coldboot_memfree_mb',
59                    'AnonPages' : 'coldboot_anonpages_mb',
60                    'Buffers'   : 'coldboot_buffers_mb',
61                    'Cached'    : 'coldboot_cached_mb',
62                    'Active'    : 'coldboot_active_mb',
63                    'Inactive'  : 'coldboot_inactive_mb',
64                    }
65
66class kernel_BootMessagesServer(test.test):
67    version = 1
68
69
70    def _read_dmesg(self, filename):
71        """Put the contents of 'dmesg -r' into the given file.
72
73        @param filename: The file to write 'dmesg -r' into.
74        """
75        f = open(filename, 'w')
76        self._client.run('dmesg -r', stdout_tee=f)
77        f.close()
78
79        return utils.read_file(filename)
80
81    def _reboot_machine(self):
82        """Reboot the client machine.
83
84        We'll wait until the client is down, then up again.
85        """
86        self._client.run('reboot')
87        self._client.wait_down()
88        self._client.wait_up()
89
90    def _read_meminfo(self, filename):
91        """Fetch /proc/meminfo from client and return lines in the file
92
93        @param filename: The file to write 'cat /proc/meminfo' into.
94        """
95
96        f = open(filename, 'w')
97        self._client.run('cat /proc/meminfo', stdout_tee=f)
98        f.close()
99
100        return utils.read_file(filename)
101
102    def _parse_meminfo(self, meminfo, perf_vals):
103        """ Parse the contents of each line of meminfo
104            if the line matches one of the interesting keys
105            save it into perf_vals in terms of megabytes
106
107            @param filelines: list of lines in meminfo
108            @param perf_vals: dictionary of performance metrics
109        """
110
111        for line in meminfo.splitlines():
112            stuff = re.match('(.*):\s+(\d+)', line)
113            stat  = stuff.group(1)
114            if stat in _meminfo_fields:
115                value  = int(stuff.group(2))/ 1024
116                metric = _meminfo_fields[stat]
117                perf_vals[metric] = value
118
119    def _check_acpi_output(self, text, fwid):
120        # This dictionary is the database of expected strings in dmesg output.
121        # The keys are platform names, the values are two tuples, the first
122        # element is the regex to filter the messages, the second element is a
123        # set of strings to be found in the filtered dmesg set.
124        message_db = {
125            'Alex' : (r'(chromeos_acpi:|ChromeOS )', (
126                    'chromeos_acpi: registering CHSW 0',
127                    'chromeos_acpi: registering VBNV 0',
128                    'chromeos_acpi: registering VBNV 1',
129                    r'chromeos_acpi: truncating buffer from \d+ to \d+',
130                    'chromeos_acpi: installed',
131                    'ChromeOS firmware detected')),
132
133            'Mario' : (r'(chromeos_acpi|ChromeOS )', (
134                    'chromeos_acpi: falling back to default list of methods',
135                    'chromeos_acpi: registering CHSW 0',
136                    'chromeos_acpi: registering CHNV 0',
137                    'chromeos_acpi: failed to retrieve MLST \(5\)',
138                    'chromeos_acpi: installed',
139                    'Legacy ChromeOS firmware detected'))
140            }
141
142        if fwid not in message_db:
143            msg = 'Unnown platform %s, acpi dmesg set not defined.' % fwid
144            logging.error(msg)
145            raise error.TestFail(msg)
146
147        rv = utils.verify_mesg_set(text,
148                                   message_db[fwid][0],
149                                   message_db[fwid][1])
150        if rv:
151            logging.error('ACPI mismatch\n%s:' % rv)
152            raise error.TestFail('ACPI dmesg mismatch')
153
154    def run_once(self, host=None):
155        """Run the test.
156
157        @param host: The client machine to connect to; should be a Host object.
158        """
159        assert host is not None, "The host must be specified."
160
161        self._client = host
162
163        # get the firmware identifier from Crossystem
164        cs = utils.Crossystem(self._client)
165        cs.init()
166        fwid = cs.fwid().split('.')[0]
167
168        dmesg_filename = os.path.join(self.resultsdir, 'dmesg')
169        meminfo_filename = os.path.join(self.resultsdir, 'meminfo')
170        perf_vals = {}
171
172        self._reboot_machine()
173        meminfo = self._read_meminfo(meminfo_filename)
174        self._parse_meminfo(meminfo, perf_vals)
175        dmesg = self._read_dmesg(dmesg_filename)
176
177        if fwid not in _WHITELIST_TARGETS:
178            msg = 'Unnown platform %s, whitelist dmesg set not defined.' % fwid
179            logging.error(msg)
180            raise error.TestFail(msg)
181
182        unexpected = utils.check_raw_dmesg(
183            dmesg, _KERN_WARNING, _WHITELIST_COMMON + _WHITELIST_TARGETS[fwid])
184
185        if unexpected:
186            f = open(os.path.join(self.resultsdir, 'dmesg.err'), 'w')
187            for line in unexpected:
188                logging.error('UNEXPECTED DMESG: %s' % line)
189                f.write('%s\n' % line)
190            f.close()
191            raise error.TestFail("Unexpected dmesg warnings and/or errors.")
192
193        self.write_perf_keyval(perf_vals)
194
195        self._check_acpi_output(dmesg, fwid)
196