blob: 2dc09be4c68a30244728e6f015ff71e88a7cf767 [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]ae831df22012-06-13 19:31:5443
44 def tearDown(self):
45 if self.temp_file:
46 os.remove(self.temp_file)
47
48 def _gen_results(self, test_case):
49 return {
[email protected]0507fc9d2012-06-14 14:09:4150 u'processes': 1,
51 u'returncode': 0,
[email protected]ae831df22012-06-13 19:31:5452 u'results': {
53 u'root': {
54 u'children': [],
55 u'command': [
56 self.executable,
57 TARGET_PATH,
58 u'--gtest_filter=%s' % test_case,
59 ],
60 u'executable': self.real_executable,
61 u'files': [
62 {
63 u'path': os.path.join(u'data', 'gtest_fake', 'gtest_fake.py'),
64 u'size': os.stat(TARGET_PATH).st_size,
65 },
66 ],
67 u'initial_cwd': self.initial_cwd,
68 },
69 },
[email protected]0507fc9d2012-06-14 14:09:4170 u'valid': True,
[email protected]ae831df22012-06-13 19:31:5471 u'variables': {
72 u'isolate_dependency_tracked': [
73 u'<(PRODUCT_DIR)/gtest_fake/gtest_fake.py',
74 ],
75 },
76 }
77
78 def _strip_result(self, result):
79 """Strips mutable information from a flattened test case Results."""
80 self.assertTrue(result.pop('duration') > 0.)
81 self.assertTrue(len(result.pop('output')) > 10)
82 def strip_pid(proc):
83 self.assertTrue(proc.pop('pid') > 100)
84 for child in proc['children']:
85 strip_pid(child)
86 strip_pid(result['results']['root'])
87
88 def test_simple(self):
89 file_handle, self.temp_file = tempfile.mkstemp(
90 prefix='trace_test_cases_test')
91 os.close(file_handle)
92
93 cmd = [
94 sys.executable,
95 os.path.join(ROOT_DIR, 'trace_test_cases.py'),
[email protected]0507fc9d2012-06-14 14:09:4196 # Forces 4 parallel jobs.
97 '--jobs', '4',
[email protected]ae831df22012-06-13 19:31:5498 '--timeout', '0',
99 '--out', self.temp_file,
100 '--root-dir', ROOT_DIR,
101 '--cwd', ROOT_DIR,
[email protected]4aebe8dc2012-06-19 01:49:06102 '--variable', 'PRODUCT_DIR', 'data',
[email protected]ae831df22012-06-13 19:31:54103 TARGET_PATH,
104 ]
[email protected]4aebe8dc2012-06-19 01:49:06105 if VERBOSE:
106 cmd.extend(['-v'] * 3)
[email protected]0507fc9d2012-06-14 14:09:41107 logging.debug(' '.join(cmd))
[email protected]ae831df22012-06-13 19:31:54108 proc = subprocess.Popen(
109 cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
110 out, err = proc.communicate() or ('', '') # pylint is confused.
111 self.assertEquals(0, proc.returncode)
112 if sys.platform == 'win32':
113 # TODO(maruel): Figure out why replace('\r\n', '\n') doesn't work.
114 out = out.replace('\r', '')
[email protected]0507fc9d2012-06-14 14:09:41115 expected_out_re = '\n'.join([
116 r'',
117 r'\d+\.\ds Done post-processing logs\. Parsing logs\.',
118 r'\d+\.\ds Done parsing logs\.',
[email protected]4aebe8dc2012-06-19 01:49:06119 r'\d+.\ds Done stripping root\.',
120 r'\d+.\ds Done flattening\.',
[email protected]0507fc9d2012-06-14 14:09:41121 r'',
122 ])
123 self.assertTrue(re.match('^%s$' % expected_out_re, out), repr(out))
[email protected]ae831df22012-06-13 19:31:54124 self.assertTrue(err.startswith('\r'), err)
125
126 expected_json = {}
127 test_cases = (
128 'Baz.Fail',
129 'Foo.Bar1',
130 'Foo.Bar2',
131 'Foo.Bar3',
132 )
133 for test_case in test_cases:
134 expected_json[unicode(test_case)] = self._gen_results(test_case)
[email protected]0507fc9d2012-06-14 14:09:41135 expected_json['Baz.Fail']['returncode'] = 1
[email protected]ae831df22012-06-13 19:31:54136 with open(self.temp_file, 'r') as f:
137 result = json.load(f)
138
139 # Trim off 'duration' and 'output', they don't have a constant value.
140 for value in result.itervalues():
141 self._strip_result(value)
142 self.assertEquals(expected_json, result)
143
144
145if __name__ == '__main__':
146 VERBOSE = '-v' in sys.argv
147 logging.basicConfig(level=logging.DEBUG if VERBOSE else logging.ERROR)
148 unittest.main()