blob: 88c2446f6e5c8cfa005218675269d8a2e2b8ca82 [file] [log] [blame]
[email protected]ae831df22012-06-13 19:31:541#!/usr/bin/env python
2# Copyright (c) 2012 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import json
7import logging
8import os
[email protected]0507fc9d2012-06-14 14:09:419import re
[email protected]ae831df22012-06-13 19:31:5410import subprocess
11import sys
12import tempfile
13import unittest
14
15import trace_inputs
16
17FILE_PATH = os.path.realpath(unicode(os.path.abspath(__file__)))
18ROOT_DIR = os.path.dirname(FILE_PATH)
19TARGET_PATH = os.path.join(ROOT_DIR, 'data', 'gtest_fake', 'gtest_fake.py')
20
21
22class TraceTestCases(unittest.TestCase):
23 def setUp(self):
24 self.temp_file = None
25
26 self.initial_cwd = ROOT_DIR
27 if sys.platform == 'win32':
28 # Windows has no kernel mode concept of current working directory.
29 self.initial_cwd = None
30
31 # There's 2 kinds of references to python, self.executable,
32 # self.real_executable. It depends how python was started and on which OS.
33 self.executable = unicode(sys.executable)
34 if sys.platform == 'darwin':
35 # /usr/bin/python is a thunk executable that decides which version of
36 # python gets executed.
37 suffix = '.'.join(map(str, sys.version_info[0:2]))
38 if os.access(self.executable + suffix, os.X_OK):
39 # So it'll look like /usr/bin/python2.7
40 self.executable += suffix
41
[email protected]b9d1e2612012-07-05 02:14:5142 self.real_executable = trace_inputs.get_native_path_case(self.executable)
[email protected]f6988622012-07-21 13:57:0143 # Make sure there's no environment variable that could do side effects.
44 os.environ.pop('GTEST_SHARD_INDEX', '')
45 os.environ.pop('GTEST_TOTAL_SHARDS', '')
[email protected]ae831df22012-06-13 19:31:5446
47 def tearDown(self):
48 if self.temp_file:
49 os.remove(self.temp_file)
50
51 def _gen_results(self, test_case):
52 return {
[email protected]0507fc9d2012-06-14 14:09:4153 u'processes': 1,
54 u'returncode': 0,
[email protected]ae831df22012-06-13 19:31:5455 u'results': {
56 u'root': {
57 u'children': [],
58 u'command': [
59 self.executable,
60 TARGET_PATH,
61 u'--gtest_filter=%s' % test_case,
62 ],
63 u'executable': self.real_executable,
64 u'files': [
65 {
66 u'path': os.path.join(u'data', 'gtest_fake', 'gtest_fake.py'),
67 u'size': os.stat(TARGET_PATH).st_size,
68 },
69 ],
70 u'initial_cwd': self.initial_cwd,
71 },
72 },
[email protected]0507fc9d2012-06-14 14:09:4173 u'valid': True,
[email protected]ae831df22012-06-13 19:31:5474 u'variables': {
75 u'isolate_dependency_tracked': [
76 u'<(PRODUCT_DIR)/gtest_fake/gtest_fake.py',
77 ],
78 },
79 }
80
81 def _strip_result(self, result):
82 """Strips mutable information from a flattened test case Results."""
83 self.assertTrue(result.pop('duration') > 0.)
84 self.assertTrue(len(result.pop('output')) > 10)
85 def strip_pid(proc):
86 self.assertTrue(proc.pop('pid') > 100)
87 for child in proc['children']:
88 strip_pid(child)
89 strip_pid(result['results']['root'])
90
91 def test_simple(self):
92 file_handle, self.temp_file = tempfile.mkstemp(
93 prefix='trace_test_cases_test')
94 os.close(file_handle)
95
96 cmd = [
97 sys.executable,
98 os.path.join(ROOT_DIR, 'trace_test_cases.py'),
[email protected]0507fc9d2012-06-14 14:09:4199 # Forces 4 parallel jobs.
100 '--jobs', '4',
[email protected]ae831df22012-06-13 19:31:54101 '--timeout', '0',
102 '--out', self.temp_file,
103 '--root-dir', ROOT_DIR,
[email protected]4aebe8dc2012-06-19 01:49:06104 '--variable', 'PRODUCT_DIR', 'data',
[email protected]ae831df22012-06-13 19:31:54105 TARGET_PATH,
106 ]
[email protected]4aebe8dc2012-06-19 01:49:06107 if VERBOSE:
108 cmd.extend(['-v'] * 3)
[email protected]0507fc9d2012-06-14 14:09:41109 logging.debug(' '.join(cmd))
[email protected]ae831df22012-06-13 19:31:54110 proc = subprocess.Popen(
111 cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
112 out, err = proc.communicate() or ('', '') # pylint is confused.
[email protected]23ca8072012-07-06 14:29:05113 self.assertEquals(0, proc.returncode, (out, err))
[email protected]162c0a32012-07-20 17:15:46114 lines = out.splitlines()
115 expected_out_re = [
116 r'\[1/4\] \d\.\d\ds .+',
117 r'\[2/4\] \d\.\d\ds .+',
118 r'\[3/4\] \d\.\d\ds .+',
119 r'\[4/4\] \d\.\d\ds .+',
120 r'\d+\.\ds Done post-processing logs\. Parsing logs\.',
121 r'\d+\.\ds Done parsing logs\.',
[email protected]f6988622012-07-21 13:57:01122 r'\d+\.\ds Done stripping root\.',
123 r'\d+\.\ds Done flattening\.',
[email protected]162c0a32012-07-20 17:15:46124 ]
125 for index in range(len(expected_out_re)):
126 self.assertTrue(
127 re.match('^%s$' % expected_out_re[index], lines[index]),
[email protected]f6988622012-07-21 13:57:01128 (index, expected_out_re[index], repr(lines[index])))
[email protected]162c0a32012-07-20 17:15:46129 # Junk is printed on win32.
130 if sys.platform != 'win32':
131 self.assertEquals('', err)
[email protected]ae831df22012-06-13 19:31:54132
133 expected_json = {}
134 test_cases = (
135 'Baz.Fail',
136 'Foo.Bar1',
137 'Foo.Bar2',
138 'Foo.Bar3',
139 )
140 for test_case in test_cases:
141 expected_json[unicode(test_case)] = self._gen_results(test_case)
[email protected]0507fc9d2012-06-14 14:09:41142 expected_json['Baz.Fail']['returncode'] = 1
[email protected]ae831df22012-06-13 19:31:54143 with open(self.temp_file, 'r') as f:
144 result = json.load(f)
145
146 # Trim off 'duration' and 'output', they don't have a constant value.
147 for value in result.itervalues():
148 self._strip_result(value)
149 self.assertEquals(expected_json, result)
150
151
152if __name__ == '__main__':
153 VERBOSE = '-v' in sys.argv
154 logging.basicConfig(level=logging.DEBUG if VERBOSE else logging.ERROR)
155 unittest.main()