#!/usr/bin/python2 # # Copyright (c) 2015 The Chromium 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 os from autotest_lib.client.bin import test, utils from autotest_lib.client.common_lib import error class platform_TraceClockMonotonic(test.test): """ This verifies that the kernel supports monotonic clock timestamps for ftrace events. This is the same clock that Chrome will use for timestamping its trace events. """ version = 1 executable = 'ftrace-clock-monotonic' TRACE_PATH = '/sys/kernel/debug/tracing/' TRACE_CLOCK = TRACE_PATH + 'trace_clock' TRACE_FILE = TRACE_PATH + 'trace' TRACE_ENABLE = TRACE_PATH + 'tracing_on' def _setup_trace(self): """ Verify that the system supports the monotonic trace clock and set up the trace system to use it, and clean up any old stuff in the trace and enable it. """ with open(self.TRACE_CLOCK, 'r+') as clock: content = clock.read() if not 'mono' in content: raise error.TestFail('Kernel does not support monotonic clock') # Set up to use the monotonic clock clock.write('mono') # clear out the trace with open(self.TRACE_FILE, 'w') as trace: trace.write('') # enable tracing with open(self.TRACE_ENABLE, 'w') as enable: enable.write('1') def setup(self): """Cleans and makes ftrace-clock-monotonic.c. Prepares environment for tests by removing directory we will extract to (if it exists), extracting tarball of tests, and making them. """ os.chdir(self.srcdir) utils.make('clean') utils.make() def process_trace(self): """Opens the trace file and processes it. Looks for the 3 markers that are written out by the binary. The binary gets a clock timestamp and then writes it out into the trace three times. This looks at each entry and the content of the entry, and verifies that they are all in chronological order. Example trace file without the header: <...>-16484 [003] ...1 509651.512676: tracing_mark_write: start: 509651.512651785 <...>-16484 [003] ...1 509651.512680: tracing_mark_write: middle: 509651.512678312 <...>-16484 [003] ...1 509651.512682: tracing_mark_write: end: 509651.512680934 """ with open(self.TRACE_FILE, 'r') as trace: prev_timestamp = 0 for line in trace: if 'tracing_mark_write' not in line: continue columns = line.split() entry_timestamp = float(columns[3].replace(':','')) sample_timestamp = float(columns[6]) if sample_timestamp > entry_timestamp: raise error.TestFail('sample timestamp after trace marker entry') if sample_timestamp < prev_timestamp: raise error.TestFail('sample timestamp before previous timestamp') prev_timestamp = entry_timestamp if prev_timestamp == 0: raise error.TestFail('no valid timestamps seen in trace file') def run_once(self): self._setup_trace() binpath = os.path.join(self.srcdir, self.executable) utils.system_output(binpath, retain_output = True) self.process_trace()