class ForwardProviderTest(unittest.TestCase): """ Test ForwardClientProvider and ForwardServerProvider """ def _runFlask(self, gw, port): """ :param gw: Gateway :type gw: smsframework.Gateway.Gateway :return: :rtype: """ # Init flask app = Flask(__name__) app.debug = True app.testing = True # Register gateway receivers gw.receiver_blueprints_register(app, prefix='/sms') # Stop manually @app.route('/kill', methods=['GET', 'POST']) def kill(): func = request.environ.get('werkzeug.server.shutdown') if func is None: raise RuntimeError('Not running with the Werkzeug Server') func() return '' # Run app.run('0.0.0.0', port, threaded=False, use_reloader=False, passthrough_errors=True) def setUp(self): # Init: client gateway # This "client" sends messages through a remote server self.gw_client = Gateway() self.gw_client.add_provider( 'fwd', ForwardClientProvider, server_url='http://*****:*****@localhost:5001/sms/fwd') # Init: server gateway # This "server" receives messages from an external SMS server and forwards them to the client self.gw_server = Gateway() self.gw_server.add_provider('lo', LoopbackProvider) self.gw_server.add_provider( 'fwd', ForwardServerProvider, clients=['http://*****:*****@localhost:5000/sms/fwd']) self.lo = self.gw_server.get_provider( 'lo' ) # This is run in another thread, but we should have access to it ' :type: LoopbackProvider ' # Run client in a thread self.t_client = threading.Thread(target=self._runFlask, args=(self.gw_client, 5000)) self.t_client.start() # Run server in a thread self.t_server = threading.Thread(target=self._runFlask, args=(self.gw_server, 5001)) self.t_server.start() # Give Flask some time to initialize time.sleep(0.5) def tearDown(self): # Kill threads for port, thread in ((5000, self.t_client), (5001, self.t_server)): #try: response = urlopen(Request( 'http://localhost:{}/kill'.format(port))) #except RemoteDisconnected: pass thread.join() def test_jsonex(self): """ Test de/coding messages """ ### OutgoingMessage om_in = OutgoingMessage('+123', 'Test', '+987', 'fwd') om_in.options(allow_reply=True) # Encode, Decode j = jsonex_dumps(om_in) om_out = jsonex_loads(j) """ :type om_out: OutgoingMessage """ # Check self.assertEqual(om_out.dst, '123') self.assertEqual(om_out.src, om_in.src) self.assertEqual(om_out.body, om_in.body) self.assertEqual(om_out.provider, om_in.provider) self.assertEqual(om_out.meta, None) self.assertEqual(om_out.provider_options.allow_reply, om_in.provider_options.allow_reply) self.assertEqual(om_out.provider_params, {}) ### IncomingMessage im_in = IncomingMessage('+123', 'Test', 'abc123def', '+987', datetime(2019, 1, 1, 15, 0, 0, 875), {'a': 1}) # Encode, Decode j = jsonex_dumps(im_in) im_out = jsonex_loads(j) """ :type im_out: IncomingMessage """ # Check self.assertEqual(im_out.src, im_in.src) self.assertEqual(im_out.body, im_in.body) self.assertEqual(im_out.msgid, im_in.msgid) self.assertEqual(im_out.dst, im_in.dst) self.assertEqual(im_out.rtime, im_in.rtime) self.assertEqual(im_out.meta, im_in.meta) def testSend(self): """ Send messages """ # Send a message om = OutgoingMessage( '+1234', 'Hi man!').options(senderId='me').params(a=1).route(1, 2, 3) rom = self.gw_client.send(om) # Check traffic traffic = self.lo.get_traffic() self.assertEqual(len(traffic), 1) tom = traffic.pop() for m in (om, rom, tom): self.assertEqual(m.src, None) self.assertEqual(m.dst, '1234') self.assertEqual(m.body, 'Hi man!') self.assertEqual(m.provider, 'lo') # Remote provider should be exposed self.assertEqual(m.provider_options.senderId, 'me') self.assertEqual(m.provider_params, {'a': 1}) self.assertEqual(m.routing_values, [1, 2, 3]) self.assertEqual(m.msgid, '1') self.assertEqual(m.meta, None) def testReceive(self): """ Receive messages """ # Message receiver received = [] def onReceive(message): received.append(message) self.gw_client.onReceive += onReceive # Receive a message self.lo.received('1111', 'Yo') # Check self.assertEqual(len(received), 1) msg = received.pop() ':type: IncomingMessage' self.assertEqual(msg.msgid, 1) self.assertEqual(msg.src, '1111') self.assertEqual(msg.body, 'Yo') self.assertEqual(msg.dst, None) self.assertIsInstance(msg.rtime, datetime) self.assertEqual(msg.meta, {}) self.assertEqual(msg.provider, 'lo') # Remote provider should be exposed def testStatus(self): """ Receive statuses """ # Status receiver statuses = [] def onStatus(status): statuses.append(status) self.gw_client.onStatus += onStatus # Subscriber incoming = [] def subscriber(message): incoming.append(message) self.lo.subscribe('1234', subscriber) # Send a message, request status report om = OutgoingMessage('+1234', 'Hi man!').options(status_report=True) rom = self.gw_client.send(om) # Check self.assertEqual(len(statuses), 1) status = statuses.pop() ':type: MessageStatus' self.assertEqual(status.msgid, '1') self.assertIsInstance(status.rtime, datetime) self.assertEqual(status.provider, 'lo') self.assertEqual(status.accepted, True) self.assertEqual(status.delivered, True) self.assertEqual(status.expired, False) self.assertEqual(status.error, False) self.assertEqual(status.status_code, None) self.assertEqual(status.status, 'OK') self.assertEqual(status.meta, {}) def testServerError(self): """ Test how errors are transferred from the server """ # Erroneous subscribers def tired_subscriber(message): raise OverflowError('Tired') self.lo.subscribe('1234', tired_subscriber) def offline_subscriber(message): raise exc.ServerError('Offline') self.lo.subscribe('5678', offline_subscriber) # Send: 1 om = OutgoingMessage('+1234', 'Hi man!') self.assertRaises( RuntimeError, self.gw_client.send, om) # Unknown error classes are converted to RuntimeError # Send: 2 om = OutgoingMessage('+5678', 'Hi man!') self.assertRaises(exc.ServerError, self.gw_client.send, om) # Known errors: as is def testClientError(self): """ Test how server behaves when the client cannot receive """ # Message receiver def failing_receiver(message): print(message) raise OverflowError(':(') self.gw_client.onReceive += failing_receiver # Receive a message self.assertRaises(RuntimeError, self.lo.received, '1111', 'Yo')
class ForwardProviderTest(unittest.TestCase): """ Test ForwardClientProvider and ForwardServerProvider """ def _runFlask(self, gw, port): """ :param gw: Gateway :type gw: smsframework.Gateway.Gateway :return: :rtype: """ # Init flask app = Flask(__name__) app.debug = True app.testing = True # Register gateway receivers gw.receiver_blueprints_register(app, prefix='/sms') # Kill @app.route('/kill', methods=['POST']) def kill(): raise KeyboardInterrupt('/kill') # Run run_simple('0.0.0.0', port, app, passthrough_errors=True) def setUp(self): self.lock = threading.Lock() # Init: client gateway self.gw_client = Gateway() self.gw_client.add_provider('fwd', ForwardClientProvider, server_url='http://*****:*****@localhost:5001/sms/fwd') # Init: server gateway self.gw_server = Gateway() self.gw_server.add_provider('lo', LoopbackProvider) self.gw_server.add_provider('fwd', ForwardServerProvider, clients=['http://*****:*****@localhost:5000/sms/fwd']) self.lo = self.gw_server.get_provider('lo') ' :type: LoopbackProvider ' # Run client in a thread self.t_client = threading.Thread(target=self._runFlask, args=(self.gw_client, 5000)) self.t_client.daemon = True self.t_client.start() # Run server in a thread self.t_server = threading.Thread(target=self._runFlask, args=(self.gw_server, 5001)) self.t_server.daemon = True self.t_server.start() # Give Flask some time to initialize time.sleep(0.5) def tearDown(self): # Kill threads for port, thread in ((5000, self.t_client), (5001, self.t_server)): try: jsonex_request('http://localhost:{}/kill'.format(port), {}) except httplib.BadStatusLine: pass thread.join() def testSend(self): """ Send messages """ # Send a message om = OutgoingMessage('+1234', 'Hi man!').options(senderId='me').params(a=1).route(1, 2, 3) rom = self.gw_client.send(om) # Check traffic traffic = self.lo.get_traffic() self.assertEqual(len(traffic), 1) tom = traffic.pop() for m in (om, rom, tom): self.assertEqual(m.src, None) self.assertEqual(m.dst, '1234') self.assertEqual(m.body, 'Hi man!') self.assertEqual(m.provider, 'lo') # Remote provider should be exposed self.assertEqual(m.provider_options.senderId, 'me') self.assertEqual(m.provider_params, {'a': 1}) self.assertEqual(m.routing_values, [1, 2, 3]) self.assertEqual(m.msgid, '1') self.assertEqual(m.meta, None) def testReceive(self): """ Receive messages """ # Message receiver received = [] def onReceive(message): received.append(message) self.gw_client.onReceive += onReceive # Receive a message self.lo.received('1111', 'Yo') # Check self.assertEqual(len(received), 1) msg = received.pop() ':type: IncomingMessage' self.assertEqual(msg.msgid, 1) self.assertEqual(msg.src, '1111') self.assertEqual(msg.body, 'Yo') self.assertEqual(msg.dst, None) self.assertIsInstance(msg.rtime, datetime) self.assertEqual(msg.meta, {}) self.assertEqual(msg.provider, 'lo') # Remote provider should be exposed def testStatus(self): """ Receive statuses """ # Status receiver statuses = [] def onStatus(status): statuses.append(status) self.gw_client.onStatus += onStatus # Subscriber incoming = [] def subscriber(message): incoming.append(message) self.lo.subscribe('1234', subscriber) # Send a message, request status report om = OutgoingMessage('+1234', 'Hi man!').options(status_report=True) rom = self.gw_client.send(om) # Check self.assertEqual(len(statuses), 1) status = statuses.pop() ':type: MessageStatus' self.assertEqual(status.msgid, '1') self.assertIsInstance(status.rtime, datetime) self.assertEqual(status.provider, 'lo') self.assertEqual(status.accepted, True) self.assertEqual(status.delivered, True) self.assertEqual(status.expired, False) self.assertEqual(status.error, False) self.assertEqual(status.status_code, None) self.assertEqual(status.status, 'OK') self.assertEqual(status.meta, {}) def testServerError(self): """ Test how errors are transferred from the server """ # Erroneous subscribers def tired_subscriber(message): raise OverflowError('Tired') self.lo.subscribe('1234', tired_subscriber) def offline_subscriber(message): raise exc.ServerError('Offline') self.lo.subscribe('5678', offline_subscriber) # Send: 1 om = OutgoingMessage('+1234', 'Hi man!') self.assertRaises(RuntimeError, self.gw_client.send, om) # Unknown error classes are converted to RuntimeError # Send: 2 om = OutgoingMessage('+5678', 'Hi man!') self.assertRaises(exc.ServerError, self.gw_client.send, om) # Known errors: as is def testClientError(self): """ Test how server behaves when the client cannot receive """ # Message receiver def failing_receiver(message): raise OverflowError(':(') self.gw_client.onReceive += failing_receiver # Receive a message self.assertRaises(RuntimeError, self.lo.received, '1111', 'Yo')
class GatewayTest(unittest.TestCase): """ Test Gateway """ def setUp(self): self.gw = Gateway() # Providers self.gw.add_provider('one', NullProvider) self.gw.add_provider('two', NullProvider) self.gw.add_provider('three', NullProvider) # Router def router(message, module, method): if module == 'main': return None # use 'one' for module 'main' elif method == 'alarm': return 'two' # use 'three' for all alerting methods else: return 'three' # use 'two' for everything else self.gw.router = router def test_struct(self): """ Test structure """ # Default provider is fine self.assertEqual(self.gw.default_provider, 'one') # Getting providers self.assertIsInstance(self.gw.get_provider('one'), NullProvider) self.assertIsInstance(self.gw.get_provider('two'), NullProvider) self.assertIsInstance(self.gw.get_provider('three'), NullProvider) self.assertRaises(KeyError, self.gw.get_provider, 'none') # Redeclare a provider self.assertRaises(AssertionError, self.gw.add_provider, 'one', NullProvider) # Pass a non-IProvider class self.assertRaises(AssertionError, self.gw.add_provider, 'ok', Exception) def test_routing(self): """ Test routing """ # Sends through 'one' msg = self.gw.send(OutgoingMessage('', '').route('main', '')) self.assertEqual(msg.provider, 'one') # Sends through 'two' msg = self.gw.send(OutgoingMessage('', '').route('', 'alarm')) self.assertEqual(msg.provider, 'two') # Sends through 'three' msg = self.gw.send(OutgoingMessage('', '').route('', '')) self.assertEqual(msg.provider, 'three') # Send through 'one' (explicitly set) msg = self.gw.send(OutgoingMessage('', '', provider='one').route('', '')) self.assertEqual(msg.provider, 'one') # No routing specified: using the default route msg = self.gw.send(OutgoingMessage('', '', provider='one')) self.assertEqual(msg.provider, 'one') # Wrong provider specified self.assertRaises(AssertionError, self.gw.send, OutgoingMessage('', '', provider='zzz')) def test_events(self): """ Test events """ # Counters self.recv = 0 self.send = 0 self.status = 0 def inc_recv(message): self.recv += 1 def inc_send(message): self.send += 1 def inc_status(message): self.status += 1 # Hooks self.gw.onReceive += inc_recv self.gw.onSend += inc_send self.gw.onStatus += inc_status # Emit some events provider = self.gw.get_provider('one') self.gw.send(OutgoingMessage('', '')) provider._receive_message(IncomingMessage('', '')) provider._receive_status(MessageStatus('')) # Check self.assertEqual(self.recv, 1) self.assertEqual(self.send, 1) self.assertEqual(self.status, 1)
class ForwardProviderTest(unittest.TestCase): """ Test ForwardClientProvider and ForwardServerProvider """ def _runFlask(self, gw, port): """ :param gw: Gateway :type gw: smsframework.Gateway.Gateway :return: :rtype: """ # Init flask app = Flask(__name__) app.debug = True app.testing = True # Register gateway receivers gw.receiver_blueprints_register(app, prefix='/sms') # Stop manually @app.route('/kill', methods=['GET','POST']) def kill(): func = request.environ.get('werkzeug.server.shutdown') if func is None: raise RuntimeError('Not running with the Werkzeug Server') func() return '' # Run app.run('0.0.0.0', port, threaded=False, use_reloader=False, passthrough_errors=True) def setUp(self): # Init: client gateway # This "client" sends messages through a remote server self.gw_client = Gateway() self.gw_client.add_provider('fwd', ForwardClientProvider, server_url='http://*****:*****@localhost:5001/sms/fwd') # Init: server gateway # This "server" receives messages from an external SMS server and forwards them to the client self.gw_server = Gateway() self.gw_server.add_provider('lo', LoopbackProvider) self.gw_server.add_provider('fwd', ForwardServerProvider, clients=['http://*****:*****@localhost:5000/sms/fwd']) self.lo = self.gw_server.get_provider('lo') # This is run in another thread, but we should have access to it ' :type: LoopbackProvider ' # Run client in a thread self.t_client = threading.Thread(target=self._runFlask, args=(self.gw_client, 5000)) self.t_client.start() # Run server in a thread self.t_server = threading.Thread(target=self._runFlask, args=(self.gw_server, 5001)) self.t_server.start() # Give Flask some time to initialize time.sleep(0.5) def tearDown(self): # Kill threads for port, thread in ((5000, self.t_client), (5001, self.t_server)): #try: response = urlopen(Request('http://localhost:{}/kill'.format(port))) #except RemoteDisconnected: pass thread.join() def test_jsonex(self): """ Test de/coding messages """ ### OutgoingMessage om_in = OutgoingMessage('+123', 'Test', '+987', 'fwd') om_in.options(allow_reply=True) # Encode, Decode j = jsonex_dumps(om_in) om_out = jsonex_loads(j) """ :type om_out: OutgoingMessage """ # Check self.assertEqual(om_out.dst, '123') self.assertEqual(om_out.src, om_in.src) self.assertEqual(om_out.body, om_in.body) self.assertEqual(om_out.provider, om_in.provider) self.assertEqual(om_out.meta, None) self.assertEqual(om_out.provider_options.allow_reply, om_in.provider_options.allow_reply) self.assertEqual(om_out.provider_params, {}) ### IncomingMessage im_in = IncomingMessage('+123', 'Test', 'abc123def', '+987', datetime(2019,1,1,15,0,0,875), {'a':1}) # Encode, Decode j = jsonex_dumps(im_in) im_out = jsonex_loads(j) """ :type im_out: IncomingMessage """ # Check self.assertEqual(im_out.src, im_in.src) self.assertEqual(im_out.body, im_in.body) self.assertEqual(im_out.msgid, im_in.msgid) self.assertEqual(im_out.dst, im_in.dst) self.assertEqual(im_out.rtime, im_in.rtime) self.assertEqual(im_out.meta, im_in.meta) def testSend(self): """ Send messages """ # Send a message om = OutgoingMessage('+1234', 'Hi man!').options(senderId='me').params(a=1).route(1, 2, 3) rom = self.gw_client.send(om) # Check traffic traffic = self.lo.get_traffic() self.assertEqual(len(traffic), 1) tom = traffic.pop() for m in (om, rom, tom): self.assertEqual(m.src, None) self.assertEqual(m.dst, '1234') self.assertEqual(m.body, 'Hi man!') self.assertEqual(m.provider, 'lo') # Remote provider should be exposed self.assertEqual(m.provider_options.senderId, 'me') self.assertEqual(m.provider_params, {'a': 1}) self.assertEqual(m.routing_values, [1, 2, 3]) self.assertEqual(m.msgid, '1') self.assertEqual(m.meta, None) def testReceive(self): """ Receive messages """ # Message receiver received = [] def onReceive(message): received.append(message) self.gw_client.onReceive += onReceive # Receive a message self.lo.received('1111', 'Yo') # Check self.assertEqual(len(received), 1) msg = received.pop() ':type: IncomingMessage' self.assertEqual(msg.msgid, 1) self.assertEqual(msg.src, '1111') self.assertEqual(msg.body, 'Yo') self.assertEqual(msg.dst, None) self.assertIsInstance(msg.rtime, datetime) self.assertEqual(msg.meta, {}) self.assertEqual(msg.provider, 'lo') # Remote provider should be exposed def testStatus(self): """ Receive statuses """ # Status receiver statuses = [] def onStatus(status): statuses.append(status) self.gw_client.onStatus += onStatus # Subscriber incoming = [] def subscriber(message): incoming.append(message) self.lo.subscribe('1234', subscriber) # Send a message, request status report om = OutgoingMessage('+1234', 'Hi man!').options(status_report=True) rom = self.gw_client.send(om) # Check self.assertEqual(len(statuses), 1) status = statuses.pop() ':type: MessageStatus' self.assertEqual(status.msgid, '1') self.assertIsInstance(status.rtime, datetime) self.assertEqual(status.provider, 'lo') self.assertEqual(status.accepted, True) self.assertEqual(status.delivered, True) self.assertEqual(status.expired, False) self.assertEqual(status.error, False) self.assertEqual(status.status_code, None) self.assertEqual(status.status, 'OK') self.assertEqual(status.meta, {}) def testServerError(self): """ Test how errors are transferred from the server """ # Erroneous subscribers def tired_subscriber(message): raise OverflowError('Tired') self.lo.subscribe('1234', tired_subscriber) def offline_subscriber(message): raise exc.ServerError('Offline') self.lo.subscribe('5678', offline_subscriber) # Send: 1 om = OutgoingMessage('+1234', 'Hi man!') self.assertRaises(RuntimeError, self.gw_client.send, om) # Unknown error classes are converted to RuntimeError # Send: 2 om = OutgoingMessage('+5678', 'Hi man!') self.assertRaises(exc.ServerError, self.gw_client.send, om) # Known errors: as is def testClientError(self): """ Test how server behaves when the client cannot receive """ # Message receiver def failing_receiver(message): print(message) raise OverflowError(':(') self.gw_client.onReceive += failing_receiver # Receive a message self.assertRaises(RuntimeError, self.lo.received, '1111', 'Yo')
class GatewayTest(unittest.TestCase): """ Test Gateway """ def setUp(self): self.gw = Gateway() # Providers self.gw.add_provider('one', NullProvider) self.gw.add_provider('two', NullProvider) self.gw.add_provider('three', NullProvider) # Router def router(message, module, method): if module == 'main': return None # use 'one' for module 'main' elif method == 'alarm': return 'two' # use 'three' for all alerting methods else: return 'three' # use 'two' for everything else self.gw.router = router def test_struct(self): """ Test structure """ # Default provider is fine self.assertEqual(self.gw.default_provider, 'one') # Getting providers self.assertIsInstance(self.gw.get_provider('one'), NullProvider) self.assertIsInstance(self.gw.get_provider('two'), NullProvider) self.assertIsInstance(self.gw.get_provider('three'), NullProvider) self.assertRaises(KeyError, self.gw.get_provider, 'none') # Redeclare a provider self.assertRaises(AssertionError, self.gw.add_provider, 'one', NullProvider) # Pass a non-IProvider class self.assertRaises(AssertionError, self.gw.add_provider, 'ok', Exception) def test_routing(self): """ Test routing """ # Sends through 'one' msg = self.gw.send(OutgoingMessage('', '').route('main', '')) self.assertEqual(msg.provider, 'one') # Sends through 'two' msg = self.gw.send(OutgoingMessage('', '').route('', 'alarm')) self.assertEqual(msg.provider, 'two') # Sends through 'three' msg = self.gw.send(OutgoingMessage('', '').route('', '')) self.assertEqual(msg.provider, 'three') # Send through 'one' (explicitly set) msg = self.gw.send( OutgoingMessage('', '', provider='one').route('', '')) self.assertEqual(msg.provider, 'one') # No routing specified: using the default route msg = self.gw.send(OutgoingMessage('', '', provider='one')) self.assertEqual(msg.provider, 'one') # Wrong provider specified self.assertRaises(AssertionError, self.gw.send, OutgoingMessage('', '', provider='zzz')) def test_events(self): """ Test events """ # Counters self.recv = 0 self.send = 0 self.status = 0 def inc_recv(message): self.recv += 1 def inc_send(message): self.send += 1 def inc_status(message): self.status += 1 # Hooks self.gw.onReceive += inc_recv self.gw.onSend += inc_send self.gw.onStatus += inc_status # Emit some events provider = self.gw.get_provider('one') self.gw.send(OutgoingMessage('', '')) provider._receive_message(IncomingMessage('', '')) provider._receive_status(MessageStatus('')) # Check self.assertEqual(self.recv, 1) self.assertEqual(self.send, 1) self.assertEqual(self.status, 1)