494 lines
16 KiB
Python
494 lines
16 KiB
Python
|
from queue import Queue
|
||
|
import random
|
||
|
import socket
|
||
|
import threading
|
||
|
import unittest
|
||
|
from coapclient import HelperClient
|
||
|
from coapforwardproxy import CoAPForwardProxy
|
||
|
from coapserver import CoAPServer
|
||
|
from coapthon import defines
|
||
|
from coapthon.messages.option import Option
|
||
|
from coapthon.messages.request import Request
|
||
|
from coapthon.messages.response import Response
|
||
|
from coapthon.serializer import Serializer
|
||
|
import time
|
||
|
|
||
|
__author__ = 'Emilio Vallati'
|
||
|
__version__ = "1.0"
|
||
|
|
||
|
|
||
|
class Tests(unittest.TestCase):
|
||
|
|
||
|
def setUp(self):
|
||
|
self.server_address = ("127.0.0.1", 5683)
|
||
|
self.current_mid = random.randint(1, 1000)
|
||
|
self.server_mid = random.randint(1000, 2000)
|
||
|
self.server = CoAPServer("127.0.0.1", 5684)
|
||
|
self.server_thread = threading.Thread(target=self.server.listen, args=(10,))
|
||
|
self.server_thread.start()
|
||
|
self.proxy = CoAPForwardProxy("127.0.0.1", 5683, cache=True)
|
||
|
self.proxy_thread = threading.Thread(target=self.proxy.listen, args=(10,))
|
||
|
self.proxy_thread.start()
|
||
|
self.queue = Queue()
|
||
|
|
||
|
def tearDown(self):
|
||
|
self.server.close()
|
||
|
self.server_thread.join(timeout=25)
|
||
|
self.server = None
|
||
|
self.proxy.close()
|
||
|
self.proxy_thread.join(timeout=25)
|
||
|
self.proxy = None
|
||
|
|
||
|
def _test_with_client_delayed(self, message_list): # pragma: no cover
|
||
|
client = HelperClient(self.server_address)
|
||
|
for message, expected in message_list:
|
||
|
if message is not None:
|
||
|
received_message = client.send_request(message)
|
||
|
time.sleep(5)
|
||
|
|
||
|
if expected is not None:
|
||
|
if expected.etag is not None:
|
||
|
self.assertEqual(received_message.etag, expected.etag)
|
||
|
if expected.type is not None:
|
||
|
self.assertEqual(received_message.type, expected.type)
|
||
|
if expected.mid is not None:
|
||
|
self.assertEqual(received_message.mid, expected.mid)
|
||
|
self.assertEqual(received_message.code, expected.code)
|
||
|
if expected.source is not None:
|
||
|
self.assertEqual(received_message.source, self.server_address)
|
||
|
if expected.token is not None:
|
||
|
self.assertEqual(received_message.token, expected.token)
|
||
|
if expected.payload is not None:
|
||
|
self.assertEqual(received_message.payload, expected.payload)
|
||
|
if expected.max_age is not None:
|
||
|
if expected.max_age != 60:
|
||
|
self.assertNotEqual(received_message.max_age, 60)
|
||
|
else:
|
||
|
self.assertEqual(received_message.max_age, expected.max_age)
|
||
|
if expected.options:
|
||
|
self.assertEqual(len(received_message.options), len(expected.options))
|
||
|
for o in expected.options:
|
||
|
assert isinstance(o, Option)
|
||
|
if o.name != defines.OptionRegistry.MAX_AGE.name and o.name != defines.OptionRegistry.ETAG.name:
|
||
|
option_value = getattr(expected, o.name.lower().replace("-", "_"))
|
||
|
option_value_rec = getattr(received_message, o.name.lower().replace("-", "_"))
|
||
|
self.assertEqual(option_value, option_value_rec)
|
||
|
client.stop()
|
||
|
|
||
|
def client_callback(self, response):
|
||
|
print("Callback")
|
||
|
self.queue.put(response)
|
||
|
|
||
|
def test_get_multiple(self):
|
||
|
print("TEST_GET_MULTIPLE")
|
||
|
path = "/basic"
|
||
|
req = Request()
|
||
|
req.code = defines.Codes.GET.number
|
||
|
req.uri_path = path
|
||
|
req.type = defines.Types["CON"]
|
||
|
req._mid = self.current_mid
|
||
|
req.destination = self.server_address
|
||
|
req.proxy_uri = "coap://127.0.0.1:5684/basic"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CONTENT.number
|
||
|
expected.token = None
|
||
|
expected.payload = "Basic Resource"
|
||
|
|
||
|
exchange1 = (req, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
# PREPARING SECOND EXPECTED RESPONSE (MAX AGE MUST BE CHECKED)
|
||
|
req2 = Request()
|
||
|
req2.code = defines.Codes.GET.number
|
||
|
req2.uri_path = path
|
||
|
req2.type = defines.Types["CON"]
|
||
|
req2._mid = self.current_mid
|
||
|
req2.destination = self.server_address
|
||
|
req2.proxy_uri = "coap://127.0.0.1:5684/basic"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CONTENT.number
|
||
|
expected.token = None
|
||
|
expected.payload = "Basic Resource"
|
||
|
expected.max_age = 61
|
||
|
|
||
|
exchange2 = (req2, expected)
|
||
|
|
||
|
self._test_with_client_delayed([exchange1, exchange2])
|
||
|
|
||
|
def test_get_post(self):
|
||
|
print("TEST_GET_POST")
|
||
|
path = "/basic"
|
||
|
req = Request()
|
||
|
req.code = defines.Codes.POST.number
|
||
|
req.uri_path = path
|
||
|
req.type = defines.Types["CON"]
|
||
|
req._mid = self.current_mid
|
||
|
req.destination = self.server_address
|
||
|
req.proxy_uri = "coap://127.0.0.1:5684/storage/new"
|
||
|
req.payload = "Hello"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CREATED.number
|
||
|
expected.token = None
|
||
|
expected.payload = None
|
||
|
|
||
|
exchange1 = (req, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
# PREPARING SECOND EXPECTED RESPONSE
|
||
|
req2 = Request()
|
||
|
req2.code = defines.Codes.GET.number
|
||
|
req2.uri_path = path
|
||
|
req2.type = defines.Types["CON"]
|
||
|
req2._mid = self.current_mid
|
||
|
req2.destination = self.server_address
|
||
|
req2.proxy_uri = "coap://127.0.0.1:5684/storage/new"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CONTENT.number
|
||
|
expected.token = None
|
||
|
expected.payload = "Hello"
|
||
|
|
||
|
exchange2 = (req2, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
# PREPARING THIRD EXPECTED RESPONSE
|
||
|
req3 = Request()
|
||
|
req3.code = defines.Codes.POST.number
|
||
|
req3.uri_path = path
|
||
|
req3.type = defines.Types["CON"]
|
||
|
req3._mid = self.current_mid
|
||
|
req3.destination = self.server_address
|
||
|
req3.proxy_uri = "coap://127.0.0.1:5684/storage/new"
|
||
|
req3.payload = "Hello"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CREATED.number
|
||
|
expected.token = None
|
||
|
expected.payload = None
|
||
|
|
||
|
exchange3 = (req3, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
# PREPARING FOURTH EXPECTED RESPONSE
|
||
|
req4 = Request()
|
||
|
req4.code = defines.Codes.GET.number
|
||
|
req4.uri_path = path
|
||
|
req4.type = defines.Types["CON"]
|
||
|
req4._mid = self.current_mid
|
||
|
req4.destination = self.server_address
|
||
|
req4.proxy_uri = "coap://127.0.0.1:5684/storage/new"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CONTENT.number
|
||
|
expected.token = None
|
||
|
expected.payload = "Hello"
|
||
|
|
||
|
exchange4 = (req4, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
self._test_with_client_delayed([exchange1, exchange2, exchange3, exchange4])
|
||
|
|
||
|
def test_get_put(self):
|
||
|
print("TEST_GET_PUT")
|
||
|
path = "/basic"
|
||
|
req = Request()
|
||
|
req.code = defines.Codes.POST.number
|
||
|
req.uri_path = path
|
||
|
req.type = defines.Types["CON"]
|
||
|
req._mid = self.current_mid
|
||
|
req.destination = self.server_address
|
||
|
req.proxy_uri = "coap://127.0.0.1:5684/storage/new"
|
||
|
req.payload = "Hello"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CREATED.number
|
||
|
expected.token = None
|
||
|
expected.payload = None
|
||
|
|
||
|
exchange1 = (req, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
# PREPARING SECOND EXPECTED RESPONSE
|
||
|
req2 = Request()
|
||
|
req2.code = defines.Codes.GET.number
|
||
|
req2.uri_path = path
|
||
|
req2.type = defines.Types["CON"]
|
||
|
req2._mid = self.current_mid
|
||
|
req2.destination = self.server_address
|
||
|
req2.proxy_uri = "coap://127.0.0.1:5684/storage/new"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CONTENT.number
|
||
|
expected.token = None
|
||
|
expected.payload = "Hello"
|
||
|
|
||
|
exchange2 = (req2, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
# PREPARING THIRD EXPECTED RESPONSE
|
||
|
req3 = Request()
|
||
|
req3.code = defines.Codes.PUT.number
|
||
|
req3.uri_path = path
|
||
|
req3.type = defines.Types["CON"]
|
||
|
req3._mid = self.current_mid
|
||
|
req3.destination = self.server_address
|
||
|
req3.proxy_uri = "coap://127.0.0.1:5684/storage/new"
|
||
|
req3.payload = "Hello"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CHANGED.number
|
||
|
expected.token = None
|
||
|
expected.payload = None
|
||
|
|
||
|
exchange3 = (req3, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
# PREPARING FOURTH EXPECTED RESPONSE
|
||
|
req4 = Request()
|
||
|
req4.code = defines.Codes.GET.number
|
||
|
req4.uri_path = path
|
||
|
req4.type = defines.Types["CON"]
|
||
|
req4._mid = self.current_mid
|
||
|
req4.destination = self.server_address
|
||
|
req4.proxy_uri = "coap://127.0.0.1:5684/storage/new"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CONTENT.number
|
||
|
expected.token = None
|
||
|
expected.payload = "Hello"
|
||
|
|
||
|
exchange4 = (req4, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
self._test_with_client_delayed([exchange1, exchange2, exchange3, exchange4])
|
||
|
|
||
|
def test_get_delete(self):
|
||
|
print("TEST_GET_DELETE")
|
||
|
path = "/basic"
|
||
|
|
||
|
req2 = Request()
|
||
|
req2.code = defines.Codes.GET.number
|
||
|
req2.uri_path = path
|
||
|
req2.type = defines.Types["CON"]
|
||
|
req2._mid = self.current_mid
|
||
|
req2.destination = self.server_address
|
||
|
req2.proxy_uri = "coap://127.0.0.1:5684/storage/new"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.NOT_FOUND.number
|
||
|
expected.token = None
|
||
|
expected.payload = None
|
||
|
|
||
|
exchange0 = (req2, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
req = Request()
|
||
|
req.code = defines.Codes.POST.number
|
||
|
req.uri_path = path
|
||
|
req.type = defines.Types["CON"]
|
||
|
req._mid = self.current_mid
|
||
|
req.destination = self.server_address
|
||
|
req.proxy_uri = "coap://127.0.0.1:5684/storage/new"
|
||
|
req.payload = "Hello"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CREATED.number
|
||
|
expected.token = None
|
||
|
expected.payload = None
|
||
|
|
||
|
exchange1 = (req, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
# PREPARING SECOND EXPECTED RESPONSE
|
||
|
req2 = Request()
|
||
|
req2.code = defines.Codes.GET.number
|
||
|
req2.uri_path = path
|
||
|
req2.type = defines.Types["CON"]
|
||
|
req2._mid = self.current_mid
|
||
|
req2.destination = self.server_address
|
||
|
req2.proxy_uri = "coap://127.0.0.1:5684/storage/new"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CONTENT.number
|
||
|
expected.token = None
|
||
|
expected.payload = "Hello"
|
||
|
|
||
|
exchange2 = (req2, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
# PREPARING THIRD EXPECTED RESPONSE
|
||
|
req3 = Request()
|
||
|
req3.code = defines.Codes.DELETE.number
|
||
|
req3.uri_path = path
|
||
|
req3.type = defines.Types["CON"]
|
||
|
req3._mid = self.current_mid
|
||
|
req3.destination = self.server_address
|
||
|
req3.proxy_uri = "coap://127.0.0.1:5684/storage/new"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.DELETED.number
|
||
|
expected.token = None
|
||
|
expected.payload = None
|
||
|
|
||
|
exchange3 = (req3, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
# PREPARING FOURTH EXPECTED RESPONSE
|
||
|
req4 = Request()
|
||
|
req4.code = defines.Codes.GET.number
|
||
|
req4.uri_path = path
|
||
|
req4.type = defines.Types["CON"]
|
||
|
req4._mid = self.current_mid
|
||
|
req4.destination = self.server_address
|
||
|
req4.proxy_uri = "coap://127.0.0.1:5684/storage/new"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.NOT_FOUND.number
|
||
|
expected.token = None
|
||
|
|
||
|
exchange4 = (req4, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
self._test_with_client_delayed([exchange0, exchange1, exchange2, exchange3, exchange4])
|
||
|
|
||
|
def test_get_etag(self):
|
||
|
print("TEST_GET_ETAG")
|
||
|
path = "/etag"
|
||
|
req = Request()
|
||
|
req.code = defines.Codes.GET.number
|
||
|
req.uri_path = path
|
||
|
req.type = defines.Types["CON"]
|
||
|
req._mid = self.current_mid
|
||
|
req.destination = self.server_address
|
||
|
req.proxy_uri = "coap://127.0.0.1:5684/etag"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CONTENT.number
|
||
|
expected.token = None
|
||
|
expected.payload = None
|
||
|
expected.etag = str(0)
|
||
|
|
||
|
exchange1 = (req, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
# PREPARING SECOND EXPECTED RESPONSE
|
||
|
req2 = Request()
|
||
|
req2.code = defines.Codes.GET.number
|
||
|
req2.uri_path = path
|
||
|
req2.type = defines.Types["CON"]
|
||
|
req2._mid = self.current_mid
|
||
|
req2.destination = self.server_address
|
||
|
req2.proxy_uri = "coap://127.0.0.1:5684/etag"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CONTENT.number
|
||
|
expected.token = None
|
||
|
expected.etag = str(0)
|
||
|
expected.max_age = 1
|
||
|
|
||
|
exchange2 = (req2, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
# PREPARING THIRD EXPECTED RESPONSE
|
||
|
req3 = Request()
|
||
|
req3.code = defines.Codes.POST.number
|
||
|
req3.uri_path = path
|
||
|
req3.type = defines.Types["CON"]
|
||
|
req3._mid = self.current_mid
|
||
|
req3.destination = self.server_address
|
||
|
req3.proxy_uri = "coap://127.0.0.1:5684/etag"
|
||
|
req3.payload = "Hello"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CHANGED.number
|
||
|
expected.token = None
|
||
|
expected.payload = None
|
||
|
expected.etag = str(1)
|
||
|
expected.location_path = "etag"
|
||
|
|
||
|
exchange3 = (req3, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
# PREPARING FOURTH EXPECTED RESPONSE
|
||
|
req4 = Request()
|
||
|
req4.code = defines.Codes.GET.number
|
||
|
req4.uri_path = path
|
||
|
req4.type = defines.Types["CON"]
|
||
|
req4._mid = self.current_mid
|
||
|
req4.destination = self.server_address
|
||
|
req4.proxy_uri = "coap://127.0.0.1:5684/etag"
|
||
|
|
||
|
expected = Response()
|
||
|
expected.type = defines.Types["ACK"]
|
||
|
expected._mid = self.current_mid
|
||
|
expected.code = defines.Codes.CONTENT.number
|
||
|
expected.token = None
|
||
|
expected.payload = "Hello"
|
||
|
expected.etag = str(1)
|
||
|
|
||
|
exchange4 = (req4, expected)
|
||
|
|
||
|
self.current_mid += 1
|
||
|
|
||
|
self._test_with_client_delayed([exchange1, exchange2, exchange3, exchange4])
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
unittest.main()
|