blob: 7106739962dbb730648021ae6e45cf0f3f58b7f8 [file] [log] [blame]
# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging, os, re
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.server import test
_KERN_WARNING = 4
_WHITELIST_COMMON = [
r"used greatest stack depth: \d+ bytes left",
"Kernel-defined memdesc doesn't match the one from EFI!",
"Use a HIGHMEM enabled kernel.",
"GPT: Use GNU Parted to correct GPT errors.",
r"GPT:\d+ != \d+",
"GPT:Alternate GPT header not at the end of the disk.",
"GPT:Primary header thinks Alt. header is not at the end of the disk.",
r"GPT:partition_entry_array_crc32 values don't match: 0x[\da-f]+ !="
" 0x[\da-f]+",
r"Warning only \d+MB will be used.",
"\[drm:intel_init_bios\] \*ERROR\* VBT signature missing",
"i2c i2c-2: The new_device interface is still experimental and may change "
"in a near future",
"i915 0000:00:02.0: Invalid ROM contents",
"industrialio: module is from the staging directory, the quality is "
"unknown, you have been warned.",
"pnp 00:01: io resource \(0x164e-0x164f\) overlaps 0000:00:1c.0 "
"BAR 7 \(0x1000-0x1fff\), disabling",
r"sd \d:\d:\d:\d: \[sd[a-z]\] Assuming drive cache: write through",
"tsl[\da-z]+: module is from the staging directory, the quality is "
"unknown, you have been warned.",
"usb 1-2: unknown number of interfaces: 4",
]
_WHITELIST_TARGETS = {
'Alex' : [
r"CE: hpet increasing min_delta_ns to \d+ nsec",
r"Measured \d+ cycles TSC warp between CPUs, turning off TSC clock.",
"pci 0000:01:00.0: BAR 6: no parent found for of device "
"\[0xffff0000-0xffffffff]",
"tsl258x 2-0029: taos_get_lux data not valid",
"usb 1-2: config 1 has an invalid interface number: 1 but max is 0",
"usb 1-2: config 1 has no interface number 0",
],
'Mario' : [
"chromeos_acpi: failed to retrieve MLST \(5\)",
r"btusb_[a-z]{4}_complete: hci\d urb [\da-f]+ failed to resubmit \(1\)",
]
}
""" Interesting fields from meminfo that we want to log
If you add fields here, you must add them to the constraints
in the control file
"""
_meminfo_fields = { 'MemFree' : 'coldboot_memfree_mb',
'AnonPages' : 'coldboot_anonpages_mb',
'Buffers' : 'coldboot_buffers_mb',
'Cached' : 'coldboot_cached_mb',
'Active' : 'coldboot_active_mb',
'Inactive' : 'coldboot_inactive_mb',
}
class kernel_BootMessagesServer(test.test):
version = 1
def _read_dmesg(self, filename):
"""Put the contents of 'dmesg -r' into the given file.
@param filename: The file to write 'dmesg -r' into.
"""
f = open(filename, 'w')
self._client.run('dmesg -r', stdout_tee=f)
f.close()
return utils.read_file(filename)
def _reboot_machine(self):
"""Reboot the client machine.
We'll wait until the client is down, then up again.
"""
self._client.run('reboot')
self._client.wait_down()
self._client.wait_up()
def _read_meminfo(self, filename):
"""Fetch /proc/meminfo from client and return lines in the file
@param filename: The file to write 'cat /proc/meminfo' into.
"""
f = open(filename, 'w')
self._client.run('cat /proc/meminfo', stdout_tee=f)
f.close()
return utils.read_file(filename)
def _parse_meminfo(self, meminfo, perf_vals):
""" Parse the contents of each line of meminfo
if the line matches one of the interesting keys
save it into perf_vals in terms of megabytes
@param filelines: list of lines in meminfo
@param perf_vals: dictionary of performance metrics
"""
for line in meminfo.splitlines():
stuff = re.match('(.*):\s+(\d+)', line)
stat = stuff.group(1)
if stat in _meminfo_fields:
value = int(stuff.group(2))/ 1024
metric = _meminfo_fields[stat]
perf_vals[metric] = value
def _check_acpi_output(self, text, fwid):
# This dictionary is the database of expected strings in dmesg output.
# The keys are platform names, the values are two tuples, the first
# element is the regex to filter the messages, the second element is a
# set of strings to be found in the filtered dmesg set.
message_db = {
'Alex' : (r'(chromeos_acpi:|ChromeOS )', (
'chromeos_acpi: registering CHSW 0',
'chromeos_acpi: registering VBNV 0',
'chromeos_acpi: registering VBNV 1',
r'chromeos_acpi: truncating buffer from \d+ to \d+',
'chromeos_acpi: installed',
'ChromeOS firmware detected')),
'Mario' : (r'(chromeos_acpi|ChromeOS )', (
'chromeos_acpi: falling back to default list of methods',
'chromeos_acpi: registering CHSW 0',
'chromeos_acpi: registering CHNV 0',
'chromeos_acpi: failed to retrieve MLST \(5\)',
'chromeos_acpi: installed',
'Legacy ChromeOS firmware detected'))
}
if fwid not in message_db:
msg = 'Unnown platform %s, acpi dmesg set not defined.' % fwid
logging.error(msg)
raise error.TestFail(msg)
rv = utils.verify_mesg_set(text,
message_db[fwid][0],
message_db[fwid][1])
if rv:
logging.error('ACPI mismatch\n%s:' % rv)
raise error.TestFail('ACPI dmesg mismatch')
def run_once(self, host=None):
"""Run the test.
@param host: The client machine to connect to; should be a Host object.
"""
assert host is not None, "The host must be specified."
self._client = host
# get the firmware identifier from Crossystem
cs = utils.Crossystem(self._client)
cs.init()
fwid = cs.fwid().split('.')[0]
dmesg_filename = os.path.join(self.resultsdir, 'dmesg')
meminfo_filename = os.path.join(self.resultsdir, 'meminfo')
perf_vals = {}
self._reboot_machine()
meminfo = self._read_meminfo(meminfo_filename)
self._parse_meminfo(meminfo, perf_vals)
dmesg = self._read_dmesg(dmesg_filename)
if fwid not in _WHITELIST_TARGETS:
msg = 'Unnown platform %s, whitelist dmesg set not defined.' % fwid
logging.error(msg)
raise error.TestFail(msg)
unexpected = utils.check_raw_dmesg(
dmesg, _KERN_WARNING, _WHITELIST_COMMON + _WHITELIST_TARGETS[fwid])
if unexpected:
f = open(os.path.join(self.resultsdir, 'dmesg.err'), 'w')
for line in unexpected:
logging.error('UNEXPECTED DMESG: %s' % line)
f.write('%s\n' % line)
f.close()
raise error.TestFail("Unexpected dmesg warnings and/or errors.")
self.write_perf_keyval(perf_vals)
self._check_acpi_output(dmesg, fwid)