blob: 0767f87e00cdbdc81cf2f3aded97bf9f81795079 [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,
[email protected]4aebe8dc2012-06-19 01:49:06101 '--variable', 'PRODUCT_DIR', 'data',
[email protected]ae831df22012-06-13 19:31:54102 TARGET_PATH,
103 ]
[email protected]4aebe8dc2012-06-19 01:49:06104 if VERBOSE:
105 cmd.extend(['-v'] * 3)
[email protected]0507fc9d2012-06-14 14:09:41106 logging.debug(' '.join(cmd))
[email protected]ae831df22012-06-13 19:31:54107 proc = subprocess.Popen(
108 cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
109 out, err = proc.communicate() or ('', '') # pylint is confused.
[email protected]23ca8072012-07-06 14:29:05110 self.assertEquals(0, proc.returncode, (out, err))
[email protected]ae831df22012-06-13 19:31:54111 if sys.platform == 'win32':
112 # TODO(maruel): Figure out why replace('\r\n', '\n') doesn't work.
113 out = out.replace('\r', '')
[email protected]0507fc9d2012-06-14 14:09:41114 expected_out_re = '\n'.join([
115 r'',
116 r'\d+\.\ds Done post-processing logs\. Parsing logs\.',
117 r'\d+\.\ds Done parsing logs\.',
[email protected]4aebe8dc2012-06-19 01:49:06118 r'\d+.\ds Done stripping root\.',
119 r'\d+.\ds Done flattening\.',
[email protected]0507fc9d2012-06-14 14:09:41120 r'',
121 ])
122 self.assertTrue(re.match('^%s$' % expected_out_re, out), repr(out))
[email protected]ae831df22012-06-13 19:31:54123 self.assertTrue(err.startswith('\r'), err)
124
125 expected_json = {}
126 test_cases = (
127 'Baz.Fail',
128 'Foo.Bar1',
129 'Foo.Bar2',
130 'Foo.Bar3',
131 )
132 for test_case in test_cases:
133 expected_json[unicode(test_case)] = self._gen_results(test_case)
[email protected]0507fc9d2012-06-14 14:09:41134 expected_json['Baz.Fail']['returncode'] = 1
[email protected]ae831df22012-06-13 19:31:54135 with open(self.temp_file, 'r') as f:
136 result = json.load(f)
137
138 # Trim off 'duration' and 'output', they don't have a constant value.
139 for value in result.itervalues():
140 self._strip_result(value)
141 self.assertEquals(expected_json, result)
142
143
144if __name__ == '__main__':
145 VERBOSE = '-v' in sys.argv
146 logging.basicConfig(level=logging.DEBUG if VERBOSE else logging.ERROR)
147 unittest.main()