def test_task_header_update(self): e = Environment() e.accept_tasks = True tk = TaskHeaderKeeper(EnvironmentsManager(), 10) tk.environments_manager.add_environment(e) assert not tk.add_task_header(dict()) task_header = get_dict_task_header() task_id = task_header["task_id"] task_header["deadline"] = timeout_to_deadline(10) assert tk.add_task_header(task_header) assert task_id in tk.supported_tasks assert tk.add_task_header(task_header) assert task_id in tk.supported_tasks task_header["max_price"] = 1 assert tk.add_task_header(task_header) assert task_id not in tk.supported_tasks tk.task_headers = {} tk.supported_tasks = [] task_header["max_price"] = 1 assert tk.add_task_header(task_header) assert task_id not in tk.supported_tasks task_header['task_id'] = "newtaskID" task_header['deadline'] = "WRONG DEADLINE" assert not tk.add_task_header(task_header)
def test_task_header_update(self): e = Environment() e.accept_tasks = True tk = TaskHeaderKeeper(environments_manager=EnvironmentsManager(), node=p2p.Node(), min_price=10) tk.environments_manager.add_environment(e) task_header = get_task_header() task_id = task_header.task_id task_header.fixed_header.deadline = timeout_to_deadline(10) task_header.fixed_header.update_checksum() assert tk.add_task_header(task_header) assert task_id in tk.supported_tasks assert tk.add_task_header(task_header) assert task_id in tk.supported_tasks task_header = copy.deepcopy(task_header) task_header.fixed_header.max_price = 1 task_header.fixed_header.update_checksum() # An attempt to update fixed header should *not* succeed assert not tk.add_task_header(task_header) assert task_id in tk.supported_tasks tk.task_headers = {} tk.supported_tasks = [] assert tk.add_task_header(task_header) assert task_id not in tk.supported_tasks
def test_is_correct(self): tk = TaskHeaderKeeper(EnvironmentsManager(), 10) th = get_dict_task_header() correct, err = tk.is_correct(th) assert correct assert err is None th['deadline'] = datetime.now() correct, err = tk.is_correct(th) assert not correct assert err == "Deadline is not a timestamp" th['deadline'] = get_timestamp_utc() - 10 correct, err = tk.is_correct(th) assert not correct assert err == "Deadline already passed" th['deadline'] = get_timestamp_utc() + 20 correct, err = tk.is_correct(th) assert correct assert err is None th['subtask_timeout'] = "abc" correct, err = tk.is_correct(th) assert not correct assert err == "Subtask timeout is not a number" th['subtask_timeout'] = -131 correct, err = tk.is_correct(th) assert not correct assert err == "Subtask timeout is less than 0"
def test_get_task(self): tk = TaskHeaderKeeper(EnvironmentsManager(), 10) self.assertIsNone(tk.get_task()) task_header = get_dict_task_header() task_header["task_id"] = "uvw" self.assertTrue(tk.add_task_header(task_header)) self.assertIsNone(tk.get_task()) e = Environment() e.accept_tasks = True tk.environments_manager.add_environment(e) task_header["task_id"] = "xyz" self.assertTrue(tk.add_task_header(task_header)) th = tk.get_task() assert isinstance(th.task_owner, Node) self.assertEqual(task_header["task_id"], th.task_id) self.assertEqual(task_header["max_price"], th.max_price) self.assertEqual(task_header["node_name"], th.node_name) self.assertEqual(task_header["task_owner_port"], th.task_owner_port) self.assertEqual(task_header["task_owner_key_id"], th.task_owner_key_id) self.assertEqual(task_header["environment"], th.environment) self.assertEqual(task_header["deadline"], th.deadline) self.assertEqual(task_header["subtask_timeout"], th.subtask_timeout) self.assertEqual(task_header["max_price"], th.max_price) self.assertEqual(task_header["task_id"], th.task_id)
def test_old_tasks(frozen_time, _): # pylint: disable=no-self-argument tk = TaskHeaderKeeper(environments_manager=EnvironmentsManager(), node=p2p.Node(), min_price=10) e = Environment() e.accept_tasks = True tk.environments_manager.add_environment(e) task_header = get_task_header() task_header.fixed_header.deadline = timeout_to_deadline(10) assert tk.add_task_header(task_header) task_id = task_header.task_id task_header2 = get_task_header("abc") task_header2.fixed_header.deadline = timeout_to_deadline(1) task_id2 = task_header2.task_id assert tk.add_task_header(task_header2) assert tk.task_headers.get(task_id2) is not None assert tk.task_headers.get(task_id) is not None assert tk.removed_tasks.get(task_id2) is None assert tk.removed_tasks.get(task_id) is None assert len(tk.supported_tasks) == 2 frozen_time.tick(timedelta(seconds=1.1)) # pylint: disable=no-member tk.remove_old_tasks() assert tk.task_headers.get(task_id2) is None assert tk.task_headers.get(task_id) is not None assert tk.removed_tasks.get(task_id2) is not None assert tk.removed_tasks.get(task_id) is None assert len(tk.supported_tasks) == 1 assert tk.supported_tasks[0] == task_id
def test_task_header_update_stats(self, tar): e = Environment() e.accept_tasks = True tk = TaskHeaderKeeper(environments_manager=EnvironmentsManager(), node=p2p.Node(), min_price=10, task_archiver=tar) tk.environments_manager.add_environment(e) task_header = get_task_header("good") assert tk.add_task_header(task_header) tar.add_task.assert_called_with(mock.ANY) task_id = task_header.task_id tar.add_support_status.assert_any_call(task_id, SupportStatus(True, {})) tar.reset_mock() task_header2 = get_task_header("bad") task_id2 = task_header2.task_id task_header2.fixed_header.max_price = 1.0 assert tk.add_task_header(task_header2) tar.add_task.assert_called_with(mock.ANY) tar.add_support_status.assert_any_call( task_id2, SupportStatus(False, {UnsupportReason.MAX_PRICE: 1.0}))
def test_get_owner(self): tk = TaskHeaderKeeper(environments_manager=EnvironmentsManager(), node=p2p.Node(), min_price=10) header = get_task_header() owner = header.task_owner.key key_id = header.task_id tk.add_task_header(header) assert tk.get_owner(key_id) == owner assert tk.get_owner("UNKNOWN") is None
def test_check_version_compatibility(self): tk = TaskHeaderKeeper(environments_manager=EnvironmentsManager(), node=p2p.Node(), min_price=10.0) tk.app_version = '0.4.5-dev+232.138018' for v in ['', '0', '1.5', '0.4-alpha+build.2004.01.01', '0.4-alpha']: with self.assertRaises(ValueError, msg=v): tk.check_version_compatibility(v) for v in ['1.5.0', '1.4.0', '0.5.0', '0.3.0']: self.assertFalse(tk.check_version_compatibility(v), msg=v) for v in [ '0.4.5', '0.4.1', '0.4.0', '0.4.0-alpha', '0.4.0-alpha+build', '0.4.0-alpha+build.2010', '0.4.6' ]: self.assertTrue(tk.check_version_compatibility(v), msg=v)
def test_get_task(self): em = EnvironmentsManager() em.environments = {} em.support_statuses = {} tk = TaskHeaderKeeper(environments_manager=em, node=p2p.Node(), min_price=10) self.assertIsNone(tk.get_task()) task_header = get_task_header("uvw") self.assertTrue(tk.add_task_header(task_header)) self.assertIsNone(tk.get_task()) e = Environment() e.accept_tasks = True tk.environments_manager.add_environment(e) task_header2 = get_task_header("xyz") self.assertTrue(tk.add_task_header(task_header2)) th = tk.get_task() assert isinstance(th.task_owner, Node) self.assertEqual(task_header2.to_dict(), th.to_dict())
def test_old_tasks(self): tk = TaskHeaderKeeper(EnvironmentsManager(), 10) e = Environment() e.accept_tasks = True tk.environments_manager.add_environment(e) task_header = get_dict_task_header() task_header["deadline"] = timeout_to_deadline(10) assert tk.add_task_header(task_header) task_header["deadline"] = timeout_to_deadline(1) task_header["task_id"] = "abc" assert tk.add_task_header(task_header) assert tk.task_headers.get("abc") is not None assert tk.task_headers.get("xyz") is not None assert tk.removed_tasks.get("abc") is None assert tk.removed_tasks.get("xyz") is None assert len(tk.supported_tasks) == 2 time.sleep(1.1) tk.remove_old_tasks() assert tk.task_headers.get("abc") is None assert tk.task_headers.get("xyz") is not None assert tk.removed_tasks.get("abc") is not None assert tk.removed_tasks.get("xyz") is None assert len(tk.supported_tasks) == 1 assert tk.supported_tasks[0] == "xyz"
def test_change_config(self): tk = TaskHeaderKeeper(EnvironmentsManager(), 10.0) e = Environment() e.accept_tasks = True tk.environments_manager.add_environment(e) task_header = get_dict_task_header() task_header["max_price"] = 9.0 tk.add_task_header(task_header) self.assertNotIn("xyz", tk.supported_tasks) self.assertIsNotNone(tk.task_headers["xyz"]) task_header["task_id"] = "abc" task_header["max_price"] = 10.0 tk.add_task_header(task_header) self.assertIn("abc", tk.supported_tasks) self.assertIsNotNone(tk.task_headers["abc"]) config_desc = Mock() config_desc.min_price = 10.0 tk.change_config(config_desc) self.assertNotIn("xyz", tk.supported_tasks) self.assertIn("abc", tk.supported_tasks) config_desc.min_price = 8.0 tk.change_config(config_desc) self.assertIn("xyz", tk.supported_tasks) self.assertIn("abc", tk.supported_tasks) config_desc.min_price = 11.0 tk.change_config(config_desc) self.assertNotIn("xyz", tk.supported_tasks) self.assertNotIn("abc", tk.supported_tasks)
def test_check_version_compatibility(self): tk = TaskHeaderKeeper(EnvironmentsManager(), 10.0) tk.app_version = '0.4.5' with self.assertRaises(ValueError): tk.check_version_compatibility('') with self.assertRaises(ValueError): tk.check_version_compatibility('0') with self.assertRaises(ValueError): tk.check_version_compatibility('1.5') with self.assertRaises(ValueError): tk.check_version_compatibility('0.4-alpha+build.2004.01.01') with self.assertRaises(ValueError): tk.check_version_compatibility('0.4-alpha') with self.assertRaises(ValueError): tk.check_version_compatibility('0.4-alpha') assert not tk.check_version_compatibility('1.5.0') assert not tk.check_version_compatibility('1.4.0') assert not tk.check_version_compatibility('0.5.0') assert not tk.check_version_compatibility('0.4.6') assert not tk.check_version_compatibility('0.3.0') assert tk.check_version_compatibility('0.4.5') assert tk.check_version_compatibility('0.4.1') assert tk.check_version_compatibility('0.4.0') assert tk.check_version_compatibility('0.4.0-alpha') assert tk.check_version_compatibility('0.4.0-alpha+build') assert tk.check_version_compatibility('0.4.0-alpha+build.2010')
def test_is_supported(self): tk = TaskHeaderKeeper(EnvironmentsManager(), 10.0) self.assertFalse(tk.is_supported({})) task = {"environment": Environment.get_id(), 'max_price': 0} self.assertFalse(tk.is_supported(task)) e = Environment() e.accept_tasks = True tk.environments_manager.add_environment(e) self.assertFalse(tk.is_supported(task)) task["max_price"] = 10.0 self.assertFalse(tk.is_supported(task)) task["min_version"] = APP_VERSION self.assertTrue(tk.is_supported(task)) task["max_price"] = 10.5 self.assertTrue(tk.is_supported(task)) config_desc = Mock() config_desc.min_price = 13.0 tk.change_config(config_desc) self.assertFalse(tk.is_supported(task)) config_desc.min_price = 10.0 tk.change_config(config_desc) self.assertTrue(tk.is_supported(task)) task["min_version"] = "120" self.assertFalse(tk.is_supported(task)) task["min_version"] = tk.app_version self.assertTrue(tk.is_supported(task)) task["min_version"] = "abc" with self.assertLogs(logger=logger, level=1): self.assertFalse(tk.is_supported(task))
def test_init(self): tk = TaskHeaderKeeper(EnvironmentsManager(), 10.0) self.assertIsInstance(tk, TaskHeaderKeeper)
def test_task_limit(frozen_time, self): # pylint: disable=no-self-argument tk = TaskHeaderKeeper(environments_manager=EnvironmentsManager(), node=p2p.Node(), min_price=10) limit = tk.max_tasks_per_requestor thd = get_task_header("ta") thd.fixed_header.deadline = timeout_to_deadline(0.1) tk.add_task_header(thd) ids = [thd.task_id] for i in range(1, limit): thd = get_task_header("ta") ids.append(thd.task_id) tk.add_task_header(thd) last_add_time = time.time() for id_ in ids: self.assertIn(id_, tk.task_headers) thd = get_task_header("tb0") tb_id = thd.task_id tk.add_task_header(thd) for id_ in ids: self.assertIn(id_, tk.task_headers) self.assertIn(tb_id, tk.task_headers) while time.time() == last_add_time: frozen_time.tick( # pylint: disable=no-member delta=timedelta(milliseconds=100)) thd = get_task_header("ta") new_task_id = thd.task_id tk.add_task_header(thd) self.assertNotIn(new_task_id, tk.task_headers) for id_ in ids: self.assertIn(id_, tk.task_headers) self.assertIn(tb_id, tk.task_headers) frozen_time.tick( # pylint: disable=no-member delta=timedelta(milliseconds=100)) tk.remove_old_tasks() thd = get_task_header("ta") new_task_id = thd.task_id tk.add_task_header(thd) self.assertIn(new_task_id, tk.task_headers) self.assertNotIn(ids[0], tk.task_headers) for i in range(1, limit): self.assertIn(ids[i], tk.task_headers) self.assertIn(tb_id, tk.task_headers)
def test_check_max_tasks_per_owner(self): tk = TaskHeaderKeeper(environments_manager=EnvironmentsManager(), node=p2p.Node(), min_price=10, max_tasks_per_requestor=10) limit = tk.max_tasks_per_requestor new_limit = 3 ids = [] for i in range(new_limit): thd = get_task_header("ta") ids.append(thd.task_id) tk.add_task_header(thd) last_add_time = time.time() thd = get_task_header("tb0") tb0_id = thd.task_id tk.add_task_header(thd) for id_ in ids: self.assertIn(id_, tk.task_headers) self.assertIn(tb0_id, tk.task_headers) while time.time() == last_add_time: time.sleep(0.1) new_ids = [] for i in range(new_limit, limit): thd = get_task_header("ta") new_ids.append(thd.task_id) tk.add_task_header(thd) for id_ in ids + new_ids: self.assertIn(id_, tk.task_headers) self.assertIn(tb0_id, tk.task_headers) self.assertEqual(limit + 1, len(tk.task_headers)) # shouldn't remove any tasks tk.check_max_tasks_per_owner(thd.task_owner.key) for id_ in ids + new_ids: self.assertIn(id_, tk.task_headers) self.assertIn(tb0_id, tk.task_headers) self.assertEqual(limit + 1, len(tk.task_headers)) tk.max_tasks_per_requestor = new_limit # should remove ta{3..9} tk.check_max_tasks_per_owner(thd.task_owner.key) for id_ in ids: self.assertIn(id_, tk.task_headers) self.assertIn(tb0_id, tk.task_headers) self.assertEqual(new_limit + 1, len(tk.task_headers))
def test_is_supported(self): em = EnvironmentsManager() em.environments = {} em.support_statuses = {} tk = TaskHeaderKeeper(environments_manager=EnvironmentsManager(), node=p2p.Node(), min_price=10.0) header = get_task_header() header.fixed_header.environment = None header.fixed_header.max_price = None header.fixed_header.min_version = None self.assertFalse(tk.check_support(header)) header.fixed_header.environment = Environment.get_id() header.fixed_header.max_price = 0 supported = tk.check_support(header) self.assertFalse(supported) self.assertIn(UnsupportReason.ENVIRONMENT_MISSING, supported.desc) e = Environment() e.accept_tasks = True tk.environments_manager.add_environment(e) supported = tk.check_support(header) self.assertFalse(supported) self.assertIn(UnsupportReason.MAX_PRICE, supported.desc) header.fixed_header.max_price = 10.0 supported = tk.check_support(header) self.assertFalse(supported) self.assertIn(UnsupportReason.APP_VERSION, supported.desc) header.fixed_header.min_version = golem.__version__ self.assertTrue(tk.check_support(header)) header.fixed_header.max_price = 10.0 self.assertTrue(tk.check_support(header)) config_desc = mock.Mock() config_desc.min_price = 13.0 tk.change_config(config_desc) self.assertFalse(tk.check_support(header)) config_desc.min_price = 10.0 tk.change_config(config_desc) self.assertTrue(tk.check_support(header)) header.fixed_header.min_version = "120" self.assertFalse(tk.check_support(header)) header.fixed_header.min_version = tk.app_version self.assertTrue(tk.check_support(header)) header.fixed_header.min_version = "abc" with self.assertLogs(logger=logger, level='WARNING'): self.assertFalse(tk.check_support(header))
def test_change_config(self, tar): tk = TaskHeaderKeeper(environments_manager=EnvironmentsManager(), node=p2p.Node(), min_price=10.0, task_archiver=tar) e = Environment() e.accept_tasks = True tk.environments_manager.add_environment(e) task_header = get_task_header() task_id = task_header.task_id task_header.fixed_header.max_price = 9.0 tk.add_task_header(task_header) self.assertNotIn(task_id, tk.supported_tasks) self.assertIn(task_id, tk.task_headers) task_header = get_task_header("abc") task_id2 = task_header.task_id task_header.fixed_header.max_price = 10.0 tk.add_task_header(task_header) self.assertIn(task_id2, tk.supported_tasks) self.assertIn(task_id2, tk.task_headers) config_desc = mock.Mock() config_desc.min_price = 10.0 tk.change_config(config_desc) self.assertNotIn(task_id, tk.supported_tasks) self.assertIn(task_id2, tk.supported_tasks) config_desc.min_price = 8.0 tk.change_config(config_desc) self.assertIn(task_id, tk.supported_tasks) self.assertIn(task_id2, tk.supported_tasks) config_desc.min_price = 11.0 tk.change_config(config_desc) self.assertNotIn(task_id, tk.supported_tasks) self.assertNotIn(task_id2, tk.supported_tasks) # Make sure the tasks stats are properly archived tar.reset_mock() config_desc.min_price = 9.5 tk.change_config(config_desc) self.assertNotIn(task_id, tk.supported_tasks) self.assertIn(task_id2, tk.supported_tasks) tar.add_support_status.assert_any_call( task_id, SupportStatus(False, {UnsupportReason.MAX_PRICE: 9.0})) tar.add_support_status.assert_any_call(task_id2, SupportStatus(True, {}))
def test_init(self): tk = TaskHeaderKeeper(environments_manager=EnvironmentsManager(), node=p2p.Node(), min_price=10.0) self.assertIsInstance(tk, TaskHeaderKeeper)
def test_get_unsupport_reasons(self): tk = TaskHeaderKeeper(environments_manager=EnvironmentsManager(), node=p2p.Node(), min_price=10) e = Environment() e.accept_tasks = True tk.environments_manager.add_environment(e) # Supported task thd = get_task_header("good") tk.add_task_header(thd) # Wrong version thd = get_task_header("wrong version") thd.fixed_header.min_version = "42.0.17" tk.add_task_header(thd) # Wrong environment thd = get_task_header("wrong env") thd.fixed_header.environment = "UNKNOWN" tk.add_task_header(thd) # Wrong price thd = get_task_header("wrong price") thd.fixed_header.max_price = 1 tk.add_task_header(thd) # Wrong price and version thd = get_task_header("wrong price and version") thd.fixed_header.min_version = "42.0.17" thd.fixed_header.max_price = 1 tk.add_task_header(thd) # And one more with wrong version thd = get_task_header("wrong version 2") thd.fixed_header.min_version = "42.0.44" tk.add_task_header(thd) reasons = tk.get_unsupport_reasons() # 3 tasks with wrong version self.assertIn( { 'avg': golem.__version__, 'reason': 'app_version', 'ntasks': 3 }, reasons) # 2 tasks with wrong price self.assertIn({'avg': 7, 'reason': 'max_price', 'ntasks': 2}, reasons) # 1 task with wrong environment self.assertIn( { 'avg': None, 'reason': 'environment_missing', 'ntasks': 1 }, reasons) self.assertIn( { 'avg': None, 'reason': 'environment_not_accepting_tasks', 'ntasks': 1 }, reasons)