def test_when_server_returns_invalid_data(self): server = FakeJoule() server.response = "notjson" self.start_server(server) runner = CliRunner() result = runner.invoke(main, ['module', 'list']) self.assertTrue('Error' in result.output) self.assertEqual(result.exit_code, 1) self.stop_server()
def test_when_server_returns_error_code(self): server = FakeJoule() error_msg = "test error" error_code = 500 server.response = error_msg server.http_code = error_code self.start_server(server) runner = CliRunner() result = runner.invoke(main, ['module', 'list']) self.assertTrue('%d' % error_code in result.output) self.assertTrue(error_msg in result.output) self.assertEqual(result.exit_code, 1) self.stop_server()
def test_when_server_returns_error_code(self): server = FakeJoule() server.response = "test error" server.http_code = 500 server.stub_annotation = True self.start_server(server) runner = CliRunner() result = runner.invoke(main, ['stream', 'annotations', 'folder/stream']) self.assertIn('500', result.output) self.assertIn("test error", result.output) self.assertEqual(result.exit_code, 1) self.stop_server()
def test_lists_streams_with_options(self): server = FakeJoule() with open(FOLDER_LIST, 'r') as f: server.response = f.read() self.start_server(server) runner = CliRunner() result = runner.invoke(main, ['folder', 'list', '-s', '-l']) self.assertEqual(result.exit_code, 0) output = result.output # check for the augmented legend self.assertTrue("configured" in output) # check for layout strings self.assertTrue("float32_3" in output) self.stop_server()
def test_reteives_time_bounded_annotations(self): server = FakeJoule() with open(ANNOTATION_LIST, 'r') as f: server.response = f.read() self.start_server(server) runner = CliRunner() result = runner.invoke(main, [ 'stream', 'annotations', '/my/stream', '--start', '28 Jun 2019 16:00', '--end', '29 Jun 2019 16:00' ]) self.assertEqual(result.exit_code, 0) query_params = self.msgs.get() self.assertEqual(query_params["start"], "1561752000000000") self.assertEqual(query_params["end"], "1561838400000000") self.stop_server()
def test_lists_all_annotations_table(self): server = FakeJoule() with open(ANNOTATION_LIST, 'r') as f: server.response = f.read() self.start_server(server) runner = CliRunner() result = runner.invoke(main, ['stream', 'annotations', '/my/stream']) self.assertEqual(result.exit_code, 0) output = result.output # check for a few lines in the table self.assertIn("Instant", output) # timestamps should be displayed as dates self.assertNotIn("1561753681898272", output) self.assertIn("Fri, 28 Jun 2019 16:05:47", output) self.stop_server()
def test_creates_output_stream_if_necessary(self): server = FakeJoule() self.start_server(server) loop = asyncio.get_event_loop() my_node = api.get_node() self.assertEqual(len(server.streams), 0) async def runner(): # the destination does not exist with self.assertRaises(errors.ApiError): await my_node.data_stream_get("/test/dest") pipes_in, pipes_out = await build_network_pipes( {}, {'output': '/test/dest:uint8[e0,e1,e2]'}, {}, my_node, None, None) await pipes_out['output'].close() # make sure the stream exists dest_stream = await my_node.data_stream_get("/test/dest") self.assertIsNotNone(dest_stream) await my_node.close() with self.assertLogs(level='INFO') as log: loop.run_until_complete(runner()) log_dump = ' '.join(log.output) self.assertIn('creating', log_dump) self.stop_server() loop.close()
def test_output_errors(self): server = FakeJoule() create_destination(server) create_source_data(server, is_destination=True) self.start_server(server) loop = asyncio.get_event_loop() my_node = api.get_node() # errors on layout differences with self.assertRaises(ConfigurationError) as e: loop.run_until_complete( build_network_pipes({}, {'output': '/test/dest:float32[x,y,z]'}, {}, my_node, None, None)) self.assertIn('uint8_3', str(e.exception)) # errors if the stream is already being produced with self.assertRaises(ApiError) as e: loop.run_until_complete( build_network_pipes({}, {'output': '/test/source:uint8[e0,e1,e2]'}, {}, my_node, None, None)) loop.run_until_complete(my_node.close()) self.assertIn('already being produced', str(e.exception)) self.stop_server() loop.close()
def test_add_lumen(self): server = FakeJoule() self.start_server(server) runner = CliRunner() # The first node joining a lumen requires a user result = runner.invoke( main, "master add lumen node1".split(" "), input="John\nDoe\[email protected]\npassword\npassword") output = result.output # make sure the node name is printed self.assertIn("node1", output) # make sure the server got the right parameters params = self.msgs.get() self.assertEqual(params["first_name"], "John") self.assertEqual(params["last_name"], "Doe") self.assertEqual(params["email"], "*****@*****.**") self.assertEqual(params["password"], "password") loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) # Subsequent nodes need an auth key result = runner.invoke(main, "master add lumen node2".split(" "), input="AC3412\n") # make sure the server got the right parameters params = self.msgs.get() self.assertEqual(params["auth_key"], "AC3412") output = result.output self.assertIn("node2", output) # make sure everything stops cleanly self.assertEqual(result.exit_code, 0) self.stop_server()
def test_builds_live_input_pipes(self): server = FakeJoule() src_data = create_source_data(server, is_destination=True) self.start_server(server) loop = asyncio.get_event_loop() my_node = api.get_node() async def runner(): pipes_in, pipes_out = await build_network_pipes( {'input': '/test/source:uint8[x,y,z]'}, {}, {}, my_node, None, None, True) blk1 = await pipes_in['input'].read() self.assertTrue(pipes_in['input'].end_of_interval) pipes_in['input'].consume(len(blk1)) blk2 = await pipes_in['input'].read() pipes_in['input'].consume(len(blk2)) rx_data = np.hstack( (blk1, interval_token(pipes_in['input'].layout), blk2)) np.testing.assert_array_equal(rx_data, src_data) with self.assertRaises(EmptyPipe): await pipes_in['input'].read() await my_node.close() with self.assertLogs(level='INFO') as log: loop.run_until_complete(runner()) log_dump = ' '.join(log.output) self.stop_server() loop.close()
def test_input_errors(self): server = FakeJoule() create_source_data(server, is_destination=False) self.start_server(server) loop = asyncio.get_event_loop() my_node = api.get_node() # errors on layout differences with self.assertRaises(ConfigurationError) as e: with self.assertLogs(level='INFO'): loop.run_until_complete( build_network_pipes({'input': '/test/source:uint8[x,y]'}, {}, {}, my_node, 10, 20, force=True)) self.assertIn('uint8_3', str(e.exception)) # errors if live stream is requested but unavailable with self.assertRaises(ApiError) as e: loop.run_until_complete( build_network_pipes({'input': '/test/source:uint8[x,y,z]'}, {}, {}, my_node, None, None)) self.assertIn('not being produced', str(e.exception)) loop.run_until_complete(my_node.close()) self.stop_server() loop.close()
def test_delete_all_annotations(self): server = FakeJoule() self.start_server(server) runner = CliRunner() result = runner.invoke( main, ['stream', 'annotations', '/my/stream', '--delete']) self._assert_no_error(result) query_params = self.msgs.get() self.assertEqual(query_params["stream_path"], "/my/stream") self.stop_server()
def test_start_time_bound_errors(self): server = FakeJoule() self.start_server(server) runner = CliRunner() result = runner.invoke(main, [ 'stream', 'annotations', '/my/stream', '--start', 'baddate', '--end', '29 Jun 2019 16:00' ]) self.assertTrue('start time' in result.output) self.assertEqual(result.exit_code, 1) self.stop_server()
def test_lists_folders(self): server = FakeJoule() with open(FOLDER_LIST, 'r') as f: server.response = f.read() self.start_server(server) runner = CliRunner() result = runner.invoke(main, ['folder', 'list']) self.assertEqual(result.exit_code, 0) output = result.output # make sure the folders are listed for folder in ['basic', 'aux', 'event', 'sensors']: self.assertTrue(folder in output) # make sure the data streams are listed for stream in ['Accel', 'Encoder', 'Gyro']: self.assertTrue(stream in output) # make sure the event streams are listed for stream in ['events0', 'events1', 'events2']: self.assertTrue(stream in output) # should check for layout strings self.assertFalse("float32_3" in output) self.stop_server()
def test_delete_time_bounded_annotations(self): server = FakeJoule() self.start_server(server) runner = CliRunner() result = runner.invoke(main, [ 'stream', 'annotations', '/my/stream', '--delete', '--start', '28 Jun 2019 16:00 EDT', '--end', '29 Jun 2019 16:00 EDT' ]) self._assert_no_error(result) query_params = self.msgs.get() self.assertEqual(query_params["stream_path"], "/my/stream") self.assertEqual(query_params["start"], "1561752000000000") self.assertEqual(query_params["end"], "1561838400000000") self.stop_server()
def test_lists_annotations_csv(self): server = FakeJoule() with open(ANNOTATION_LIST, 'r') as f: server.response = f.read() self.start_server(server) runner = CliRunner() result = runner.invoke( main, ['stream', 'annotations', '/my/stream', '--csv']) self._assert_no_error(result) output = result.output lines = output.split("\n") reader = csv.reader(lines[1:]) annotations = [] for row in reader: annotations.append(row) # first annotation is an event self.assertEqual( ['Instant', 'instant temperature', '1561752347819968'], annotations[0]) # second annoation is a range with no comment self.assertEqual( ['hot!!!', '', '1561861116610000', '1561862838572000'], annotations[1]) self.stop_server()
def test_add_joule(self): server = FakeJoule() self.start_server(server) runner = CliRunner() result = runner.invoke(main, "master add joule node1".split(" ")) output = result.output # make sure the node name is printed self.assertIn("node1", output) # make sure the server got the right parameters params = self.msgs.get() self.assertEqual(params['identifier'], "node1") self.assertEqual(params['master_type'], "joule") # make sure everything stops cleanly self.assertEqual(result.exit_code, 0) self.stop_server()
def test_add_user(self): server = FakeJoule() self.start_server(server) runner = CliRunner() result = runner.invoke(main, "master add user johndoe".split(" ")) output = result.output # make sure the username and key are printed self.assertIn("fakekey", output) self.assertIn("johndoe", output) # make sure the server got the right parameters params = self.msgs.get() self.assertEqual(params['identifier'], "johndoe") self.assertEqual(params['master_type'], "user") # make sure everything stops cleanly self.assertEqual(result.exit_code, 0) self.stop_server()
def test_configuration_errors(self): server = FakeJoule() loop = asyncio.get_event_loop() self.start_server(server) my_node = api.get_node() # must specify an inline configuration with self.assertRaises(ConfigurationError): loop.run_until_complete( build_network_pipes({'input': '/test/source'}, {}, {}, my_node, 10, 20, force=True)) loop.run_until_complete(my_node.close()) self.stop_server() loop.close()
def test_builds_output_pipes(self): server = FakeJoule() blk1 = helpers.create_data("uint8_3", start=10, step=1, length=10) blk2 = helpers.create_data("uint8_3", start=200, step=1, length=10) create_destination(server) self.start_server(server) my_node = api.get_node() async def runner(): pipes_in, pipes_out = await build_network_pipes( {}, {'output': '/test/dest:uint8[e0,e1,e2]'}, {}, my_node, 10, 210, force=True) await pipes_out['output'].write(blk1) await pipes_out['output'].close_interval() await pipes_out['output'].write(blk2) await pipes_out['output'].close_interval() await pipes_out['output'].close() await my_node.close() asyncio.run(runner()) # first msg should be the data removal (stream_id, start, end) = self.msgs.get() self.assertEqual(int(stream_id), 8) self.assertEqual(int(start), 10) self.assertEqual(int(end), 210) # next message should be the output data mock_entry: MockDbEntry = self.msgs.get() np.testing.assert_array_equal(mock_entry.data[:len(blk1)], blk1) np.testing.assert_array_equal(mock_entry.data[len(blk1):], blk2) self.assertEqual(mock_entry.intervals, [[10, 19], [200, 209]]) self.stop_server()
def test_warns_before_data_removal(self): server = FakeJoule() create_destination(server) self.start_server(server) loop = asyncio.get_event_loop() my_node = api.get_node() async def runner(): with mock.patch('joule.client.helpers.pipes.click') as mock_click: mock_click.confirm = mock.Mock(return_value=False) with self.assertRaises(SystemExit): await build_network_pipes( {}, {'output': '/test/dest:uint8[e0,e1,e2]'}, {}, my_node, 1472500708000000, 1476475108000000, force=False) msg = mock_click.confirm.call_args[0][0] # check for start time self.assertIn("29 Aug", msg) # check for end time self.assertIn("14 Oct", msg) # if end_time not specified anything *after* start is removed mock_click.confirm = mock.Mock(return_value=False) with self.assertRaises(SystemExit): await build_network_pipes( {}, {'output': '/test/dest:uint8[e0,e1,e2]'}, {}, my_node, 1472500708000000, None, force=False) msg = mock_click.confirm.call_args[0][0] # check for start time self.assertIn("29 Aug", msg) # check for *after* self.assertIn("after", msg) # if start_time not specified anything *before* end is removed mock_click.confirm = mock.Mock(return_value=False) with self.assertRaises(SystemExit): await build_network_pipes( {}, {'output': '/test/dest:uint8[e0,e1,e2]'}, {}, my_node, None, 1476475108000000, force=False) msg = mock_click.confirm.call_args[0][0] # check for *before* self.assertIn("before", msg) # check for end time self.assertIn("14 Oct", msg) await my_node.close() # suppress "cancelled" notifications when program exits #with self.assertLogs(level='INFO'): loop.run_until_complete(runner()) self.stop_server() loop.close()