def test_receive_filesystem_moved_success(self): filesystem = FileFactory() moved = MovedFileFactory.build() error_status = Status.ok({ 'method': 'filesystem_move', 'result': moved.hash_value, }) error_status.uuid = filesystem.command_uuid # connect webinterface webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_status.to_json()}, ) query = FilesystemModel.objects.get(id=filesystem.id) self.assertEqual(query.hash_value, moved.hash_value) self.assertEqual(query.error_code, "") self.assertEqual( Status.ok({ 'filesystem_status': 'moved', 'fid': str(filesystem.id), }), Status.from_json(json.dumps(webinterface.receive())), )
def test_trigger_outbound_create_non_auto_pk(self): class TestBinding(WebsocketBinding): model = models.TestUUIDModel stream = 'test' fields = ['name'] @classmethod def group_names(cls, instance): return ["testuuidmodels"] def has_permission(self, user, action, pk): return True client = WSClient() client.join_group('testuuidmodels') instance = models.TestUUIDModel.objects.create(name='testname') received = client.receive() self.assertTrue('payload' in received) self.assertTrue('action' in received['payload']) self.assertTrue('data' in received['payload']) self.assertTrue('name' in received['payload']['data']) self.assertTrue('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertEqual(received['payload']['action'], 'create') self.assertEqual(received['payload']['model'], 'tests.testuuidmodel') self.assertEqual(received['payload']['pk'], str(instance.pk)) self.assertEqual(received['payload']['data']['name'], 'testname') received = client.receive() self.assertIsNone(received)
def test_join_subscription(self): game = Game.objects.first() client = WSClient() client.join_group(GameBinding.group_name(GameBinding.JOIN_SUB, game.pk)) user = User.objects.get(username='******') game.join(user) received = client.receive() self.assertIsNotNone(received) self.assertEqual(received['stream'], GameBinding.stream) self.assertEqual(received['payload']['action'], GameBinding.JOIN_SUB) self.assertEqual(received['payload']['pk'], game.pk) self.assertEqual(received['payload']['data']['user']['username'], user.username) user2 = User.objects.get(username='******') game.join(user2) received = client.receive() self.assertIsNotNone(received) self.assertEqual(received['stream'], GameBinding.stream) self.assertEqual(received['payload']['action'], GameBinding.JOIN_SUB) self.assertEqual(received['payload']['pk'], game.pk) self.assertEqual(received['payload']['data']['user']['username'], user2.username)
def test_timer_slave_timeout(self): from threading import Timer webinterface = WSClient() webinterface.join_group('notifications') self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__script = self.script.id self.sched._Scheduler__state = SchedulerStatus.WAITING_FOR_SLAVES timer = Timer( 1, self.sched.slave_timeout_callback, ) timer.start() timer.join() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.ERROR, ) self.assertEqual( self.sched._Scheduler__error_code, "Not all slaves connected within 5 minutes.", )
def test_next_question_subscription(self): game = Game.objects.first() client = WSClient() client.join_group( GameBinding.group_name(GameBinding.NEXT_QUESTION_SUB, game.pk)) # Start game game.next_question() received = client.receive() self.assertIsNotNone(received) self.assertEqual(received['stream'], GameBinding.stream) self.assertEqual(received['payload']['action'], GameBinding.NEXT_QUESTION_SUB) self.assertEqual(received['payload']['pk'], game.pk) self.assertEqual(received['payload']['data']['id'], game.pk) self.assertIsNotNone(received['payload']['data']['current_question']) # Next question game.next_question() received = client.receive() self.assertIsNotNone(received) self.assertEqual(received['stream'], GameBinding.stream) self.assertEqual(received['payload']['action'], GameBinding.NEXT_QUESTION_SUB) self.assertEqual(received['payload']['pk'], game.pk) self.assertEqual(received['payload']['data']['id'], game.pk) self.assertIsNotNone(received['payload']['data']['current_question'])
def test_receive_online_with_error_status(self): slave = SlaveOnlineFactory(online=False) error_status = Status.err({ 'method': 'online', 'result': str(Exception('foobar')) }) error_status.uuid = slave.command_uuid # connect webinterface on /notifications webinterface = WSClient() webinterface.join_group('notifications') # send online answer ws_client = WSClient() ws_client.send_and_consume('websocket.receive', path='/commands', content={'text': error_status.to_json()}) self.assertFalse(SlaveModel.objects.get(id=slave.id).is_online) # test if a connected message was send on /notifications self.assertEqual( Status.err( 'An error occurred while connecting to client {}!'.format( slave.name)), Status.from_json(json.dumps(webinterface.receive())), )
def test_receive_online_success(self): slave = SlaveOnlineFactory(online=False) expected_status = Status.ok({'method': 'online'}) expected_status.uuid = slave.command_uuid # connect webinterface on /notifications webinterface = WSClient() webinterface.join_group('notifications') # send online answer ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': expected_status.to_json()}, ) self.assertTrue(SlaveModel.objects.get(id=slave.id).is_online) # test if a connected message was send on /notifications self.assertEqual( Status.ok({ 'slave_status': 'connected', 'sid': str(slave.id), }), Status.from_json(json.dumps(webinterface.receive())), )
def test_receive_get_log_success(self): program_status = ProgramStatusFactory(running=True) program = program_status.program error_status = Status.ok({ 'method': 'get_log', 'result': { 'log': 'this is the content of a logfile', 'uuid': program_status.command_uuid, }, }) # connect webinterface webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_status.to_json()}, ) # test if the webinterface gets the error message self.assertEqual( Status.ok({ 'log': 'this is the content of a logfile', 'pid': str(program.id), }), Status.from_json(json.dumps(webinterface.receive())), )
def test_receive_execute_with_error_status(self): program_status = ProgramStatusFactory(running=True) program = program_status.program error_status = Status.err({ 'method': 'execute', 'result': str(Exception('foobar')), }) error_status.uuid = program_status.command_uuid # connect webinterface webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_status.to_json()}, ) query = ProgramStatusModel.objects.get(program=program) self.assertFalse(query.running) self.assertEqual(query.code, 'foobar') # test if the webinterface gets the error message self.assertEqual( Status.ok({ 'program_status': 'finished', 'pid': str(program.id), 'code': 'foobar', }), Status.from_json(json.dumps(webinterface.receive())), )
def test_websocket_custom_json_serialization(self): class WebsocketConsumer(websockets.JsonWebsocketConsumer): @classmethod def decode_json(cls, text): obj = json.loads(text) return dict((key.upper(), obj[key]) for key in obj) @classmethod def encode_json(cls, content): lowered = dict((key.lower(), content[key]) for key in content) return json.dumps(lowered) def receive(self, content, multiplexer=None, **kwargs): self.content_received = content self.send({"RESPONSE": "HI"}) class MyMultiplexer(websockets.WebsocketMultiplexer): @classmethod def encode_json(cls, content): lowered = dict((key.lower(), content[key]) for key in content) return json.dumps(lowered) with apply_routes([route_class(WebsocketConsumer, path='/path')]): client = WSClient() consumer = client.send_and_consume('websocket.receive', path='/path', text={"key": "value"}) self.assertEqual(consumer.content_received, {"KEY": "value"}) self.assertEqual(client.receive(), {"response": "HI"}) client.join_group('test_group') WebsocketConsumer.group_send('test_group', {"KEY": "VALUE"}) self.assertEqual(client.receive(), {"key": "VALUE"})
def test_receive_get_log_program_not_exists(self): error_status = Status.ok({ 'method': 'get_log', 'result': { 'log': '', 'uuid': '0' }, }) # connect webinterface webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_status.to_json()}, ) # test if the webinterface gets the error message self.assertEqual( Status.err('Received log from unknown program!'), Status.from_json(json.dumps(webinterface.receive())), )
def test_receive_filesystem_restore_with_error_code(self): filesystem = MovedFileFactory() error_code = 'any kind of string' error_status = Status.err({ 'method': 'filesystem_restore', 'result': error_code, }) error_status.uuid = filesystem.command_uuid # connect webinterface webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_status.to_json()}, ) query = FilesystemModel.objects.get(id=filesystem.id) self.assertEqual(query.error_code, error_code) self.assertEqual( Status.ok({ 'filesystem_status': 'error', 'fid': str(filesystem.id), 'error_code': error_code, }), Status.from_json(json.dumps(webinterface.receive())), )
def test_finish_subscription(self): game = Game.objects.get(label='Last question') client = WSClient() client.join_group( GameBinding.group_name(GameBinding.FINISH_SUB, game.pk)) # Finish game game.next_question() received = client.receive() self.assertIsNotNone(received) self.assertEqual(received['stream'], GameBinding.stream) self.assertEqual(received['payload']['action'], GameBinding.FINISH_SUB) self.assertEqual(received['payload']['pk'], game.pk) self.assertEqual(received['payload']['data']['id'], game.pk)
def test_receive_filesystem_restore_filesystem_not_exists(self): webinterface = WSClient() webinterface.join_group('notifications') error_status = Status.ok({ 'method': 'filesystem_restore', 'result': None, }) ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_status.to_json()}, ) self.assertIsNone(webinterface.receive())
def test_receive_chain_commands_with_error_status(self): error_chain = Status.err({ 'method': 'chain_execution', 'result': None, }) # connect webinterface webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_chain.to_json()}, ) self.assertIsNone(webinterface.receive())
def test_answer_subscription(self): game = Game.objects.get(label='Last question') player = game.players.first() answer = game.current_question.answer client = WSClient() client.join_group( GameBinding.group_name(GameBinding.ANSWER_SUB, game.pk)) game.answer(player, answer) received = client.receive() self.assertIsNotNone(received) self.assertEqual(received['stream'], GameBinding.stream) self.assertEqual(received['payload']['action'], GameBinding.ANSWER_SUB) self.assertEqual(received['payload']['pk'], game.pk) self.assertEqual(received['payload']['data']['answer'][0]['id'], answer[0])
def test_trigger_outbound_update(self): class TestBinding(WebsocketBinding): model = User stream = 'test' fields = ['__all__'] @classmethod def group_names(cls, instance): return ["users2"] def has_permission(self, user, action, pk): return True # Make model and clear out pending sends user = User.objects.create(username='******', email='*****@*****.**') client = WSClient() client.join_group('users2') user.username = '******' user.save() received = client.receive() self.assertTrue('payload' in received) self.assertTrue('action' in received['payload']) self.assertTrue('data' in received['payload']) self.assertTrue('username' in received['payload']['data']) self.assertTrue('email' in received['payload']['data']) self.assertTrue('password' in received['payload']['data']) self.assertTrue('last_name' in received['payload']['data']) self.assertTrue('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertEqual(received['payload']['action'], 'update') self.assertEqual(received['payload']['model'], 'auth.user') self.assertEqual(received['payload']['pk'], user.pk) self.assertEqual(received['payload']['data']['email'], '*****@*****.**') self.assertEqual(received['payload']['data']['username'], 'test_new') self.assertEqual(received['payload']['data']['password'], '') self.assertEqual(received['payload']['data']['last_name'], '') received = client.receive() self.assertIsNone(received)
def test_state_init(self): webinterface = WSClient() webinterface.join_group('notifications') ScriptModel.objects.filter(id=self.script.id).update( is_running=True, is_initialized=True, current_index=-1, ) self.sched._Scheduler__index = -1 self.sched._Scheduler__script = self.script.id self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__state = SchedulerStatus.INIT self.sched._Scheduler__state_init() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_SLAVES, ) msg1 = Status.from_json(json.dumps(webinterface.receive())) msg2 = Status.from_json(json.dumps(webinterface.receive())) msg3 = Status.from_json(json.dumps(webinterface.receive())) expct1 = Status.ok({ 'script_status': 'waiting_for_slaves', 'script_id': self.script.id, }) expct2 = Status.ok({ 'message': "Send start command to client `{}`".format(self.prog1.slave.name), }) expct3 = Status.ok({ 'message': "Send start command to client `{}`".format(self.prog2.slave.name), }) self.assertStatusSet( [msg1, msg2, msg3], [expct1, expct2, expct3], )
def test_state_waiting_slaves(self): webinterface = WSClient() webinterface.join_group('notifications') ScriptModel.objects.filter(id=self.script.id).update( is_running=True, is_initialized=True, current_index=-1, ) self.sched._Scheduler__index = -1 self.sched._Scheduler__script = self.script.id self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__state = SchedulerStatus.WAITING_FOR_SLAVES self.sched._Scheduler__state_wait_slaves() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_SLAVES, ) self.slave1.online = True self.slave1.save() self.sched._Scheduler__state_wait_slaves() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_SLAVES, ) self.slave2.online = True self.slave2.save() self.sched._Scheduler__state_wait_slaves() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.NEXT_STEP, ) self.assertIsNone(webinterface.receive())
def test_trigger_outbound_create_exclude(self): class TestBinding(WebsocketBinding): model = User stream = 'test' exclude = ['first_name', 'last_name'] @classmethod def group_names(cls, instance): return ["users_exclude"] def has_permission(self, user, action, pk): return True with apply_routes([route('test', TestBinding.consumer)]): client = WSClient() client.join_group('users_exclude') user = User.objects.create(username='******', email='*****@*****.**') received = client.receive() self.assertTrue('payload' in received) self.assertTrue('action' in received['payload']) self.assertTrue('data' in received['payload']) self.assertTrue('username' in received['payload']['data']) self.assertTrue('email' in received['payload']['data']) self.assertTrue('password' in received['payload']['data']) self.assertTrue('model' in received['payload']) self.assertTrue('pk' in received['payload']) self.assertFalse('last_name' in received['payload']['data']) self.assertFalse('first_name' in received['payload']['data']) self.assertEqual(received['payload']['action'], 'create') self.assertEqual(received['payload']['model'], 'auth.user') self.assertEqual(received['payload']['pk'], user.pk) self.assertEqual(received['payload']['data']['email'], '*****@*****.**') self.assertEqual(received['payload']['data']['username'], 'test') self.assertEqual(received['payload']['data']['password'], '') received = client.receive() self.assertIsNone(received)
def test_state_next_offline_filesystem(self): webinterface = WSClient() webinterface.join_group('notifications') self.prog1.delete() self.sched._Scheduler__index = -1 self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__script = self.script.id self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.ERROR, ) self.assertStatusRegex( Status.err(SlaveOfflineError), Status.err(self.sched._Scheduler__error_code), )
def test_state_success(self): webinterface = WSClient() webinterface.join_group('notifications') self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__script = self.script.id self.sched._Scheduler__state = SchedulerStatus.SUCCESS self.sched._Scheduler__state_success() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.SUCCESS, ) self.assertEqual( Status.ok({ 'script_status': 'success', 'script_id': self.script.id, }), Status.from_json(json.dumps(webinterface.receive())), )
def test_receive_get_log_with_error_status(self): error_status = Status.err({ 'method': 'get_log', 'result': str(Exception('foobar')), }) # connect webinterface webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_status.to_json()}, ) # test if the webinterface gets the error message self.assertEqual( Status.err('An error occured while reading a log file!'), Status.from_json(json.dumps(webinterface.receive())), )
def test_state_next_offline_program(self): webinterface = WSClient() webinterface.join_group('notifications') self.slave1.online = True self.slave1.save() self.sched._Scheduler__index = -1 self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__script = self.script.id self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( Status.ok({ 'program_status': 'started', 'pid': self.prog1.id, }), Status.from_json(json.dumps(webinterface.receive())), ) self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_PROGRAMS_FILESYSTEMS, ) self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.ERROR, ) self.assertStatusRegex( Status.err(SlaveOfflineError), Status.err(self.sched._Scheduler__error_code), )
def test_connect_and_disconnect_success(self): webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume('websocket.connect', path='/logs') self.assertIsNone(ws_client.receive()) msg = Status.ok({ 'log': ''.join([ choice(string.ascii_letters + string.digits) for _ in range(500) ]), 'pid': choice(string.digits) }) ws_client.send_and_consume('websocket.receive', path='/logs', content={'text': msg.to_json()}) self.assertEqual(msg, Status.from_json(json.dumps(webinterface.receive())))
def test_state_error(self): webinterface = WSClient() webinterface.join_group('notifications') self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__script = self.script.id self.sched._Scheduler__error_code = "Wow an error occurred." self.sched._Scheduler__state = SchedulerStatus.ERROR self.sched._Scheduler__state_error() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.ERROR, ) self.assertEqual( Status.ok({ 'script_status': 'error', 'error_code': 'Wow an error occurred.', 'script_id': self.script.id, }), Status.from_json(json.dumps(webinterface.receive())), )
def test_receive_online_slave_not_exists(self): slave = SlaveOnlineFactory(online=False) expected_status = Status.ok({'method': 'online'}) expected_status.uuid = slave.command_uuid # connect webinterface on /notifications webinterface = WSClient() webinterface.join_group('notifications') slave.delete() # send online answer ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': expected_status.to_json()}, ) self.assertFalse(SlaveModel.objects.filter(id=slave.id).exists()) # test if a connected message was send on /notifications self.assertIsNone(webinterface.receive())
def test_state_next_finished(self): webinterface = WSClient() webinterface.join_group('notifications') self.slave1.online = True self.slave1.save() self.slave2.online = True self.slave2.save() ProgramStatusModel.objects.create(program=self.prog1, code='0', command_uuid='0', start_time=now()) self.sched._Scheduler__index = -1 self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__script = self.script.id self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_PROGRAMS_FILESYSTEMS, ) if self.prog1.start_time > 0: start_time = self.prog1.start_time else: start_time = 0 msg1 = Status.from_json(json.dumps(webinterface.receive())) expct1 = Status.ok({ 'script_status': 'next_step', 'index': 0, 'last_index': -1, 'start_time': start_time, 'script_id': self.script.id, }) self.assertStatusSet([msg1], [expct1]) ProgramStatusModel.objects.create(program=self.prog2, code='0', command_uuid='1', start_time=now()) self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_PROGRAMS_FILESYSTEMS, ) if self.prog2.start_time > 0: start_time = self.prog2.start_time else: start_time = 0 msg1 = Status.from_json(json.dumps(webinterface.receive())) expct1 = Status.ok({ 'script_status': 'next_step', 'index': 2, 'last_index': 0, 'start_time': start_time, 'script_id': self.script.id, }) self.assertStatusSet([msg1], [expct1]) self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.SUCCESS, ) self.assertEqual( Status.ok({ 'script_status': 'next_step', 'index': -1, 'last_index': 2, 'start_time': 0, 'script_id': self.script.id, }), Status.from_json(json.dumps(webinterface.receive())), )
def test_state_next(self): webinterface = WSClient() webinterface.join_group('notifications') self.slave1.online = True self.slave1.save() self.slave2.online = True self.slave2.save() self.sched._Scheduler__index = -1 self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__script = self.script.id self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_PROGRAMS_FILESYSTEMS, ) if self.prog1.start_time > 0: start_time = self.prog1.start_time else: start_time = 0 msg1 = Status.from_json(json.dumps(webinterface.receive())) msg2 = Status.from_json(json.dumps(webinterface.receive())) expct1 = Status.ok({ 'script_status': 'next_step', 'index': 0, 'last_index': -1, 'start_time': start_time, 'script_id': self.script.id, }) expct2 = Status.ok({ 'program_status': 'started', 'pid': self.prog1.id, }) self.assertStatusSet([msg1, msg2], [expct1, expct2]) self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_PROGRAMS_FILESYSTEMS, ) if self.prog2.start_time > 0: start_time = self.prog2.start_time else: start_time = 0 msg1 = Status.from_json(json.dumps(webinterface.receive())) msg2 = Status.from_json(json.dumps(webinterface.receive())) expct1 = Status.ok({ 'script_status': 'next_step', 'index': 2, 'last_index': 0, 'start_time': start_time, 'script_id': self.script.id, }) expct2 = Status.ok({ 'program_status': 'started', 'pid': self.prog2.id, }) self.assertStatusSet([msg1, msg2], [expct1, expct2]) self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.SUCCESS, ) self.assertEqual( Status.ok({ 'script_status': 'next_step', 'index': -1, 'last_index': 2, 'start_time': 0, 'script_id': self.script.id, }), Status.from_json(json.dumps(webinterface.receive())), )