Skip to content
Snippets Groups Projects
Commit a8ac0b59 authored by piscione's avatar piscione
Browse files

Review of APPSAQ TCs of MEC011v3.2.1

parent 6ff2d981
No related branches found
No related tags found
1 merge request!3Merge of TT027 branch into master
......@@ -4,8 +4,10 @@ Documentation
... A test suite for validating Application Service Availability Query (APPSAQ) operations.
Resource ../../../GenericKeywords.robot
Resource environment/variables.txt
#Resource environment/variables.txt
Resource environment/variables_sandbox.txt
Library REST ${SCHEMA}://${HOST}:${PORT} ssl_verify=false
Library libraries/Server.py
Default Tags TC_MEC_SRV_APPSAQ
......@@ -22,6 +24,7 @@ TC_MEC_MEC011_SRV_APPSAQ_001_OK
... ETSI GS MEC 011 3.2.1, clause 8.2.6.3.1
[Tags] PIC_MEC_PLAT PIC_SERVICES
[Setup] Create new service ServiceInfo ${APP_INSTANCE_ID}
Set Suite Variable ${SERVICE_ID} ${response['body']['serInstanceId']}
Get a list of mecService of an application instance ${APP_INSTANCE_ID}
Check HTTP Response Status Code Is 200
Check HTTP Response Body Json Schema Is ServiceInfoList
......@@ -33,7 +36,7 @@ TC_MEC_MEC011_SRV_APPSAQ_001_BR
... Check that the IUT responds with an error when
... a request with incorrect parameters is sent by a MEC Application
...
... Reference ETSI GS MEC 011 3.2.1, clause 5.2.5,
... Reference ETSI G3.2.1 011 3.2.1, clause 5.2.5,
... ETSI GS MEC 011 3.2.1, clause 8.1.2.2,
... ETSI GS MEC 011 3.2.1, clause 8.2.6.3.1
[Tags] PIC_MEC_PLAT PIC_SERVICES
......@@ -51,13 +54,16 @@ TC_MEC_MEC011_SRV_APPSAQ_002_OK
... ETSI GS MEC 011 3.2.1, clause 8.1.2.2,
... ETSI GS MEC 011 3.2.1, clause 8.2.6.3.4
[Tags] PIC_MEC_PLAT PIC_SERVICES
[Setup]
Create new service ServiceInfo ${APP_INSTANCE_ID}
Check HTTP Response Status Code Is 201
Check HTTP Response Body Json Schema Is ServiceInfo
Check HTTP Response Header Contains Location
Check Response Contains ${response['body']} serName ${NEW_SERVICE_NAME}
##TODO add notification server
Spawn Notification Server SerAvailabilityNotificationSubscription
Validate Json SerAvailabilityNotificationSubscription.schema.json ${payload_notification}
[TearDown] Remove individual service ${APP_INSTANCE_ID} ${SERVICE_ID}
TC_MEC_MEC011_SRV_APPSAQ_002_BR
[Documentation]
......@@ -96,6 +102,7 @@ TC_MEC_MEC011_SRV_APPSAQ_003_OK
... ETSI GS MEC 011 3.2.1, clause 8.2.7.3.1
[Tags] PIC_MEC_PLAT PIC_SERVICES
[Setup] Create new service ServiceInfo ${APP_INSTANCE_ID}
Set Suite Variable ${SERVICE_ID} ${response['body']['serInstanceId']}
Get individual service ${APP_INSTANCE_ID} ${SERVICE_ID}
Check HTTP Response Status Code Is 200
Check HTTP Response Body Json Schema Is ServiceInfo
......@@ -127,6 +134,7 @@ TC_MEC_MEC011_SRV_APPSAQ_004_OK
... ETSI GS MEC 011 3.2.1, clause 8.2.7.3.2
[Tags] PIC_MEC_PLAT PIC_SERVICES
[Setup] Create new service ServiceInfo ${APP_INSTANCE_ID}
Set Suite Variable ${SERVICE_ID} ${response['body']['serInstanceId']}
Update service ${APP_INSTANCE_ID} ${SERVICE_ID} ServiceInfoUpdated
Check HTTP Response Status Code Is 200
Check HTTP Response Body Json Schema Is ServiceInfo
......@@ -143,7 +151,8 @@ TC_MEC_MEC011_SRV_APPSAQ_004_BR
... ETSI GS MEC 011 3.2.1, clause 8.1.2.2,
... ETSI GS MEC 011 3.2.1, clause 8.2.7.3.2
[Tags] PIC_MEC_PLAT PIC_SERVICES
[Setup] Create new service ServiceInfo ${APP_INSTANCE_ID}
[Setup] Create new service ServiceInfo ${APP_INSTANCE_ID}
Set Suite Variable ${SERVICE_ID} ${response['body']['serInstanceId']}
Update service ${APP_INSTANCE_ID} ${SERVICE_ID} ServiceInfoUpdatedError
Check HTTP Response Status Code Is 400
[TearDown] Remove individual service ${APP_INSTANCE_ID} ${SERVICE_ID}
......@@ -173,6 +182,7 @@ TC_MEC_MEC011_SRV_APPSAQ_004_PF
... ETSI GS MEC 011 3.2.1, clause 8.2.7.3.2
[Tags] PIC_MEC_PLAT PIC_SERVICES
[Setup] Create new service ServiceInfo ${APP_INSTANCE_ID}
Set Suite Variable ${SERVICE_ID} ${response['body']['serInstanceId']}
Update service with etag ${APP_INSTANCE_ID} ${SERVICE_ID} ServiceInfoUpdated ${INVALID_ETAG}
Check HTTP Response Status Code Is 412
[TearDown] Remove individual service ${APP_INSTANCE_ID} ${SERVICE_ID}
......@@ -186,6 +196,7 @@ TC_MEC_MEC011_SRV_APPSAQ_005_OK
... Reference ETSI GS MEC 011 3.2.1, clause 8.2.7.3.5
[Tags] PIC_MEC_PLAT PIC_SERVICES
[Setup] Create new service ServiceInfo ${APP_INSTANCE_ID}
Set Suite Variable ${SERVICE_ID} ${response['body']['serInstanceId']}
Remove individual service ${APP_INSTANCE_ID} ${SERVICE_ID}
Check HTTP Response Status Code Is 204
......@@ -207,7 +218,7 @@ TC_MEC_MEC011_SRV_APPSAQ_005_NF
Get a list of mecService of an application instance with parameters
[Arguments] ${appInstanceId} ${key}=None ${value}=None
Set Headers {"Accept":"application/json"}
Set Headers {"Authorization":"${TOKEN}"}
#Set Headers {"Authorization":"${TOKEN}"}
Set Headers {"Content-Type":"*/*"}
Get ${apiRoot}/${apiName}/${apiVersion}/applications/${appInstanceId}/services?${key}=${value}
${output}= Output response
......@@ -217,7 +228,7 @@ Get a list of mecService of an application instance
[Arguments] ${appInstanceId}
Set Headers {"Accept":"application/json"}
Set Headers {"Content-Type":"*/*"}
Set Headers {"Authorization":"${TOKEN}"}
#Set Headers {"Authorization":"${TOKEN}"}
Get ${apiRoot}/${apiName}/${apiVersion}/applications/${appInstanceId}/services
${output}= Output response
Set Suite Variable ${response} ${output}
......@@ -228,11 +239,11 @@ Create new service
Set Headers {"Accept":"application/json"}
Set Headers {"Content-Type":"application/json"}
#Set Headers {"Content-Type":"*/*"}
Set Headers {"Authorization":"${TOKEN}"}
#Set Headers {"Authorization":"${TOKEN}"}
${file}= Catenate SEPARATOR= jsons/ ${content} .json
${body}= Get File ${file}
Log ${appInstanceId}
Post ${apiRoot}/${apiName}/${apiVersion}/applications/${appInstanceId}/services ${body}
Log ${apiRoot}/${apiName}/${apiVersion}/applications/${appInstanceId}/services
${output}= Output response
Set Suite Variable ${response} ${output}
......@@ -240,7 +251,7 @@ Create new service
Get individual service
[Arguments] ${appInstanceId} ${serviceName}
Set Headers {"Accept":"application/json"}
Set Headers {"Authorization":"${TOKEN}"}
#Set Headers {"Authorization":"${TOKEN}"}
Set Headers {"Content-Type":"*/*"}
Get ${apiRoot}/${apiName}/${apiVersion}/applications/${appInstanceId}/services/${serviceName}
${output}= Output response
......@@ -250,7 +261,7 @@ Update service
[Arguments] ${appInstanceId} ${serviceId} ${content}
Set Headers {"Accept":"application/json"}
Set Headers {"Content-Type":"application/json"}
Set Headers {"Authorization":"${TOKEN}"}
#Set Headers {"Authorization":"${TOKEN}"}
#Set Headers {"Content-Type":"*/*"}
${file}= Catenate SEPARATOR= jsons/ ${content} .json
${body}= Get File ${file}
......@@ -262,7 +273,7 @@ Update service with etag
[Arguments] ${appInstanceId} ${serviceId} ${content} ${etag}
Set Headers {"Accept":"application/json"}
Set Headers {"Content-Type":"application/json"}
Set Headers {"Authorization":"${TOKEN}"}
#Set Headers {"Authorization":"${TOKEN}"}
Set Headers {"If-Match":"${etag}"}
${file}= Catenate SEPARATOR= jsons/ ${content} .json
${body}= Get File ${file}
......@@ -274,31 +285,29 @@ Update service with etag
Remove individual service
[Arguments] ${appInstanceId} ${serviceName}
Set Headers {"Accept":"application/json"}
Set Headers {"Authorization":"${TOKEN}"}
#Set Headers {"Authorization":"${TOKEN}"}
Set Headers {"Content-Type":"*/*"}
Delete ${apiRoot}/${apiName}/${apiVersion}/applications/${appInstanceId}/services/${serviceName}
${output}= Output response
Set Suite Variable ${response} ${output}
# Check Plaform IUT notifies the MEC Application instances
# [Documentation]
# ...
# [Arguments] ${instance_id} ${content}
Create a new subscription
[Arguments] ${appInstanceId} ${content}
Set Headers {"Accept":"application/json"}
Set Headers {"Content-Type":"application/json"}
Set Headers {"Authorization":"${TOKEN}"}
${file}= Catenate SEPARATOR= jsons/ ${content} .json
${body}= Get File ${file}
Post ${apiRoot}/${apiName}/${apiVersion}/applications/${appInstanceId}/subscriptions ${body}
${output}= Output response
Set Suite Variable ${response} ${output}
# TODO check how to send the message (isn't defined). Does it need to be tested as it's not defined?
Spawn Notification Server
[Arguments] ${payload_notification}
# // MEC 011, clause 6.4.2
# the IUT entity sends a notification_message containing
# body containing
# notificationType set to "SerAvailabilityNotification",
# services containing
# serName set to SERVICE_NAME
# _links containing
# subscription set to MP1_SUBSCRIPTION_A
# ;
# ;
# ;
# ;
# to the MEC_APP_Subscriber entity
${output} Spawn Web Server ${NOTIFICATION_SERVER_IP} ${NOTIFICATION_SERVER_PORT} ${NOTIFICATION_SERVER_TIMEOUT} ${NOTIFICATION_SERVER_HTTP_METHOD} ${NOTIFICATION_SERVER_URI} ${payload_notification}
${length} = Get Length ${output}
Set Suite Variable ${payload_notification} ${output}
Run Keyword If ${length} == 0 Skip
\ No newline at end of file
*** Variables ***
# Generic variables
${response} {}
#########Env variable for validating TCs locally with Mockoon
${SCHEMA} http
${HOST} 127.0.0.1
${PORT} 8081
${response} {}
${PORT} 8082
${TOKEN} Basic YWxhZGRpbjpvcGVuc2VzYW1l
${apiRoot}
${apiName} mec_service_mgmt
${apiVersion} v1
##Notification Server variables
${NOTIFICATION_SERVER_IP} 127.0.0.1
${NOTIFICATION_SERVER_PORT} 8888
${NOTIFICATION_SERVER_HTTP_METHOD} POST
${NOTIFICATION_SERVER_URI} /callback_url
${NOTIFICATION_SERVER_TIMEOUT} 5
# Specific variables
${APP_INSTANCE_ID} 5abe4782-2c70-4e47-9a4e-0ee3a1a0fd1f
${APP_INSTANCE_ID} f1e4d448-e277-496b-bf63-98391cfd20fb
${INSTANCE_ID} instance_id
${FAKE_INSTANCE_ID_VALUE} 5
${NON_EXISTENT_APP_INSTANCE_ID} NON_EXISTENT_APP_INSTANCE_ID
......
*** Variables ***
# Generic variables
${response} {}
####Env variable for the ETSI MEC Sandbox
${SCHEMA} https
${HOST} try-mec.etsi.org
${PORT} 443
#${TOKEN} Basic YWxhZGRpbjpvcGVuc2VzYW1l
${apiRoot} /<replace_with_what_provided_by_sandbox>/mep1
${apiName} mec_service_mgmt
${apiVersion} v1
# Specific variables
${APP_INSTANCE_ID} f1e4d448-e277-496b-bf63-98391cfd20fb
${INSTANCE_ID} instance_id
${FAKE_INSTANCE_ID_VALUE} 5
${NON_EXISTENT_APP_INSTANCE_ID} NON_EXISTENT_APP_INSTANCE_ID
${SERVICE_ID} e0deee2b-6e50-4f33-ab09-8bf0585025d3
${NON_EXISTENT_SERVICE_ID} NON_EXISTENT_SERVICE_ID
## this parameter should be the same as in jsons/ServiceInfo.json on param serName
${NEW_SERVICE_NAME} NEW_SERVICE_NAME
## this parameter should be the same as in jsons/ServiceInfoUpdated.json on param sversion
${SVC_NEW_VERSION} v2.0
${INVALID_ETAG} INVALID_ETAG
\ No newline at end of file
{
"subscriptionType": "SerAvailabilityNotificationSubscription",
"callbackReference": "http://127.0.0.1:8888/someendpoint",
"_links": {
"self": {
"href": "http://127.0.0.1:8888/someendpoint"
}
}
}
\ No newline at end of file
......@@ -3,6 +3,5 @@
"version": "0.1",
"state": "INACTIVE",
"serializer": "XML",
"serInstanceId": "3F897E85-ABCD-FFFF-A957-FCF0CCE649FD",
"transportId": "transportId"
}
\ No newline at end of file
#!/usr/bin/python3
from http.server import BaseHTTPRequestHandler, HTTPServer
import json, os
import logging
# Library version
__version__ = '0.0.1'
def import_notification_json(subscription_type):
notification_type = subscription_type.split("Subscription")[0]
file_path = "./jsons/"+notification_type+".json"
logging.info(file_path)
logging.info(os.listdir())
try:
with open(file_path, 'r') as json_file:
# Load the JSON data
data = json.load(json_file)
logging.info(data)
return data
except FileNotFoundError:
logging.error(f"Error: File not found at {file_path}")
class Server ( object ):
ROBOT_LIBRARY_VERSION = '0.0.1'
def spawn_web_server (self, host="127.0.0.1", port=8080, timeout=15, method="POST", endpoint="/callback_url", resp_body=None):
class GET_Server(BaseHTTPRequestHandler):
def __call__(self, *args, **kwargs):
"""Handle a request."""
super().__init__(*args, **kwargs)
def __init__(self, endpoint, resp_body):
self.resp_body = resp_body
self.endpoint = endpoint
def do_GET(self):
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
if self.path == self.endpoint:
self.wfile.write(json.dumps(self.resp_body).encode(encoding='utf_8'))
else:
self.wfile.write(json.dumps("wrong endpoint").encode(encoding='utf_8'))
class POST_Server(BaseHTTPRequestHandler):
def __call__(self, *args, **kwargs):
"""Handle a request."""
super().__init__(*args, **kwargs)
def __init__(self, endpoint, resp_body):
self.resp_body = resp_body
self.endpoint = endpoint
self.req_body = None
def do_POST(self):
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
#if self.path == self.endpoint:
# self.wfile.write(json.dumps(self.resp_body).encode(encoding='utf_8'))
#else:
# self.wfile.write(json.dumps("wrong endpoint").encode(encoding='utf_8'))
content_len = int(self.headers.get('Content-Length'))
post_body = self.rfile.read(content_len)
self.req_body=post_body
def get_req_body(self):
return self.req_body
def get_resp_body(self):
return self.resp_body
class PUT_Server(BaseHTTPRequestHandler):
def __call__(self, *args, **kwargs):
"""Handle a request."""
super().__init__(*args, **kwargs)
def __init__(self, endpoint, resp_body):
self.resp_body = resp_body
self.endpoint = endpoint
def do_PUT(self):
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
if self.path == self.endpoint:
self.wfile.write(json.dumps(self.resp_body).encode(encoding='utf_8'))
else:
self.wfile.write(json.dumps("wrong endpoint").encode(encoding='utf_8'))
class DELETE_Server(BaseHTTPRequestHandler):
def __call__(self, *args, **kwargs):
"""Handle a request."""
super().__init__(*args, **kwargs)
def __init__(self, endpoint, resp_body):
self.resp_body = resp_body
self.endpoint = endpoint
def do_DELETE(self):
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
if self.path == self.endpoint:
self.wfile.write(json.dumps(self.resp_body).encode(encoding='utf_8'))
else:
self.wfile.write(json.dumps("wrong endpoint").encode(encoding='utf_8'))
if method == "GET":
self.handler = GET_Server(endpoint, resp_body)
elif method == "POST":
self.handler = POST_Server(endpoint, resp_body)
elif method == "PUT":
self.handler = PUT_Server(endpoint, resp_body)
elif method == "DELETE":
self.handler = DELETE_Server(endpoint, resp_body)
else:
logging.info("Error, unknown endpoint")
exit(1)
self.app = HTTPServer((host, int(port)), self.handler)
self.app.timeout = int(timeout)
self.app.handle_request()
self.app.server_close()
logging.info(self.handler.get_resp_body())
## If a notification is received, then is returned. Otherwise an empty dictionary.
if(self.handler.get_req_body()!=None):
return json.loads(self.handler.get_req_body().decode("windows-1252"))
##OLD mechanism commented: if no response is received, then read the Notification JSON file and return it.
notification_json= import_notification_json(self.handler.get_resp_body())
#return notification_json ##Decomment if you want to use the notification read from file
return {}
{
"title": "SerAvailabilityNotificationSubscription",
"required": [
"subscriptionType",
"callbackReference",
"_links"
],
"type": "object",
"properties": {
"subscriptionType": {
"type": "string",
"description": "Shall be set to SerAvailabilityNotificationSubscription.",
"examples": [
"SerAvailabilityNotificationSubscription"
]
},
"callbackReference": {
"type": "string",
"description": "URI selected by the MEC application instance to receive notifications on the subscribed MEC service availability information. This shall be included in both the request and the response."
},
"_links": {
"title": "Self",
"required": [
"self"
],
"type": "object",
"properties": {
"self": {
"title": "LinkType",
"type": "object",
"properties": {
"href": {
"type": "string",
"description": "URI referring to a resource",
"examples": [
"/mecSerMgmtApi/example"
]
}
},
"description": "This type represents a type of link and may be referenced from data structures"
}
},
"description": "Self-referring URI."
},
"filteringCriteria": {
"title": "SerAvailabilityNotificationSubscription.FilteringCriteria",
"type": "object",
"properties": {
"serInstanceIds": {
"type": "array",
"items": {
"type": "string"
},
"description": "Identifiers of service instances about which to report events."
},
"serNames": {
"type": "array",
"items": {
"type": "string"
},
"description": "Names of services about which to report events."
},
"serCategories": {
"type": "array",
"items": {
"title": "CategoryRef",
"required": [
"href",
"id",
"name",
"version"
],
"type": "object",
"properties": {
"href": {
"type": "string",
"description": "Reference of the catalogue",
"examples": [
"/example/catalogue1"
]
},
"id": {
"type": "string",
"description": "Unique identifier of the category",
"examples": [
"id12345"
]
},
"name": {
"type": "string",
"description": "Name of the category, example values include RNI, Location & Bandwidth Management",
"examples": [
"RNI"
]
},
"version": {
"type": "string",
"description": "Category version",
"examples": [
"version1"
]
}
},
"description": "This type represents the category reference"
},
"description": "Categories of services about which to report events."
},
"states": {
"type": "array",
"items": {
"title": "ServiceState",
"enum": [
"ACTIVE",
"INACTIVE",
"SUSPENDED"
],
"type": "string",
"description": "This enumeration defines the possible states of a service.",
"examples": [
"ACTIVE"
]
},
"description": "States of the services about which to report events. If the event is a state change, this filter represents the state after the change."
},
"isLocal": {
"type": "boolean",
"description": "Indicate whether the service is located in the same locality (as defined by scopeOfLocality) as the consuming MEC application.",
"examples": [
true
]
}
},
"description": "Filtering criteria to match services for which events are requested to be reported. If absent, matches all services. All child attributes are combined with the logical \"AND\" operation."
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment