blob: db13507f16830b45d64215337afdd9123aa4733f [file] [log] [blame]
#!/usr/bin/env python
# Copyright (c) 2012 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 json
import logging
import os
import re
import subprocess
import sys
import tempfile
import unittest
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT_DIR = os.path.dirname(BASE_DIR)
sys.path.insert(0, ROOT_DIR)
import trace_inputs
FILE_PATH = os.path.realpath(unicode(os.path.abspath(__file__)))
TARGET_UTIL_PATH = os.path.join(BASE_DIR, 'gtest_fake', 'gtest_fake_base.py')
TARGET_PATH = os.path.join(BASE_DIR, 'gtest_fake', 'gtest_fake_fail.py')
class TraceTestCases(unittest.TestCase):
def setUp(self):
self.temp_file = None
self.initial_cwd = ROOT_DIR
if sys.platform == 'win32':
# Windows has no kernel mode concept of current working directory.
self.initial_cwd = None
# There's 2 kinds of references to python, self.executable,
# self.real_executable. It depends how python was started and on which OS.
self.executable = unicode(sys.executable)
if sys.platform == 'darwin':
# /usr/bin/python is a thunk executable that decides which version of
# python gets executed.
suffix = '.'.join(map(str, sys.version_info[0:2]))
if os.access(self.executable + suffix, os.X_OK):
# So it'll look like /usr/bin/python2.7
self.executable += suffix
self.real_executable = trace_inputs.get_native_path_case(self.executable)
# Make sure there's no environment variable that could do side effects.
os.environ.pop('GTEST_SHARD_INDEX', '')
os.environ.pop('GTEST_TOTAL_SHARDS', '')
def tearDown(self):
if self.temp_file:
os.remove(self.temp_file)
def _gen_results(self, test_case):
return {
u'processes': 1,
u'returncode': 0,
u'results': {
u'root': {
u'children': [],
u'command': [
self.executable,
TARGET_PATH,
u'--gtest_filter=%s' % test_case,
],
u'executable': self.real_executable,
u'files': [
{
u'path': os.path.join(u'tests', 'gtest_fake',
'gtest_fake_base.py'),
u'size': os.stat(TARGET_UTIL_PATH).st_size,
},
{
u'path': os.path.join(u'tests', 'gtest_fake',
'gtest_fake_fail.py'),
u'size': os.stat(TARGET_PATH).st_size,
},
],
u'initial_cwd': self.initial_cwd,
},
},
u'valid': True,
u'variables': {
u'isolate_dependency_tracked': [
u'<(PRODUCT_DIR)/gtest_fake/gtest_fake_base.py',
u'<(PRODUCT_DIR)/gtest_fake/gtest_fake_fail.py',
],
},
}
def _strip_result(self, result):
"""Strips mutable information from a flattened test case Results."""
self.assertTrue(result.pop('duration') > 0.)
self.assertTrue(len(result.pop('output')) > 10)
def strip_pid(proc):
self.assertTrue(proc.pop('pid') > 100)
for child in proc['children']:
strip_pid(child)
strip_pid(result['results']['root'])
def test_simple(self):
file_handle, self.temp_file = tempfile.mkstemp(
prefix='trace_test_cases_test')
os.close(file_handle)
cmd = [
sys.executable,
os.path.join(ROOT_DIR, 'trace_test_cases.py'),
# Forces 4 parallel jobs.
'--jobs', '4',
'--timeout', '0',
'--out', self.temp_file,
'--root-dir', ROOT_DIR,
'--variable', 'PRODUCT_DIR', 'tests',
TARGET_PATH,
]
if VERBOSE:
cmd.extend(['-v'] * 3)
logging.debug(' '.join(cmd))
proc = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate() or ('', '') # pylint is confused.
self.assertEquals(0, proc.returncode, (out, err))
lines = out.splitlines()
expected_out_re = [
r'\[1/4\] \d\.\d\ds .+',
r'\[2/4\] \d\.\d\ds .+',
r'\[3/4\] \d\.\d\ds .+',
r'\[4/4\] \d\.\d\ds .+',
r'\d+\.\ds Done post-processing logs\. Parsing logs\.',
r'\d+\.\ds Done parsing logs\.',
r'\d+\.\ds Done stripping root\.',
r'\d+\.\ds Done flattening\.',
]
for index in range(len(expected_out_re)):
self.assertTrue(
re.match('^%s$' % expected_out_re[index], lines[index]),
'%d: %s\n%r\n%s' % (
index, expected_out_re[index], lines[index], out))
# Junk is printed on win32.
if sys.platform != 'win32' and not VERBOSE:
self.assertEquals('', err)
expected_json = {}
test_cases = (
'Baz.Fail',
'Foo.Bar1',
'Foo.Bar2',
'Foo.Bar3',
)
for test_case in test_cases:
expected_json[unicode(test_case)] = self._gen_results(test_case)
expected_json['Baz.Fail']['returncode'] = 1
with open(self.temp_file, 'r') as f:
result = json.load(f)
# Trim off 'duration' and 'output', they don't have a constant value.
for value in result.itervalues():
self._strip_result(value)
self.assertEquals(expected_json, result)
if __name__ == '__main__':
VERBOSE = '-v' in sys.argv
logging.basicConfig(level=logging.DEBUG if VERBOSE else logging.ERROR)
unittest.main()