Exemplo n.º 1
0
    def wrapped(*args, **params):
        if args:
            raise Exception(
                'Invoking %s with positional arguments is not allowed.' %
                func.__name__)

        log_params = params.copy()
        log_params['command'] = func.__module__.split('.')[-1]
        try:
            try:
                send_start(log_params)
                func(**params)
                send_success(log_params)
            except BaseException as e:
                send_failure(e, traceback.format_exc(), log_params)
                raise
        except KeyboardInterrupt as e:
            print
            logger.info(common.colorize('%s', common.BASH_YELLOW_MARKER),
                        e.__class__.__name__)
            sys.exit(1)
        except error.ExpectedException as e:
            print
            logger.info(common.colorize('%s: %s', common.BASH_YELLOW_MARKER),
                        e.__class__.__name__, e.message)
            sys.exit(e.exit_code)
        finally:
            print('\nDetailed log of this run can be found in: %s' %
                  local_logging.LOG_FILE_PATH)
Exemplo n.º 2
0
def warn_unreproducible_if_needed(current_testcase):
  """Print warning if the testcase is unreproducible."""
  if current_testcase.gestures:
    print
    logger.info(common.colorize(
        'WARNING: the testcase is using gestures and inherently flaky. '
        "Therefore, we cannot guarantee that it'll reproduce correctly.",
        common.BASH_YELLOW_MARKER))
  if not current_testcase.reproducible:
    print
    logger.info(common.colorize(
        'WARNING: the testcase is marked as unreproducible. Therefore, it '
        'might not be reproduced.',
        common.BASH_YELLOW_MARKER))
Exemplo n.º 3
0
    def test_empty_default(self):
        """Tests functionality when default is explicitly None."""

        self.mock.raw_input.side_effect = ['y', 'n', '', 'n']

        self.assertTrue(common.confirm('A question', default=None))
        self.assertFalse(common.confirm('A question', default=None))
        self.assertFalse(common.confirm('A question', default=None))

        msg = common.colorize('A question [y/n]: ', common.BASH_MAGENTA_MARKER)
        another_msg = common.colorize('Please type either "y" or "n": ',
                                      common.BASH_MAGENTA_MARKER)
        self.mock.raw_input.assert_has_calls([mock.call(msg)] * 3 +
                                             [mock.call(another_msg)])
        self.assert_n_calls(4, [self.mock.raw_input])
  def gn_gen(self):
    """Finalize args.gn and run `gn gen`."""
    args_gn_path = os.path.join(self.get_build_dir_path(), ARGS_GN_FILENAME)

    common.ensure_dir(self.get_build_dir_path())
    common.delete_if_exists(args_gn_path)

    # Let users edit the current args.
    content = serialize_gn_args(self.get_gn_args())
    content = common.edit_if_needed(
        content, prefix='edit-args-gn-',
        comment='Edit %s before building.' % ARGS_GN_FILENAME,
        should_edit=self.options.edit_mode)

    # Write args to file and store.
    with open(args_gn_path, 'w') as f:
      f.write(content)

    logger.info(
        common.colorize('\nGenerating %s:\n%s\n', common.BASH_GREEN_MARKER),
        args_gn_path, content)

    common.execute(
        'gn', 'gen %s' % (self.get_build_dir_path()),
        self.get_source_dir_path())
Exemplo n.º 5
0
    def test_returns_when_correct(self):
        """Tests that the method only returns when the answer fits validation."""

        question = 'Initial Question'
        error_message = 'Please answer correctly'
        validate_fn = lambda x: x == 'correct'

        result = common.ask(question, error_message, validate_fn)
        self.assert_n_calls(4, [self.mock.raw_input])
        self.mock.raw_input.assert_has_calls([
            mock.call(
                common.emphasize(
                    common.colorize('Initial Question: ',
                                    common.BASH_MAGENTA_MARKER))),
            mock.call(
                common.emphasize(
                    common.colorize('Please answer correctly: ',
                                    common.BASH_MAGENTA_MARKER)))
        ])
        self.assertEqual(result, 'correct')
Exemplo n.º 6
0
    def test_no_default(self):
        """Tests functionality when no is the default."""

        self.mock.raw_input.side_effect = ['y', 'n', '']

        self.assertTrue(common.confirm('A question', default='n'))
        self.assertFalse(common.confirm('A question', default='n'))
        self.assertFalse(common.confirm('A question', default='n'))

        msg = common.colorize('A question [y/N]: ', common.BASH_MAGENTA_MARKER)
        self.mock.raw_input.assert_has_calls([mock.call(msg)] * 3)
        self.assert_n_calls(3, [self.mock.raw_input])
Exemplo n.º 7
0
def write_content(path, content):
    """Write content to path on Android."""
    with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
        tmp_file.write(content)

    logger.info(
        common.colorize('\nWriting %s:\n%s\n', common.BASH_GREEN_MARKER), path,
        content)

    adb('push %s %s' % (tmp_file.name, path))
    adb_shell('chmod 0644 %s' % path)
    common.delete_if_exists(tmp_file.name)
Exemplo n.º 8
0
    def reproduce_normal(self, iteration_max):
        """Reproduce normally."""
        iterations = 1
        signatures = set()
        has_signature = False
        while iterations <= iteration_max:
            _, output = self.reproduce_crash()

            new_signature = get_crash_signature(self.job_type, output)
            new_signature.output = output
            signatures.add(new_signature)

            has_signature = (bool(new_signature.crash_type)
                             or bool(new_signature.crash_state_lines))
            logger.info(
                'New crash type: %s\n'
                'New crash state:\n  %s\n\n'
                'Original crash type: %s\n'
                'Original crash state:\n  %s\n', new_signature.crash_type,
                '\n  '.join(new_signature.crash_state_lines),
                self.get_crash_signature().crash_type,
                '\n  '.join(self.get_crash_signature().crash_state_lines))

            # The crash signature validation is intentionally forgiving.
            if is_similar(new_signature, self.get_crash_signature()):
                logger.info(
                    common.colorize(
                        'The stacktrace seems similar to the original stacktrace.\n'
                        "Since you've reproduced the crash correctly, there are some "
                        'tricks that might help you move faster:\n'
                        '- In case of fixing the crash, you can use `--current` to run '
                        'on tip-of-tree (or, in other words, avoid git-checkout).\n'
                        '- You can save time by using `--skip-deps` to avoid '
                        '`gclient sync`, `gclient runhooks`, and other dependency '
                        'installations in subsequential runs.\n'
                        '- You can debug with gdb using `--enable-debug`.\n'
                        '- You can modify args.gn and arguments using `--edit-mode`.',
                        common.BASH_GREEN_MARKER))
                return True
            else:
                logger.info(
                    "The stacktrace doesn't match the original stacktrace.")
                logger.info(
                    'Try again (%d times). Press Ctrl+C to stop trying to '
                    'reproduce.', iterations)
            iterations += 1
            time.sleep(3)

        if has_signature:
            raise error.DifferentStacktraceError(iteration_max, signatures)
        else:
            raise error.UnreproducibleError(iteration_max, signatures)
Exemplo n.º 9
0
    def test_yes_default(self):
        """Tests functionality with yes as default."""

        self.mock.raw_input.side_effect = ['y', 'n', '']

        self.assertTrue(common.confirm('A question'))
        self.assertFalse(common.confirm('A question'))
        self.assertTrue(common.confirm('A question'))

        msg = common.emphasize(
            common.colorize('A question [Y/n]: ', common.BASH_MAGENTA_MARKER))
        self.mock.raw_input.assert_has_calls([mock.call(msg)] * 3)
        self.assert_n_calls(3, [self.mock.raw_input])
Exemplo n.º 10
0
 def get_gn_args(self):
   """Ensures that args.gn is set up properly."""
   args = super(ClankiumBuilder, self).get_gn_args()
   # android_asan_chrome_x86 is on a VM. Therefore, it's not possible to
   # deploy it on a device. Therefore, we change its target CPU to arm, so that
   # it can be deployed on an android device.
   if 'arm' not in args.get('target_cpu'):
     logger.info(common.colorize(
         'WARNING: this crash is NOT on `target_cpu = arm`. '
         '`target_cpu` is modified to `arm` to make it work on an android '
         'device.', common.BASH_YELLOW_MARKER))
     args['target_cpu'] = '"arm"'
   return args
Exemplo n.º 11
0
    def setup_gn_args(self):
        """Ensures that args.gn is set up properly."""
        # Remove existing gn file from build directory.
        args_gn_path = os.path.join(self.build_directory, 'args.gn')
        if os.path.isfile(args_gn_path):
            os.remove(args_gn_path)

        # Create build directory if it does not already exist.
        if not os.path.exists(self.build_directory):
            os.makedirs(self.build_directory)

        # If no args.gn file is found, get it from downloaded build.
        if self.gn_args:
            gn_args = self.gn_args
        else:
            args_gn_downloaded_build_path = os.path.join(
                self.build_dir_name(), 'args.gn')
            with open(args_gn_downloaded_build_path, 'r') as f:
                gn_args = f.read()

        # Add additional options to existing gn args.
        args_hash = self.deserialize_gn_args(gn_args)
        args_hash = self.setup_gn_goma_params(args_hash)
        args_hash = setup_debug_symbol_if_needed(args_hash,
                                                 self.options.enable_debug)
        if self.gn_args_options:
            for k, v in self.gn_args_options.iteritems():
                args_hash[k] = v

        # Let users edit the current args.
        content = self.serialize_gn_args(args_hash)
        content = edit_if_needed(content, self.options.edit_mode)

        # Write args to file and store.
        with open(args_gn_path, 'w') as f:
            f.write(content)
        self.gn_args = content

        logger.info(
            common.colorize('\nGenerating %s:\n%s\n',
                            common.BASH_GREEN_MARKER), args_gn_path,
            self.gn_args)

        common.execute('gn',
                       'gen %s %s' % (self.gn_flags, self.build_directory),
                       self.source_directory)
Exemplo n.º 12
0
    def reproduce(self, iteration_max):
        """Reproduces the crash and prints the stacktrace."""

        logger.info('Reproducing...')

        self.pre_build_steps()

        iterations = 1
        signatures = set()
        while iterations <= iteration_max:
            _, output = self.reproduce_crash()

            new_signature = self.get_stacktrace_info(output)
            new_signature.output = output
            signatures.add(new_signature)

            logger.info(
                'New crash type: %s\n'
                'New crash state:\n  %s\n\n'
                'Original crash type: %s\n'
                'Original crash state:\n  %s\n', new_signature.crash_type,
                '\n  '.join(new_signature.crash_state_lines),
                self.crash_signature.crash_type,
                '\n  '.join(self.crash_signature.crash_state_lines))

            # The crash signature validation is intentionally forgiving.
            if is_similar(new_signature, self.crash_signature):
                logger.info(
                    common.colorize(
                        'The stacktrace seems similar to the original stacktrace.',
                        common.BASH_GREEN_MARKER))
                return True
            else:
                logger.info(
                    "The stacktrace doesn't match the original stacktrace.")
                logger.info(
                    'Try again (%d times). Press Ctrl+C to stop trying to '
                    'reproduce.', iterations)
            iterations += 1
            time.sleep(3)

        raise common.UnreproducibleError(iteration_max, signatures)
Exemplo n.º 13
0
 def test_colorize(self):
     """Test colorize."""
     self.assertEqual('style', common.colorize('s',
                                               common.BASH_BLUE_MARKER))
     self.mock.style.assert_called_once_with('s', common.BASH_BLUE_MARKER,
                                             common.BASH_RESET_COLOR_MARKER)
Exemplo n.º 14
0
 def test_not_posix(self):
     """Test not posix."""
     self.mock.get_os_name.return_value = 'windows'
     self.assertEqual('test',
                      common.colorize('test', common.BASH_BLUE_MARKER))
Exemplo n.º 15
0
 def test_posix(self):
     """Test posix."""
     self.mock.get_os_name.return_value = 'posix'
     self.assertEqual(
         common.BASH_BLUE_MARKER + 'test' + common.BASH_RESET_MARKER,
         common.colorize('test', common.BASH_BLUE_MARKER))
Exemplo n.º 16
0
def execute(testcase_id,
            current,
            build,
            disable_goma,
            goma_threads,
            iterations,
            disable_xvfb,
            target_args,
            edit_mode,
            disable_gclient,
            enable_debug,
            goma_dir=None):
    """Execute the reproduce command."""
    options = common.Options(testcase_id=testcase_id,
                             current=current,
                             build=build,
                             disable_goma=disable_goma,
                             goma_threads=goma_threads,
                             iterations=iterations,
                             disable_xvfb=disable_xvfb,
                             target_args=target_args,
                             edit_mode=edit_mode,
                             disable_gclient=disable_gclient,
                             enable_debug=enable_debug,
                             goma_dir=goma_dir)

    logger.info('Reproducing testcase %s', testcase_id)
    logger.debug('%s', str(options))
    logger.info('Downloading testcase information...')

    response = get_testcase_info(testcase_id)
    current_testcase = testcase.Testcase(response)

    if 'gestures' in response['testcase']:
        logger.info(
            common.colorize(
                'Warning: the testcase is using gestures and inherently flaky. '
                "Therefore, we cannot guaranteed that it'll reproduce correctly.",
                common.BASH_YELLOW_MARKER))

    definition = get_definition(current_testcase.job_type, build)

    maybe_warn_unreproducible(current_testcase)

    if build == 'download':
        if definition.binary_name:
            binary_name = definition.binary_name
        else:
            binary_name = common.get_binary_name(
                current_testcase.stacktrace_lines)
        binary_provider = binary_providers.DownloadedBinary(
            testcase_id=current_testcase.id,
            build_url=current_testcase.build_url,
            binary_name=binary_name)
    else:
        options.goma_dir = None if options.disable_goma else ensure_goma()
        binary_provider = definition.builder(testcase=current_testcase,
                                             definition=definition,
                                             options=options)

    reproducer = definition.reproducer(definition=definition,
                                       binary_provider=binary_provider,
                                       testcase=current_testcase,
                                       sanitizer=definition.sanitizer,
                                       options=options)
    try:
        reproducer.reproduce(iterations)
    finally:
        maybe_warn_unreproducible(current_testcase)