def test_upload_without_component_revisions(self):
        """Log should contain message on empty component revisions."""
        self.mock.get_component_range_list.return_value = []

        mock_gsutil = mock.MagicMock()
        self.mock.write_data.return_value = mock_gsutil

        self.fs.create_file(
            self.testcase_path + '.stats2',
            contents='{"stat": 1000, "timestamp": 1472846341.017923, "kind": '
            '"TestcaseRun", "job": "job", "fuzzer": "fuzzer", '
            '"build_revision": 123}\n')

        crash_result = CrashResult(return_code=1,
                                   crash_time=5,
                                   output='fake output')
        log = testcase_manager.prepare_log_for_upload(
            crash_result.get_stacktrace(), crash_result.return_code)
        log_time = testcase_manager._get_testcase_time(self.testcase_path)
        testcase_manager.upload_log(log, log_time)

        # Date and time below is derived from 1472846341 timestamp value.
        self.mock.write_data.assert_called_once_with(
            b'Component revisions (build r123):\n'
            b'Not available.\n\n'
            b'Return code: 1\n\nfake output',
            'gs://fake-gcs-logs/fuzzer/job/2016-09-02/19:59:01:017923.log')
  def test_upload_with_hostname_and_serial(self):
    """Log name should be generated using current (mocked) timestamp value."""
    mock_gsutil = mock.MagicMock()
    self.mock.write_data.return_value = mock_gsutil
    environment.set_value('BOT_NAME', 'hostname.company.com')
    environment.set_value('OS_OVERRIDE', 'ANDROID_KERNEL')
    environment.set_value('ANDROID_SERIAL', '123456789')

    self.fs.create_file(
        self.testcase_path + '.stats2',
        contents='{"stat": 1000, "kind": "TestcaseRun", "job": "job", '
        '"fuzzer": "fuzzer", "build_revision": 123}\n')

    crash_result = CrashResult(return_code=None, crash_time=None, output=None)
    log = testcase_manager.prepare_log_for_upload(crash_result.get_stacktrace(),
                                                  crash_result.return_code)
    log_time = testcase_manager._get_testcase_time(self.testcase_path)
    testcase_manager.upload_log(log, log_time)
    self.mock.write_data.assert_called_once_with(
        b'Component revisions (build r123):\n'
        b'Component: REVISION\nComponent2: REVISION2\n\n'
        b'Bot name: hostname.company.com\n'
        b'Device serial: 123456789\n'
        b'Return code: None\n\nNo output!',
        'gs://fake-gcs-logs/fuzzer/job/2017-05-15/16:10:28:374119.log')
  def test_upload_with_timestamp_from_stats(self):
    """Log name should be generated using timestamp value from the stats."""
    mock_gsutil = mock.MagicMock()
    self.mock.write_data.return_value = mock_gsutil

    self.fs.create_file(
        self.testcase_path + '.stats2',
        contents='{"stat": 1000, "timestamp": 1472846341.017923, "kind": '
        '"TestcaseRun", "job": "job", "fuzzer": "fuzzer", '
        '"build_revision": 123}\n')

    environment.set_value('BOT_NAME', 'hostname.company.com')
    crash_result = CrashResult(
        return_code=1, crash_time=5, output='fake output')

    log = testcase_manager.prepare_log_for_upload(crash_result.get_stacktrace(),
                                                  crash_result.return_code)
    log_time = testcase_manager._get_testcase_time(self.testcase_path)
    testcase_manager.upload_log(log, log_time)

    # Date and time below is derived from 1472846341 timestamp value.
    self.mock.write_data.assert_called_once_with(
        b'Component revisions (build r123):\n'
        b'Component: REVISION\nComponent2: REVISION2\n\n'
        b'Bot name: hostname.company.com\n'
        b'Return code: 1\n\nfake output',
        'gs://fake-gcs-logs/fuzzer/job/2016-09-02/19:59:01:017923.log')
Exemple #4
0
  def test_upload_without_timestamp(self):
    """Log name should be generated using current (mocked) timestamp value."""
    mock_gsutil = mock.MagicMock()
    self.mock.write_data.return_value = mock_gsutil

    self.fs.create_file(
        self.testcase_path + '.stats2',
        contents='{"stat": 1000, "kind": "TestcaseRun", "job": "job", '
        '"fuzzer": "fuzzer", "build_revision": 123}\n')

    crash_result = CrashResult(return_code=None, crash_time=None, output=None)
    log = testcase_manager.prepare_log_for_upload(crash_result.get_stacktrace(),
                                                  crash_result.return_code)
    log_time = testcase_manager._get_testcase_time(self.testcase_path)
    testcase_manager.upload_log(log, log_time)
    self.mock.write_data.assert_called_once_with(
        b'Component revisions (build r123):\n'
        b'Component: REVISION\nComponent2: REVISION2\n\n'
        b'Return code: None\n\nNo output!',
        'gs://fake-gcs-logs/fuzzer/job/2017-05-15/16:10:28:374119.log')
Exemple #5
0
def run_testcase_and_return_result_in_queue(crash_queue,
                                            thread_index,
                                            file_path,
                                            gestures,
                                            env_copy,
                                            upload_output=False):
    """Run a single testcase and return crash results in the crash queue."""

    # Since this is running in its own process, initialize the log handler again.
    # This is needed for Windows where instances are not shared across child
    # processes. See:
    # https://stackoverflow.com/questions/34724643/python-logging-with-multiprocessing-root-logger-different-in-windows
    logs.configure('run_testcase', {
        'testcase_path': file_path,
    })

    try:
        # Run testcase and check whether a crash occurred or not.
        return_code, crash_time, output = run_testcase(thread_index, file_path,
                                                       gestures, env_copy)

        # Pull testcase directory to host to get any stats files.
        if environment.is_trusted_host():
            from bot.untrusted_runner import file_host
            file_host.pull_testcases_from_worker()

        # Analyze the crash.
        crash_output = _get_crash_output(output)
        crash_result = CrashResult(return_code, crash_time, crash_output)

        # To provide consistency between stats and logs, we use timestamp taken
        # from stats when uploading logs and testcase.
        if upload_output:
            log_time = _get_testcase_time(file_path)

        if crash_result.is_crash():
            # Initialize resource list with the testcase path.
            resource_list = [file_path]
            resource_list += get_resource_paths(crash_output)

            # Store the crash stack file in the crash stacktrace directory
            # with filename as the hash of the testcase path.
            crash_stacks_directory = environment.get_value(
                'CRASH_STACKTRACES_DIR')
            stack_file_path = os.path.join(crash_stacks_directory,
                                           utils.string_hash(file_path))
            utils.write_data_to_file(crash_output, stack_file_path)

            # Put crash/no-crash results in the crash queue.
            crash_queue.put(
                Crash(file_path=file_path,
                      crash_time=crash_time,
                      return_code=return_code,
                      resource_list=resource_list,
                      gestures=gestures,
                      stack_file_path=stack_file_path))

            # Don't upload uninteresting testcases (no crash) or if there is no log to
            # correlate it with (not upload_output).
            if upload_output:
                upload_testcase(file_path, log_time)

        if upload_output:
            # Include full output for uploaded logs (crash output, merge output, etc).
            crash_result_full = CrashResult(return_code, crash_time, output)
            log = prepare_log_for_upload(crash_result_full.get_stacktrace(),
                                         return_code)
            upload_log(log, log_time)
    except Exception:
        logs.log_error('Exception occurred while running '
                       'run_testcase_and_return_result_in_queue.')
Exemple #6
0
def check_for_bad_build(job_type, crash_revision):
    """Return true if the build is bad, i.e. crashes on startup."""
    # Check the bad build check flag to see if we want do this.
    if not environment.get_value('BAD_BUILD_CHECK'):
        return False

    # Create a blank command line with no file to run and no http.
    command = get_command_line_for_application(file_to_run='',
                                               needs_http=False)

    # When checking for bad builds, we use the default window size.
    # We don't want to pick a custom size since it can potentially cause a
    # startup crash and cause a build to be detected incorrectly as bad.
    default_window_argument = environment.get_value('WINDOW_ARG', '')
    if default_window_argument:
        command = command.replace(' %s' % default_window_argument, '')

    # TSAN is slow, and boots slow on first startup. Increase the warmup
    # timeout for this case.
    if environment.tool_matches('TSAN', job_type):
        fast_warmup_timeout = environment.get_value('WARMUP_TIMEOUT')
    else:
        fast_warmup_timeout = environment.get_value('FAST_WARMUP_TIMEOUT')

    # Initialize helper variables.
    is_bad_build = False
    build_run_console_output = ''
    app_directory = environment.get_value('APP_DIR')

    # Exit all running instances.
    process_handler.terminate_stale_application_instances()

    # Check if the build is bad.
    return_code, crash_time, output = process_handler.run_process(
        command,
        timeout=fast_warmup_timeout,
        current_working_directory=app_directory)
    crash_result = CrashResult(return_code, crash_time, output)

    # 1. Need to account for startup crashes with no crash state. E.g. failed to
    #    load shared library. So, ignore state for comparison.
    # 2. Ignore leaks as they don't block a build from reporting regular crashes
    #    and also don't impact regression range calculations.
    if (crash_result.is_crash(ignore_state=True)
            and not crash_result.should_ignore() and
            not crash_result.get_type() in ['Direct-leak', 'Indirect-leak']):
        is_bad_build = True
        build_run_console_output = utils.get_crash_stacktrace_output(
            command, crash_result.get_stacktrace(symbolized=True),
            crash_result.get_stacktrace(symbolized=False))
        logs.log('Bad build for %s detected at r%d.' %
                 (job_type, crash_revision),
                 output=build_run_console_output)

    # Exit all running instances.
    process_handler.terminate_stale_application_instances()

    # Any of the conditions below indicate that bot is in a bad state and it is
    # not caused by the build itself. In that case, just exit.
    build_state = data_handler.get_build_state(job_type, crash_revision)
    if is_bad_build and utils.sub_string_exists_in(BAD_STATE_HINTS, output):
        logs.log_fatal_and_exit(
            'Bad bot environment detected, exiting.',
            output=build_run_console_output,
            snapshot=process_handler.get_runtime_snapshot())

    # If none of the other bots have added information about this build,
    # then add it now.
    if (build_state == data_types.BuildState.UNMARKED
            and not crash_result.should_ignore()):
        data_handler.add_build_metadata(job_type, crash_revision, is_bad_build,
                                        build_run_console_output)

    return is_bad_build
def get_symbolized_stacktraces(testcase_file_path, testcase,
                               old_crash_stacktrace, expected_state):
  """Use the symbolized builds to generate an updated stacktrace."""
  # Initialize variables.
  app_path = environment.get_value("APP_PATH")
  app_path_debug = environment.get_value("APP_PATH_DEBUG")
  long_test_timeout = environment.get_value("WARMUP_TIMEOUT")
  retry_limit = environment.get_value("FAIL_RETRIES")
  symbolized = False

  debug_build_stacktrace = ""
  release_build_stacktrace = old_crash_stacktrace

  # Symbolize using the debug build first so that the debug build stacktrace
  # comes after the more important release build stacktrace.
  if app_path_debug:
    for _ in range(retry_limit):
      process_handler.terminate_stale_application_instances()
      command = testcase_manager.get_command_line_for_application(
          testcase_file_path,
          app_path=app_path_debug,
          needs_http=testcase.http_flag,
      )
      return_code, crash_time, output = process_handler.run_process(
          command, timeout=long_test_timeout, gestures=testcase.gestures)
      crash_result = CrashResult(return_code, crash_time, output)

      if crash_result.is_crash():
        state = crash_result.get_symbolized_data()

        if crash_analyzer.ignore_stacktrace(state.crash_stacktrace):
          continue

        unsymbolized_crash_stacktrace = crash_result.get_stacktrace(
            symbolized=False)
        debug_build_stacktrace = utils.get_crash_stacktrace_output(
            command,
            state.crash_stacktrace,
            unsymbolized_crash_stacktrace,
            build_type="debug",
        )
        symbolized = True
        break

  # Symbolize using the release build.
  if app_path:
    for _ in range(retry_limit):
      process_handler.terminate_stale_application_instances()
      command = testcase_manager.get_command_line_for_application(
          testcase_file_path, app_path=app_path, needs_http=testcase.http_flag)
      return_code, crash_time, output = process_handler.run_process(
          command, timeout=long_test_timeout, gestures=testcase.gestures)
      crash_result = CrashResult(return_code, crash_time, output)

      if crash_result.is_crash():
        state = crash_result.get_symbolized_data()

        if crash_analyzer.ignore_stacktrace(state.crash_stacktrace):
          continue

        if state.crash_state != expected_state:
          continue

        # Release stack's security flag has to match the symbolized release
        # stack's security flag.
        security_flag = crash_result.is_security_issue()
        if security_flag != testcase.security_flag:
          continue

        unsymbolized_crash_stacktrace = crash_result.get_stacktrace(
            symbolized=False)
        release_build_stacktrace = utils.get_crash_stacktrace_output(
            command,
            state.crash_stacktrace,
            unsymbolized_crash_stacktrace,
            build_type="release",
        )
        symbolized = True
        break

  stacktrace = release_build_stacktrace
  if debug_build_stacktrace:
    stacktrace += "\n\n" + debug_build_stacktrace

  return symbolized, stacktrace
Exemple #8
0
    parser.add_argument("--outputfile",
                        type=str,
                        help="crashing program output",
                        required=True)
    parser.add_argument("--exitcode",
                        type=int,
                        help="crashing program exit code",
                        required=True)
    parser.add_argument("--time",
                        type=int,
                        help="crash collection time, Unix timestamp",
                        default=0)

    args = parser.parse_args()

    output = open(args.outputfile).read()

    cr = CrashResult(args.exitcode, args.time, output)

    result = {
        'type': cr.get_type(),
        'is_crash': cr.is_crash(),
        'is_security_issue': cr.is_security_issue(),
        'should_ignore': cr.should_ignore(),
        'stacktrace': cr.get_stacktrace(),
        'output': cr.output,
        'return_code': cr.return_code,
    }

    print(json.dumps(result, indent=4))