OLD | NEW |
1 # Copyright 2014 Google Inc. All rights reserved. | 1 # Copyright 2014 Google Inc. All rights reserved. |
2 # | 2 # |
3 # Licensed under the Apache License, Version 2.0 (the "License"); | 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
4 # you may not use this file except in compliance with the License. | 4 # you may not use this file except in compliance with the License. |
5 # You may obtain a copy of the License at | 5 # You may obtain a copy of the License at |
6 # | 6 # |
7 # http://www.apache.org/licenses/LICENSE-2.0 | 7 # http://www.apache.org/licenses/LICENSE-2.0 |
8 # | 8 # |
9 # Unless required by applicable law or agreed to in writing, software | 9 # Unless required by applicable law or agreed to in writing, software |
10 # distributed under the License is distributed on an "AS IS" BASIS, | 10 # distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 self.cov = None | 104 self.cov = None |
105 self.context = None | 105 self.context = None |
106 self.coverage_source = None | 106 self.coverage_source = None |
107 self.host = host or Host() | 107 self.host = host or Host() |
108 self.loader = unittest.loader.TestLoader() | 108 self.loader = unittest.loader.TestLoader() |
109 self.printer = None | 109 self.printer = None |
110 self.setup_fn = None | 110 self.setup_fn = None |
111 self.stats = None | 111 self.stats = None |
112 self.teardown_fn = None | 112 self.teardown_fn = None |
113 self.top_level_dir = None | 113 self.top_level_dir = None |
| 114 self.top_level_dirs = [] |
114 self.win_multiprocessing = WinMultiprocessing.spawn | 115 self.win_multiprocessing = WinMultiprocessing.spawn |
115 self.final_responses = [] | 116 self.final_responses = [] |
116 | 117 |
117 # initialize self.args to the defaults. | 118 # initialize self.args to the defaults. |
118 parser = ArgumentParser(self.host) | 119 parser = ArgumentParser(self.host) |
119 self.parse_args(parser, []) | 120 self.parse_args(parser, []) |
120 | 121 |
121 def main(self, argv=None, **defaults): | 122 def main(self, argv=None, **defaults): |
122 parser = ArgumentParser(self.host) | 123 parser = ArgumentParser(self.host) |
123 self.parse_args(parser, argv, **defaults) | 124 self.parse_args(parser, argv, **defaults) |
(...skipping 28 matching lines...) Expand all Loading... |
152 | 153 |
153 if self.args.version: | 154 if self.args.version: |
154 self.print_(VERSION) | 155 self.print_(VERSION) |
155 return ret, None, None | 156 return ret, None, None |
156 | 157 |
157 should_spawn = self._check_win_multiprocessing() | 158 should_spawn = self._check_win_multiprocessing() |
158 if should_spawn: | 159 if should_spawn: |
159 return self._spawn(test_set) | 160 return self._spawn(test_set) |
160 | 161 |
161 ret = self._set_up_runner() | 162 ret = self._set_up_runner() |
162 if ret: # pragma: no cover | 163 if ret: |
163 return ret, None, None | 164 return ret, None, None |
164 | 165 |
165 find_start = h.time() | 166 find_start = h.time() |
166 if self.cov: # pragma: no cover | 167 if self.cov: # pragma: no cover |
167 self.cov.erase() | 168 self.cov.erase() |
168 self.cov.start() | 169 self.cov.start() |
169 | 170 |
170 full_results = None | 171 full_results = None |
171 result_set = ResultSet() | 172 result_set = ResultSet() |
172 | 173 |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 return ret, full_results, trace | 283 return ret, full_results, trace |
283 | 284 |
284 def _set_up_runner(self): | 285 def _set_up_runner(self): |
285 h = self.host | 286 h = self.host |
286 args = self.args | 287 args = self.args |
287 | 288 |
288 self.stats = Stats(args.status_format, h.time, args.jobs) | 289 self.stats = Stats(args.status_format, h.time, args.jobs) |
289 self.printer = Printer( | 290 self.printer = Printer( |
290 self.print_, args.overwrite, args.terminal_width) | 291 self.print_, args.overwrite, args.terminal_width) |
291 | 292 |
292 self.top_level_dir = args.top_level_dir | 293 if self.args.top_level_dirs and self.args.top_level_dir: |
293 if not self.top_level_dir: | 294 self.print_( |
294 if args.tests and h.isdir(args.tests[0]): | 295 'Cannot specify both --top-level-dir and --top-level-dirs', |
295 # TODO: figure out what to do if multiple files are | 296 stream=h.stderr) |
296 # specified and they don't all have the same correct | 297 return 1 |
297 # top level dir. | 298 |
298 d = h.realpath(h.dirname(args.tests[0])) | 299 self.top_level_dirs = args.top_level_dirs |
299 if h.exists(d, '__init__.py'): | 300 if not self.top_level_dirs and args.top_level_dir: |
300 top_dir = d | 301 self.top_level_dirs = [args.top_level_dir] |
| 302 |
| 303 if not self.top_level_dirs: |
| 304 for test in [t for t in args.tests if h.exists(t)]: |
| 305 if h.isdir(test): |
| 306 top_dir = test |
301 else: | 307 else: |
302 top_dir = args.tests[0] | 308 top_dir = h.dirname(test) |
303 else: | 309 while h.exists(top_dir, '__init__.py'): |
304 top_dir = h.getcwd() | 310 top_dir = h.dirname(top_dir) |
| 311 top_dir = h.realpath(top_dir) |
| 312 if not top_dir in self.top_level_dirs: |
| 313 self.top_level_dirs.append(top_dir) |
| 314 if not self.top_level_dirs: |
| 315 top_dir = h.getcwd() |
305 while h.exists(top_dir, '__init__.py'): | 316 while h.exists(top_dir, '__init__.py'): |
306 top_dir = h.dirname(top_dir) | 317 top_dir = h.dirname(top_dir) |
307 self.top_level_dir = h.realpath(top_dir) | 318 top_dir = h.realpath(top_dir) |
| 319 self.top_level_dirs.append(top_dir) |
308 | 320 |
309 h.add_to_path(self.top_level_dir) | 321 if not self.top_level_dir and self.top_level_dirs: |
| 322 self.top_level_dir = self.top_level_dirs[0] |
| 323 |
| 324 for path in self.top_level_dirs: |
| 325 h.add_to_path(path) |
310 | 326 |
311 for path in args.path: | 327 for path in args.path: |
312 h.add_to_path(path) | 328 h.add_to_path(path) |
313 | 329 |
314 if args.coverage: # pragma: no cover | 330 if args.coverage: # pragma: no cover |
315 try: | 331 try: |
316 import coverage | 332 import coverage |
317 except ImportError: | 333 except ImportError: |
318 h.print_("Error: coverage is not installed") | |
319 return 1 | 334 return 1 |
| 335 |
320 source = self.args.coverage_source | 336 source = self.args.coverage_source |
321 if not source: | 337 if not source: |
322 source = [self.top_level_dir] + self.args.path | 338 source = self.top_level_dirs + self.args.path |
323 self.coverage_source = source | 339 self.coverage_source = source |
324 self.cov = coverage.coverage(source=self.coverage_source, | 340 self.cov = coverage.coverage(source=self.coverage_source, |
325 data_suffix=True) | 341 data_suffix=True) |
326 self.cov.erase() | 342 self.cov.erase() |
327 return 0 | 343 return 0 |
328 | 344 |
329 def find_tests(self, args): | 345 def find_tests(self, args): |
330 test_set = TestSet() | 346 test_set = TestSet() |
331 | 347 |
332 orig_skip = unittest.skip | 348 orig_skip = unittest.skip |
333 orig_skip_if = unittest.skipIf | 349 orig_skip_if = unittest.skipIf |
334 if args.all: | 350 if args.all: |
335 unittest.skip = lambda reason: lambda x: x | 351 unittest.skip = lambda reason: lambda x: x |
336 unittest.skipIf = lambda condition, reason: lambda x: x | 352 unittest.skipIf = lambda condition, reason: lambda x: x |
337 | 353 |
338 try: | 354 try: |
339 names = self._name_list_from_args(args) | 355 names = self._name_list_from_args(args) |
340 classifier = self.classifier or _default_classifier(args) | 356 classifier = self.classifier or _default_classifier(args) |
341 | 357 |
342 for name in names: | 358 for name in names: |
343 try: | 359 try: |
344 self._add_tests_to_set(test_set, args.suffixes, | 360 self._add_tests_to_set(test_set, args.suffixes, |
345 self.top_level_dir, classifier, | 361 self.top_level_dirs, classifier, |
346 name) | 362 name) |
347 except (AttributeError, ImportError, SyntaxError) as e: | 363 except (AttributeError, ImportError, SyntaxError) as e: |
348 ex_str = traceback.format_exc() | 364 ex_str = traceback.format_exc() |
349 self.print_('Failed to load "%s" in find_tests: %s' % | 365 self.print_('Failed to load "%s" in find_tests: %s' % |
350 (name, e)) | 366 (name, e)) |
351 self.print_(' %s' % | 367 self.print_(' %s' % |
352 '\n '.join(ex_str.splitlines())) | 368 '\n '.join(ex_str.splitlines())) |
353 self.print_(ex_str) | 369 self.print_(ex_str) |
354 return 1, None | 370 return 1, None |
355 except _AddTestsError as e: | 371 except _AddTestsError as e: |
(...skipping 22 matching lines...) Expand all Loading... |
378 def _name_list_from_args(self, args): | 394 def _name_list_from_args(self, args): |
379 if args.tests: | 395 if args.tests: |
380 names = args.tests | 396 names = args.tests |
381 elif args.file_list: | 397 elif args.file_list: |
382 if args.file_list == '-': | 398 if args.file_list == '-': |
383 s = self.host.stdin.read() | 399 s = self.host.stdin.read() |
384 else: | 400 else: |
385 s = self.host.read_text_file(args.file_list) | 401 s = self.host.read_text_file(args.file_list) |
386 names = [line.strip() for line in s.splitlines()] | 402 names = [line.strip() for line in s.splitlines()] |
387 else: | 403 else: |
388 names = [self.top_level_dir] | 404 names = self.top_level_dirs |
389 return names | 405 return names |
390 | 406 |
391 def _add_tests_to_set(self, test_set, suffixes, top_level_dir, classifier, | 407 def _add_tests_to_set(self, test_set, suffixes, top_level_dirs, classifier, |
392 name): | 408 name): |
393 h = self.host | 409 h = self.host |
394 loader = self.loader | 410 loader = self.loader |
395 add_tests = _test_adder(test_set, classifier) | 411 add_tests = _test_adder(test_set, classifier) |
396 | 412 |
397 if h.isfile(name): | 413 found = set() |
398 rpath = h.relpath(name, top_level_dir) | 414 for d in top_level_dirs: |
399 if rpath.endswith('.py'): | 415 if h.isfile(name): |
400 rpath = rpath[:-3] | 416 rpath = h.relpath(name, d) |
401 module = rpath.replace(h.sep, '.') | 417 if rpath.startswith('..'): |
402 add_tests(loader.loadTestsFromName(module)) | 418 continue |
403 elif h.isdir(name): | 419 if rpath.endswith('.py'): |
404 for suffix in suffixes: | 420 rpath = rpath[:-3] |
405 add_tests(loader.discover(name, suffix, top_level_dir)) | 421 module = rpath.replace(h.sep, '.') |
406 else: | 422 if module not in found: |
407 possible_dir = name.replace('.', h.sep) | 423 found.add(module) |
408 if h.isdir(top_level_dir, possible_dir): | 424 add_tests(loader.loadTestsFromName(module)) |
| 425 elif h.isdir(name): |
| 426 rpath = h.relpath(name, d) |
| 427 if rpath.startswith('..'): |
| 428 continue |
409 for suffix in suffixes: | 429 for suffix in suffixes: |
410 path = h.join(top_level_dir, possible_dir) | 430 if not name in found: |
411 suite = loader.discover(path, suffix, top_level_dir) | 431 found.add(name + '/' + suffix) |
412 add_tests(suite) | 432 add_tests(loader.discover(name, suffix, d)) |
413 else: | 433 else: |
414 add_tests(loader.loadTestsFromName(name)) | 434 possible_dir = name.replace('.', h.sep) |
| 435 if h.isdir(d, possible_dir): |
| 436 for suffix in suffixes: |
| 437 path = h.join(d, possible_dir) |
| 438 if not path in found: |
| 439 found.add(path + '/' + suffix) |
| 440 suite = loader.discover(path, suffix, d) |
| 441 add_tests(suite) |
| 442 elif not name in found: |
| 443 found.add(name) |
| 444 add_tests(loader.loadTestsFromName(name)) |
415 | 445 |
416 # pylint: disable=no-member | 446 # pylint: disable=no-member |
417 if hasattr(loader, 'errors') and loader.errors: # pragma: python3 | 447 if hasattr(loader, 'errors') and loader.errors: # pragma: python3 |
418 # In Python3's version of unittest, loader failures get converted | 448 # In Python3's version of unittest, loader failures get converted |
419 # into failed test cases, rather than raising exceptions. However, | 449 # into failed test cases, rather than raising exceptions. However, |
420 # the errors also get recorded so you can err out immediately. | 450 # the errors also get recorded so you can err out immediately. |
421 raise ImportError(loader.errors) | 451 raise ImportError(loader.errors) |
422 | 452 |
423 def _run_tests(self, result_set, test_set): | 453 def _run_tests(self, result_set, test_set): |
424 h = self.host | 454 h = self.host |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 self.coverage = parent.args.coverage and parent.args.jobs > 1 | 778 self.coverage = parent.args.coverage and parent.args.jobs > 1 |
749 self.coverage_source = parent.coverage_source | 779 self.coverage_source = parent.coverage_source |
750 self.dry_run = parent.args.dry_run | 780 self.dry_run = parent.args.dry_run |
751 self.loader = parent.loader | 781 self.loader = parent.loader |
752 self.passthrough = parent.args.passthrough | 782 self.passthrough = parent.args.passthrough |
753 self.context = parent.context | 783 self.context = parent.context |
754 self.setup_fn = parent.setup_fn | 784 self.setup_fn = parent.setup_fn |
755 self.teardown_fn = parent.teardown_fn | 785 self.teardown_fn = parent.teardown_fn |
756 self.context_after_setup = None | 786 self.context_after_setup = None |
757 self.top_level_dir = parent.top_level_dir | 787 self.top_level_dir = parent.top_level_dir |
| 788 self.top_level_dirs = parent.top_level_dirs |
758 self.loaded_suites = {} | 789 self.loaded_suites = {} |
759 self.cov = None | 790 self.cov = None |
760 | 791 |
761 | 792 |
762 def _setup_process(host, worker_num, child): | 793 def _setup_process(host, worker_num, child): |
763 child.host = host | 794 child.host = host |
764 child.worker_num = worker_num | 795 child.worker_num = worker_num |
765 # pylint: disable=protected-access | 796 # pylint: disable=protected-access |
766 | 797 |
767 if child.coverage: # pragma: no cover | 798 if child.coverage: # pragma: no cover |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
953 return new_suite | 984 return new_suite |
954 | 985 |
955 | 986 |
956 def _sort_inputs(inps): | 987 def _sort_inputs(inps): |
957 return sorted(inps, key=lambda inp: inp.name) | 988 return sorted(inps, key=lambda inp: inp.name) |
958 | 989 |
959 | 990 |
960 if __name__ == '__main__': # pragma: no cover | 991 if __name__ == '__main__': # pragma: no cover |
961 sys.modules['__main__'].__file__ = path_to_file | 992 sys.modules['__main__'].__file__ = path_to_file |
962 sys.exit(main(win_multiprocessing=WinMultiprocessing.importable)) | 993 sys.exit(main(win_multiprocessing=WinMultiprocessing.importable)) |
OLD | NEW |