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 |