OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import cStringIO | 6 import cStringIO |
7 import logging | 7 import logging |
8 import os | 8 import os |
9 import unittest | 9 import unittest |
10 import sys | 10 import sys |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 " },\n" | 88 " },\n" |
89 " }, {\n" | 89 " }, {\n" |
90 " 'variables': {\n" | 90 " 'variables': {\n" |
91 " },\n" | 91 " },\n" |
92 " }],\n" | 92 " }],\n" |
93 " ],\n" | 93 " ],\n" |
94 "}\n") | 94 "}\n") |
95 self._test(value, expected) | 95 self._test(value, expected) |
96 | 96 |
97 | 97 |
| 98 def join_norm(*args): |
| 99 """Joins and normalizes path in a single step.""" |
| 100 return unicode(os.path.normpath(os.path.join(*args))) |
| 101 |
| 102 |
98 if trace_inputs.get_flavor() == 'linux': | 103 if trace_inputs.get_flavor() == 'linux': |
99 class StraceInputs(unittest.TestCase): | 104 class StraceInputs(unittest.TestCase): |
100 def _test_lines( | 105 # Represents the root process pid (an arbitrary number). |
101 self, lines, initial_cwd, expected_files, expected_non_existent): | 106 _ROOT_PID = 27 |
| 107 _CHILD_PID = 14 |
| 108 _GRAND_CHILD_PID = 70 |
| 109 |
| 110 @staticmethod |
| 111 def _load_context(lines, initial_cwd): |
102 context = trace_inputs.Strace.Context(lambda _: False, initial_cwd) | 112 context = trace_inputs.Strace.Context(lambda _: False, initial_cwd) |
103 for line in lines: | 113 for line in lines: |
104 context.on_line(*line) | 114 context.on_line(*line) |
105 actual_files, actual_non_existent = context.resolve() | 115 return context.to_results().flatten() |
106 self.assertEquals(sorted(expected_files), sorted(actual_files)) | 116 |
107 self.assertEquals( | 117 def _test_lines(self, lines, initial_cwd, files, command=None): |
108 sorted(expected_non_existent), sorted(actual_non_existent)) | 118 command = command or ['../out/unittests'] |
| 119 expected = { |
| 120 'root': { |
| 121 'children': [], |
| 122 'command': None, |
| 123 'executable': None, |
| 124 'files': files, |
| 125 'initial_cwd': initial_cwd, |
| 126 'pid': self._ROOT_PID, |
| 127 } |
| 128 } |
| 129 if not files: |
| 130 expected['root']['command'] = None |
| 131 expected['root']['executable'] = None |
| 132 self.assertEquals(expected, self._load_context(lines, initial_cwd)) |
| 133 |
| 134 def test_execve(self): |
| 135 lines = [ |
| 136 (self._ROOT_PID, |
| 137 'execve("/home/foo_bar_user/out/unittests", ' |
| 138 '["/home/foo_bar_user/out/unittests", ' |
| 139 '"--gtest_filter=AtExitTest.Basic"], [/* 44 vars */]) = 0'), |
| 140 (self._ROOT_PID, |
| 141 'open("out/unittests.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 8'), |
| 142 ] |
| 143 files = [ |
| 144 { |
| 145 'path': u'/home/foo_bar_user/out/unittests', |
| 146 'size': -1, |
| 147 }, |
| 148 { |
| 149 'path': u'/home/foo_bar_user/src/out/unittests.log', |
| 150 'size': -1, |
| 151 }, |
| 152 ] |
| 153 command = [ |
| 154 '/home/foo_bar_user/out/unittests', '--gtest_filter=AtExitTest.Basic', |
| 155 ] |
| 156 self._test_lines(lines, '/home/foo_bar_user/src', files, command) |
109 | 157 |
110 def test_empty(self): | 158 def test_empty(self): |
111 self._test_lines([], None, [], []) | 159 try: |
| 160 self._load_context([], None) |
| 161 self.fail() |
| 162 except AssertionError: |
| 163 pass |
112 | 164 |
113 def test_close(self): | 165 def test_close(self): |
114 lines = [ | 166 lines = [ |
115 (90, 'close(7) = 0'), | 167 (self._ROOT_PID, 'close(7) = 0'), |
116 ] | 168 ] |
117 self._test_lines(lines, None, [], []) | 169 self._test_lines(lines, '/home/foo_bar_user/src', []) |
118 | 170 |
119 def test_clone(self): | 171 def test_clone(self): |
120 # Grand-child with relative directory. | 172 # Grand-child with relative directory. |
121 lines = [ | 173 lines = [ |
122 (86, 'clone(child_stack=0, flags=CLONE_CHILD_CLEARTID' | 174 (self._ROOT_PID, |
123 '|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f5350f829d0) = 14'), | 175 'clone(child_stack=0, flags=CLONE_CHILD_CLEARTID' |
124 (86, ') = ? <unavailable>'), | 176 '|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f5350f829d0) = %d' % |
125 (14, 'clone(child_stack=0, flags=CLONE_CHILD_CLEARTID' | 177 self._CHILD_PID), |
126 '|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f5350f829d0) = 70'), | 178 (self._CHILD_PID, |
127 (14, 'close(75) = 0'), | 179 'clone(child_stack=0, flags=CLONE_CHILD_CLEARTID' |
128 (70, 'open("%s", O_RDONLY) = 76' % os.path.basename(FILE_NAME)), | 180 '|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f5350f829d0) = %d' % |
129 ] | 181 self._GRAND_CHILD_PID), |
130 files = [ | 182 (self._GRAND_CHILD_PID, |
131 FILE_NAME, | 183 'open("%s", O_RDONLY) = 76' % os.path.basename(FILE_NAME)), |
132 ] | 184 ] |
133 self._test_lines(lines, ROOT_DIR, files, []) | 185 size = os.stat(FILE_NAME).st_size |
| 186 expected = { |
| 187 'root': { |
| 188 'children': [ |
| 189 { |
| 190 'children': [ |
| 191 { |
| 192 'children': [], |
| 193 'command': None, |
| 194 'executable': None, |
| 195 'files': [ |
| 196 { |
| 197 'path': unicode(FILE_NAME), |
| 198 'size': size, |
| 199 }, |
| 200 ], |
| 201 'initial_cwd': ROOT_DIR, |
| 202 'pid': self._GRAND_CHILD_PID, |
| 203 }, |
| 204 ], |
| 205 'command': None, |
| 206 'executable': None, |
| 207 'files': [], |
| 208 'initial_cwd': ROOT_DIR, |
| 209 'pid': self._CHILD_PID, |
| 210 }, |
| 211 ], |
| 212 'command': None, |
| 213 'executable': None, |
| 214 'files': [], |
| 215 'initial_cwd': ROOT_DIR, |
| 216 'pid': self._ROOT_PID, |
| 217 }, |
| 218 } |
| 219 self.assertEquals(expected, self._load_context(lines, ROOT_DIR)) |
| 220 |
| 221 def test_clone_chdir(self): |
| 222 # Grand-child with relative directory. |
| 223 lines = [ |
| 224 (self._ROOT_PID, |
| 225 'execve("../out/unittests", ' |
| 226 '["../out/unittests"...], [/* 44 vars */]) = 0'), |
| 227 (self._ROOT_PID, |
| 228 'clone(child_stack=0, flags=CLONE_CHILD_CLEARTID' |
| 229 '|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f5350f829d0) = %d' % |
| 230 self._CHILD_PID), |
| 231 (self._CHILD_PID, |
| 232 'chdir("/home_foo_bar_user/path1") = 0'), |
| 233 (self._CHILD_PID, |
| 234 'clone(child_stack=0, flags=CLONE_CHILD_CLEARTID' |
| 235 '|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f5350f829d0) = %d' % |
| 236 self._GRAND_CHILD_PID), |
| 237 (self._ROOT_PID, 'chdir("/home_foo_bar_user/path2") = 0'), |
| 238 (self._GRAND_CHILD_PID, |
| 239 'open("random.txt", O_RDONLY) = 76'), |
| 240 ] |
| 241 expected = { |
| 242 'root': { |
| 243 'children': [ |
| 244 { |
| 245 'children': [ |
| 246 { |
| 247 'children': [], |
| 248 'command': None, |
| 249 'executable': None, |
| 250 'files': [ |
| 251 { |
| 252 'path': u'/home_foo_bar_user/path1/random.txt', |
| 253 'size': -1, |
| 254 }, |
| 255 ], |
| 256 'initial_cwd': '/home_foo_bar_user/path1', |
| 257 'pid': self._GRAND_CHILD_PID, |
| 258 }, |
| 259 ], |
| 260 'command': None, |
| 261 'executable': None, |
| 262 # This is important, since no execve call was done, it didn't |
| 263 # touch the executable file. |
| 264 'files': [], |
| 265 'initial_cwd': ROOT_DIR, |
| 266 'pid': self._CHILD_PID, |
| 267 }, |
| 268 ], |
| 269 'command': None, |
| 270 'executable': None, |
| 271 'files': [ |
| 272 { |
| 273 'path': join_norm(ROOT_DIR, '../out/unittests'), |
| 274 'size': -1, |
| 275 }, |
| 276 ], |
| 277 'initial_cwd': ROOT_DIR, |
| 278 'pid': self._ROOT_PID, |
| 279 }, |
| 280 } |
| 281 self.assertEquals(expected, self._load_context(lines, ROOT_DIR)) |
134 | 282 |
135 def test_open(self): | 283 def test_open(self): |
136 lines = [ | 284 lines = [ |
137 (42, 'execve("../out/unittests", ' | 285 (self._ROOT_PID, |
138 '["../out/unittests"...], [/* 44 vars */]) = 0'), | 286 'execve("../out/unittests", ' |
139 (42, 'open("out/unittests.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 8'), | 287 '["../out/unittests"...], [/* 44 vars */]) = 0'), |
140 ] | 288 (self._ROOT_PID, |
141 files = [ | 289 'open("out/unittests.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 8'), |
142 u'/home/foo_bar_user/out/unittests', | 290 ] |
143 u'/home/foo_bar_user/src/out/unittests.log', | 291 files = [ |
144 ] | 292 { |
145 self._test_lines(lines, '/home/foo_bar_user/src', [], files) | 293 'path': u'/home/foo_bar_user/out/unittests', |
| 294 'size': -1, |
| 295 }, |
| 296 { |
| 297 'path': u'/home/foo_bar_user/src/out/unittests.log', |
| 298 'size': -1, |
| 299 }, |
| 300 ] |
| 301 self._test_lines(lines, '/home/foo_bar_user/src', files) |
146 | 302 |
147 def test_open_resumed(self): | 303 def test_open_resumed(self): |
148 lines = [ | 304 lines = [ |
149 (42, 'execve("../out/unittests", ' | 305 (self._ROOT_PID, |
150 '["../out/unittests"...], [/* 44 vars */]) = 0'), | 306 'execve("../out/unittests", ' |
151 (42, 'open("out/unittests.log", O_WRONLY|O_CREAT|O_APPEND ' | 307 '["../out/unittests"...], [/* 44 vars */]) = 0'), |
152 '<unfinished ...>'), | 308 (self._ROOT_PID, |
153 (42, '<... open resumed> ) = 3'), | 309 'open("out/unittests.log", O_WRONLY|O_CREAT|O_APPEND ' |
154 ] | 310 '<unfinished ...>'), |
155 files = [ | 311 (self._ROOT_PID, '<... open resumed> ) = 3'), |
156 u'/home/foo_bar_user/out/unittests', | 312 ] |
157 u'/home/foo_bar_user/src/out/unittests.log', | 313 files = [ |
158 ] | 314 { |
159 self._test_lines(lines, '/home/foo_bar_user/src', [], files) | 315 'path': u'/home/foo_bar_user/out/unittests', |
| 316 'size': -1, |
| 317 }, |
| 318 { |
| 319 'path': u'/home/foo_bar_user/src/out/unittests.log', |
| 320 'size': -1, |
| 321 }, |
| 322 ] |
| 323 self._test_lines(lines, '/home/foo_bar_user/src', files) |
160 | 324 |
161 def test_sig_unexpected(self): | 325 def test_sig_unexpected(self): |
162 lines = [ | 326 lines = [ |
163 (27, 'exit_group(0) = ?'), | 327 (self._ROOT_PID, 'exit_group(0) = ?'), |
164 ] | 328 ] |
165 self._test_lines(lines, ROOT_DIR, [], []) | 329 self._test_lines(lines, '/home/foo_bar_user/src', []) |
| 330 |
| 331 def test_stray(self): |
| 332 lines = [ |
| 333 (self._ROOT_PID, |
| 334 'execve("../out/unittests", ' |
| 335 '["../out/unittests"...], [/* 44 vars */]) = 0'), |
| 336 (self._ROOT_PID, |
| 337 ') = ? <unavailable>'), |
| 338 ] |
| 339 files = [ |
| 340 { |
| 341 'path': u'/home/foo_bar_user/out/unittests', |
| 342 'size': -1, |
| 343 }, |
| 344 ] |
| 345 self._test_lines(lines, '/home/foo_bar_user/src', files) |
166 | 346 |
167 | 347 |
168 if __name__ == '__main__': | 348 if __name__ == '__main__': |
169 VERBOSE = '-v' in sys.argv | 349 VERBOSE = '-v' in sys.argv |
170 logging.basicConfig(level=logging.DEBUG if VERBOSE else logging.ERROR) | 350 logging.basicConfig(level=logging.DEBUG if VERBOSE else logging.ERROR) |
171 unittest.main() | 351 unittest.main() |
OLD | NEW |