| #!/usr/bin/env vpython |
| # Copyright 2020 The LUCI Authors. All rights reserved. |
| # Use of this source code is governed under the Apache License, Version 2.0 |
| # that can be found in the LICENSE file. |
| |
| import datetime |
| import logging |
| import sys |
| import unittest |
| import uuid |
| |
| import mock |
| |
| import test_env |
| test_env.setup_test_env() |
| |
| from google.appengine.api import app_identity |
| from google.appengine.ext import ndb |
| |
| from test_support import test_case |
| |
| from components import net |
| |
| from server import config |
| from server import resultdb |
| |
| from proto.config import config_pb2 |
| |
| |
| class ResultDBTest(test_case.TestCase): |
| # This test needs to be run independently. |
| # run by test.py |
| no_run = 1 |
| |
| def setUp(self): |
| super(ResultDBTest, self).setUp() |
| mock.patch('google.appengine.api.app_identity.get_default_version_hostname' |
| ).start().return_value = 'test-swarming.appspot.com' |
| mock.patch('uuid.uuid4').start().return_value = uuid.UUID(int=0) |
| |
| def tearDown(self): |
| super(ResultDBTest, self).tearDown() |
| mock.patch.stopall() |
| |
| @ndb.tasklet |
| def nop_async(self, *_args, **_kwargs): |
| pass |
| |
| @ndb.tasklet |
| def _mock_call_resultdb_recorder_api_async(self, _method, _request, |
| response_headers, **_kwargs): |
| response_headers['update-token'] = 'token' |
| |
| def test_create_invocation_async(self): |
| |
| with mock.patch( |
| 'server.resultdb._call_resultdb_recorder_api_async', |
| mock.MagicMock(side_effect=self._mock_call_resultdb_recorder_api_async) |
| ) as mock_call: |
| |
| update_token = resultdb.create_invocation_async( |
| 'task001', 'infra:try', datetime.datetime(2020, 1, 2, 3, 4, |
| 5)).get_result() |
| self.assertEqual(update_token, 'token') |
| mock_call.assert_called_once_with( |
| 'CreateInvocation', { |
| 'invocation': { |
| 'producerResource': |
| '//test-swarming.appspot.com/tasks/task001', |
| 'realm': |
| 'infra:try', |
| 'deadline': |
| '2020-01-02T03:04:05Z', |
| }, |
| 'requestId': '00000000-0000-0000-0000-000000000000', |
| 'invocationId': 'task-test-swarming.appspot.com-task001' |
| }, |
| project_id='infra', |
| response_headers=mock.ANY) |
| |
| def test_create_invocation_async_no_update_token(self): |
| with mock.patch('server.resultdb._call_resultdb_recorder_api_async', |
| mock.Mock(side_effect=self.nop_async)): |
| with self.assertRaisesRegexp( |
| AssertionError, |
| "^response_headers should have valid update-token: {}$"): |
| resultdb.create_invocation_async( |
| 'task001', |
| 'infra:try', |
| datetime.datetime(2020, 1, 2, 3, 4, 5), |
| ).get_result() |
| |
| def test_finalize_invocation_async_success(self): |
| |
| with mock.patch( |
| 'server.resultdb._call_resultdb_recorder_api_async') as mock_call: |
| mock_call.side_effect = self.nop_async |
| resultdb.finalize_invocation_async('task001', 'secret').get_result() |
| mock_call.assert_called_once_with( |
| 'FinalizeInvocation', { |
| 'name': 'invocations/task-test-swarming.appspot.com-task001', |
| }, |
| headers={'update-token': 'secret'}, |
| scopes=None) |
| |
| def test_finalize_invocation_async_failed_precondition(self): |
| with mock.patch( |
| 'server.resultdb._call_resultdb_recorder_api_async') as mock_call: |
| mock_call.side_effect = net.Error( |
| msg='error', |
| status_code=400, |
| response='error', |
| headers={'X-Prpc-Grpc-Code': '9'}) |
| resultdb.finalize_invocation_async('task001', 'secret').get_result() |
| mock_call.assert_called_once_with( |
| 'FinalizeInvocation', { |
| 'name': 'invocations/task-test-swarming.appspot.com-task001', |
| }, |
| headers={'update-token': 'secret'}, |
| scopes=None) |
| |
| def test_finalize_invocation_async_failed(self): |
| with mock.patch( |
| 'server.resultdb._call_resultdb_recorder_api_async') as mock_call: |
| mock_call.side_effect = Exception('failed') |
| with self.assertRaises(Exception): |
| resultdb.finalize_invocation_async('task001', 'secret').get_result() |
| mock_call.assert_called_once_with( |
| 'FinalizeInvocation', { |
| 'name': 'invocations/task-test-swarming.appspot.com-task001', |
| }, |
| headers={'update-token': 'secret'}, |
| scopes=None) |
| |
| def test_call_resultdb_recorder_api(self): |
| |
| with mock.patch('server.config.settings') as mock_settings, mock.patch( |
| 'components.net.json_request_async') as mock_json_request_async: |
| mock_settings.return_value = config_pb2.SettingsCfg( |
| resultdb=config_pb2.ResultDBSettings( |
| server='https://results.api.cr.dev'),) |
| mock_json_request_async.side_effect = self.nop_async |
| |
| resultdb._call_resultdb_recorder_api_async('FinalizeInvocation', |
| {}).get_result() |
| |
| mock_settings.assert_called_once() |
| mock_json_request_async.assert_called_once() |
| |
| def test_get_invocation_name(self): |
| self.assertEqual( |
| resultdb.get_invocation_name('run_result_id_01'), |
| 'invocations/task-test-swarming.appspot.com-run_result_id_01') |
| |
| |
| if __name__ == '__main__': |
| if '-v' in sys.argv: |
| unittest.TestCase.maxDiff = None |
| logging.basicConfig( |
| level=logging.DEBUG if '-v' in sys.argv else logging.CRITICAL) |
| unittest.main() |