Commit 5b8f8e43 authored by Federico Sismondi's avatar Federico Sismondi
Browse files

Merge branch 'develop' into 'webserver_enhacements'

# Conflicts:
#   coap_testing_tool/test_coordinator/coordinator.py
#   coap_testing_tool/utils/event_bus_messages.py
parents 26e31939 ea97d680
Pipeline #922 passed with stage
in 0 seconds
......@@ -135,7 +135,7 @@ if __name__ == '__main__':
# lets start the test suite coordination phase
try:
logger.info('Instantiating coordinator..')
logger.info('Starting test-coordinator..')
coordinator = Coordinator(connection, TD_COAP, TD_COAP_CFG)
except Exception as e:
......
......@@ -12,6 +12,7 @@ import pika
import time
import logging
from urllib.parse import urlparse
from itertools import cycle
from collections import OrderedDict
from coap_testing_tool import AMQP_EXCHANGE
......@@ -33,10 +34,11 @@ SNIFFER_FILTER_IF = 'tun0'
# component identification & bus params
COMPONENT_ID = 'test_coordinator'
session_config = None
logger = logging.getLogger()
### AUX functions ###
# # # AUX functions # # #
def list_to_str(ls):
"""
......@@ -60,7 +62,7 @@ def list_to_str(ls):
return ret
### YAML parser aux classes and methods ###
# # # YAML parser aux classes and methods # # #
def testcase_constructor(loader, node):
instance = TestCase.__new__(TestCase)
yield instance
......@@ -386,11 +388,11 @@ class TestCase:
d = OrderedDict()
d['testcase_id'] = self.id
d['testcase_ref'] = self.uri
d['state'] = self.state
if verbose:
d['objective'] = self.objective
d['pre_conditions'] = self.pre_conditions
d['state'] = self.state
return d
......@@ -541,6 +543,10 @@ class Coordinator:
queue=self.events_q_name,
routing_key='control.testcoordination')
self.channel.queue_bind(exchange=AMQP_EXCHANGE,
queue=self.events_q_name,
routing_key='control.session')
self.channel.basic_consume(self.handle_service,
queue=self.services_q_name,
no_ack=False)
......@@ -573,7 +579,7 @@ class Coordinator:
logger.info('start consuming..')
self.channel.start_consuming()
### AUXILIARY AMQP MESSAGING FUNCTIONS ###
# # # AUXILIARY AMQP MESSAGING FUNCTIONS # # #
def notify_tun_interfaces_start(self):
"""
......@@ -636,7 +642,7 @@ class Coordinator:
msg_fields = {}
msg_fields.update(self.current_tc.report)
msg_fields.update(self.current_tc.to_dict(verbose=False))
event = MsgTestCaseVerdict( **msg_fields)
event = MsgTestCaseVerdict(**msg_fields)
publish_message(self.channel, event)
# Overwrite final verdict file with final details
......@@ -734,21 +740,21 @@ class Coordinator:
logger.info("Received answer from sniffer: %s, answer: %s" % (response._type, repr(response)))
return response
### API ENDPOINTS ###
# # # API ENDPOINTS # # #
def handle_service(self, ch, method, properties, body):
ch.basic_ack(delivery_tag=method.delivery_tag)
props_dict = {
'content_type': properties.content_type,
'delivery_mode': properties.delivery_mode,
'content_type': properties.content_type,
'delivery_mode': properties.delivery_mode,
'correlation_id': properties.correlation_id,
'reply_to': properties.reply_to,
'message_id': properties.message_id,
'timestamp': properties.timestamp,
'user_id': properties.user_id,
'app_id': properties.app_id,
'reply_to': properties.reply_to,
'message_id': properties.message_id,
'timestamp': properties.timestamp,
'user_id': properties.user_id,
'app_id': properties.app_id,
}
request = Message.from_json(body)
request.update_properties(**props_dict)
......@@ -781,14 +787,14 @@ class Coordinator:
ch.basic_ack(delivery_tag=method.delivery_tag)
props_dict = {
'content_type': properties.content_type,
'delivery_mode': properties.delivery_mode,
'content_type': properties.content_type,
'delivery_mode': properties.delivery_mode,
'correlation_id': properties.correlation_id,
'reply_to': properties.reply_to,
'message_id': properties.message_id,
'timestamp': properties.timestamp,
'user_id': properties.user_id,
'app_id': properties.app_id,
'reply_to': properties.reply_to,
'message_id': properties.message_id,
'timestamp': properties.timestamp,
'user_id': properties.user_id,
'app_id': properties.app_id,
}
event = Message.from_json(body)
event.update_properties(**props_dict)
......@@ -796,43 +802,30 @@ class Coordinator:
logger.info('Event received: %s' % event._type)
if isinstance(event, MsgTestCaseSkip):
if self.current_tc is None:
# operation health check
if self.current_tc is None and event.testcase_id is None:
error_msg = "No current testcase. Please provide a testcase_id to skip."
# notify all
self.notify_coordination_error(message=error_msg, error_code=None)
return
try:
testcase_id_skip = event.testcase_id
if testcase_id_skip is None: # if {'testcase_id' : null} was sent then I skip the current one
testcase_t = self.current_tc
else:
testcase_t = self.get_testcase(testcase_id_skip)
testcase_id_skip = self.current_tc.id
except: # if no testcase_id was sent then I skip the current one
testcase_t = self.current_tc
testcase_id_skip = self.current_tc.id
# change tc state to 'skipped'
try:
if self.skip_testcase(testcase_id_skip): # if there's more TCs
self.notify_testcase_is_ready()
elif self.check_testsuite_finished(): # no more TCs to execute
self.finish_testsuite()
self.notify_testsuite_finished()
if testcase_t is None:
error_msg = "Non existent testcase: %s" % testcase_id_skip
self.notify_coordination_error(message=error_msg, error_code=None)
except Exception as e:
self.notify_coordination_error(message=str(e), error_code=None)
return
logger.info("Skipping testcase: %s" % testcase_t.id)
testcase_t.change_state("skipped")
# if skipped tc is current test case then next tc
if self.current_tc is not None and (testcase_t.id == self.current_tc.id):
self.next_testcase()
self.notify_testcase_is_ready()
if self.current_tc is None and self.check_testsuite_finished():
self.finish_testsuite()
self.notify_testsuite_finished()
elif isinstance(event, MsgTestSuiteStart):
# lets open tun interfaces
self.notify_tun_interfaces_start()
......@@ -930,7 +923,6 @@ class Coordinator:
self.finish_testsuite()
self.notify_testsuite_finished()
elif isinstance(event, MsgVerifyResponse):
if self.current_tc is None:
......@@ -989,6 +981,52 @@ class Coordinator:
self.finish_testsuite()
self.notify_testsuite_finished()
elif isinstance(event, MsgInteropSessionConfiguration):
global session_config
session_config = event.to_dict()
tc_list_requested = []
for test in event.tests:
test_url = urlparse(test['testcase_ref'])
tc_id = str(test_url.path).lstrip("/tests/")
tc_list_requested.append(tc_id)
tc_list_available = self.get_testcases_list()
# check selected test cases available in testing tool
tc_non_existent = list(set(tc_list_requested) - set(tc_list_available))
tc_to_skip = list(set(tc_list_available) - set(tc_list_requested))
if len(tc_list_requested) == 0:
self.notify_coordination_error(
message='No testcases selected. Using default selection: ALL',
error_code='TBD'
)
return
if len(tc_non_existent) != 0:
self.notify_coordination_error(
message='The following testcases are not available in the testing tool: %s'
% str(tc_non_existent),
error_code='TBD'
)
return
if len(tc_to_skip) != 0:
for item in tc_to_skip:
self.skip_testcase(item)
testcases = self.get_testcases_basic(verbose=False)
event = MsgTestingToolConfigured(
session_id=event.session_id,
testing_tools=event.testing_tools,
tc_list=testcases,
)
publish_message(self.channel, event)
elif isinstance(event, MsgCheckResponse):
if self.current_tc is None:
......@@ -1050,7 +1088,7 @@ class Coordinator:
else:
logger.error('Malformed message')
### TRANSITION METHODS for the Coordinator FSM ###
# # # TRANSITION METHODS for the Coordinator FSM # # #
def get_testcases_basic(self, verbose=None):
......@@ -1130,9 +1168,9 @@ class Coordinator:
sniff_params = {
'capture_id': self.current_tc.id[:-4],
'filter_proto': filter_proto,
'filter_if': SNIFFER_FILTER_IF,
'link_id': link_id,
'filter_proto': filter_proto,
'filter_if': SNIFFER_FILTER_IF,
'link_id': link_id,
}
if self.call_service_sniffer_start(**sniff_params):
......@@ -1142,6 +1180,27 @@ class Coordinator:
return self.current_tc.current_step
def skip_testcase(self, testcase_id):
"""
:param testcase_id: testcase id to skip
:return: next test case (Testcase type) to execute, None if no more testcases to execute
"""
testcase_t = self.get_testcase(testcase_id)
if testcase_t is None:
error_msg = "Non existent testcase: %s" % testcase_id
raise Exception(error_msg)
logger.info("Skipping testcase: %s" % testcase_t.id)
testcase_t.change_state("skipped")
# if skipped tc is current test case then next tc
if self.current_tc is not None and (testcase_t.id == self.current_tc.id):
self.next_testcase()
return self.current_tc
def handle_verify_step_response(self, verify_response):
# some sanity checks on the states
assert self.current_tc is not None
......@@ -1430,4 +1489,4 @@ class Coordinator:
try:
return self.teds[testcase_id]
except KeyError:
return None
return None
\ No newline at end of file
import unittest, logging, os, pika, json
from collections import OrderedDict
from coap_testing_tool import AMQP_URL
from coap_testing_tool.test_coordinator.coordinator import Coordinator, TD_COAP_CFG,TD_COAP, import_teds
from coap_testing_tool.test_coordinator.coordinator import Coordinator, TD_COAP_CFG, TD_COAP, import_teds
class CoordinatorTestCase(unittest.TestCase):
class CoordinatorTestCase(unittest.TestCase):
number_of_implemented_TCs = 24
def setUp(self):
connection = pika.BlockingConnection(pika.URLParameters(AMQP_URL))
......@@ -18,7 +19,7 @@ class CoordinatorTestCase(unittest.TestCase):
it_docs = import_teds(TD_COAP)
for d in self.coord.teds:
print(d)
print( it_docs)
print(it_docs)
for item in it_docs:
print(str(type(item)))
print(str(type(item)))
......@@ -34,7 +35,6 @@ class CoordinatorTestCase(unittest.TestCase):
self.coord.select_testcase('TD_COAP_CORE_02_v01')
assert self.coord.current_tc.id == 'TD_COAP_CORE_02_v01'
def test_check_all_steps_finished(self):
# this must not raise any errors during the iteration, control flow is done with None when iter is over!
c = self.coord
......@@ -44,7 +44,7 @@ class CoordinatorTestCase(unittest.TestCase):
for p in tc.sequence:
assert tc.check_all_steps_finished() is False
p.change_state('postponed')
print('step state: '+ str(p.state))
print('step state: ' + str(p.state))
assert tc.check_all_steps_finished() is True
print("TD finished!")
......@@ -57,7 +57,6 @@ class CoordinatorTestCase(unittest.TestCase):
print("iter over TCs: \n" + str(tc))
assert tc == None
def test_stepping_over_the_steps_and_the_TCs(self):
# this must not raise any errors during the iteration, control flow is done with None when iter is over!
c = self.coord
......@@ -68,7 +67,7 @@ class CoordinatorTestCase(unittest.TestCase):
print("starting with: " + tc.id)
while tc is not None:
print("running TC: "+ str(tc.id))
print("running TC: " + str(tc.id))
s = c.next_step()
while s is not None:
......@@ -80,7 +79,6 @@ class CoordinatorTestCase(unittest.TestCase):
tc = c.next_testcase()
print("TD finished!")
def test_testsuite_report(self):
# this must not raise any errors during the iteration, control flow is done with None when iter is over!
c = self.coord
......@@ -91,7 +89,7 @@ class CoordinatorTestCase(unittest.TestCase):
print("starting with: " + tc.id)
while tc is not None:
print("running TC: "+ str(tc.id))
print("running TC: " + str(tc.id))
s = c.next_step()
while s is not None:
......@@ -112,8 +110,6 @@ class CoordinatorTestCase(unittest.TestCase):
print(json.dumps(c.testsuite_report()))
def test_stepping_over_TC_config_atributes_chech_not_None(self):
# this must not raise any errors during the iteration, control flow is done with None when iter is over!
c = self.coord
......@@ -130,4 +126,4 @@ class CoordinatorTestCase(unittest.TestCase):
if __name__ == '__main__':
unittest.test_stepping_over_TC_config_atributes_chech_not_None()
\ No newline at end of file
unittest.test_stepping_over_TC_config_atributes_chech_not_None()
......@@ -28,7 +28,7 @@
{
"field_name": "Testing Tool Description",
"type": "text",
"value": [
"values": [
"Reference-based interoperability (~conformance) Testing Tool for validating conformance to CoAP RFCs.",
"The testing tool uses as reference implementation (golden image) Californium implementation (CoAP client and CoAP server).",
"The implementation of the tests are based on ETSI test description [ETSI CoAP test description](http://www.etsi.org/plugtests/CoAP/Document/CoAP_TestDescriptions_v015.pdf)"
......
......@@ -28,7 +28,7 @@
{
"field_name": "Testing Tool Description",
"type": "text",
"value": [
"values": [
"Interoperability Testing Tool for testing CoAP interoperability between two IUTs (CoAP client and CoAP server).",
"The implementation of the tests are based on ETSI test description [ETSI CoAP test description](http://www.etsi.org/plugtests/CoAP/Document/CoAP_TestDescriptions_v015.pdf"
]
......
......@@ -32,12 +32,13 @@ services_backlog = []
"""
PRE-CONDITIONS:
- Export AMQP_URL in the running environment
- Have CoAP testing tool and listening to the bus
- Have CoAP testing tool running & listening to the bus
"""
# for a typical user input, for a user (coap client) vs automated-iut ( coap server) session type:
user_sequence = [
MsgTestSuiteGetStatus(),
MsgTestCaseConfiguration(),
MsgTestSuiteStart(),
MsgTestSuiteGetStatus(),
MsgTestCaseSkip(testcase_id='TD_COAP_CORE_02_v01'),
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment