OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # coding=utf-8 | 2 # coding=utf-8 |
3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 import StringIO | 7 import StringIO |
8 import logging | 8 import logging |
9 import os | 9 import os |
10 import tempfile | 10 import tempfile |
11 import unittest | 11 import unittest |
12 import shutil | 12 import shutil |
13 import sys | 13 import sys |
14 | 14 |
15 BASE_DIR = unicode(os.path.dirname(os.path.abspath(__file__))) | 15 BASE_DIR = unicode(os.path.dirname(os.path.abspath(__file__))) |
16 ROOT_DIR = os.path.dirname(BASE_DIR) | 16 ROOT_DIR = os.path.dirname(BASE_DIR) |
17 sys.path.insert(0, ROOT_DIR) | 17 sys.path.insert(0, ROOT_DIR) |
18 | 18 |
19 FILE_PATH = unicode(os.path.abspath(__file__)) | 19 FILE_PATH = unicode(os.path.abspath(__file__)) |
20 | 20 |
21 import trace_inputs | 21 import trace_inputs |
22 | 22 |
| 23 # Access to a protected member _FOO of a client class |
| 24 # pylint: disable=W0212 |
| 25 |
23 | 26 |
24 def join_norm(*args): | 27 def join_norm(*args): |
25 """Joins and normalizes path in a single step.""" | 28 """Joins and normalizes path in a single step.""" |
26 return unicode(os.path.normpath(os.path.join(*args))) | 29 return unicode(os.path.normpath(os.path.join(*args))) |
27 | 30 |
28 | 31 |
29 class TraceInputs(unittest.TestCase): | 32 class TraceInputs(unittest.TestCase): |
30 def test_process_quoted_arguments(self): | 33 def test_process_quoted_arguments(self): |
31 test_cases = ( | 34 test_cases = ( |
32 ('"foo"', ['foo']), | 35 ('"foo"', ['foo']), |
33 ('"foo", "bar"', ['foo', 'bar']), | 36 ('"foo", "bar"', ['foo', 'bar']), |
34 ('"foo"..., "bar"', ['foo', 'bar']), | 37 ('"foo"..., "bar"', ['foo', 'bar']), |
35 ('"foo", "bar"...', ['foo', 'bar']), | 38 ('"foo", "bar"...', ['foo', 'bar']), |
36 ( | 39 ( |
37 '"/browser_tests", "--type=use,comma"', | 40 '"/browser_tests", "--type=use,comma"', |
38 ['/browser_tests', '--type=use,comma'] | 41 ['/browser_tests', '--type=use,comma'] |
39 ), | 42 ), |
40 ( | 43 ( |
41 '"/browser_tests", "--ignored=\\" --type=renderer \\""', | 44 '"/browser_tests", "--ignored=\\" --type=renderer \\""', |
42 ['/browser_tests', '--ignored=" --type=renderer "'] | 45 ['/browser_tests', '--ignored=" --type=renderer "'] |
43 ), | 46 ), |
44 ) | 47 ) |
45 for actual, expected in test_cases: | 48 for actual, expected in test_cases: |
46 self.assertEquals( | 49 self.assertEqual( |
47 expected, trace_inputs.strace_process_quoted_arguments(actual)) | 50 expected, trace_inputs.strace_process_quoted_arguments(actual)) |
48 | 51 |
49 def test_process_escaped_arguments(self): | 52 def test_process_escaped_arguments(self): |
50 test_cases = ( | 53 test_cases = ( |
51 ('foo\\0', ['foo']), | 54 ('foo\\0', ['foo']), |
52 ('foo\\001bar\\0', ['foo', 'bar']), | 55 ('foo\\001bar\\0', ['foo', 'bar']), |
53 ('\\"foo\\"\\0', ['"foo"']), | 56 ('\\"foo\\"\\0', ['"foo"']), |
54 ) | 57 ) |
55 for actual, expected in test_cases: | 58 for actual, expected in test_cases: |
56 self.assertEquals( | 59 self.assertEqual( |
57 expected, | 60 expected, |
58 trace_inputs.Dtrace.Context.process_escaped_arguments(actual)) | 61 trace_inputs.Dtrace.Context.process_escaped_arguments(actual)) |
59 | 62 |
60 def test_variable_abs(self): | 63 def test_variable_abs(self): |
61 value = trace_inputs.Results.File(None, u'/foo/bar', False, False) | 64 value = trace_inputs.Results.File(None, u'/foo/bar', False, False) |
62 actual = value.replace_variables({'$FOO': '/foo'}) | 65 actual = value.replace_variables({'$FOO': '/foo'}) |
63 self.assertEquals('$FOO/bar', actual.path) | 66 self.assertEqual('$FOO/bar', actual.path) |
64 self.assertEquals('$FOO/bar', actual.full_path) | 67 self.assertEqual('$FOO/bar', actual.full_path) |
65 self.assertEquals(True, actual.tainted) | 68 self.assertEqual(True, actual.tainted) |
66 | 69 |
67 def test_variable_rel(self): | 70 def test_variable_rel(self): |
68 value = trace_inputs.Results.File(u'/usr', u'foo/bar', False, False) | 71 value = trace_inputs.Results.File(u'/usr', u'foo/bar', False, False) |
69 actual = value.replace_variables({'$FOO': 'foo'}) | 72 actual = value.replace_variables({'$FOO': 'foo'}) |
70 self.assertEquals('$FOO/bar', actual.path) | 73 self.assertEqual('$FOO/bar', actual.path) |
71 self.assertEquals(os.path.join('/usr', '$FOO/bar'), actual.full_path) | 74 self.assertEqual(os.path.join('/usr', '$FOO/bar'), actual.full_path) |
72 self.assertEquals(True, actual.tainted) | 75 self.assertEqual(True, actual.tainted) |
73 | 76 |
74 def test_native_case_end_with_os_path_sep(self): | 77 def test_native_case_end_with_os_path_sep(self): |
75 # Make sure the trailing os.path.sep is kept. | 78 # Make sure the trailing os.path.sep is kept. |
76 path = trace_inputs.get_native_path_case(ROOT_DIR) + os.path.sep | 79 path = trace_inputs.get_native_path_case(ROOT_DIR) + os.path.sep |
77 self.assertEquals(trace_inputs.get_native_path_case(path), path) | 80 self.assertEqual(trace_inputs.get_native_path_case(path), path) |
78 | 81 |
79 def test_native_case_non_existing(self): | 82 def test_native_case_non_existing(self): |
80 # Make sure it doesn't throw on non-existing files. | 83 # Make sure it doesn't throw on non-existing files. |
81 non_existing = 'trace_input_test_this_file_should_not_exist' | 84 non_existing = 'trace_input_test_this_file_should_not_exist' |
82 path = os.path.expanduser('~/' + non_existing) | 85 path = os.path.expanduser('~/' + non_existing) |
83 self.assertFalse(os.path.exists(path)) | 86 self.assertFalse(os.path.exists(path)) |
84 path = trace_inputs.get_native_path_case(ROOT_DIR) + os.path.sep | 87 path = trace_inputs.get_native_path_case(ROOT_DIR) + os.path.sep |
85 self.assertEquals(trace_inputs.get_native_path_case(path), path) | 88 self.assertEqual(trace_inputs.get_native_path_case(path), path) |
86 | 89 |
87 def test_strace_filename(self): | 90 def test_strace_filename(self): |
88 filename = u'foo, bar, ~p#o,,ué^t%t.txt' | 91 filename = u'foo, bar, ~p#o,,ué^t%t.txt' |
89 data = 'foo, bar, ~p#o,,u\\303\\251^t%t.txt' | 92 data = 'foo, bar, ~p#o,,u\\303\\251^t%t.txt' |
90 self.assertEqual(filename, trace_inputs.Strace.load_filename(data)) | 93 self.assertEqual(filename, trace_inputs.Strace.load_filename(data)) |
91 | 94 |
92 def test_CsvReader(self): | 95 def test_CsvReader(self): |
93 test_cases = { | 96 test_cases = { |
94 u' Next is empty, , {00000000-0000}': | 97 u' Next is empty, , {00000000-0000}': |
95 [u'Next is empty', u'', u'{00000000-0000}'], | 98 [u'Next is empty', u'', u'{00000000-0000}'], |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 # This test also ensures that the output is independent on the input | 132 # This test also ensures that the output is independent on the input |
130 # string case. | 133 # string case. |
131 path = os.path.expanduser(u'~') | 134 path = os.path.expanduser(u'~') |
132 self.assertTrue(os.path.isdir(path)) | 135 self.assertTrue(os.path.isdir(path)) |
133 path = path.replace('/', os.path.sep) | 136 path = path.replace('/', os.path.sep) |
134 if sys.platform == 'win32': | 137 if sys.platform == 'win32': |
135 # Make sure the drive letter is upper case for consistency. | 138 # Make sure the drive letter is upper case for consistency. |
136 path = path[0].upper() + path[1:] | 139 path = path[0].upper() + path[1:] |
137 # This test assumes the variable is in the native path case on disk, this | 140 # This test assumes the variable is in the native path case on disk, this |
138 # should be the case. Verify this assumption: | 141 # should be the case. Verify this assumption: |
139 self.assertEquals(path, trace_inputs.get_native_path_case(path)) | 142 self.assertEqual(path, trace_inputs.get_native_path_case(path)) |
140 self.assertEquals( | 143 self.assertEqual( |
141 trace_inputs.get_native_path_case(path.lower()), | 144 trace_inputs.get_native_path_case(path.lower()), |
142 trace_inputs.get_native_path_case(path.upper())) | 145 trace_inputs.get_native_path_case(path.upper())) |
143 | 146 |
144 def test_native_case_not_sensitive_non_existent(self): | 147 def test_native_case_not_sensitive_non_existent(self): |
145 # This test also ensures that the output is independent on the input | 148 # This test also ensures that the output is independent on the input |
146 # string case. | 149 # string case. |
147 non_existing = os.path.join( | 150 non_existing = os.path.join( |
148 'trace_input_test_this_dir_should_not_exist', 'really not', '') | 151 'trace_input_test_this_dir_should_not_exist', 'really not', '') |
149 path = os.path.expanduser(os.path.join(u'~', non_existing)) | 152 path = os.path.expanduser(os.path.join(u'~', non_existing)) |
150 path = path.replace('/', os.path.sep) | 153 path = path.replace('/', os.path.sep) |
151 self.assertFalse(os.path.exists(path)) | 154 self.assertFalse(os.path.exists(path)) |
152 lower = trace_inputs.get_native_path_case(path.lower()) | 155 lower = trace_inputs.get_native_path_case(path.lower()) |
153 upper = trace_inputs.get_native_path_case(path.upper()) | 156 upper = trace_inputs.get_native_path_case(path.upper()) |
154 # Make sure non-existing element is not modified: | 157 # Make sure non-existing element is not modified: |
155 self.assertTrue(lower.endswith(non_existing.lower())) | 158 self.assertTrue(lower.endswith(non_existing.lower())) |
156 self.assertTrue(upper.endswith(non_existing.upper())) | 159 self.assertTrue(upper.endswith(non_existing.upper())) |
157 self.assertEquals(lower[:-len(non_existing)], upper[:-len(non_existing)]) | 160 self.assertEqual(lower[:-len(non_existing)], upper[:-len(non_existing)]) |
158 | 161 |
159 if sys.platform != 'win32': | 162 if sys.platform != 'win32': |
160 def test_symlink(self): | 163 def test_symlink(self): |
161 # This test will fail if the checkout is in a symlink. | 164 # This test will fail if the checkout is in a symlink. |
162 actual = trace_inputs.split_at_symlink(None, ROOT_DIR) | 165 actual = trace_inputs.split_at_symlink(None, ROOT_DIR) |
163 expected = (ROOT_DIR, None, None) | 166 expected = (ROOT_DIR, None, None) |
164 self.assertEquals(expected, actual) | 167 self.assertEqual(expected, actual) |
165 | 168 |
166 actual = trace_inputs.split_at_symlink( | 169 actual = trace_inputs.split_at_symlink( |
167 None, os.path.join(BASE_DIR, 'trace_inputs')) | 170 None, os.path.join(BASE_DIR, 'trace_inputs')) |
168 expected = ( | 171 expected = ( |
169 os.path.join(BASE_DIR, 'trace_inputs'), None, None) | 172 os.path.join(BASE_DIR, 'trace_inputs'), None, None) |
170 self.assertEquals(expected, actual) | 173 self.assertEqual(expected, actual) |
171 | 174 |
172 actual = trace_inputs.split_at_symlink( | 175 actual = trace_inputs.split_at_symlink( |
173 None, os.path.join(BASE_DIR, 'trace_inputs', 'files2')) | 176 None, os.path.join(BASE_DIR, 'trace_inputs', 'files2')) |
174 expected = ( | 177 expected = ( |
175 os.path.join(BASE_DIR, 'trace_inputs'), 'files2', '') | 178 os.path.join(BASE_DIR, 'trace_inputs'), 'files2', '') |
176 self.assertEquals(expected, actual) | 179 self.assertEqual(expected, actual) |
177 | 180 |
178 actual = trace_inputs.split_at_symlink( | 181 actual = trace_inputs.split_at_symlink( |
179 ROOT_DIR, os.path.join('tests', 'trace_inputs', 'files2')) | 182 ROOT_DIR, os.path.join('tests', 'trace_inputs', 'files2')) |
180 expected = ( | 183 expected = ( |
181 os.path.join('tests', 'trace_inputs'), 'files2', '') | 184 os.path.join('tests', 'trace_inputs'), 'files2', '') |
182 self.assertEquals(expected, actual) | 185 self.assertEqual(expected, actual) |
183 actual = trace_inputs.split_at_symlink( | 186 actual = trace_inputs.split_at_symlink( |
184 ROOT_DIR, os.path.join('tests', 'trace_inputs', 'files2', 'bar')) | 187 ROOT_DIR, os.path.join('tests', 'trace_inputs', 'files2', 'bar')) |
185 expected = ( | 188 expected = ( |
186 os.path.join('tests', 'trace_inputs'), 'files2', '/bar') | 189 os.path.join('tests', 'trace_inputs'), 'files2', '/bar') |
187 self.assertEquals(expected, actual) | 190 self.assertEqual(expected, actual) |
188 | 191 |
189 def test_native_case_symlink_right_case(self): | 192 def test_native_case_symlink_right_case(self): |
190 actual = trace_inputs.get_native_path_case( | 193 actual = trace_inputs.get_native_path_case( |
191 os.path.join(BASE_DIR, 'trace_inputs')) | 194 os.path.join(BASE_DIR, 'trace_inputs')) |
192 self.assertEquals('trace_inputs', os.path.basename(actual)) | 195 self.assertEqual('trace_inputs', os.path.basename(actual)) |
193 | 196 |
194 # Make sure the symlink is not resolved. | 197 # Make sure the symlink is not resolved. |
195 actual = trace_inputs.get_native_path_case( | 198 actual = trace_inputs.get_native_path_case( |
196 os.path.join(BASE_DIR, 'trace_inputs', 'files2')) | 199 os.path.join(BASE_DIR, 'trace_inputs', 'files2')) |
197 self.assertEquals('files2', os.path.basename(actual)) | 200 self.assertEqual('files2', os.path.basename(actual)) |
198 | 201 |
199 if sys.platform == 'darwin': | 202 if sys.platform == 'darwin': |
200 def test_native_case_symlink_wrong_case(self): | 203 def test_native_case_symlink_wrong_case(self): |
201 base_dir = trace_inputs.get_native_path_case(BASE_DIR) | 204 base_dir = trace_inputs.get_native_path_case(BASE_DIR) |
202 trace_inputs_dir = os.path.join(base_dir, 'trace_inputs') | 205 trace_inputs_dir = os.path.join(base_dir, 'trace_inputs') |
203 actual = trace_inputs.get_native_path_case(trace_inputs_dir) | 206 actual = trace_inputs.get_native_path_case(trace_inputs_dir) |
204 self.assertEquals(trace_inputs_dir, actual) | 207 self.assertEqual(trace_inputs_dir, actual) |
205 | 208 |
206 # Make sure the symlink is not resolved. | 209 # Make sure the symlink is not resolved. |
207 data = os.path.join(trace_inputs_dir, 'Files2') | 210 data = os.path.join(trace_inputs_dir, 'Files2') |
208 actual = trace_inputs.get_native_path_case(data) | 211 actual = trace_inputs.get_native_path_case(data) |
209 self.assertEquals( | 212 self.assertEqual( |
210 os.path.join(trace_inputs_dir, 'files2'), actual) | 213 os.path.join(trace_inputs_dir, 'files2'), actual) |
211 | 214 |
212 data = os.path.join(trace_inputs_dir, 'Files2', '') | 215 data = os.path.join(trace_inputs_dir, 'Files2', '') |
213 actual = trace_inputs.get_native_path_case(data) | 216 actual = trace_inputs.get_native_path_case(data) |
214 self.assertEquals( | 217 self.assertEqual( |
215 os.path.join(trace_inputs_dir, 'files2', ''), actual) | 218 os.path.join(trace_inputs_dir, 'files2', ''), actual) |
216 | 219 |
217 data = os.path.join(trace_inputs_dir, 'Files2', 'Child1.py') | 220 data = os.path.join(trace_inputs_dir, 'Files2', 'Child1.py') |
218 actual = trace_inputs.get_native_path_case(data) | 221 actual = trace_inputs.get_native_path_case(data) |
219 # TODO(maruel): Should be child1.py. | 222 # TODO(maruel): Should be child1.py. |
220 self.assertEquals( | 223 self.assertEqual( |
221 os.path.join(trace_inputs_dir, 'files2', 'Child1.py'), actual) | 224 os.path.join(trace_inputs_dir, 'files2', 'Child1.py'), actual) |
222 | 225 |
223 if sys.platform == 'win32': | 226 if sys.platform == 'win32': |
224 def test_native_case_alternate_datastream(self): | 227 def test_native_case_alternate_datastream(self): |
225 # Create the file manually, since tempfile doesn't support ADS. | 228 # Create the file manually, since tempfile doesn't support ADS. |
226 tempdir = unicode(tempfile.mkdtemp(prefix='trace_inputs')) | 229 tempdir = unicode(tempfile.mkdtemp(prefix='trace_inputs')) |
227 try: | 230 try: |
228 tempdir = trace_inputs.get_native_path_case(tempdir) | 231 tempdir = trace_inputs.get_native_path_case(tempdir) |
229 basename = 'foo.txt' | 232 basename = 'foo.txt' |
230 filename = basename + ':Zone.Identifier' | 233 filename = basename + ':Zone.Identifier' |
(...skipping 21 matching lines...) Expand all Loading... |
252 # Represents the root process pid (an arbitrary number). | 255 # Represents the root process pid (an arbitrary number). |
253 _ROOT_PID = 27 | 256 _ROOT_PID = 27 |
254 _CHILD_PID = 14 | 257 _CHILD_PID = 14 |
255 _GRAND_CHILD_PID = 70 | 258 _GRAND_CHILD_PID = 70 |
256 | 259 |
257 @staticmethod | 260 @staticmethod |
258 def _load_context(lines, initial_cwd): | 261 def _load_context(lines, initial_cwd): |
259 context = trace_inputs.Strace.Context(lambda _: False, initial_cwd) | 262 context = trace_inputs.Strace.Context(lambda _: False, initial_cwd) |
260 for line in lines: | 263 for line in lines: |
261 context.on_line(*line) | 264 context.on_line(*line) |
262 return context.to_results().flatten() | 265 done = any(p._done for p in context._process_lookup.itervalues()) |
| 266 return context.to_results().flatten(), done |
| 267 |
| 268 def assertContext(self, lines, initial_cwd, expected, expected_done): |
| 269 actual, actual_done = self._load_context(lines, initial_cwd) |
| 270 self.assertEqual(expected, actual) |
| 271 # If actual_done is True, this means the log was cut off abruptly. |
| 272 self.assertEqual(expected_done, actual_done) |
263 | 273 |
264 def _test_lines(self, lines, initial_cwd, files, command=None): | 274 def _test_lines(self, lines, initial_cwd, files, command=None): |
265 filepath = join_norm(initial_cwd, '../out/unittests') | 275 filepath = join_norm(initial_cwd, '../out/unittests') |
266 command = command or ['../out/unittests'] | 276 command = command or ['../out/unittests'] |
267 expected = { | 277 expected = { |
268 'root': { | 278 'root': { |
269 'children': [], | 279 'children': [], |
270 'command': command, | 280 'command': command, |
271 'executable': filepath, | 281 'executable': filepath, |
272 'files': files, | 282 'files': files, |
273 'initial_cwd': initial_cwd, | 283 'initial_cwd': initial_cwd, |
274 'pid': self._ROOT_PID, | 284 'pid': self._ROOT_PID, |
275 } | 285 } |
276 } | 286 } |
277 if not files: | 287 if not files: |
278 expected['root']['command'] = None | 288 expected['root']['command'] = None |
279 expected['root']['executable'] = None | 289 expected['root']['executable'] = None |
280 self.assertEquals(expected, self._load_context(lines, initial_cwd)) | 290 self.assertContext(lines, initial_cwd, expected, False) |
281 | 291 |
282 def test_execve(self): | 292 def test_execve(self): |
283 lines = [ | 293 lines = [ |
284 (self._ROOT_PID, | 294 (self._ROOT_PID, |
285 'execve("/home/foo_bar_user/out/unittests", ' | 295 'execve("/home/foo_bar_user/out/unittests", ' |
286 '["/home/foo_bar_user/out/unittests", ' | 296 '["/home/foo_bar_user/out/unittests", ' |
287 '"--gtest_filter=AtExitTest.Basic"], [/* 44 vars */]) = 0'), | 297 '"--gtest_filter=AtExitTest.Basic"], [/* 44 vars */]) = 0'), |
288 (self._ROOT_PID, | 298 (self._ROOT_PID, |
289 'open("out/unittests.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 8'), | 299 'open("out/unittests.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 8'), |
290 ] | 300 ] |
(...skipping 17 matching lines...) Expand all Loading... |
308 self._load_context([], None) | 318 self._load_context([], None) |
309 self.fail() | 319 self.fail() |
310 except trace_inputs.TracingFailure, e: | 320 except trace_inputs.TracingFailure, e: |
311 expected = ( | 321 expected = ( |
312 'Found internal inconsitency in process lifetime detection ' | 322 'Found internal inconsitency in process lifetime detection ' |
313 'while finding the root process', | 323 'while finding the root process', |
314 None, | 324 None, |
315 None, | 325 None, |
316 None, | 326 None, |
317 []) | 327 []) |
318 self.assertEquals(expected, e.args) | 328 self.assertEqual(expected, e.args) |
319 | 329 |
320 def test_chmod(self): | 330 def test_chmod(self): |
321 lines = [ | 331 lines = [ |
322 (self._ROOT_PID, 'chmod("temp/file", 0100644) = 0'), | 332 (self._ROOT_PID, 'chmod("temp/file", 0100644) = 0'), |
323 ] | 333 ] |
324 self._test_lines(lines, u'/home/foo_bar_user/src', []) | 334 self._test_lines(lines, u'/home/foo_bar_user/src', []) |
325 | 335 |
326 def test_close(self): | 336 def test_close(self): |
327 lines = [ | 337 lines = [ |
328 (self._ROOT_PID, 'close(7) = 0'), | 338 (self._ROOT_PID, 'close(7) = 0'), |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 'pid': self._CHILD_PID, | 380 'pid': self._CHILD_PID, |
371 }, | 381 }, |
372 ], | 382 ], |
373 'command': None, | 383 'command': None, |
374 'executable': None, | 384 'executable': None, |
375 'files': [], | 385 'files': [], |
376 'initial_cwd': BASE_DIR, | 386 'initial_cwd': BASE_DIR, |
377 'pid': self._ROOT_PID, | 387 'pid': self._ROOT_PID, |
378 }, | 388 }, |
379 } | 389 } |
380 self.assertEquals(expected, self._load_context(lines, BASE_DIR)) | 390 self.assertContext(lines, BASE_DIR, expected, False) |
381 | 391 |
382 def test_clone_chdir(self): | 392 def test_clone_chdir(self): |
383 # Grand-child with relative directory. | 393 # Grand-child with relative directory. |
384 lines = [ | 394 lines = [ |
385 (self._ROOT_PID, | 395 (self._ROOT_PID, |
386 'execve("../out/unittests", ' | 396 'execve("../out/unittests", ' |
387 '["../out/unittests"...], [/* 44 vars */]) = 0'), | 397 '["../out/unittests"...], [/* 44 vars */]) = 0'), |
388 (self._ROOT_PID, | 398 (self._ROOT_PID, |
389 'clone(child_stack=0, flags=CLONE_CHILD_CLEARTID' | 399 'clone(child_stack=0, flags=CLONE_CHILD_CLEARTID' |
390 '|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f5350f829d0) = %d' % | 400 '|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f5350f829d0) = %d' % |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 'files': [ | 451 'files': [ |
442 { | 452 { |
443 'path': join_norm(ROOT_DIR, '../out/unittests'), | 453 'path': join_norm(ROOT_DIR, '../out/unittests'), |
444 'size': -1, | 454 'size': -1, |
445 }, | 455 }, |
446 ], | 456 ], |
447 'initial_cwd': unicode(ROOT_DIR), | 457 'initial_cwd': unicode(ROOT_DIR), |
448 'pid': self._ROOT_PID, | 458 'pid': self._ROOT_PID, |
449 }, | 459 }, |
450 } | 460 } |
451 self.assertEquals(expected, self._load_context(lines, ROOT_DIR)) | 461 self.assertContext(lines, ROOT_DIR, expected, False) |
452 | 462 |
453 def test_faccess(self): | 463 def test_faccess(self): |
454 lines = [ | 464 lines = [ |
455 (self._ROOT_PID, | 465 (self._ROOT_PID, |
456 'faccessat(AT_FDCWD, "/home_foo_bar_user/file", W_OK) = 0'), | 466 'faccessat(AT_FDCWD, "/home_foo_bar_user/file", W_OK) = 0'), |
457 ] | 467 ] |
458 expected = { | 468 expected = { |
459 'root': { | 469 'root': { |
460 'children': [], | 470 'children': [], |
461 'command': None, | 471 'command': None, |
462 'executable': None, | 472 'executable': None, |
463 'files': [{'path': '/home_foo_bar_user/file', 'size': 0}], | 473 'files': [{'path': '/home_foo_bar_user/file', 'size': 0}], |
464 'initial_cwd': unicode(ROOT_DIR), | 474 'initial_cwd': unicode(ROOT_DIR), |
465 'pid': self._ROOT_PID, | 475 'pid': self._ROOT_PID, |
466 }, | 476 }, |
467 } | 477 } |
468 self.assertEquals(expected, self._load_context(lines, ROOT_DIR)) | 478 self.assertContext(lines, ROOT_DIR, expected, False) |
469 | 479 |
470 def test_futex_died(self): | 480 def test_futex_died(self): |
471 # That's a pretty bad fork, copy-pasted from a real log. | 481 # That's a pretty bad fork, copy-pasted from a real log. |
472 lines = [ | 482 lines = [ |
473 (self._ROOT_PID, 'close(9) = 0'), | 483 (self._ROOT_PID, 'close(9) = 0'), |
474 (self._ROOT_PID, 'futex( <unfinished ... exit status 0>'), | 484 (self._ROOT_PID, 'futex( <unfinished ... exit status 0>'), |
475 ] | 485 ] |
476 expected = { | 486 expected = { |
477 'root': { | 487 'root': { |
478 'children': [], | 488 'children': [], |
479 'command': None, | 489 'command': None, |
480 'executable': None, | 490 'executable': None, |
481 'files': [], | 491 'files': [], |
482 'initial_cwd': unicode(ROOT_DIR), | 492 'initial_cwd': unicode(ROOT_DIR), |
483 'pid': self._ROOT_PID, | 493 'pid': self._ROOT_PID, |
484 }, | 494 }, |
485 } | 495 } |
486 self.assertEquals(expected, self._load_context(lines, ROOT_DIR)) | 496 self.assertContext(lines, ROOT_DIR, expected, True) |
487 | 497 |
488 def test_futex_missing_in_action(self): | 498 def test_futex_missing_in_action(self): |
489 # That's how futex() calls roll. | 499 # That's how futex() calls roll. |
490 lines = [ | 500 lines = [ |
491 (self._ROOT_PID, | 501 (self._ROOT_PID, |
492 'clone(child_stack=0x7fae9f4bed70, flags=CLONE_VM|CLONE_FS|' | 502 'clone(child_stack=0x7fae9f4bed70, flags=CLONE_VM|CLONE_FS|' |
493 'CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|' | 503 'CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|' |
494 'CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, ' | 504 'CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, ' |
495 'parent_tidptr=0x7fae9f4bf9d0, tls=0x7fae9f4bf700, ' | 505 'parent_tidptr=0x7fae9f4bf9d0, tls=0x7fae9f4bf700, ' |
496 'child_tidptr=0x7fae9f4bf9d0) = 3862'), | 506 'child_tidptr=0x7fae9f4bf9d0) = 3862'), |
(...skipping 16 matching lines...) Expand all Loading... |
513 'pid': 3862, | 523 'pid': 3862, |
514 }, | 524 }, |
515 ], | 525 ], |
516 'command': None, | 526 'command': None, |
517 'executable': None, | 527 'executable': None, |
518 'files': [], | 528 'files': [], |
519 'initial_cwd': unicode(ROOT_DIR), | 529 'initial_cwd': unicode(ROOT_DIR), |
520 'pid': self._ROOT_PID, | 530 'pid': self._ROOT_PID, |
521 }, | 531 }, |
522 } | 532 } |
523 self.assertEquals(expected, self._load_context(lines, ROOT_DIR)) | 533 self.assertContext(lines, ROOT_DIR, expected, True) |
524 | 534 |
525 def test_futex_missing_in_partial_action(self): | 535 def test_futex_missing_in_partial_action(self): |
526 # That's how futex() calls roll even more. | 536 # That's how futex() calls roll even more. |
527 lines = [ | 537 lines = [ |
528 (self._ROOT_PID, | 538 (self._ROOT_PID, |
529 'futex(0x7fff25718b14, FUTEX_CMP_REQUEUE_PRIVATE, 1, 2147483647, ' | 539 'futex(0x7fff25718b14, FUTEX_CMP_REQUEUE_PRIVATE, 1, 2147483647, ' |
530 '0x7fff25718ae8, 2) = 1'), | 540 '0x7fff25718ae8, 2) = 1'), |
531 (self._ROOT_PID, 'futex(0x7fff25718ae8, FUTEX_WAKE_PRIVATE, 1) = 0'), | 541 (self._ROOT_PID, 'futex(0x7fff25718ae8, FUTEX_WAKE_PRIVATE, 1) = 0'), |
532 (self._ROOT_PID, 'futex(0x697263c, FUTEX_WAIT_PRIVATE, 1, NULL) = 0'), | 542 (self._ROOT_PID, 'futex(0x697263c, FUTEX_WAIT_PRIVATE, 1, NULL) = 0'), |
533 (self._ROOT_PID, 'futex(0x6972610, FUTEX_WAKE_PRIVATE, 1) = 0'), | 543 (self._ROOT_PID, 'futex(0x6972610, FUTEX_WAKE_PRIVATE, 1) = 0'), |
(...skipping 10 matching lines...) Expand all Loading... |
544 expected = { | 554 expected = { |
545 'root': { | 555 'root': { |
546 'children': [], | 556 'children': [], |
547 'command': None, | 557 'command': None, |
548 'executable': None, | 558 'executable': None, |
549 'files': [], | 559 'files': [], |
550 'initial_cwd': unicode(ROOT_DIR), | 560 'initial_cwd': unicode(ROOT_DIR), |
551 'pid': self._ROOT_PID, | 561 'pid': self._ROOT_PID, |
552 }, | 562 }, |
553 } | 563 } |
554 self.assertEquals(expected, self._load_context(lines, ROOT_DIR)) | 564 self.assertContext(lines, ROOT_DIR, expected, True) |
555 | 565 |
556 def test_futex_missing_in_partial_action_with_no_process(self): | 566 def test_futex_missing_in_partial_action_with_no_process(self): |
557 # That's how futex() calls roll even more (again). | 567 # That's how futex() calls roll even more (again). |
558 lines = [ | 568 lines = [ |
559 (self._ROOT_PID, 'futex(0x7134840, FUTEX_WAIT_PRIVATE, 2, ' | 569 (self._ROOT_PID, 'futex(0x7134840, FUTEX_WAIT_PRIVATE, 2, ' |
560 'NULL <ptrace(SYSCALL):No such process>'), | 570 'NULL <ptrace(SYSCALL):No such process>'), |
561 ] | 571 ] |
562 expected = { | 572 expected = { |
563 'root': { | 573 'root': { |
564 'children': [], | 574 'children': [], |
565 'command': None, | 575 'command': None, |
566 'executable': None, | 576 'executable': None, |
567 'files': [], | 577 'files': [], |
568 'initial_cwd': unicode(ROOT_DIR), | 578 'initial_cwd': unicode(ROOT_DIR), |
569 'pid': self._ROOT_PID, | 579 'pid': self._ROOT_PID, |
570 }, | 580 }, |
571 } | 581 } |
572 self.assertEquals(expected, self._load_context(lines, ROOT_DIR)) | 582 self.assertContext(lines, ROOT_DIR, expected, True) |
573 | 583 |
574 def test_open(self): | 584 def test_open(self): |
575 lines = [ | 585 lines = [ |
576 (self._ROOT_PID, | 586 (self._ROOT_PID, |
577 'execve("../out/unittests", ' | 587 'execve("../out/unittests", ' |
578 '["../out/unittests"...], [/* 44 vars */]) = 0'), | 588 '["../out/unittests"...], [/* 44 vars */]) = 0'), |
579 (self._ROOT_PID, | 589 (self._ROOT_PID, |
580 'open("out/unittests.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 8'), | 590 'open("out/unittests.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 8'), |
581 ] | 591 ] |
582 files = [ | 592 files = [ |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
627 'size': -1, | 637 'size': -1, |
628 }, | 638 }, |
629 { | 639 { |
630 'path': u'/home/foo_bar_user/out/unittests', | 640 'path': u'/home/foo_bar_user/out/unittests', |
631 'size': -1, | 641 'size': -1, |
632 }, | 642 }, |
633 ] | 643 ] |
634 | 644 |
635 self._test_lines(lines, u'/home/foo_bar_user/src', files) | 645 self._test_lines(lines, u'/home/foo_bar_user/src', files) |
636 | 646 |
| 647 def test_openat_died(self): |
| 648 lines = [ |
| 649 # It's fine as long as there is nothing after. |
| 650 ( self._ROOT_PID, |
| 651 'openat(AT_FDCWD, "/tmp/.org.chromium.Chromium.NLRojh/Plugins", ' |
| 652 'O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC'), |
| 653 ] |
| 654 expected = { |
| 655 'root': { |
| 656 'children': [], |
| 657 'command': None, |
| 658 'executable': None, |
| 659 'files': [], |
| 660 'initial_cwd': unicode(ROOT_DIR), |
| 661 'pid': self._ROOT_PID, |
| 662 }, |
| 663 } |
| 664 self.assertContext(lines, ROOT_DIR, expected, True) |
| 665 |
637 def test_rmdir(self): | 666 def test_rmdir(self): |
638 lines = [ | 667 lines = [ |
639 (self._ROOT_PID, 'rmdir("directory/to/delete") = 0'), | 668 (self._ROOT_PID, 'rmdir("directory/to/delete") = 0'), |
640 ] | 669 ] |
641 self._test_lines(lines, u'/home/foo_bar_user/src', []) | 670 self._test_lines(lines, u'/home/foo_bar_user/src', []) |
642 | 671 |
643 def test_setxattr(self): | 672 def test_setxattr(self): |
644 lines = [ | 673 lines = [ |
645 (self._ROOT_PID, | 674 (self._ROOT_PID, |
646 'setxattr("file.exe", "attribute", "value", 0, 0) = 0'), | 675 'setxattr("file.exe", "attribute", "value", 0, 0) = 0'), |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 'size': -1, | 716 'size': -1, |
688 }, | 717 }, |
689 ] | 718 ] |
690 self._test_lines(lines, u'/home/foo_bar_user/src', files) | 719 self._test_lines(lines, u'/home/foo_bar_user/src', files) |
691 | 720 |
692 | 721 |
693 if __name__ == '__main__': | 722 if __name__ == '__main__': |
694 VERBOSE = '-v' in sys.argv | 723 VERBOSE = '-v' in sys.argv |
695 logging.basicConfig(level=logging.DEBUG if VERBOSE else logging.ERROR) | 724 logging.basicConfig(level=logging.DEBUG if VERBOSE else logging.ERROR) |
696 unittest.main() | 725 unittest.main() |
OLD | NEW |