OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The LUCI Authors. All rights reserved. | 2 # Copyright 2014 The LUCI Authors. All rights reserved. |
3 # Use of this source code is governed under the Apache License, Version 2.0 | 3 # Use of this source code is governed under the Apache License, Version 2.0 |
4 # that can be found in the LICENSE file. | 4 # that can be found in the LICENSE file. |
5 | 5 |
6 import datetime | 6 import datetime |
7 import hashlib | 7 import hashlib |
8 import logging | 8 import logging |
9 import os | 9 import os |
10 import random | 10 import random |
11 import sys | 11 import sys |
12 import timeit | 12 import timeit |
13 import unittest | 13 import unittest |
14 | 14 |
15 import test_env | 15 # Setups environment. |
16 test_env.setup_test_env() | 16 APP_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| 17 sys.path.insert(0, APP_DIR) |
| 18 import test_env_handlers |
| 19 |
| 20 import webtest |
17 | 21 |
18 from google.appengine.ext import ndb | 22 from google.appengine.ext import ndb |
19 | 23 |
| 24 import handlers_backend |
| 25 |
20 from components import auth_testing | 26 from components import auth_testing |
21 from components import utils | 27 from components import utils |
22 from test_support import test_case | 28 from test_support import test_case |
23 | 29 |
24 from server import bot_management | 30 from server import bot_management |
25 from server import task_queues | 31 from server import task_queues |
26 from server import task_request | 32 from server import task_request |
27 from server import task_to_run | 33 from server import task_to_run |
28 | 34 |
29 | 35 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 for _request, to_run in | 79 for _request, to_run in |
74 task_to_run.yield_next_available_task_to_dispatch( | 80 task_to_run.yield_next_available_task_to_dispatch( |
75 bot_dimensions, deadline) | 81 bot_dimensions, deadline) |
76 ] | 82 ] |
77 | 83 |
78 | 84 |
79 def _hash_dimensions(dimensions): | 85 def _hash_dimensions(dimensions): |
80 return task_to_run._hash_dimensions(utils.encode_to_json(dimensions)) | 86 return task_to_run._hash_dimensions(utils.encode_to_json(dimensions)) |
81 | 87 |
82 | 88 |
83 class TestCase(test_case.TestCase): | 89 class TaskToRunPrivateTest(test_case.TestCase): |
84 def setUp(self): | 90 def setUp(self): |
85 super(TestCase, self).setUp() | 91 super(TaskToRunPrivateTest, self).setUp() |
86 auth_testing.mock_get_current_identity(self) | 92 auth_testing.mock_get_current_identity(self) |
87 | 93 |
88 | |
89 class TaskToRunPrivateTest(TestCase): | |
90 def test_powerset(self): | 94 def test_powerset(self): |
91 # tuples of (input, expected). | 95 # tuples of (input, expected). |
92 # TODO(maruel): We'd want the code to deterministically try 'Windows-6.1' | 96 # TODO(maruel): We'd want the code to deterministically try 'Windows-6.1' |
93 # before 'Windows'. Probably do a reverse() on the values? | 97 # before 'Windows'. Probably do a reverse() on the values? |
94 data = [ | 98 data = [ |
95 ({'OS': 'Windows'}, [{'OS': 'Windows'}, {}]), | 99 ({'OS': 'Windows'}, [{'OS': 'Windows'}, {}]), |
96 ( | 100 ( |
97 {'OS': ['Windows', 'Windows-6.1']}, | 101 {'OS': ['Windows', 'Windows-6.1']}, |
98 [{'OS': 'Windows'}, {'OS': 'Windows-6.1'}, {}], | 102 [{'OS': 'Windows'}, {'OS': 'Windows-6.1'}, {}], |
99 ), | 103 ), |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 self.assertEqual(16384, len(items)) | 245 self.assertEqual(16384, len(items)) |
242 | 246 |
243 def test_dimensions_search_sizing_14_1(self): | 247 def test_dimensions_search_sizing_14_1(self): |
244 dimensions = {str(k): '01234567890123456789' for k in xrange(14)} | 248 dimensions = {str(k): '01234567890123456789' for k in xrange(14)} |
245 items = tuple(sorted( | 249 items = tuple(sorted( |
246 task_to_run._hash_dimensions(utils.encode_to_json(i)) | 250 task_to_run._hash_dimensions(utils.encode_to_json(i)) |
247 for i in task_to_run._powerset(dimensions))) | 251 for i in task_to_run._powerset(dimensions))) |
248 self.assertEqual(16384, len(items)) | 252 self.assertEqual(16384, len(items)) |
249 | 253 |
250 | 254 |
251 class TaskToRunApiTest(TestCase): | 255 class TaskToRunApiTest(test_env_handlers.AppTestBase): |
252 def setUp(self): | 256 def setUp(self): |
253 super(TaskToRunApiTest, self).setUp() | 257 super(TaskToRunApiTest, self).setUp() |
254 self.now = datetime.datetime(2014, 01, 02, 03, 04, 05, 06) | 258 self.now = datetime.datetime(2014, 01, 02, 03, 04, 05, 06) |
255 self.mock_now(self.now) | 259 self.mock_now(self.now) |
| 260 auth_testing.mock_get_current_identity(self) |
256 # The default expiration_secs for _gen_request(). | 261 # The default expiration_secs for _gen_request(). |
257 self.expiration_ts = self.now + datetime.timedelta(seconds=60) | 262 self.expiration_ts = self.now + datetime.timedelta(seconds=60) |
| 263 # Setup the backend to handle task queues for 'task-dimensions'. |
| 264 self.app = webtest.TestApp( |
| 265 handlers_backend.create_application(True), |
| 266 extra_environ={ |
| 267 'REMOTE_ADDR': self.source_ip, |
| 268 'SERVER_SOFTWARE': os.environ['SERVER_SOFTWARE'], |
| 269 }) |
| 270 self._enqueue_orig = self.mock(utils, 'enqueue_task', self._enqueue) |
258 | 271 |
259 def mkreq(self, req, nb_tasks=0): | 272 def _enqueue(self, *args, **kwargs): |
| 273 return self._enqueue_orig(*args, use_dedicated_module=False, **kwargs) |
| 274 |
| 275 def mkreq(self, req, nb_task=0): |
260 """Stores a new initialized TaskRequest. | 276 """Stores a new initialized TaskRequest. |
261 | 277 |
262 nb_task is 1 or 0. It is 1 when the request.properties.dimensions was new | 278 nb_task is 1 or 0. It is 1 when the request.properties.dimensions was new |
263 (unseen before) and 0 otherwise. | 279 (unseen before) and 0 otherwise. |
264 """ | 280 """ |
265 task_request.init_new_request(req, True, None) | 281 task_request.init_new_request(req, True, None) |
266 task_queues.assert_task(req) | 282 task_queues.assert_task(req) |
267 self.assertEqual(nb_tasks, self.execute_tasks()) | 283 self.assertEqual(nb_task, self.execute_tasks()) |
268 req.key = task_request.new_request_key() | 284 req.key = task_request.new_request_key() |
269 req.put() | 285 req.put() |
270 return req | 286 return req |
271 | 287 |
272 def _gen_new_task_to_run(self, **kwargs): | 288 def _gen_new_task_to_run(self, **kwargs): |
273 """Returns a TaskToRun saved in the DB.""" | 289 """Returns a TaskToRun saved in the DB.""" |
274 request = self.mkreq(_gen_request(**kwargs)) | 290 request = self.mkreq(_gen_request(**kwargs)) |
275 to_run = task_to_run.new_task_to_run(request) | 291 to_run = task_to_run.new_task_to_run(request) |
276 to_run.put() | 292 to_run.put() |
277 return to_run | 293 return to_run |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 data = _gen_request( | 368 data = _gen_request( |
353 properties={ | 369 properties={ |
354 'command': [u'command1', u'arg1'], | 370 'command': [u'command1', u'arg1'], |
355 'dimensions': request_dimensions, | 371 'dimensions': request_dimensions, |
356 'env': {u'foo': u'bar'}, | 372 'env': {u'foo': u'bar'}, |
357 'execution_timeout_secs': 30, | 373 'execution_timeout_secs': 30, |
358 }, | 374 }, |
359 priority=10, | 375 priority=10, |
360 created_ts=now, | 376 created_ts=now, |
361 expiration_ts=now+datetime.timedelta(seconds=31)) | 377 expiration_ts=now+datetime.timedelta(seconds=31)) |
362 task_to_run.new_task_to_run(self.mkreq(data, nb_tasks=0)).put() | 378 task_to_run.new_task_to_run(self.mkreq(data, nb_task=0)).put() |
363 | 379 |
364 expected = [ | 380 expected = [ |
365 { | 381 { |
366 'dimensions_hash': _hash_dimensions(request_dimensions), | 382 'dimensions_hash': _hash_dimensions(request_dimensions), |
367 'expiration_ts': self.now + datetime.timedelta(seconds=31), | 383 'expiration_ts': self.now + datetime.timedelta(seconds=31), |
368 'request_key': '0x7e296460f77ffdce', | 384 'request_key': '0x7e296460f77ffdce', |
369 # Lower priority value means higher priority. | 385 # Lower priority value means higher priority. |
370 'queue_number': '0x00060dc5849f1346', | 386 'queue_number': '0x00060dc5849f1346', |
371 }, | 387 }, |
372 { | 388 { |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 # Task added later but with higher priority are returned first. | 625 # Task added later but with higher priority are returned first. |
610 request_dimensions_1 = {u'os': u'Windows-3.1.1', u'pool': u'default'} | 626 request_dimensions_1 = {u'os': u'Windows-3.1.1', u'pool': u'default'} |
611 self._gen_new_task_to_run(properties=dict(dimensions=request_dimensions_1)) | 627 self._gen_new_task_to_run(properties=dict(dimensions=request_dimensions_1)) |
612 | 628 |
613 # This one is later but has higher priority. | 629 # This one is later but has higher priority. |
614 self.mock_now(self.now, 60) | 630 self.mock_now(self.now, 60) |
615 request_dimensions_2 = {u'os': u'Windows-3.1.1', u'pool': u'default'} | 631 request_dimensions_2 = {u'os': u'Windows-3.1.1', u'pool': u'default'} |
616 request = self.mkreq( | 632 request = self.mkreq( |
617 _gen_request( | 633 _gen_request( |
618 properties=dict(dimensions=request_dimensions_2), priority=10), | 634 properties=dict(dimensions=request_dimensions_2), priority=10), |
619 nb_tasks=0) | 635 nb_task=0) |
620 task_to_run.new_task_to_run(request).put() | 636 task_to_run.new_task_to_run(request).put() |
621 | 637 |
622 # It should return them all, in the expected order. | 638 # It should return them all, in the expected order. |
623 expected = [ | 639 expected = [ |
624 { | 640 { |
625 'dimensions_hash': _hash_dimensions(request_dimensions_1), | 641 'dimensions_hash': _hash_dimensions(request_dimensions_1), |
626 'expiration_ts': datetime.datetime(2014, 1, 2, 3, 6, 5, 6), | 642 'expiration_ts': datetime.datetime(2014, 1, 2, 3, 6, 5, 6), |
627 'queue_number': '0x00060dc588329a46', | 643 'queue_number': '0x00060dc588329a46', |
628 }, | 644 }, |
629 { | 645 { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 task_to_run.set_lookup_cache(to_run.key, True) | 767 task_to_run.set_lookup_cache(to_run.key, True) |
752 self.assertEqual(False, task_to_run._lookup_cache_is_taken(to_run.key)) | 768 self.assertEqual(False, task_to_run._lookup_cache_is_taken(to_run.key)) |
753 | 769 |
754 | 770 |
755 if __name__ == '__main__': | 771 if __name__ == '__main__': |
756 if '-v' in sys.argv: | 772 if '-v' in sys.argv: |
757 unittest.TestCase.maxDiff = None | 773 unittest.TestCase.maxDiff = None |
758 logging.basicConfig( | 774 logging.basicConfig( |
759 level=logging.DEBUG if '-v' in sys.argv else logging.ERROR) | 775 level=logging.DEBUG if '-v' in sys.argv else logging.ERROR) |
760 unittest.main() | 776 unittest.main() |
OLD | NEW |