text: # Copyright (c) 2014 The Chromium Authors. All rights reserved.
  # Use of this source code is governed by a BSD-style license that can be
  # found in the LICENSE file.
  
  
  """Utility script to launch browser-tests on the Chromoting bot."""
  import argparse
  import time
  
  from chromoting_test_utilities import CleanupUserProfileDir
  from chromoting_test_utilities import GetJidFromHostLog
  from chromoting_test_utilities import GetJidListFromTestResults
  from chromoting_test_utilities import InitialiseTestMachineForLinux
  from chromoting_test_utilities import MAX_RETRIES
  from chromoting_test_utilities import PrintHostLogContents
  from chromoting_test_utilities import PROD_DIR_ID
  from chromoting_test_utilities import RunCommandInSubProcess
  from chromoting_test_utilities import TestCaseSetup
  from chromoting_test_utilities import TestMachineCleanup
  
  SUCCESS_INDICATOR = 'SUCCESS: all tests passed.'
  TEST_FAILURE = False
  FAILING_TESTS = ''
  BROWSER_NOT_STARTED_ERROR = (
      'Still waiting for the following processes to finish')
  TIME_OUT_INDICATOR = '(TIMED OUT)'
  
  
  def LaunchBTCommand(args, command):
    """Launches the specified browser-test command.
  
      Retry if the execution failed because a browser-instance was not launched or
      because the JID used did not match the host-JID.
    Args:
      args: Command line args, used for test-case startup tasks.
      command: Browser-test command line.
  
    Returns:
      host_log_file_names: Array of host logs created for this command, including
           retries.
    """
    global TEST_FAILURE, FAILING_TESTS
    host_log_file_names = []
  
    retries = 0
    host_jid_mismatch = False
    host_jid = None
    while retries <= MAX_RETRIES:
      # TestCaseSetup restarts the me2me host, and sets up user-profile dir.
      # It returns the file-name of the me2me host log.
      # If we are attempting to run this test because of a JID-mismatch, don't
      # restart host.
      if host_jid_mismatch:
        # Cleanup user-profile directory, but don't restart host.
        CleanupUserProfileDir(args)
      else:
        host_log_file_names.append(TestCaseSetup(args))
        # Parse the me2me host log to obtain the JID that the host registered.
        host_jid = GetJidFromHostLog(host_log_file_names[retries])
  
      results = RunCommandInSubProcess(command)
  
      # Get the JID used by this test to connect a remote-host, if any.
      jids_used = GetJidListFromTestResults(results)
  
      # Check for JID mismatch before checking for test success, so that we may
      # record instances where a test passed despite a JID mismatch.
      if jids_used and host_jid.rstrip() not in jids_used:
        host_jid_mismatch = True
        print 'Host JID mismatch. JID in host log = %s.' % host_jid.rstrip()
        print 'Host JIDs used by test:'
        for jid in jids_used:
          print jid
  
      if host_jid_mismatch:
        # The JID for the remote-host did not match the JID that was used for this
        # execution of the test. This happens because of a replication delay in
        # updating all instances of the Chromoting Directory Server. To
        # work-around this, sleep for 30s, which, based off a recent (08/2015)
        # query for average replication delay for Chromoting, should be sufficient
        # for the current JID value to have fully propagated.
        retries += 1
        time.sleep(30)
        continue
      elif jids_used:
        print 'JID used by test matched me2me host JID: %s' % host_jid
      else:
        # There wasn't a mismatch and no JIDs were returned. If no JIDs were
        # returned, that means the test didn't use any JIDs, so there is nothing
        # further for us to do.
        pass
  
      if SUCCESS_INDICATOR in results:
        break
  
      # Sometimes, during execution of browser-tests, a browser instance is
      # not started and the test times out. See http://crbug/480025.
      # To work around it, check if this execution failed owing to that
      # problem and retry.
      # There are 2 things to look for in the results:
      # A line saying "Still waiting for the following processes to finish",
      # and, because sometimes that line gets logged even if the test
      # eventually passes, we'll also look for "(TIMED OUT)", before retrying.
      if BROWSER_NOT_STARTED_ERROR in results and TIME_OUT_INDICATOR in results:
        print 'Browser-instance not started (http://crbug/480025). Retrying.'
      else:
        print 'Test failed for unknown reason. Retrying.'
  
      retries += 1
  
    # Check that the test passed.
    if SUCCESS_INDICATOR not in results:
      TEST_FAILURE = True
      # Add this command-line to list of tests that failed.
      FAILING_TESTS += command
  
    return host_log_file_names
  
  
  def main(args):
  
    InitialiseTestMachineForLinux(args.cfg_file)
  
    host_log_files = []
    with open(args.commands_file) as f:
      for line in f:
        # Replace the PROD_DIR value in the command-line with
        # the passed in value.
        line = line.replace(PROD_DIR_ID, args.prod_dir)
        # Launch specified command line for test.
        host_log_files.extend(LaunchBTCommand(args, line))
  
    # All tests completed. Include host-logs in the test results.
    PrintHostLogContents(host_log_files)
  
    return host_log_files
  
  if __name__ == '__main__':
  
    parser = argparse.ArgumentParser()
    parser.add_argument('-f', '--commands_file',
                        help='path to file listing commands to be launched.')
    parser.add_argument('-p', '--prod_dir',
                        help='path to folder having product and test binaries.')
    parser.add_argument('-c', '--cfg_file',
                        help='path to test host config file.')
    parser.add_argument('--me2me_manifest_file',
                        help='path to me2me host manifest file.')
    parser.add_argument('--it2me_manifest_file',
                        help='path to it2me host manifest file.')
    parser.add_argument(
        '-u', '--user_profile_dir',
        help='path to user-profile-dir, used by connect-to-host tests.')
    command_line_args = parser.parse_args()
    host_logs = ''
    try:
      host_logs = main(command_line_args)
      if TEST_FAILURE:
        print '++++++++++AT LEAST 1 TEST FAILED++++++++++'
        print FAILING_TESTS.rstrip('\n')
        print '++++++++++++++++++++++++++++++++++++++++++'
        raise Exception('At least one test failed.')
    finally:
      # Stop host and cleanup user-profile-dir.
      TestMachineCleanup(command_line_args.user_profile_dir, host_logs)
  