def testKickTestRun_withPrevTestContext(
      self, mock_download_resources, mock_new_request):
    test_run = self._CreateMockTestRun(
        command='command',
        retry_command_line='retry_command_line',
        runner_sharding_args='--shard-count ${TF_SHARD_COUNT}',
        shard_count=6)
    test_run.prev_test_context = ndb_models.TestContextObj(
        command_line='prev_command_line',
        env_vars=[],
        test_resources=[ndb_models.TestResourceObj(name='bar', url='zzz')])
    test_run.put()
    test_run_id = test_run.key.id()
    test_run = ndb_models.TestRun.get_by_id(test_run_id)
    mock_download_resources.return_value = {
        r.url: 'cache_url' for r in test_run.test_resources
    }
    mock_request = api_messages.RequestMessage(id='request_id')
    mock_new_request.return_value = mock_request

    test_kicker.KickTestRun(test_run_id)

    mock_download_resources.assert_called_once_with(
        [r.url for r in test_run.test_resources], test_run=test_run)
    mock_new_request.assert_called()
    msg = mock_new_request.call_args[0][0]
    self._CheckNewRequestMessage(
        msg=msg,
        test_run=test_run,
        output_url='file:///data/app_default_bucket/test_runs/{}/output'.format(
            test_run_id),
        test_resource_urls={
            'foo':
                'cache_url',
            'bar':
                'cache_url',
            'mtt.json':
                'http://localhost:8000/_ah/api/mtt/v1/test_runs/{}/metadata'
                .format(test_run_id)
        },
        command_lines=['command --shard-count 6 --invocation-data mtt=1'],
        retry_command_line=(
            'retry_command_line --shard-count 6 --invocation-data mtt=1'),
        shard_count=1)
    # prev_test_context's command_line should be replaced.
    self.assertEqual(
        'retry_command_line --shard-count 6 --invocation-data mtt=1',
        msg.prev_test_context.command_line)
    test_run = ndb_models.TestRun.get_by_id(test_run_id)
    self.assertEqual(mock_request.id, test_run.request_id)
    self.assertEqual(ndb_models.TestRunState.QUEUED, test_run.state)
  def testKickTestRun_onPremiseMode(self, mock_download_resources,
                                    mock_new_request):
    test_run = self._CreateMockTestRun()
    # test_run = ndb_models.TestRun.get_by_id(test_run_id)
    test_run.prev_test_context = ndb_models.TestContextObj(
        command_line='prev_command_line',
        env_vars=[],
        test_resources=[
            ndb_models.TestResourceObj(name='bar', url='file:///root/path')
        ])
    test_run.put()
    test_run_id = test_run.key.id()
    test_run = ndb_models.TestRun.get_by_id(test_run_id)
    mock_download_resources.return_value = {
        r.url: 'file:///data/cache_url' for r in test_run.test_resources
    }
    mock_request = api_messages.RequestMessage(id='request_id')
    mock_new_request.return_value = mock_request

    test_kicker.KickTestRun(test_run_id)

    mock_download_resources.assert_called_once_with(
        [r.url for r in test_run.test_resources], test_run=test_run)
    mock_new_request.assert_called()
    msg = mock_new_request.call_args[0][0]
    self._CheckNewRequestMessage(
        msg=msg,
        test_run=test_run,
        output_url='http://test.hostname.com:8006/file/app_default_bucket/test_runs/{}/output'
        .format(test_run_id),
        test_resource_urls={
            'foo':
                'http://test.hostname.com:8006/file/cache_url',
            'bar':
                'http://test.hostname.com:8006/file/cache_url',
            'mtt.json':
                'http://test.hostname.com:8000/_ah/api/mtt/v1/test_runs/{}/metadata'
                .format(test_run_id)
        },
        command_lines=['command --invocation-data mtt=1'])
    self.assertEqual([
        api_messages.TestResource(
            name='bar', url='http://test.hostname.com:8006/file/root/path')
    ], msg.prev_test_context.test_resources)
  def testKickTestRun_runnerSharding(
      self, mock_download_resources, mock_new_request):
    test_run_id = self._CreateMockTestRun(
        command='command',
        runner_sharding_args='--shard-count ${TF_SHARD_COUNT}',
        run_target='run_target;run_target',
        shard_count=2,
        sharding_mode=ndb_models.ShardingMode.RUNNER).key.id()
    test_run = ndb_models.TestRun.get_by_id(test_run_id)
    mock_download_resources.return_value = {
        r.url: 'cache_url' for r in test_run.test_resources
    }
    mock_request = api_messages.RequestMessage(id='request_id')
    mock_new_request.return_value = mock_request

    test_kicker.KickTestRun(test_run_id)

    mock_download_resources.assert_called_once_with(
        [r.url for r in test_run.test_resources], test_run=test_run)
    mock_new_request.assert_called()
    msg = mock_new_request.call_args[0][0]
    self._CheckNewRequestMessage(
        msg=msg,
        test_run=test_run,
        output_url='file:///data/app_default_bucket/test_runs/{}/output'.format(
            test_run_id),
        test_resource_urls={
            'foo':
                'cache_url',
            'bar':
                'cache_url',
            'mtt.json':
                'http://localhost:8000/_ah/api/mtt/v1/test_runs/{}/metadata'
                .format(test_run_id)
        },
        command_lines=['command --shard-count 2 --invocation-data mtt=1'],
        run_target='run_target;run_target',
        shard_count=1)
    test_run = ndb_models.TestRun.get_by_id(test_run_id)
    self.assertEqual(mock_request.id, test_run.request_id)
    self.assertEqual(ndb_models.TestRunState.QUEUED, test_run.state)
  def testKickTestRun(
      self, mock_download_resources, mock_new_request, mock_track_test_run):
    test_run_id = self._CreateMockTestRun().key.id()
    test_run = ndb_models.TestRun.get_by_id(test_run_id)
    test_run.test_run_config.use_parallel_setup = True
    test_run.put()
    mock_download_resources.return_value = {
        r.url: 'cache_url' for r in test_run.test_resources
    }
    mock_request = api_messages.RequestMessage(id='request_id')
    mock_new_request.return_value = mock_request

    test_kicker.KickTestRun(test_run_id)

    mock_download_resources.assert_called_once_with(
        [r.url for r in test_run.test_resources], test_run=test_run)
    mock_new_request.assert_called()
    msg = mock_new_request.call_args[0][0]
    self._CheckNewRequestMessage(
        msg=msg,
        test_run=test_run,
        output_url='file:///data/app_default_bucket/test_runs/{}/output'.format(
            test_run_id),
        test_resource_urls={
            'foo':
                'cache_url',
            'bar':
                'cache_url',
            'mtt.json':
                'http://localhost:8000/_ah/api/mtt/v1/test_runs/{}/metadata'
                .format(test_run_id)
        },
        command_lines=['command --invocation-data mtt=1'])
    test_run = ndb_models.TestRun.get_by_id(test_run_id)
    self.assertEqual(mock_request.id, test_run.request_id)
    self.assertEqual(ndb_models.TestRunState.QUEUED, test_run.state)
    # metrics tracked
    mock_track_test_run.assert_called_with(test_run)
  def testKickTestRun_withTestRunActions(
      self, mock_download_resources, mock_execute_hooks, mock_new_request):
    # Create test run action with two TF result reporters
    test_run_action = ndb_models.TestRunAction(
        name='Foo',
        hook_class_name='foo',
        tradefed_result_reporters=[
            ndb_models.TradefedConfigObject(
                class_name='com.android.foo',
                option_values=[ndb_models.NameMultiValuePair(
                    name='test-run-id', values=['${MTT_TEST_RUN_ID}'])]
            ),
            ndb_models.TradefedConfigObject(class_name='com.android.bar'),
        ])
    test_run_action.put()
    # Create test run with test run action
    test_run = self._CreateMockTestRun(command='command')
    test_run.test_run_actions = [test_run_action]
    test_run.put()
    test_run_id = test_run.key.id()
    test_run = ndb_models.TestRun.get_by_id(test_run_id)
    # Mock responses
    mock_download_resources.return_value = {
        r.url: 'cache_url' for r in test_run.test_resources
    }
    mock_request = api_messages.RequestMessage(id='request_id')
    mock_new_request.return_value = mock_request

    test_kicker.KickTestRun(test_run_id)

    # Resources downloaded, hooks executed, and new TFC request created
    mock_download_resources.assert_called_once_with(
        [r.url for r in test_run.test_resources], test_run=test_run)
    mock_execute_hooks.assert_called_with(
        test_run_id, ndb_models.TestRunPhase.BEFORE_RUN)
    mock_new_request.assert_called()
    msg = mock_new_request.call_args[0][0]
    self._CheckNewRequestMessage(
        msg=msg,
        test_run=test_run,
        output_url='file:///data/app_default_bucket/test_runs/{}/output'.format(
            test_run_id),
        test_resource_urls={
            'foo':
                'cache_url',
            'bar':
                'cache_url',
            'mtt.json':
                'http://localhost:8000/_ah/api/mtt/v1/test_runs/{}/metadata'
                .format(test_run_id)
        },
        command_lines=['command --invocation-data mtt=1'])

    # TFC request has two TF result reporters with right class names and options
    tradefed_config_objects = msg.test_environment.tradefed_config_objects
    self.assertEqual(
        [tradefed_config_objects.pop(0)], test_kicker.DEFAULT_TF_CONFIG_OBJECTS)
    self.assertLen(tradefed_config_objects, 2)
    self.assertEqual(api_messages.TradefedConfigObjectType.RESULT_REPORTER,
                     tradefed_config_objects[1].type)
    self.assertEqual('com.android.foo', tradefed_config_objects[0].class_name)
    self.assertEqual('test-run-id',
                     tradefed_config_objects[0].option_values[0].key)
    self.assertEqual([str(test_run_id)],
                     tradefed_config_objects[0].option_values[0].values)
    self.assertEqual(api_messages.TradefedConfigObjectType.RESULT_REPORTER,
                     tradefed_config_objects[1].type)
    self.assertEqual('com.android.bar', tradefed_config_objects[1].class_name)
    self.assertEmpty(tradefed_config_objects[1].option_values)

    # Test run now queued
    test_run = ndb_models.TestRun.get_by_id(test_run_id)
    self.assertEqual(mock_request.id, test_run.request_id)
    self.assertEqual(ndb_models.TestRunState.QUEUED, test_run.state)
  def testKickTestRun_moduleSharding(
      self,
      mock_download_resources,
      mock_open_file,
      mock_get_test_module_infos,
      mock_new_request):
    test_run = self._CreateMockTestRun(
        command='command',
        run_target='run_target',
        shard_count=6,
        sharding_mode=ndb_models.ShardingMode.MODULE,
        module_config_pattern='path/to/.*\\.config',
        module_execution_args='-m ${MODULE_NAME}',
        extra_test_resources=[
            ndb_models.TestResourceObj(
                name='test_package',
                url='test_package_url',
                test_resource_type=ndb_models.TestResourceType.TEST_PACKAGE)
        ])
    test_run_id = test_run.key.id()
    test_run = ndb_models.TestRun.get_by_id(test_run_id)
    mock_download_resources.return_value = {
        r.url: '%s_cache_url' % r.name for r in test_run.test_resources
    }
    mock_get_test_module_infos.return_value = [
        file_util.TestModuleInfo(name='CtsFooTestCases'),
        file_util.TestModuleInfo(name='CtsDeqpTestCases'),
        file_util.TestModuleInfo(name='CtsBarTestCases'),
    ]
    mock_request = api_messages.RequestMessage(id='request_id')
    mock_new_request.return_value = mock_request

    test_kicker.KickTestRun(test_run_id)

    mock_download_resources.assert_called_once_with(
        [r.url for r in test_run.test_resources], test_run=test_run)
    mock_open_file.assert_called_with('test_package_cache_url')
    mock_get_test_module_infos.assert_called_once_with(
        mock_open_file.return_value, 'path/to/.*\\.config')
    mock_new_request.assert_called()
    msg = mock_new_request.call_args[0][0]
    self._CheckNewRequestMessage(
        msg=msg,
        test_run=test_run,
        output_url='file:///data/app_default_bucket/test_runs/{}/output'.format(
            test_run_id),
        test_resource_urls={
            'foo': 'foo_cache_url',
            'bar': 'bar_cache_url',
            'test_package': 'test_package_cache_url',
            'mtt.json':
                'http://localhost:8000/_ah/api/mtt/v1/test_runs/{}/metadata'
                .format(test_run_id)
        },
        command_lines=[
            'command -m CtsDeqpTestCases --invocation-data mtt=1',
            'command -m CtsBarTestCases --invocation-data mtt=1',
            'command -m CtsFooTestCases --invocation-data mtt=1',
        ],
        run_target='run_target',
        shard_count=1,
        max_concurrent_tasks=6)
    test_run = ndb_models.TestRun.get_by_id(test_run_id)
    self.assertEqual(mock_request.id, test_run.request_id)
    self.assertEqual(ndb_models.TestRunState.QUEUED, test_run.state)