OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # coding=utf-8 | 2 # coding=utf-8 |
3 # Copyright 2015 The LUCI Authors. All rights reserved. | 3 # Copyright 2015 The LUCI Authors. All rights reserved. |
4 # Use of this source code is governed under the Apache License, Version 2.0 | 4 # Use of this source code is governed under the Apache License, Version 2.0 |
5 # that can be found in the LICENSE file. | 5 # that can be found in the LICENSE file. |
6 | 6 |
7 import base64 | 7 import base64 |
8 import datetime | 8 import datetime |
9 import json | 9 import json |
10 import logging | 10 import logging |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 webapp2.WSGIApplication(handlers_bot.get_routes(), debug=True), | 56 webapp2.WSGIApplication(handlers_bot.get_routes(), debug=True), |
57 extra_environ={ | 57 extra_environ={ |
58 'REMOTE_ADDR': self.source_ip, | 58 'REMOTE_ADDR': self.source_ip, |
59 'SERVER_SOFTWARE': os.environ['SERVER_SOFTWARE'], | 59 'SERVER_SOFTWARE': os.environ['SERVER_SOFTWARE'], |
60 }) | 60 }) |
61 self.mock( | 61 self.mock( |
62 ereporter2, 'log_request', | 62 ereporter2, 'log_request', |
63 lambda *args, **kwargs: self.fail('%s, %s' % (args, kwargs))) | 63 lambda *args, **kwargs: self.fail('%s, %s' % (args, kwargs))) |
64 # Client API test cases run by default as user. | 64 # Client API test cases run by default as user. |
65 self.set_as_user() | 65 self.set_as_user() |
| 66 self.pubsub_tasks = [] |
66 self.mock(utils, 'enqueue_task', self._enqueue_task) | 67 self.mock(utils, 'enqueue_task', self._enqueue_task) |
67 | 68 |
68 @ndb.non_transactional | 69 @ndb.non_transactional |
69 def _enqueue_task(self, url, queue_name, **kwargs): | 70 def _enqueue_task(self, url, queue_name, **kwargs): |
70 if queue_name == 'task-dimensions': | 71 if queue_name == 'task-dimensions': |
71 # Call directly into it, ignores any current transaction. | 72 # Call directly into it, ignores any current transaction. |
72 handlers_backend.TaskDimensionsHandler.tidy_stale(kwargs['payload']) | 73 handlers_backend.TaskDimensionsHandler.tidy_stale(kwargs['payload']) |
73 return True | 74 return True |
74 if queue_name == 'pubsub': | 75 if queue_name == 'pubsub': |
| 76 task = {'url': url, 'queue_name': queue_name} |
| 77 task.update(kwargs) |
| 78 self.pubsub_tasks.append(task) |
75 return True | 79 return True |
76 self.fail(url) | 80 self.fail(url) |
77 | 81 |
78 | 82 |
79 class ServerApiTest(BaseTest): | 83 class ServerApiTest(BaseTest): |
80 api_service_cls = handlers_endpoints.SwarmingServerService | 84 api_service_cls = handlers_endpoints.SwarmingServerService |
81 | 85 |
82 def test_details(self): | 86 def test_details(self): |
83 """Asserts that server_details returns the correct version.""" | 87 """Asserts that server_details returns the correct version.""" |
84 self.mock(config.config, 'config_service_hostname', lambda: 'a.server') | 88 self.mock(config.config, 'config_service_hostname', lambda: 'a.server') |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 ], | 622 ], |
619 u'user': u'joe@localhost', | 623 u'user': u'joe@localhost', |
620 }, | 624 }, |
621 ], | 625 ], |
622 u'now': str_now_30, | 626 u'now': str_now_30, |
623 } | 627 } |
624 self.assertEqual( | 628 self.assertEqual( |
625 expected, | 629 expected, |
626 self.call_api('requests', body=message_to_dict(request)).json) | 630 self.call_api('requests', body=message_to_dict(request)).json) |
627 | 631 |
| 632 def test_new_ok_deduped_by_transaction_id(self): |
| 633 """Asserts that new returns task result for deduped.""" |
| 634 # Run a task to completion. |
| 635 self.mock(random, 'getrandbits', lambda _: 0x88) |
| 636 now = self.mock_now(datetime.datetime(2010, 1, 2, 3, 4, 5)) |
| 637 str_now = unicode(now.strftime(self.DATETIME_NO_MICRO)) |
| 638 new_req, _, task_id = self.client_create_task_raw( |
| 639 name='task', tags=['project:yay', 'commit:post'], |
| 640 properties=dict(idempotent=True), |
| 641 transaction_id='txn') |
| 642 self.set_as_bot() |
| 643 self.bot_run_task() |
| 644 |
| 645 self.mock(random, 'getrandbits', lambda _: 0x66) |
| 646 self.set_as_user() |
| 647 |
| 648 expected = { |
| 649 u'request': { |
| 650 u'authenticated': u'user:user@example.com', |
| 651 u'created_ts': str_now, |
| 652 u'expiration_secs': u'86400', |
| 653 u'name': u'task', |
| 654 u'priority': u'100', |
| 655 u'properties': { |
| 656 u'cipd_input': { |
| 657 u'client_package': { |
| 658 u'package_name': u'infra/tools/cipd/${platform}', |
| 659 u'version': u'git_revision:deadbeef', |
| 660 }, |
| 661 u'packages': [{ |
| 662 u'package_name': u'rm', |
| 663 u'path': u'bin', |
| 664 u'version': u'git_revision:deadbeef', |
| 665 }], |
| 666 u'server': u'https://chrome-infra-packages.appspot.com', |
| 667 }, |
| 668 u'command': [u'python', u'run_test.py'], |
| 669 u'dimensions': [ |
| 670 {u'key': u'os', u'value': u'Amiga'}, |
| 671 {u'key': u'pool', u'value': u'default'}, |
| 672 ], |
| 673 u'execution_timeout_secs': u'3600', |
| 674 u'grace_period_secs': u'30', |
| 675 u'idempotent': True, |
| 676 u'io_timeout_secs': u'1200', |
| 677 u'outputs': [u'foo', u'path/to/foobar'], |
| 678 }, |
| 679 u'service_account': u'none', |
| 680 u'tags': [ |
| 681 u'commit:post', |
| 682 u'os:Amiga', |
| 683 u'pool:default', |
| 684 u'priority:100', |
| 685 u'project:yay', |
| 686 u'service_account:none', |
| 687 u'user:joe@localhost', |
| 688 ], |
| 689 u'user': u'joe@localhost', |
| 690 }, |
| 691 u'task_id': unicode(task_id), |
| 692 u'task_result': { |
| 693 u'bot_dimensions': [ |
| 694 {u'key': u'id', u'value': [u'bot1']}, |
| 695 {u'key': u'os', u'value': [u'Amiga']}, |
| 696 {u'key': u'pool', u'value': [u'default']}, |
| 697 ], |
| 698 u'bot_id': u'bot1', |
| 699 u'bot_version': self.bot_version, |
| 700 u'completed_ts': str_now, |
| 701 u'costs_usd': [0.1], |
| 702 u'created_ts': str_now, |
| 703 u'duration': 0.1, |
| 704 u'exit_code': u'0', |
| 705 u'failure': False, |
| 706 u'internal_failure': False, |
| 707 u'modified_ts': str_now, |
| 708 u'name': u'task', |
| 709 u'properties_hash': ( |
| 710 u'd35fe05074cbd9a2356c77c9983c71476f3a5f9415c5c5b1f3e2cdf7826b7261' |
| 711 ), |
| 712 u'run_id': u'5cee488008811', |
| 713 u'server_versions': [u'v1a'], |
| 714 u'started_ts': str_now, |
| 715 u'state': u'COMPLETED', |
| 716 u'tags': [ |
| 717 u'commit:post', |
| 718 u'os:Amiga', |
| 719 u'pool:default', |
| 720 u'priority:100', |
| 721 u'project:yay', |
| 722 u'service_account:none', |
| 723 u'user:joe@localhost', |
| 724 ], |
| 725 u'task_id': unicode(task_id), |
| 726 u'try_number': u'1', |
| 727 u'user': u'joe@localhost', |
| 728 }, |
| 729 } |
| 730 response = self.call_api('new', body=message_to_dict(new_req)) |
| 731 self.assertEqual(expected, response.json) |
| 732 |
628 def test_new_ok_isolated(self): | 733 def test_new_ok_isolated(self): |
629 """Asserts that new generates appropriate metadata.""" | 734 """Asserts that new generates appropriate metadata.""" |
630 self.mock(random, 'getrandbits', lambda _: 0x88) | 735 self.mock(random, 'getrandbits', lambda _: 0x88) |
631 now = datetime.datetime(2010, 1, 2, 3, 4, 5) | 736 now = datetime.datetime(2010, 1, 2, 3, 4, 5) |
632 self.mock_now(now) | 737 self.mock_now(now) |
633 str_now = unicode(now.strftime(self.DATETIME_NO_MICRO)) | 738 str_now = unicode(now.strftime(self.DATETIME_NO_MICRO)) |
634 request = swarming_rpcs.NewTaskRequest( | 739 request = swarming_rpcs.NewTaskRequest( |
635 expiration_secs=30, | 740 expiration_secs=30, |
636 name='job1', | 741 name='job1', |
637 priority=200, | 742 priority=200, |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 u'user:joe@localhost', | 948 u'user:joe@localhost', |
844 ], | 949 ], |
845 u'user': u'joe@localhost', | 950 u'user': u'joe@localhost', |
846 }, | 951 }, |
847 u'task_id': u'5cee488008810', | 952 u'task_id': u'5cee488008810', |
848 } | 953 } |
849 response = self.call_api('new', body=message_to_dict(request)) | 954 response = self.call_api('new', body=message_to_dict(request)) |
850 self.assertEqual(expected, response.json) | 955 self.assertEqual(expected, response.json) |
851 | 956 |
852 def test_mass_cancel(self): | 957 def test_mass_cancel(self): |
853 notifies = [] | |
854 def enqueue_task_mock(**kwargs): | |
855 notifies.append(kwargs) | |
856 return True | |
857 self.mock(utils, 'enqueue_task', enqueue_task_mock) | |
858 | |
859 # Create two tasks. | 958 # Create two tasks. |
860 self.mock(random, 'getrandbits', lambda _: 0x88) | 959 self.mock(random, 'getrandbits', lambda _: 0x88) |
861 first, second, _, _, _, now_120 = self._gen_three_pending_tasks() | 960 first, second, _, _, _, now_120 = self._gen_three_pending_tasks() |
862 now_120_str = unicode(now_120.strftime(self.DATETIME_NO_MICRO)) | 961 now_120_str = unicode(now_120.strftime(self.DATETIME_NO_MICRO)) |
863 | 962 |
864 expected = { | 963 expected = { |
865 u'matched': u'2', | 964 u'matched': u'2', |
866 u'now': now_120_str, | 965 u'now': now_120_str, |
867 } | 966 } |
868 self.set_as_admin() | 967 self.set_as_admin() |
869 | 968 |
870 def enqueue_task(*args, **kwargs): | 969 def enqueue_task(*args, **kwargs): |
871 self.assertEqual('%s,%s' % (second, first), | 970 self.assertEqual('%s,%s' % (second, first), |
872 kwargs.get('payload', '')) | 971 kwargs.get('payload', '')) |
873 # check URL | 972 # check URL |
874 self.assertEqual('/internal/taskqueue/cancel-tasks', args[0]) | 973 self.assertEqual('/internal/taskqueue/cancel-tasks', args[0]) |
875 # check task queue | 974 # check task queue |
876 self.assertEqual('cancel-tasks', args[1]) | 975 self.assertEqual('cancel-tasks', args[1]) |
877 return True | 976 return True |
878 self.mock(utils, 'enqueue_task', enqueue_task) | 977 self.mock(utils, 'enqueue_task', enqueue_task) |
879 | 978 |
880 response = self.call_api('cancel', body={u'tags': [u'os:Win']}) | 979 response = self.call_api('cancel', body={u'tags': [u'os:Win']}) |
881 self.assertEqual(expected, response.json) | 980 self.assertEqual(expected, response.json) |
882 | 981 |
| 982 def test_cancel_by_transaction_id_ok(self): |
| 983 """Asserts that task cancellation goes smoothly.""" |
| 984 # Create and cancel a task as a non-privileged user. |
| 985 self.mock(random, 'getrandbits', lambda _: 0x88) |
| 986 now = datetime.datetime(2010, 1, 2, 3, 4, 5) |
| 987 self.mock_now(now) |
| 988 _, _, task_id = self.client_create_task_raw( |
| 989 pubsub_topic='projects/abc/topics/def', |
| 990 pubsub_userdata='blah', |
| 991 transaction_id='txn') |
| 992 expected = { |
| 993 u'task_id': task_id, |
| 994 u'ok': True, |
| 995 u'was_running': False |
| 996 } |
| 997 response = self.call_api( |
| 998 'cancel_by_transaction_id', body={'transaction_id': 'txn'}) |
| 999 self.assertEqual(expected, response.json) |
883 | 1000 |
| 1001 _, result = handlers_endpoints.get_request_and_result(task_id) |
| 1002 self.assertEqual(result.state, task_result.State.CANCELED) |
| 1003 |
| 1004 expected = [ |
| 1005 { |
| 1006 'payload': '{"auth_token":null,"task_id":"5cee488008810",' |
| 1007 '"topic":"projects/abc/topics/def","userdata":"blah"}', |
| 1008 'queue_name': 'pubsub', |
| 1009 'transactional': True, |
| 1010 'url': '/internal/taskqueue/pubsub/5cee488008810', |
| 1011 }, |
| 1012 ] |
| 1013 self.assertEqual(expected, self.pubsub_tasks) |
| 1014 |
| 1015 def test_cancel_by_transaction_id_forbidden(self): |
| 1016 """Asserts that non-privileged non-owner can't cancel tasks.""" |
| 1017 # Create a task as an admin. |
| 1018 self.mock(random, 'getrandbits', lambda _: 0x88) |
| 1019 now = datetime.datetime(2010, 1, 2, 3, 4, 5) |
| 1020 self.mock_now(now) |
| 1021 self.set_as_admin() |
| 1022 self.client_create_task_raw( |
| 1023 pubsub_topic='projects/abc/topics/def', |
| 1024 pubsub_userdata='blah', |
| 1025 transaction_id='txn') |
| 1026 |
| 1027 # Attempt to cancel as non-privileged user -> HTTP 403. |
| 1028 self.set_as_user() |
| 1029 self.call_api( |
| 1030 'cancel_by_transaction_id', body={'transaction_id': 'txn'}, status=403) |
| 1031 |
| 1032 self.assertEqual([], self.pubsub_tasks) |
884 | 1033 |
885 def test_list_ok(self): | 1034 def test_list_ok(self): |
886 """Asserts that list requests all TaskResultSummaries.""" | 1035 """Asserts that list requests all TaskResultSummaries.""" |
887 first, second, str_now_120, start, end = self._gen_two_tasks() | 1036 first, second, str_now_120, start, end = self._gen_two_tasks() |
888 first_no_perf = first.copy() | 1037 first_no_perf = first.copy() |
889 first_no_perf.pop('performance_stats') | 1038 first_no_perf.pop('performance_stats') |
890 # Basic request. | 1039 # Basic request. |
891 request = swarming_rpcs.TasksRequest( | 1040 request = swarming_rpcs.TasksRequest( |
892 end=end, start=start, include_performance_stats=True) | 1041 end=end, start=start, include_performance_stats=True) |
893 expected = {u'now': str_now_120, u'items': [second, first]} | 1042 expected = {u'now': str_now_120, u'items': [second, first]} |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 u'ts': unicode(now.strftime(self.DATETIME_FORMAT)), | 1208 u'ts': unicode(now.strftime(self.DATETIME_FORMAT)), |
1060 } | 1209 } |
1061 self.assertEqual(expected, self.call_api('tags', body={}).json) | 1210 self.assertEqual(expected, self.call_api('tags', body={}).json) |
1062 | 1211 |
1063 def _gen_two_tasks(self): | 1212 def _gen_two_tasks(self): |
1064 # first request | 1213 # first request |
1065 now = datetime.datetime(2010, 1, 2, 3, 4, 5) | 1214 now = datetime.datetime(2010, 1, 2, 3, 4, 5) |
1066 str_now = unicode(now.strftime(self.DATETIME_NO_MICRO)) | 1215 str_now = unicode(now.strftime(self.DATETIME_NO_MICRO)) |
1067 self.mock_now(now) | 1216 self.mock_now(now) |
1068 self.mock(random, 'getrandbits', lambda _: 0x66) | 1217 self.mock(random, 'getrandbits', lambda _: 0x66) |
1069 _, first_id = self.client_create_task_raw( | 1218 _, _, first_id = self.client_create_task_raw( |
1070 name='first', tags=['project:yay', 'commit:post', 'os:Win'], | 1219 name='first', tags=['project:yay', 'commit:post', 'os:Win'], |
1071 properties=dict(idempotent=True)) | 1220 properties=dict(idempotent=True)) |
1072 self.set_as_bot() | 1221 self.set_as_bot() |
1073 self.bot_run_task() | 1222 self.bot_run_task() |
1074 | 1223 |
1075 # second request | 1224 # second request |
1076 self.set_as_user() | 1225 self.set_as_user() |
1077 self.mock(random, 'getrandbits', lambda _: 0x88) | 1226 self.mock(random, 'getrandbits', lambda _: 0x88) |
1078 now_60 = self.mock_now(now, 60) | 1227 now_60 = self.mock_now(now, 60) |
1079 str_now_60 = unicode(now_60.strftime(self.DATETIME_NO_MICRO)) | 1228 str_now_60 = unicode(now_60.strftime(self.DATETIME_NO_MICRO)) |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1186 utils.datetime_to_timestamp(now + datetime.timedelta(days=1)) / | 1335 utils.datetime_to_timestamp(now + datetime.timedelta(days=1)) / |
1187 1000000.) | 1336 1000000.) |
1188 self.set_as_privileged_user() | 1337 self.set_as_privileged_user() |
1189 return first, second, str_now_120, start, end | 1338 return first, second, str_now_120, start, end |
1190 | 1339 |
1191 def _gen_three_pending_tasks(self): | 1340 def _gen_three_pending_tasks(self): |
1192 # Creates three pending tasks, spaced 1 minute apart | 1341 # Creates three pending tasks, spaced 1 minute apart |
1193 now = datetime.datetime(2010, 1, 2, 3, 4, 5) | 1342 now = datetime.datetime(2010, 1, 2, 3, 4, 5) |
1194 self.mock_now(now) | 1343 self.mock_now(now) |
1195 self.mock(random, 'getrandbits', lambda _: 0x66) | 1344 self.mock(random, 'getrandbits', lambda _: 0x66) |
1196 _, first_id = self.client_create_task_raw( | 1345 _, _, first_id = self.client_create_task_raw( |
1197 name='first', tags=['project:yay', 'commit:abcd', 'os:Win'], | 1346 name='first', tags=['project:yay', 'commit:abcd', 'os:Win'], |
1198 pubsub_topic='projects/abc/topics/def', | 1347 pubsub_topic='projects/abc/topics/def', |
1199 pubsub_userdata='1234', | 1348 pubsub_userdata='1234', |
1200 properties=dict(idempotent=True)) | 1349 properties=dict(idempotent=True)) |
1201 | 1350 |
1202 now_60 = self.mock_now(now, 60) | 1351 now_60 = self.mock_now(now, 60) |
1203 self.mock(random, 'getrandbits', lambda _: 0x88) | 1352 self.mock(random, 'getrandbits', lambda _: 0x88) |
1204 _, second_id = self.client_create_task_raw( | 1353 _, _, second_id = self.client_create_task_raw( |
1205 name='second', user='jack@localhost', | 1354 name='second', user='jack@localhost', |
1206 pubsub_topic='projects/abc/topics/def', | 1355 pubsub_topic='projects/abc/topics/def', |
1207 pubsub_userdata='5678', | 1356 pubsub_userdata='5678', |
1208 tags=['project:yay', 'commit:efgh', 'os:Win'], | 1357 tags=['project:yay', 'commit:efgh', 'os:Win'], |
1209 properties=dict(idempotent=True)) | 1358 properties=dict(idempotent=True)) |
1210 | 1359 |
1211 now_120 = self.mock_now(now, 120) | 1360 now_120 = self.mock_now(now, 120) |
1212 _, third_id = self.client_create_task_raw( | 1361 _, _, third_id = self.client_create_task_raw( |
1213 name='third', user='jack@localhost', | 1362 name='third', user='jack@localhost', |
1214 pubsub_topic='projects/abc/topics/def', | 1363 pubsub_topic='projects/abc/topics/def', |
1215 pubsub_userdata='9000', | 1364 pubsub_userdata='9000', |
1216 tags=['project:yay', 'commit:ijkhl', 'os:Linux'], | 1365 tags=['project:yay', 'commit:ijkhl', 'os:Linux'], |
1217 properties=dict(idempotent=True)) | 1366 properties=dict(idempotent=True)) |
1218 | 1367 |
1219 return first_id, second_id, third_id, now, now_60, now_120 | 1368 return first_id, second_id, third_id, now, now_60, now_120 |
1220 | 1369 |
1221 | 1370 |
1222 class TaskApiTest(BaseTest): | 1371 class TaskApiTest(BaseTest): |
1223 api_service_cls = handlers_endpoints.SwarmingTaskService | 1372 api_service_cls = handlers_endpoints.SwarmingTaskService |
1224 | 1373 |
1225 def setUp(self): | 1374 def setUp(self): |
1226 super(TaskApiTest, self).setUp() | 1375 super(TaskApiTest, self).setUp() |
1227 self.tasks_api = test_case.Endpoints( | 1376 self.tasks_api = test_case.Endpoints( |
1228 handlers_endpoints.SwarmingTasksService) | 1377 handlers_endpoints.SwarmingTasksService) |
1229 | 1378 |
1230 def test_cancel_ok(self): | 1379 def test_cancel_ok(self): |
1231 """Asserts that task cancellation goes smoothly.""" | 1380 """Asserts that task cancellation goes smoothly.""" |
1232 # catch PubSub notification | |
1233 # Create and cancel a task as a non-privileged user. | 1381 # Create and cancel a task as a non-privileged user. |
1234 self.mock(random, 'getrandbits', lambda _: 0x88) | 1382 self.mock(random, 'getrandbits', lambda _: 0x88) |
1235 now = datetime.datetime(2010, 1, 2, 3, 4, 5) | 1383 now = datetime.datetime(2010, 1, 2, 3, 4, 5) |
1236 self.mock_now(now) | 1384 self.mock_now(now) |
1237 str_now = unicode(now.strftime(self.DATETIME_NO_MICRO)) | 1385 str_now = unicode(now.strftime(self.DATETIME_NO_MICRO)) |
1238 _, task_id = self.client_create_task_raw( | 1386 _, _, task_id = self.client_create_task_raw( |
1239 pubsub_topic='projects/abc/topics/def', | 1387 pubsub_topic='projects/abc/topics/def', |
1240 pubsub_userdata='blah') | 1388 pubsub_userdata='blah') |
1241 expected = {u'ok': True, u'was_running': False} | 1389 expected = {u'ok': True, u'was_running': False} |
1242 response = self.call_api('cancel', body={'task_id': task_id}) | 1390 response = self.call_api('cancel', body={'task_id': task_id}) |
1243 self.assertEqual(expected, response.json) | 1391 self.assertEqual(expected, response.json) |
1244 | 1392 |
1245 # determine that the task's state updates correctly | 1393 # determine that the task's state updates correctly |
1246 expected = { | 1394 expected = { |
1247 u'abandoned_ts': str_now, | 1395 u'abandoned_ts': str_now, |
1248 u'created_ts': str_now, | 1396 u'created_ts': str_now, |
(...skipping 18 matching lines...) Expand all Loading... |
1267 # notification has been sent. | 1415 # notification has been sent. |
1268 expected = [ | 1416 expected = [ |
1269 { | 1417 { |
1270 'payload': '{"auth_token":null,"task_id":"5cee488008810",' | 1418 'payload': '{"auth_token":null,"task_id":"5cee488008810",' |
1271 '"topic":"projects/abc/topics/def","userdata":"blah"}', | 1419 '"topic":"projects/abc/topics/def","userdata":"blah"}', |
1272 'queue_name': 'pubsub', | 1420 'queue_name': 'pubsub', |
1273 'transactional': True, | 1421 'transactional': True, |
1274 'url': '/internal/taskqueue/pubsub/5cee488008810', | 1422 'url': '/internal/taskqueue/pubsub/5cee488008810', |
1275 }, | 1423 }, |
1276 ] | 1424 ] |
| 1425 self.assertEqual(expected, self.pubsub_tasks) |
1277 | 1426 |
1278 def test_cancel_forbidden(self): | 1427 def test_cancel_forbidden(self): |
1279 """Asserts that non-privileged non-owner can't cancel tasks.""" | 1428 """Asserts that non-privileged non-owner can't cancel tasks.""" |
1280 # catch PubSub notification | |
1281 notifies = [] | |
1282 def enqueue_task_mock(**kwargs): | |
1283 notifies.append(kwargs) | |
1284 return True | |
1285 self.mock(utils, 'enqueue_task', enqueue_task_mock) | |
1286 | |
1287 # Create a task as an admin. | 1429 # Create a task as an admin. |
1288 self.mock(random, 'getrandbits', lambda _: 0x88) | 1430 self.mock(random, 'getrandbits', lambda _: 0x88) |
1289 now = datetime.datetime(2010, 1, 2, 3, 4, 5) | 1431 now = datetime.datetime(2010, 1, 2, 3, 4, 5) |
1290 self.mock_now(now) | 1432 self.mock_now(now) |
1291 self.set_as_admin() | 1433 self.set_as_admin() |
1292 _, task_id = self.client_create_task_raw( | 1434 _, _, task_id = self.client_create_task_raw( |
1293 pubsub_topic='projects/abc/topics/def', | 1435 pubsub_topic='projects/abc/topics/def', |
1294 pubsub_userdata='blah') | 1436 pubsub_userdata='blah') |
1295 | 1437 |
1296 # Attempt to cancel as non-privileged user -> HTTP 403. | 1438 # Attempt to cancel as non-privileged user -> HTTP 403. |
1297 self.set_as_user() | 1439 self.set_as_user() |
1298 self.call_api('cancel', body={'task_id': task_id}, status=403) | 1440 self.call_api('cancel', body={'task_id': task_id}, status=403) |
1299 | 1441 |
| 1442 self.assertEqual([], self.pubsub_tasks) |
| 1443 |
1300 def test_task_canceled(self): | 1444 def test_task_canceled(self): |
1301 self.mock(random, 'getrandbits', lambda _: 0x88) | 1445 self.mock(random, 'getrandbits', lambda _: 0x88) |
1302 now = datetime.datetime(2010, 1, 2, 3, 4, 5) | 1446 now = datetime.datetime(2010, 1, 2, 3, 4, 5) |
1303 self.mock_now(now) | 1447 self.mock_now(now) |
1304 str_now = unicode(now.strftime(self.DATETIME_NO_MICRO)) | 1448 str_now = unicode(now.strftime(self.DATETIME_NO_MICRO)) |
1305 _, task_id = self.client_create_task_raw( | 1449 _, _, task_id = self.client_create_task_raw( |
1306 properties=dict(command=['python', 'runtest.py'])) | 1450 properties=dict(command=['python', 'runtest.py'])) |
1307 | 1451 |
1308 self.set_as_bot() | 1452 self.set_as_bot() |
1309 params = self.do_handshake() | 1453 params = self.do_handshake() |
1310 data = self.post_json('/swarming/api/v1/bot/poll', params) | 1454 data = self.post_json('/swarming/api/v1/bot/poll', params) |
1311 run_id = data['manifest']['task_id'] | 1455 run_id = data['manifest']['task_id'] |
1312 def _params(**kwargs): | 1456 def _params(**kwargs): |
1313 out = { | 1457 out = { |
1314 'cost_usd': 0.1, | 1458 'cost_usd': 0.1, |
1315 'duration': None, | 1459 'duration': None, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1380 self.call_api('result', body={'task_id': '12310'}, status=404) | 1524 self.call_api('result', body={'task_id': '12310'}, status=404) |
1381 | 1525 |
1382 def test_result_ok(self): | 1526 def test_result_ok(self): |
1383 """Asserts that result produces a result entity.""" | 1527 """Asserts that result produces a result entity.""" |
1384 self.mock(random, 'getrandbits', lambda _: 0x88) | 1528 self.mock(random, 'getrandbits', lambda _: 0x88) |
1385 | 1529 |
1386 # pending task | 1530 # pending task |
1387 now = datetime.datetime(2010, 1, 2, 3, 4, 5) | 1531 now = datetime.datetime(2010, 1, 2, 3, 4, 5) |
1388 self.mock_now(now) | 1532 self.mock_now(now) |
1389 str_now = unicode(now.strftime(self.DATETIME_NO_MICRO)) | 1533 str_now = unicode(now.strftime(self.DATETIME_NO_MICRO)) |
1390 _, task_id = self.client_create_task_raw() | 1534 _, _, task_id = self.client_create_task_raw() |
1391 response = self.call_api('result', body={'task_id': task_id}) | 1535 response = self.call_api('result', body={'task_id': task_id}) |
1392 expected = { | 1536 expected = { |
1393 u'created_ts': str_now, | 1537 u'created_ts': str_now, |
1394 u'failure': False, | 1538 u'failure': False, |
1395 u'internal_failure': False, | 1539 u'internal_failure': False, |
1396 u'modified_ts': str_now, | 1540 u'modified_ts': str_now, |
1397 u'name': u'hi', | 1541 u'name': u'hi', |
1398 u'state': u'PENDING', | 1542 u'state': u'PENDING', |
1399 u'tags': [ | 1543 u'tags': [ |
1400 u'os:Amiga', | 1544 u'os:Amiga', |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1512 | 1656 |
1513 self.set_as_privileged_user() | 1657 self.set_as_privileged_user() |
1514 run_id = task_id[:-1] + '1' | 1658 run_id = task_id[:-1] + '1' |
1515 expected = {u'output': u'rÉsult string'} | 1659 expected = {u'output': u'rÉsult string'} |
1516 for i in (task_id, run_id): | 1660 for i in (task_id, run_id): |
1517 response = self.call_api('stdout', body={'task_id': i}) | 1661 response = self.call_api('stdout', body={'task_id': i}) |
1518 self.assertEqual(expected, response.json) | 1662 self.assertEqual(expected, response.json) |
1519 | 1663 |
1520 def test_stdout_empty(self): | 1664 def test_stdout_empty(self): |
1521 """Asserts that incipient tasks produce no output.""" | 1665 """Asserts that incipient tasks produce no output.""" |
1522 _, task_id = self.client_create_task_raw() | 1666 _, _, task_id = self.client_create_task_raw() |
1523 response = self.call_api('stdout', body={'task_id': task_id}) | 1667 response = self.call_api('stdout', body={'task_id': task_id}) |
1524 self.assertEqual({}, response.json) | 1668 self.assertEqual({}, response.json) |
1525 | 1669 |
1526 run_id = task_id[:-1] + '1' | 1670 run_id = task_id[:-1] + '1' |
1527 self.call_api('stdout', body={'task_id': run_id}, status=404) | 1671 self.call_api('stdout', body={'task_id': run_id}, status=404) |
1528 | 1672 |
1529 def test_result_run_not_found(self): | 1673 def test_result_run_not_found(self): |
1530 """Asserts that getting results from incipient tasks raises 404.""" | 1674 """Asserts that getting results from incipient tasks raises 404.""" |
1531 _, task_id = self.client_create_task_raw() | 1675 _, _, task_id = self.client_create_task_raw() |
1532 run_id = task_id[:-1] + '1' | 1676 run_id = task_id[:-1] + '1' |
1533 self.call_api('stdout', body={'task_id': run_id}, status=404) | 1677 self.call_api('stdout', body={'task_id': run_id}, status=404) |
1534 | 1678 |
1535 def test_task_deduped(self): | 1679 def test_task_deduped(self): |
1536 """Asserts that task deduplication works as expected.""" | 1680 """Asserts that task deduplication works as expected.""" |
1537 _, task_id_1 = self.client_create_task_raw(properties=dict(idempotent=True)) | 1681 _, _, task_id_1 = self.client_create_task_raw( |
| 1682 properties=dict(idempotent=True)) |
1538 | 1683 |
1539 self.set_as_bot() | 1684 self.set_as_bot() |
1540 task_id_bot = self.bot_run_task() | 1685 task_id_bot = self.bot_run_task() |
1541 self.assertEqual(task_id_1, task_id_bot[:-1] + '0') | 1686 self.assertEqual(task_id_1, task_id_bot[:-1] + '0') |
1542 self.assertEqual('1', task_id_bot[-1:]) | 1687 self.assertEqual('1', task_id_bot[-1:]) |
1543 | 1688 |
1544 # second task; this one's results should be returned immediately | 1689 # second task; this one's results should be returned immediately |
1545 self.set_as_user() | 1690 self.set_as_user() |
1546 _, task_id_2 = self.client_create_task_raw( | 1691 _, _, task_id_2 = self.client_create_task_raw( |
1547 name='second', user='jack@localhost', properties=dict(idempotent=True)) | 1692 name='second', user='jack@localhost', properties=dict(idempotent=True)) |
1548 | 1693 |
1549 self.set_as_bot() | 1694 self.set_as_bot() |
1550 resp = self.bot_poll() | 1695 resp = self.bot_poll() |
1551 self.assertEqual('sleep', resp['cmd']) | 1696 self.assertEqual('sleep', resp['cmd']) |
1552 | 1697 |
1553 self.set_as_user() | 1698 self.set_as_user() |
1554 | 1699 |
1555 # results shouldn't change, even if the second task wasn't executed | 1700 # results shouldn't change, even if the second task wasn't executed |
1556 response = self.call_api('stdout', body={'task_id': task_id_2}) | 1701 response = self.call_api('stdout', body={'task_id': task_id_2}) |
1557 self.assertEqual({'output': u'rÉsult string'}, response.json) | 1702 self.assertEqual({'output': u'rÉsult string'}, response.json) |
1558 | 1703 |
1559 def test_request_unknown(self): | 1704 def test_request_unknown(self): |
1560 """Asserts that 404 is raised for unknown tasks.""" | 1705 """Asserts that 404 is raised for unknown tasks.""" |
1561 self.call_api('request', body={'task_id': '12310'}, status=404) | 1706 self.call_api('request', body={'task_id': '12310'}, status=404) |
1562 | 1707 |
1563 def test_request_ok(self): | 1708 def test_request_ok(self): |
1564 """Asserts that request produces a task request.""" | 1709 """Asserts that request produces a task request.""" |
1565 now = datetime.datetime(2010, 1, 2, 3, 4, 5, 6) | 1710 now = datetime.datetime(2010, 1, 2, 3, 4, 5, 6) |
1566 self.mock_now(now) | 1711 self.mock_now(now) |
1567 _, task_id = self.client_create_task_raw() | 1712 _, _, task_id = self.client_create_task_raw() |
1568 response = self.call_api('request', body={'task_id': task_id}) | 1713 response = self.call_api('request', body={'task_id': task_id}) |
1569 expected = { | 1714 expected = { |
1570 u'authenticated': u'user:user@example.com', | 1715 u'authenticated': u'user:user@example.com', |
1571 u'created_ts': unicode(now.strftime(self.DATETIME_FORMAT)), | 1716 u'created_ts': unicode(now.strftime(self.DATETIME_FORMAT)), |
1572 u'expiration_secs': unicode(24 * 60 * 60), | 1717 u'expiration_secs': unicode(24 * 60 * 60), |
1573 u'name': u'hi', | 1718 u'name': u'hi', |
1574 u'priority': u'100', | 1719 u'priority': u'100', |
1575 u'properties': { | 1720 u'properties': { |
1576 u'cipd_input': { | 1721 u'cipd_input': { |
1577 u'client_package': { | 1722 u'client_package': { |
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2191 self.call_api('terminate', body={'bot_id': 'bot1'}, status=403) | 2336 self.call_api('terminate', body={'bot_id': 'bot1'}, status=403) |
2192 | 2337 |
2193 | 2338 |
2194 if __name__ == '__main__': | 2339 if __name__ == '__main__': |
2195 if '-v' in sys.argv: | 2340 if '-v' in sys.argv: |
2196 unittest.TestCase.maxDiff = None | 2341 unittest.TestCase.maxDiff = None |
2197 logging.basicConfig(level=logging.DEBUG) | 2342 logging.basicConfig(level=logging.DEBUG) |
2198 else: | 2343 else: |
2199 logging.basicConfig(level=logging.CRITICAL) | 2344 logging.basicConfig(level=logging.CRITICAL) |
2200 unittest.main() | 2345 unittest.main() |
OLD | NEW |