blob: faa11130062329b28e89386169efa5012284956b [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
42 self.real_executable = trace_inputs.get_native_path_case(
43 self.executable)
44
45 if sys.platform == 'darwin':
46 # Interestingly, only OSX does resolve the symlink manually before
47 # starting the executable.
48 if os.path.islink(self.real_executable):
49 self.real_executable = os.path.normpath(
50 os.path.join(
51 os.path.dirname(self.real_executable),
52 os.readlink(self.real_executable)))
53
54 def tearDown(self):
55 if self.temp_file:
56 os.remove(self.temp_file)
57
58 def _gen_results(self, test_case):
59 return {
[email protected]0507fc9d2012-06-14 14:09:4160 u'processes': 1,
61 u'returncode': 0,
[email protected]ae831df22012-06-13 19:31:5462 u'results': {
63 u'root': {
64 u'children': [],
65 u'command': [
66 self.executable,
67 TARGET_PATH,
68 u'--gtest_filter=%s' % test_case,
69 ],
70 u'executable': self.real_executable,
71 u'files': [
72 {
73 u'path': os.path.join(u'data', 'gtest_fake', 'gtest_fake.py'),
74 u'size': os.stat(TARGET_PATH).st_size,
75 },
76 ],
77 u'initial_cwd': self.initial_cwd,
78 },
79 },
[email protected]0507fc9d2012-06-14 14:09:4180 u'valid': True,
[email protected]ae831df22012-06-13 19:31:5481 u'variables': {
82 u'isolate_dependency_tracked': [
83 u'<(PRODUCT_DIR)/gtest_fake/gtest_fake.py',
84 ],
85 },
86 }
87
88 def _strip_result(self, result):
89 """Strips mutable information from a flattened test case Results."""
90 self.assertTrue(result.pop('duration') > 0.)
91 self.assertTrue(len(result.pop('output')) > 10)
92 def strip_pid(proc):
93 self.assertTrue(proc.pop('pid') > 100)
94 for child in proc['children']:
95 strip_pid(child)
96 strip_pid(result['results']['root'])
97
98 def test_simple(self):
99 file_handle, self.temp_file = tempfile.mkstemp(
100 prefix='trace_test_cases_test')
101 os.close(file_handle)
102
103 cmd = [
104 sys.executable,
105 os.path.join(ROOT_DIR, 'trace_test_cases.py'),
[email protected]0507fc9d2012-06-14 14:09:41106 # Forces 4 parallel jobs.
107 '--jobs', '4',
[email protected]ae831df22012-06-13 19:31:54108 '--timeout', '0',
109 '--out', self.temp_file,
110 '--root-dir', ROOT_DIR,
111 '--cwd', ROOT_DIR,
112 '--product-dir', 'data',
113 TARGET_PATH,
114 ]
[email protected]0507fc9d2012-06-14 14:09:41115 logging.debug(' '.join(cmd))
[email protected]ae831df22012-06-13 19:31:54116 proc = subprocess.Popen(
117 cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
118 out, err = proc.communicate() or ('', '') # pylint is confused.
119 self.assertEquals(0, proc.returncode)
120 if sys.platform == 'win32':
121 # TODO(maruel): Figure out why replace('\r\n', '\n') doesn't work.
122 out = out.replace('\r', '')
[email protected]0507fc9d2012-06-14 14:09:41123 expected_out_re = '\n'.join([
124 r'',
125 r'\d+\.\ds Done post-processing logs\. Parsing logs\.',
126 r'\d+\.\ds Done parsing logs\.',
127 r'',
128 ])
129 self.assertTrue(re.match('^%s$' % expected_out_re, out), repr(out))
[email protected]ae831df22012-06-13 19:31:54130 self.assertTrue(err.startswith('\r'), err)
131
132 expected_json = {}
133 test_cases = (
134 'Baz.Fail',
135 'Foo.Bar1',
136 'Foo.Bar2',
137 'Foo.Bar3',
138 )
139 for test_case in test_cases:
140 expected_json[unicode(test_case)] = self._gen_results(test_case)
[email protected]0507fc9d2012-06-14 14:09:41141 expected_json['Baz.Fail']['returncode'] = 1
[email protected]ae831df22012-06-13 19:31:54142 with open(self.temp_file, 'r') as f:
143 result = json.load(f)
144
145 # Trim off 'duration' and 'output', they don't have a constant value.
146 for value in result.itervalues():
147 self._strip_result(value)
148 self.assertEquals(expected_json, result)
149
150
151if __name__ == '__main__':
152 VERBOSE = '-v' in sys.argv
153 logging.basicConfig(level=logging.DEBUG if VERBOSE else logging.ERROR)
154 unittest.main()