| # 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.", |
| ] |
| |
| _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 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) |
| 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) |