def test_exception_detail_codes(self): ''' Test that each exception code sets exception_details ''' blk = ModbusTCP() # Check that the message is different for each code signal = Signal() prev_details = '' for code in [1, 2, 3, 4, 5, 6, 7, 8, 10, 11]: signal.exception_code = code blk._check_exceptions(signal) self.assertNotEqual(signal.exception_details, prev_details) prev_details = signal.exception_details # Check unkown status code does not give details signal = Signal() signal.exception_code = 12 blk._check_exceptions(signal) self.assertFalse(hasattr(signal, 'exception_details'))
def test_process_signal(self, mock_socket): blk = TCPAsynchClient() self.configure_block(blk, { 'message': '{{ $hello }}\n', 'host': '1.2.3.4', 'port': '1234' }), blk.start() blk.process_signals([Signal({'hello': 'n.io'})]) mock_socket.return_value.connect.assert_called_with(('1.2.3.4', 1234)) mock_socket.return_value.send.assert_called_with('n.io\n') blk.stop()
def test_expression_props(self, mock_serial, mock_xbee): blk = XBeeTX() self.configure_block(blk, { "dest_addr": "00 42", "data": "{{ $iama }}", }) blk.start() blk.process_signals([Signal({'iama': 'signal'})]) blk._xbee.send.assert_called_once_with('tx', frame_id=b'\x01', dest_addr=b'\x00\x42', data=b'signal')
def test_xbee_long_defaults(self, mock_serial, mock_xbee): blk = XBeeTXLongFrame() self.configure_block(blk, {}) blk.start() blk.process_signals([Signal({'iama': 'signal'})]) blk._xbee._build_command.assert_called_once_with( 'tx_long_addr', frame_id=b'\x01', dest_addr=b'\x00\x00\x00\x00\x00\x00\xFF\xFF', data=b"{'iama': 'signal'}") self.assertTrue(len(self.last_notified[DEFAULT_TERMINAL])) blk.stop()
def process_signals(self, signals): for signal in signals: if self.AQ.pollProbe(0) == 0: #TODO: Add polling for temperature value = self.AQ.moistureData results = {self.signalName(): value} self.logger.debug("Got results: {}".format(results)) try: self.notify_signals([Signal(results)]) except: self.logger.exception("Signal is not valid:" " {}".format(results))
def test_video_convert(self): blk = VideoConvert() with patch(VideoConvert.__module__ + '.cv2.imencode') as \ mock_cv2_imencode,\ patch(VideoConvert.__module__ + '.io.BytesIO') as mock_bytesIO: mock_temp_image = MagicMock() mock_cv2_imencode.return_value = 'mockRet', mock_temp_image self.configure_block(blk, {'extension': '.jpg'}) blk.start() blk.process_signals([Signal({'frame': [[1], [2]]})]) mock_cv2_imencode.assert_called_with('.jpg', [[1], [2]]) mock_bytesIO.return_value.write.assert_called_once_with( mock_temp_image.tobytes()) self.assert_num_signals_notified(1) self.assert_last_signal_notified( Signal({ 'image': mock_bytesIO.return_value, 'extension': '.jpg' })) blk.stop()
def test_whitelist_attributes(self): """'hello' attribute passes through the block unmodified.""" blk = AttributeSelector() self.configure_block(blk, {'mode': 'WHITELIST', 'attributes': ['hello']}) blk.start() blk.process_signals([Signal({'hello': 'n.io', 'goodbye': 'n.io'})]) blk.stop() self.assert_num_signals_notified(1) self.assertDictEqual( self.last_notified[DEFAULT_TERMINAL][0].to_dict(), {'hello': 'n.io'})
def _handle_message(self, client, userdata, message): # client and userdata params are deprecated and passed None self.logger.debug("Received message on topic {}".format(message.topic)) try: payload = json.loads(message.payload.decode()) except json_decode_error: payload = message.payload.decode() self.notify_signals( [Signal({ "payload": payload, "topic": message.topic })])
def test_process_signals(self, mock_gpio): """Signals pass through block unmodified.""" blk = GPIORead() self.configure_block(blk, {}) blk._gpio.read.return_value = True blk.start() blk.process_signals([Signal()]) blk.stop() blk._gpio.read.assert_called_once_with(0, None) self.assert_num_signals_notified(1) self.assertDictEqual(self.last_notified[DEFAULT_TERMINAL][0].to_dict(), {"value": True})
def test_process_signal(self): blk = RethinkDBInsert() self.configure_block(blk, {'port': 8888, 'host': '127.0.0.1'}) blk.start() with patch(blk.__module__ + '.rdb') as mock_rdb: mock_rdb.db.return_value.table.return_value.insert.return_value.\ run.return_value = {"errors": 0} blk.process_signals([Signal({'id': 1, 'test': 1})]) blk.stop() self.assert_num_signals_notified(1) self.assertDictEqual(self.last_signal_notified().to_dict(), { "errors": 0})
def test_process_signals(self, mock_subprocess): """Signals are enriched with CPU temperature.""" mock_subprocess.check_output.return_value = b'temp=3.14\'C\n' blk = RasPiTemp() self.configure_block(blk, {'enrich': {'exclude_existing': False}}) blk.start() blk.process_signals([Signal({'foo': 'bar'})]) blk.stop() self.assert_num_signals_notified(1) self.assertDictEqual( self.last_notified[DEFAULT_TERMINAL][0].to_dict(), {'temp_C': 3.14, 'foo': 'bar'})
def test_preview(self): blk = Picamera() self.configure_block(blk, {'preview': True}) blk.start() blk.process_signals([Signal({"hi": "there"})]) blk.stop() self.assert_num_signals_notified(1) self.assertDictEqual(self.last_notified[DEFAULT_TERMINAL][0].to_dict(), {"hi": "there"}) blk.camera.capture.assert_called_with('image_0.jpeg', format='jpeg') blk.camera.start_preview.assert_called() blk.camera.stop_preview.assert_called()
def test_invalid_column(self, mock_odbc): mock_cnxn = mock_odbc.connect.return_value = MagicMock() mock_cursor = mock_cnxn.cursor.return_value = MagicMock() mock_cursor.columns.return_value = [MagicMock(column_name='foo')] blk = MSSQLQuery() self.configure_block(blk, self.config) blk.start() with self.assertRaises(ValueError): blk.process_signals([Signal({'testSignal': 'testSignalValue'})]) self.assertEqual(mock_cnxn.close.call_count, 0) self.assertEqual(mock_cursor.close.call_count, 1) blk.stop()
def test_defaults(self, mock_serial, mock_xbee): blk = XBeeATCommandFrame() self.configure_block(blk, {}) blk.start() blk.process_signals([Signal({'iama': 'signal'})]) blk._xbee._build_command.assert_called_once_with( 'at', frame_id=b'\x01', command=b'ID', parameter=b'') self.assertTrue(len(self.last_notified[DEFAULT_TERMINAL])) blk.stop()
def test_grouping(self): signals = [{ 'group': 'fruit', 'key': 'cherry', 'value': 'S' }, { 'group': 'fruit', 'key': 'cherry', 'value': 'M' }, { 'group': 'fruit', 'key': 'cherry', 'value': 'L' }, { 'group': 'pie', 'key': 'banana', 'value': 'S' }, { 'group': 'pie', 'key': 'cherry', 'value': 'M' }, { 'group': 'pie', 'key': 'cherry', 'value': 'L' }, { 'group': 'fruit', 'key': 'banana', 'value': 'S' }] blk = Join() config = { 'group_attr': 'my_group', 'group_by': '{{$group}}', 'log_level': 'DEBUG' } self.configure_block(blk, config) blk.process_signals([Signal(s) for s in signals]) self.assert_num_signals_notified(2, blk) # Assert that only one list of signals was notified by checking that # the last notified had ALL of the signals self.assertEqual(len(self.last_notified[DEFAULT_TERMINAL]), 2) for sig_out in self.last_notified[DEFAULT_TERMINAL]: # Make sure the group got assigned to the right attr self.assertIn(sig_out.my_group, ['fruit', 'pie']) # Assert the right values went to the right groups if sig_out.my_group == 'fruit': self.assertEqual(len(sig_out.cherry), 3) self.assertEqual(len(sig_out.banana), 1) elif sig_out.my_group == 'pie': self.assertEqual(len(sig_out.cherry), 2) self.assertEqual(len(sig_out.banana), 1)
def test_temp(self): with patch(TemperatureSensor.__module__ + '.rh.weather') as mock_weather: blk = TemperatureSensor() self.configure_block(blk, {}) blk.start() blk.process_signals([Signal({'incoming': 'pewpew'})]) blk.stop() mock_weather.pressure.assert_called() mock_weather.temperature.assert_called() self.assertDictEqual( {'temp_C': ANY, 'pressure_Pa': ANY}, self.last_notified[DEFAULT_TERMINAL][0].to_dict())
def test_process_signals(self): # Pass a list of three signals blk = TrendAnalysis() self.configure_block(blk, {"data": "{{ $data }}"}) blk.start() blk.process_signals([ Signal({"data": [5, 4, 3, 2, 1]}), Signal({"data": [3, 3, 4, 3, 5]}), Signal({ "data": [3, 3, 3, 3, 3], "group": "null" }) ]) blk.stop() self.assert_num_signals_notified(3) self.assertDictEqual( self.last_notified[DEFAULT_TERMINAL][0].to_dict(), { "trend": -1.0, "trend_start": 5.0, "trend_end": 1.0, "data": [5, 4, 3, 2, 1], "std_error": 0.0 }) self.assertDictEqual( self.last_notified[DEFAULT_TERMINAL][1].to_dict(), { "trend": 0.4, "trend_start": 2.8, "trend_end": 4.4, "data": [3, 3, 4, 3, 5], "std_error": 0.33466401061363016 }) self.assertDictEqual( self.last_notified[DEFAULT_TERMINAL][2].to_dict(), { "trend": 0.0, "trend_start": 3.0, "trend_end": 3.0, "data": [3, 3, 3, 3, 3], "std_error": 0.0, "group": "null" })
def test_request_exceptions(self, mock_get): from requests.exceptions import Timeout url = "http://httpbin.org/get" block = HTTPRequests() resp = MagicMock() resp.status_code = 200 resp.json = MagicMock(return_value={'url': url}) mock_get.side_effect = [ Timeout, Timeout, Timeout, resp, ] self.configure_block( block, { "http_method": "GET", "url": url, "timeout": 10, "log_level": "DEBUG", "enrich": { "exclude_existing": False, "enrich_field": "response" }, "retry_options": { "max_retry": 2, "multiplier": 0 } }) block.start() block.process_signals([ Signal({'input_attr': 'value1'}), Signal({'input_attr': 'value2'}) ]) block.stop() self.assertEqual(len(self.last_notified[DEFAULT_TERMINAL]), 1) self.assertEqual( self.last_notified[DEFAULT_TERMINAL][0].response['url'], url) self.assertEqual(self.last_notified[DEFAULT_TERMINAL][0].input_attr, 'value2')
def test_buffer_groups(self): event = Event() block = EventBuffer(event) block._backup = MagicMock() self.configure_block(block, { "interval": { "milliseconds": 200 }, "group_by": "{{ $group }}", }) block.start() block.process_signals([ Signal({ "iama": "signal", "group": "a" }), Signal({ "iama": "signal", "group": "b" }), Signal({ "iama": "signal", "group": "b" }), ]) event.wait(.3) self.assert_num_signals_notified(3, block) self.assertTrue({ "iama": "signal", "group": "a" } in [n.to_dict() for n in self.last_notified[DEFAULT_TERMINAL]]) self.assertEqual( len([ n.to_dict() for n in self.last_notified[DEFAULT_TERMINAL] if n.to_dict() == { "iama": "signal", "group": "b" } ]), 2) block.stop()
def test_invalid_command(self, mock_serial, mock_xbee): blk = XBeeRemoteAT() self.configure_block(blk, {"command": "{{ 1 }}"}) blk.logger = MagicMock() blk.start() blk.process_signals([Signal({'iama': 'signal'})]) # send is never called because of the command not being ascii encodable # It needs to be a two ascii characters self.assertFalse(blk._xbee.send.called) # expected behavior is to log error blk.logger.exception.assert_called_once_with( 'Failed to execute remote at command') blk.stop()
def _run(self): while self._is_broadcasting.is_set(): (grabbed, frame) = self.camera.read() if self.frame_rate(): sleep(1 / self.frame_rate()) if not grabbed: self._is_broadcasting.clear() self.logger.exception('Failed to grab frame') else: if self.grayscale(): frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) self.notify_signals([Signal({'frame': frame})])
def test_invalid_dest_addr(self, mock_serial, mock_xbee): blk = XBeeRemoteAT() self.configure_block(blk, {"dest_addr": "0"}) blk.logger = MagicMock() blk.start() blk.process_signals([Signal({'iama': 'signal'})]) # send is never called because of the odd length dest_addr # It needs to be a byte, represented as two ascii chars self.assertFalse(blk._xbee.send.called) # expected behavior is to log error blk.logger.exception.assert_called_once_with( 'Failed to execute remote at command') blk.stop()
def test_process_data(self): blk = BatchTweetClassifier() self.configure_block(blk, {}) blk.logger = MagicMock() blk.start() blk.process_signals([Signal({ "text": "this is sample text", "prof_img": "img.jpeg", "target": "sample_target"}), Signal({ "text": "this text is different from the previous text", "prof_img": "img2.jpeg", "target": "different_target"})], input_id='training') blk.process_signals([Signal({ "text": "this is sample text", "prof_img": "img.jpeg"})], input_id='classify') blk.stop() self.assert_num_signals_notified(1) self.assertTrue( 'sample_target' == self.last_notified[DEFAULT_TERMINAL][0].to_dict()['target'])
def test_execute_retry_fails(self, mock_client): ''' Test behavior when execute retry fails and runs out of retries ''' blk = ModbusTCP() self.configure_block(blk, { "enrich": {"exclude_existing": False}, "retry_options": {"multiplier": 0}}) blk._client(blk.host(),blk.port()).read_coils.side_effect = Exception blk.start() blk.process_signals([Signal({'input': 'signal'})]) self.assertDictEqual( self.last_notified[DEFAULT_TERMINAL][0].to_dict(), { 'input': 'signal'}) blk.stop()
def test_get_with_response_body(self, mock_get): url = "http://httpbin.org/get" resp = MagicMock() resp.status_code = 200 resp.json = MagicMock(return_value={'url': url}) mock_get.return_value = resp block = HTTPRequestsPostSignal() self.configure_block(block, {"http_method": "GET", "url": url}) block.start() block.process_signals([Signal()]) self.assertTrue(mock_get.called) self.assertEqual(self.last_notified[DEFAULT_TERMINAL][0].url, url) block.stop()
def test_optional_milliseconds(self, Signal): """ Milliseconds in incoming timestamps can optionally be truncated.""" blk = ElapsedTime() config = { 'milliseconds': '{{ $ms }}', 'units': { 'days': True, 'hours': True, 'minutes': True, 'seconds': True, }, 'timestamp_a': '1984-05-03T00:00:00.999Z', 'timestamp_b': '1984-05-03T00:00:01.001Z', } self.configure_block(blk, config) # process a list of signals blk.start() blk.process_signals([ Signal({ 'ms': False, }), ]) blk.stop() # check output # milliseconds are truncated BEFORE comparing timestamps self.assert_last_signal_list_notified([ Signal({ 'ms': False, 'days': 0, 'hours': 0, 'minutes': 0, 'seconds': 1, }), ]) # check that seconds was cast to int seconds = self.last_notified[DEFAULT_TERMINAL][0].seconds self.assertTrue(isinstance(seconds, int))
def test_multiple_values(self): """Pack two values from one signal""" blk = PackBytes() self.configure_block( blk, { 'new_attributes': [{ 'key': 'one', 'value': '{{ $value_1 }}' }, { 'key': 'two', 'value': '{{ $value_2 }}' }] }) blk.start() blk.process_signals([Signal({'value_1': 42, 'value_2': -42})]) blk.stop() self.assert_num_signals_notified(1) self.assert_last_signal_notified( Signal({ 'one': b'\x00\x00\x00*', 'two': b'\xff\xff\xff\xd6' }))
def test_blacklist_attributes(self): """The 'hello' signal attribute will get blacklisted""" blk = AttributeSelector() self.configure_block(blk, {'mode': 'BLACKLIST', 'attributes': ['hello']}) blk.start() blk.process_signals([Signal({'hello': 'n.io', 'goodbye': 'n.io'})]) blk.stop() self.assert_num_signals_notified(1) # should have blacklisted just hello self.assertDictEqual( self.last_notified[DEFAULT_TERMINAL][0].to_dict(), {'goodbye': 'n.io'})
def test_exception(self, put_func, count_func, create_func, connect_func): """ Make sure exceptions are handled for blocks that raise them """ blk = ExceptionDynamoDB() self.configure_block(blk, { 'log_level': 'DEBUG' }) blk.start() blk.process_signals([Signal({'_id': ''}) for i in range(5)]) self.assert_num_signals_notified(0) blk.stop()
def test_invalid_command(self, mock_serial, mock_xbee): blk = XBeeQueuedATFrame() self.configure_block(blk, {"command": "{{ 1 }}"}) blk.logger = MagicMock() blk.start() blk.process_signals([Signal({'iama': 'signal'})]) # Because of the command not being ascii encodable # It needs to be a two ascii characters self.assertFalse(len(self.last_notified[DEFAULT_TERMINAL])) # expected behavior is to log error blk.logger.exception.assert_called_once_with( 'Failed to execute queued at command') blk.stop()
def test_tx_long_hidden_expression_props(self, mock_serial, mock_xbee): blk = XBeeTXLongFrame() self.configure_block(blk, { "dest_addr": "AB Cd ef 12 99 35 00 42", "data": "{{ $iama }}", }) blk.start() blk.process_signals([Signal({'iama': 'signal', 'frame_id': '00'})]) blk._xbee._build_command.assert_called_once_with( 'tx_long_addr', frame_id=b'\x00', dest_addr=b'\xAB\xCD\xEF\x12\x99\x35\x00\x42', data=b'signal')