Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 Google Inc. All rights reserved. | 1 # Copyright (c) 2012 Google Inc. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """ | 5 """ |
| 6 TestGyp.py: a testing framework for GYP integration tests. | 6 TestGyp.py: a testing framework for GYP integration tests. |
| 7 """ | 7 """ |
| 8 | 8 |
| 9 import collections | 9 import collections |
| 10 from contextlib import contextmanager | 10 from contextlib import contextmanager |
| 11 import itertools | 11 import itertools |
| 12 import os | 12 import os |
| 13 import random | |
| 13 import re | 14 import re |
| 14 import shutil | 15 import shutil |
| 15 import stat | 16 import stat |
| 16 import subprocess | 17 import subprocess |
| 17 import sys | 18 import sys |
| 18 import tempfile | 19 import tempfile |
| 20 import time | |
| 19 | 21 |
| 20 import TestCmd | 22 import TestCmd |
| 21 import TestCommon | 23 import TestCommon |
| 22 from TestCommon import __all__ | 24 from TestCommon import __all__ |
| 23 | 25 |
| 24 __all__.extend([ | 26 __all__.extend([ |
| 25 'TestGyp', | 27 'TestGyp', |
| 26 ]) | 28 ]) |
| 27 | 29 |
| 28 | 30 |
| (...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 545 """ | 547 """ |
| 546 print '%s failed%s' % (' '.join(command), ': %s' % msg if msg else '') | 548 print '%s failed%s' % (' '.join(command), ': %s' % msg if msg else '') |
| 547 print self.banner('STDOUT ') | 549 print self.banner('STDOUT ') |
| 548 stdout.seek(0) | 550 stdout.seek(0) |
| 549 print stdout.read() | 551 print stdout.read() |
| 550 print self.banner('STDERR ') | 552 print self.banner('STDERR ') |
| 551 stderr.seek(0) | 553 stderr.seek(0) |
| 552 print stderr.read() | 554 print stderr.read() |
| 553 self.fail_test() | 555 self.fail_test() |
| 554 | 556 |
| 555 def _call_adb(self, command): | 557 def _call_adb(self, command, timeout=15, retry=3): |
| 556 """ Calls the provided adb command. | 558 """ Calls the provided adb command. |
| 557 | 559 |
| 558 If the command fails, the test fails. | 560 If the command fails, the test fails. |
| 559 | 561 |
| 560 Args: | 562 Args: |
| 561 command: The adb command to call. | 563 command: The adb command to call. |
| 562 Returns: | 564 Returns: |
| 563 The command's output. | 565 The command's output. |
| 564 """ | 566 """ |
| 565 with tempfile.TemporaryFile(bufsize=0) as adb_out: | 567 with tempfile.TemporaryFile(bufsize=0) as adb_out: |
| 566 with tempfile.TemporaryFile(bufsize=0) as adb_err: | 568 with tempfile.TemporaryFile(bufsize=0) as adb_err: |
| 567 adb_command = [self._adb_path] | 569 adb_command = [self._adb_path] |
| 568 if self._device_serial: | 570 if self._device_serial: |
| 569 adb_command += ['-s', self._device_serial] | 571 adb_command += ['-s', self._device_serial] |
| 570 is_shell = (command[0] == 'shell') | 572 is_shell = (command[0] == 'shell') |
| 571 if is_shell: | 573 if is_shell: |
| 572 command = [command[0], '%s; echo "\n$?";' % ' '.join(command[1:])] | 574 command = [command[0], '%s; echo "\n$?";' % ' '.join(command[1:])] |
| 573 adb_command += command | 575 adb_command += command |
| 574 if subprocess.call(adb_command, stdout=adb_out, stderr=adb_err) != 0: | 576 |
| 575 self._adb_failure(adb_command, None, adb_out, adb_err) | 577 for attempt in xrange(1, retry + 1): |
| 576 else: | |
| 577 adb_out.seek(0) | 578 adb_out.seek(0) |
| 578 output = adb_out.read() | 579 adb_out.truncate(0) |
| 579 if is_shell: | 580 adb_err.seek(0) |
| 580 output = output.splitlines(True) | 581 adb_err.truncate(0) |
| 582 proc = subprocess.Popen(adb_command, stdout=adb_out, stderr=adb_err) | |
| 583 deadline = time.time() + timeout | |
|
bradn
2014/08/22 16:13:32
I assume there's no need for exponential backoff?
| |
| 584 timed_out = False | |
| 585 while proc.poll() is None and not timed_out: | |
| 586 time.sleep(1) | |
| 587 timed_out = time.time() > deadline | |
| 588 if timed_out: | |
| 589 print 'Timeout for command %s (attempt %d of %s)' % ( | |
| 590 adb_command, attempt, retry) | |
| 581 try: | 591 try: |
| 582 output[-2] = output[-2].rstrip('\r\n') | 592 proc.kill() |
| 583 output, rc = (''.join(output[:-1]), int(output[-1])) | 593 except: |
| 584 except ValueError: | 594 pass |
| 585 self._adb_failure(adb_command, 'unexpected output format', | 595 else: |
| 586 adb_out, adb_err) | 596 break |
| 587 if rc != 0: | 597 |
| 588 self._adb_failure(adb_command, 'exited with %d' % rc, adb_out, | 598 if proc.returncode != 0: # returncode is None in the case of a timeout. |
| 589 adb_err) | 599 self._adb_failure( |
| 590 return output | 600 adb_command, 'retcode=%s' % proc.returncode, adb_out, adb_err) |
| 601 return | |
| 602 | |
| 603 adb_out.seek(0) | |
| 604 output = adb_out.read() | |
| 605 if is_shell: | |
| 606 output = output.splitlines(True) | |
| 607 try: | |
| 608 output[-2] = output[-2].rstrip('\r\n') | |
| 609 output, rc = (''.join(output[:-1]), int(output[-1])) | |
| 610 except ValueError: | |
| 611 self._adb_failure(adb_command, 'unexpected output format', | |
| 612 adb_out, adb_err) | |
| 613 if rc != 0: | |
| 614 self._adb_failure(adb_command, 'exited with %d' % rc, adb_out, | |
| 615 adb_err) | |
| 616 return output | |
| 591 | 617 |
| 592 def run_built_executable(self, name, *args, **kw): | 618 def run_built_executable(self, name, *args, **kw): |
| 593 """ | 619 """ |
| 594 Runs an executable program built from a gyp-generated configuration. | 620 Runs an executable program built from a gyp-generated configuration. |
| 595 """ | 621 """ |
| 596 match = kw.pop('match', self.match) | 622 match = kw.pop('match', self.match) |
| 597 | 623 |
| 598 executable_file = self.built_file_path(name, type=self.EXECUTABLE, **kw) | 624 executable_file = self.built_file_path(name, type=self.EXECUTABLE, **kw) |
| 599 if executable_file not in self._to_install: | 625 if executable_file not in self._to_install: |
| 600 self.fail_test() | 626 self.fail_test() |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 613 os.path.join(os.environ['ANDROID_BUILD_TOP'], i)) | 639 os.path.join(os.environ['ANDROID_BUILD_TOP'], i)) |
| 614 dest = '%s/%s' % (storage, os.path.basename(a)) | 640 dest = '%s/%s' % (storage, os.path.basename(a)) |
| 615 self._call_adb(['push', os.path.abspath(a), dest]) | 641 self._call_adb(['push', os.path.abspath(a), dest]) |
| 616 installed.add(dest) | 642 installed.add(dest) |
| 617 if i == executable_file: | 643 if i == executable_file: |
| 618 device_executable = dest | 644 device_executable = dest |
| 619 self._call_adb(['shell', 'chmod', '755', device_executable]) | 645 self._call_adb(['shell', 'chmod', '755', device_executable]) |
| 620 | 646 |
| 621 out = self._call_adb( | 647 out = self._call_adb( |
| 622 ['shell', 'LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%s' % storage, | 648 ['shell', 'LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%s' % storage, |
| 623 device_executable]) | 649 device_executable], |
| 650 timeout=60, | |
| 651 retry=1) | |
| 624 out = out.replace('\r\n', '\n') | 652 out = out.replace('\r\n', '\n') |
| 625 self._complete(out, kw.pop('stdout', None), None, None, None, match) | 653 self._complete(out, kw.pop('stdout', None), None, None, None, match) |
| 626 finally: | 654 finally: |
| 627 if len(installed): | 655 if len(installed): |
| 628 self._call_adb(['shell', 'rm'] + list(installed)) | 656 self._call_adb(['shell', 'rm'] + list(installed)) |
| 629 | 657 |
| 630 def match_single_line(self, lines = None, expected_line = None): | 658 def match_single_line(self, lines = None, expected_line = None): |
| 631 """ | 659 """ |
| 632 Checks that specified line appears in the text. | 660 Checks that specified line appears in the text. |
| 633 """ | 661 """ |
| (...skipping 676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1310 | 1338 |
| 1311 def TestGyp(*args, **kw): | 1339 def TestGyp(*args, **kw): |
| 1312 """ | 1340 """ |
| 1313 Returns an appropriate TestGyp* instance for a specified GYP format. | 1341 Returns an appropriate TestGyp* instance for a specified GYP format. |
| 1314 """ | 1342 """ |
| 1315 format = kw.pop('format', os.environ.get('TESTGYP_FORMAT')) | 1343 format = kw.pop('format', os.environ.get('TESTGYP_FORMAT')) |
| 1316 for format_class in format_class_list: | 1344 for format_class in format_class_list: |
| 1317 if format == format_class.format: | 1345 if format == format_class.format: |
| 1318 return format_class(*args, **kw) | 1346 return format_class(*args, **kw) |
| 1319 raise Exception, "unknown format %r" % format | 1347 raise Exception, "unknown format %r" % format |
| OLD | NEW |