Sonar corrections. Unit tests and code coverage added 95/4695/1
authorBjornMagnussonXA <bjorn.magnusson@est.tech>
Thu, 3 Sep 2020 13:42:49 +0000 (15:42 +0200)
committerBjornMagnussonXA <bjorn.magnusson@est.tech>
Thu, 10 Sep 2020 08:44:13 +0000 (10:44 +0200)
Not used sim verion 1.1.x-alpha.2 removed.

Issue-ID: NONRTRIC-279

Signed-off-by: BjornMagnussonXA <bjorn.magnusson@est.tech>
Change-Id: I75cb200902da21a7eb2d0efabaa88b32d6695751

23 files changed:
near-rt-ric-simulator/README.md
near-rt-ric-simulator/api/1.1.x-alpha.2/a1-openapi.yaml [deleted file]
near-rt-ric-simulator/src/1.1.x-alpha.2/a1.py [deleted file]
near-rt-ric-simulator/src/1.1.x-alpha.2/main.py [deleted file]
near-rt-ric-simulator/src/1.1.x-alpha.2/var_declaration.py [deleted file]
near-rt-ric-simulator/src/OSC_2.1.0/a1.py
near-rt-ric-simulator/src/OSC_2.1.0/main.py
near-rt-ric-simulator/src/STD_1.1.3/a1.py
near-rt-ric-simulator/src/STD_1.1.3/callBack.py
near-rt-ric-simulator/src/STD_1.1.3/main.py
near-rt-ric-simulator/src/common/maincommon.py
near-rt-ric-simulator/test/1.1.x-alpha.2/build_and_start.sh [deleted file]
near-rt-ric-simulator/test/1.1.x-alpha.2/commands.sh [deleted file]
near-rt-ric-simulator/test/1.1.x-alpha.2/example_files/policy_instance_1_STD_QoSNudging_0.2.0.json [deleted file]
near-rt-ric-simulator/test/1.1.x-alpha.2/example_files/policy_instance_1_bis_STD_QoSNudging_0.2.0.json [deleted file]
near-rt-ric-simulator/test/1.1.x-alpha.2/example_files/policy_instance_2_STD_QoSNudging_0.2.0.json [deleted file]
near-rt-ric-simulator/test/1.1.x-alpha.2/example_files/policy_type_STD_QoSNudging_0.2.0.json [deleted file]
near-rt-ric-simulator/test/OSC_2.1.0/basic_test.sh
near-rt-ric-simulator/test/STD_1.1.3/basic_test.sh
near-rt-ric-simulator/test/common/compare_json.py
near-rt-ric-simulator/tests/OSC_2.1.0/test_osc_2_1_0.py [new file with mode: 0644]
near-rt-ric-simulator/tests/STD_1.1.3/test_std_1_1_3.py [new file with mode: 0644]
tox.ini

index a55d8d7..1789ce1 100644 (file)
@@ -7,7 +7,6 @@ The simulator supports multiple A1 interface versions (version of the open API y
 | --------------------- | ------------------- |
 | OSC 2.1.0,            |      OSC\_2.1.0     |
 | A1 Standard 1.1.3,    |      STD\_1.1.3     |
-| 1.1.x-alpha.2 ,       |      1.1.x-alpha.2  |
 
 All versions are supported by the same container, see section 'Configuring the simulator' below for details about how to the start the simulator with the intended version id.
 
@@ -107,39 +106,6 @@ URIs for admin operations:
 
 
 
-# Supported operations in simulator 1.1.x-alpha.2
-
-For the complete yaml specification, see [a1-openapi.yaml](../near-rt-ric-simulator/api/1.1.x-alpha.2/a1-openapi.yaml).
-
-The available requests and the addresses are currently:
-| Function              | Path and parameters |
-| --------------------- | ------------------- |
-|  GET all policy identities (respectively for a policy type if query parameter used) | http://localhost:8085/A1-P/v1/policies?policyTypeId={policyTypeId} |
-|  PUT a policy instance(create or update it) | http://localhost:8085/A1-P/v1/policies/{policyId}?policyTypeId={policyTypeId} |
-|  GET a policy | http://localhost:8085/A1-P/v1/policies/{policyId} |
-|  DELETE a policy instance | http://localhost:8085/A1-P/v1/policies/{policyId} |
-|  GET a policy status | http://localhost:8085/A1-P/v1/policystatus |
-|  GET all policy types | http://localhost:8085/A1-P/v1/policytypes |
-|  GET the schemas for a policy type | http://localhost:8085/A1-P/v1/policytypes/{policyTypeId} |
-
-Nota Bene: It could happen that this page is not updated as soon as the yaml file is. The yaml file can be found under /near-rt-ric-simulator/a1-openapi.yaml.
-
-For the documentation of the admin API, see [1.1.x-alpha.2](https://docs.o-ran-sc.org/projects/o-ran-sc-sim-a1-interface/en/latest/simulator-api.html#x-alpha-2).
-
-Additionally, there are requests that are defined in main.py as an administrative API. The goal is to handle information that couldn't be handled using the A1 interface. The available requests and the addresses are currently:
-| Function              | Path and parameters |
-| --------------------- | ------------------- |
-|  GET, a basic healthcheck | http://localhost:8085/ |
-|  PUT a policy type | http://localhost:8085/policytypes/{policyTypeId} |
-|  DELETE a policy type | http://localhost:8085/policytypes/{policyTypeId} |
-|  DELETE all policy instances | http://localhost:8085/deleteinstances |
-|  DELETE all policy types | http://localhost:8085/deletetypes |
-|  PUT a status to a policy instance with an enforceStatus parameter only | http://localhost:8085/{policyId}/{enforceStatus} |
-|  PUT a status to a policy instance with both enforceStatus and enforceReason | http://localhost:8085/{policyId}/{enforceStatus}/{enforceReason} |
-|  GET a counter  <br> (counter-name: 'num\_instances', 'num\_types', 'interface' or 'remote\_hosts') | http://localhost:8085/counter/{counter-name} |
-
-The backend server publishes live API documentation at the URL `http://localhost:8085/A1-P/v1/ui/`
-
 # Configuring the simulator
 An env variable, A1\_VERSION need to be passed to the container at start to select the desired interface version. The variable shall be set to one of the version-ids shown in the table in the first section. For example A1\_VERSIION=STD\_1.1.3.
 An env variable, REMOTE_HOSTS_LOGGING, can be set (any value is ok) and the the counter remote\_hosts will log the host names of all remote hosts that has accessed the A1 URIs. If host names cannot be resolved, the ip address of the remote host is logged instead. This logging is default off so must be configured to be enabled. If not configured, the counter remote\_hosts will return a fixed text indicating that host name logging is not enabled. Use this feature with caution, remote host lookup may take time in certain environments.
@@ -178,6 +144,8 @@ With certificate dir mounted  "--volume /PATH_TO_CERT_DIR/certificate:/usr/src/a
 The openapi specifications are stored in the 'api/&lt;version&gt;/'. If adding/replacing with a new file, make sure to copy the 'operationId' parameter for each operation to the new file.
 
 # Start and test of the simulator
+See also 'Basic test and code coverage'.
+
 First, download the sim/a1-interface repo on gerrit:
 git clone "https://gerrit.o-ran-sc.org/oransc/sim/a1-interface"
 
@@ -195,9 +163,19 @@ Note, the default port is 8085 for http and 8185 for https. When running the sim
 In a second terminal, go to the same folder and run the basic test script, basic\_test.sh nonsecure|secure or commands.sh nonsecure|secure depending on version.
 This script runs a number of tests towards the simulator to make sure it works properply.
 
-Only for version 1.1.x-alpha.2
-Let the simulator run in one terminal; in another terminal, one can run the command ./commands.sh nonsecure|secure. It contains the main requests, and will eventually leave the user with a policy type STD\_QoSNudging\_0.2.0 and a policy instance pi1 with an enforceStatus set to NOT\_ENFORCED and an enforce Reason set to 300.
-All the response codes should be 20X, otherwise something went wrong.
+# Basic test and code coverage
+
+Basic test, or unit test, using a python script is also supported. This test basically the same thing as the bash script mentioned in the section above. Follow the instruction of how to clone the repo described in that section.
+Only http is tested as the internal flask server is only using http (https is part of the webserver inteface).
+
+Navigate to 'near-rt-ric-simulator/tests'. This location contains one dir for each simulator version. Choose the version to test and go to that sub dir.
+
+Use 'python3 -m unittest' to run unit test only with no coverage check
+
+Or use 'coverage run  -m unittest' to run unit test and produce coverage data.
+List coverage data by 'coverage report -m --include=../../*' - the include flag makes the list to only contain coverage data from the simulator python file.
+
+To use the 'coverage' cmd, coverage need to be installed use 'pip install coverage'
 
 ## License
 
diff --git a/near-rt-ric-simulator/api/1.1.x-alpha.2/a1-openapi.yaml b/near-rt-ric-simulator/api/1.1.x-alpha.2/a1-openapi.yaml
deleted file mode 100644 (file)
index 223d1bd..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-openapi: 3.0.0
-info:
-  title: 'A1-P Policy Management Service'
-  version: 1.1.x-alpha.2
-  description: |
-    API for Policy Management Service.
-    © 2019, O-RAN Alliance.
-    All rights reserved.
-externalDocs:
-  description: 'ORAN-WG2.A1.AP-v01.01 A1 interface: Application protocol'
-  url: 'https://www.o-ran.org/specifications'
-servers:
-  - url: '{apiRoot}/A1-P/v1'
-    variables:
-      apiRoot:
-        default: 'https://example.com'
-        description: 'apiRoot as defined in clause 4.2.1 in ORAN-WG2.A1.AP'
-paths:
-  '/policies':
-    get:
-      operationId: a1.get_all_policy_identities
-      description: 'Get all policy identities'
-      tags:
-      - All Policy Identities
-      parameters:
-        - name: policyTypeId
-          in: query
-          required: false
-          schema:
-            "$ref": "#/components/schemas/PolicyTypeId"
-      responses:
-        200:
-          description: 'Array of all policy identities'
-          content:
-            application/json:
-              schema:
-                type: array
-                items:
-                  "$ref": "#/components/schemas/PolicyId"
-                minItems: 0
-        429:
-          "$ref": "#/components/responses/429-TooManyRequests"
-        503:
-          "$ref": "#/components/responses/503-ServiceUnavailable"
-
-  '/policies/{policyId}':
-    parameters:
-      - name: policyId
-        in: path
-        required: true
-        schema:
-          "$ref": "#/components/schemas/PolicyId"
-    put:
-      operationId: a1.put_policy
-      description: 'Create, or update, a policy'
-      tags:
-      - Individual Policy Object
-      parameters:
-        - name: policyTypeId
-          in: query
-          required: false
-          schema:
-            "$ref": "#/components/schemas/PolicyTypeId"
-      requestBody:
-        content:
-          application/json:
-            schema:
-              "$ref": "#/components/schemas/PolicyObject"
-      responses:
-        200:
-          description: 'The policy was updated'
-          content:
-            application/json:
-              schema:
-                "$ref": "#/components/schemas/PolicyObject"
-        201:
-          description: 'The policy was created'
-          content:
-            application/json:
-              schema:
-                "$ref": "#/components/schemas/PolicyObject"
-          headers:
-            Location:
-              description: 'Contains the URI of the created policy'
-              required: true
-              schema:
-                type: string
-        400:
-          "$ref": "#/components/responses/400-BadRequest"
-        429:
-          "$ref": "#/components/responses/429-TooManyRequests"
-        503:
-          "$ref": "#/components/responses/503-ServiceUnavailable"
-        507:
-          "$ref": "#/components/responses/507-InsufficientStorage"
-    get:
-      operationId: a1.get_policy
-      description: 'Query a policy'
-      tags:
-      - Individual Policy Object
-      responses:
-        200:
-          description: 'The requested policy'
-          content:
-            application/json:
-              schema:
-                "$ref": "#/components/schemas/PolicyObject"
-        404:
-          "$ref": "#/components/responses/404-NotFound"
-        429:
-          "$ref": "#/components/responses/429-TooManyRequests"
-        503:
-          "$ref": "#/components/responses/503-ServiceUnavailable"
-    delete:
-      operationId: a1.delete_policy
-      description: 'Delete a policy'
-      tags:
-      - Individual Policy Object
-      responses:
-        204:
-          description: 'The policy was deleted'
-        404:
-          "$ref": "#/components/responses/404-NotFound"
-        429:
-          "$ref": "#/components/responses/429-TooManyRequests"
-        503:
-          "$ref": "#/components/responses/503-ServiceUnavailable"
-
-  '/policystatus/{policyId}':
-    parameters:
-      - name: policyId
-        in: path
-        required: true
-        schema:
-          "$ref": "#/components/schemas/PolicyId"
-    get:
-      operationId: a1.get_policy_status
-      description: 'Query a policy status'
-      tags:
-      - Individual Policy Status Object
-      responses:
-        200:
-          description: 'The requested policy status'
-          content:
-            application/json:
-              schema:
-                "$ref": "#/components/schemas/PolicyStatusObject"
-        404:
-          "$ref": "#/components/responses/404-NotFound"
-        429:
-          "$ref": "#/components/responses/429-TooManyRequests"
-        503:
-          "$ref": "#/components/responses/503-ServiceUnavailable"
-
-  '/policytypes':
-    get:
-      operationId: a1.get_all_policytypes_identities
-      description: 'Get all policy type identities'
-      tags:
-      - All Policy Type Identities
-      responses:
-        200:
-          description: 'Array of all policy type identities'
-          content:
-            application/json:
-              schema:
-                type: array
-                items:
-                  "$ref": "#/components/schemas/PolicyTypeId"
-                minItems: 0
-        429:
-          "$ref": "#/components/responses/429-TooManyRequests"
-        503:
-          "$ref": "#/components/responses/503-ServiceUnavailable"
-
-  '/policytypes/{policyTypeId}':
-    parameters:
-      - name: policyTypeId
-        in: path
-        required: true
-        schema:
-          "$ref": "#/components/schemas/PolicyTypeId"
-    get:
-      operationId: a1.get_policytypes
-      description: 'Get the schemas for a policy type'
-      tags:
-      - Individual Policy Type
-      responses:
-        200:
-          description: 'The policy type schemas'
-          content:
-            application/json:
-              schema:
-                "$ref": "#/components/schemas/PolicyTypeObject"
-        404:
-          "$ref": "#/components/responses/404-NotFound"
-        429:
-          "$ref": "#/components/responses/429-TooManyRequests"
-        503:
-          "$ref": "#/components/responses/503-ServiceUnavailable"
-
-components:
-  schemas:
-    #
-    # Representation objects
-    #
-    PolicyObject:
-      description: 'A generic policy object that can be used to transport any policy. Additionally, a policy shall be valid according to the schema of its specific policy type.'
-      type: object
-
-    PolicyStatusObject:
-      description: 'A generic policy status object that can be used to transport any policy status. Additionally, a policy status shall be valid according to the schema of its specific policy type.'
-      type: object
-
-    PolicyTypeObject:
-      description: 'A definition of a policy type, i.e. the schemas for a policy respectively its status'
-      type: object
-      properties:
-        policySchema:
-          "$ref": "#/components/schemas/JsonSchema"
-        statusSchema:
-          "$ref": "#/components/schemas/JsonSchema"
-      required:
-        - policySchema
-
-    ProblemDetails:
-      description: 'A problem detail to carry details in a HTTP response according to RFC 7807 extended with A1 specific attributes'
-      type: object
-      properties:
-        type:
-          type: string
-        title:
-          type: string
-        status:
-          type: number
-        detail:
-          type: string
-        instance:
-          type: string
-        cause:
-          type: string
-        invalidParams:
-          type: array
-          items:
-            "$ref": "#/components/schemas/InvalidParam"
-          minItems: 1
-
-    #
-    # Structured data types
-    #
-    InvalidParam:
-      description: 'Used in a ProblemDetails to indicate a specific invalid parameter'
-      type: object
-      properties:
-        param:
-          type: string
-        reason:
-          type: string
-      required:
-        - param
-
-    #
-    # Simple data types
-    #
-    JsonSchema:
-      description: 'A JSON schema following http://json-schema.org/draft-07/schema'
-      type: object
-
-    PolicyId:
-      description: 'Policy identifier assigned by the A1-P Consumer when a policy is created'
-      type: string
-
-    PolicyTypeId:
-      description: 'Policy type identifier assigned by the A1-P Provider'
-      type: string
-
-  responses:
-    400-BadRequest:
-      description: 'Object in payload not properly formulated or not related to the method'
-      content:
-        application/problem+json:
-          schema:
-            "$ref": "#/components/schemas/ProblemDetails"
-
-    404-NotFound:
-      description: 'No resource found at the URI'
-      content:
-        application/problem+json:
-          schema:
-            "$ref": "#/components/schemas/ProblemDetails"
-
-    405-MethodNotAllowed:
-      description: 'Method not allowed for the URI'
-      content:
-        application/problem+json:
-          schema:
-            "$ref": "#/components/schemas/ProblemDetails"
-
-    429-TooManyRequests:
-      description: 'Too many requests have been sent in a given amount of time'
-      content:
-        application/problem+json:
-          schema:
-            "$ref": "#/components/schemas/ProblemDetails"
-
-    503-ServiceUnavailable:
-      description: 'The provider is currently unable to handle the request due to a temporary overload'
-      content:
-        application/problem+json:
-          schema:
-            "$ref": "#/components/schemas/ProblemDetails"
-
-    507-InsufficientStorage:
-      description: 'The method could not be performed on the resource because the provider is unable to store the representation needed to successfully complete the request'
-      content:
-        application/problem+json:
-          schema:
-            "$ref": "#/components/schemas/ProblemDetails"
diff --git a/near-rt-ric-simulator/src/1.1.x-alpha.2/a1.py b/near-rt-ric-simulator/src/1.1.x-alpha.2/a1.py
deleted file mode 100644 (file)
index b326d10..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-#  ============LICENSE_START===============================================
-#  Copyright (C) 2020 Nordix Foundation. All rights reserved.
-#  ========================================================================
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#  ============LICENSE_END=================================================
-#
-
-import copy
-import datetime
-import json
-import logging
-
-from connexion import NoContent
-from flask import Flask, escape, request, make_response
-from jsonschema import validate
-from random import random, choice
-from var_declaration import policy_instances, policy_types, policy_status, policy_type_per_instance, hosts_set
-from maincommon import *
-
-def get_all_policy_identities():
-  extract_host_name(hosts_set, request)
-  if len(request.args) == 0:
-    return(list(policy_instances.keys()), 200)
-  elif 'policyTypeId' in request.args:
-    policyTypeId = request.args.get('policyTypeId')
-    if policyTypeId not in list(policy_types.keys()):
-      return(set_error(None, "The policy type provided does not exist.", 400, "The policy type " + data["policyTypeId"] + " is not defined as a policy type.", None, None, "policyTypeId", None))
-    else:
-      return(list({key for key in policy_instances.keys() if policy_type_per_instance[key]==policyTypeId}), 200)
-  else:
-    return(send_error_code(request.args))
-
-def put_policy(policyId):
-  extract_host_name(hosts_set, request)
-  data = request.data.decode("utf-8")
-  data = data.replace("'", "\"")
-  data = json.loads(data)
-  ps = {}
-  if 'policyTypeId' in request.args:
-    policyTypeId = request.args.get('policyTypeId')
-
-    if policyTypeId not in list(policy_types.keys()):
-      return(set_error(None, "The policy type provided does not exist.", 400, "The policy type " + policyTypeId + " is not defined as a policy type.", None, None, "policyTypeId", None))
-
-    policy_schema = policy_types[policyTypeId]["policySchema"]
-    try:
-      validate(instance=data, schema=policy_schema)
-    except:
-      return(set_error(None, "The json does not validate against the schema.", 400, None, None, None, None, None))
-
-    for i in list(policy_instances.keys()):
-      if policyId != i and \
-         data == policy_instances[i] and \
-         policyTypeId == policy_type_per_instance[i]:
-        return(set_error(None, "The policy already exists with a different id.", 400, "No action has been taken. The id of the existing policy instance is: " + i + ".", None, None, None, None))
-
-  if policyId in list(policy_instances.keys()):
-    if data["scope"] != policy_instances[policyId]["scope"]:
-      return(set_error(None, "The policy already exists with a different scope.", 400, "The policy put involves a modification of the existing scope, which is not allowed.", None, None, "scope", None))
-
-  if 'code' in request.args:
-    return(send_error_code(request.args))
-
-  if policyId in policy_instances.keys():
-    code = 201
-  else:
-    code = 200
-
-  policy_instances[policyId] = data
-  policy_status[policyId] = set_status("UNDEFINED")
-  if 'policyTypeId' in request.args:
-    status_schema = policy_types[policyTypeId]["statusSchema"]
-    try:
-      validate(instance=policy_status[policyId], schema=status_schema)
-    except:
-      return(set_error(None, "The json does not validate against the status schema.", 400, None, None, None, None, None))
-    policy_type_per_instance[policyId] = policyTypeId
-  else:
-    policy_type_per_instance[policyId] = "UNDEFINED"
-
-  response = make_response(policy_instances[policyId], code)
-  if code == 201:
-    response.headers['Location'] = "http://localhost:8085/A1-P/v1/policies/" + policyId
-  return response
-
-def set_status(*args):
-  ps = {}
-  ps["enforceStatus"] = args[0]
-  if len(args) == 2:
-    ps["enforceReason"] = args[1]
-  if len(args) > 2:
-    return(set_error(None, "Too many arguments", 400, "There should be no more than two status arguments: enforceStatus and enforceReason", None, None, None, None))
-  return ps
-
-def get_policy(policyId):
-  extract_host_name(hosts_set, request)
-  if len(request.args) == 0:
-    if policyId in policy_instances.keys():
-      res = policy_instances[policyId]
-      res["enforceStatus"] = policy_status[policyId]["enforceStatus"]
-      return(res, 200)
-    else:
-      return(set_error(None, "The requested policy does not exist.", 404, None, None, None, "policyId", None))
-  else:
-    return(send_error_code(request.args))
-
-def delete_policy(policyId):
-  extract_host_name(hosts_set, request)
-  if len(request.args) == 0:
-    if policyId in policy_instances.keys():
-      policy_instances.pop(policyId)
-      policy_status.pop(policyId)
-      policy_type_per_instance.pop(policyId)
-      return(None, 204)
-    else:
-      return(set_error(None, "The policy identity does not exist.", 404, "No policy instance has been deleted.", None, None, "policyId", None))
-  else:
-    return(send_error_code(request.args))
-
-def get_policy_status(policyId):
-  extract_host_name(hosts_set, request)
-  if len(request.args) == 0:
-    if policyId in policy_instances.keys():
-      return(policy_status[policyId], 200)
-    else:
-      return(set_error(None, "The policy identity does not exist.", 404, "There is no existing policy instance with the identity: " + policyId, None, None, "policyId", None))
-  else:
-    return(send_error_code(request.args))
-
-def get_all_policytypes_identities():
-  extract_host_name(hosts_set, request)
-  if len(request.args) == 0:
-    return(list(policy_types.keys()), 200)
-  else:
-    return(send_error_code(request.args))
-
-def get_policytypes(policyTypeId):
-  extract_host_name(hosts_set, request)
-  if len(request.args) == 0:
-    if policyTypeId in policy_types.keys():
-      return(policy_types[policyTypeId], 200)
-    else:
-      return(set_error(None, "The requested policy type does not exist.", 404, None, None, None, "policyTypeId", None))
-  else:
-    return(send_error_code(request.args))
-
-def set_error(type_of, title, status, detail, instance, cause, param, reason):
-  error = {}
-  params = {}
-  if type_of is not None:
-    error["type"] = type_of
-  if title is not None:
-    error["title"] = title
-  if status is not None:
-    error["status"] = status
-  if detail is not None:
-    error["detail"] = detail
-  if instance is not None:
-    error["instance"] = instance
-  if cause is not None:
-    error["cause"] = cause
-  if param is not None:
-    params["param"] = param
-  if reason is not None:
-    params["reason"] = reason
-  if params:
-    error["invalidParams"] = params
-  return(error, error["status"])
-
-def send_error_code(args):
-  if 'code' in args.keys():
-    code = args['code']
-    if code == '405':
-      return(set_error(None, "Method not allowed", 405, "Method not allowed for the URI", None, None, None, None))
-    elif code == '429':
-      return(set_error(None, "Too many requests", 429, "Too many requests have been sent in a given amount of time", None, None, None, None))
-    elif code == '507':
-      return(set_error(None, "Insufficient storage", 507, "The method could not be performed on the resource because the provider is unable to store the representation needed to successfully complete the request", None, None, None, None))
-    elif code == '503':
-      return(set_error(None, "Service unavailable", 503, "The provider is currently unable to handle the request due to a temporary overload", None, None, None, None))
-    else:
-      return(set_error(None, "Not found", 400, "Object in payload not properly formulated or not related to the method", None, None, None, None))
-  else:
-    return(set_error(None, "Not found", 404, "No resource found at the URI", None, None, None, None))
diff --git a/near-rt-ric-simulator/src/1.1.x-alpha.2/main.py b/near-rt-ric-simulator/src/1.1.x-alpha.2/main.py
deleted file mode 100644 (file)
index ddba11e..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-#  ============LICENSE_START===============================================
-#  Copyright (C) 2020 Nordix Foundation. All rights reserved.
-#  ========================================================================
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#  ============LICENSE_END=================================================
-#
-
-import connexion
-import fileinput
-import json
-import sys
-import os
-
-
-from pathlib import Path
-from flask import Flask, escape, request, make_response
-from jsonschema import validate
-from var_declaration import policy_instances, policy_types, policy_status, policy_type_per_instance, hosts_set
-from maincommon import *
-
-check_apipath()
-
-app = connexion.App(__name__, specification_dir=apipath)
-
-@app.route('/policytypes/<string:policyTypeId>', methods=['PUT','DELETE'])
-def policy_type(policyTypeId):
-  if request.method == 'PUT':
-    data = request.data.decode("utf-8")
-    data = data.replace("'", "\"")
-    data = json.loads(data)
-    policy_types[policyTypeId] = data
-    return ('The policy type was either created or updated for policy type id: ' + policyTypeId, 200)
-  elif request.method == 'DELETE':
-    if policyTypeId in policy_types.keys():
-      policy_types.pop(policyTypeId)
-      return make_response("policy type successfully deleted for policy type id: " + policyTypeId, 200)
-    else:
-      return make_response("No policy type defined for the specified id", 404)
-
-@app.route('/', methods=['GET'])
-def test():
-    return("Everything is fine", 200)
-
-@app.route('/deleteinstances', methods=['DELETE'])
-def delete_instances():
-  global policy_instances
-  global policy_status
-  global policy_type_per_instance
-  policy_instances.clear()
-  policy_status.clear()
-  policy_type_per_instance.clear()
-  return("All policy instances deleted", 200)
-
-@app.route('/deletetypes', methods=['DELETE'])
-def delete_types():
-  global policy_types
-  policy_types.clear()
-  return("All policy types deleted", 200)
-
-@app.route('/<string:policyId>/<string:enforceStatus>', methods=['PUT'])
-def set_status(policyId, enforceStatus):
-  if policyId in policy_instances.keys():
-    if policy_type_per_instance[policyId] == "UNDEFINED":
-      ps = {}
-      ps["policyId"] = policyId
-      ps["enforceStatus"] = enforceStatus
-    else:
-      policy_type_id = policy_type_per_instance[policyId]
-      status_schema = policy_types[policy_type_id]["statusSchema"]
-      ps = {}
-      ps["policyId"] = policyId
-      ps["enforceStatus"] = enforceStatus
-      try:
-        validate(instance=ps, schema=status_schema)
-      except:
-        return(set_error(None, "The json does not validate against the status schema.", 400, None, None, None, None, None))
-  policy_status.pop(policyId)
-  policy_status[policyId] = ps
-  return("Status updated for policy: " + policyId, 200)
-
-@app.route('/<string:policyId>/<string:enforceStatus>/<string:enforceReason>', methods=['PUT'])
-def set_status_with_reason(policyId, enforceStatus, enforceReason):
-  if policyId in policy_instances.keys():
-    if policy_type_per_instance[policyId] == "UNDEFINED":
-      ps = {}
-      ps["policyId"] = policyId
-      ps["enforceStatus"] = enforceStatus
-      ps["enforceReason"] = enforceReason
-    else:
-      policy_type_id = policy_type_per_instance[policyId]
-      status_schema = policy_types[policy_type_id]["statusSchema"]
-      ps = {}
-      ps["policyId"] = policyId
-      ps["enforceStatus"] = enforceStatus
-      ps["enforceReason"] = enforceReason
-      try:
-        validate(instance=ps, schema=status_schema)
-      except:
-        return(set_error(None, "The json does not validate against the status schema.", 400, None, None, None, None, None))
-  policy_status.pop(policyId)
-  policy_status[policyId] = ps
-  return("Status updated for policy: " + policyId, 200)
-
-#Metrics function
-
-@app.route('/counter/<string:countername>', methods=['GET'])
-def getCounter(countername):
-    if (countername == "num_instances"):
-      return str(len(policy_instances)),200
-    elif (countername == "num_types"):
-      return str(len(policy_types)),200
-    elif (countername == "interface"):
-      p=Path(os.getcwd())
-      pp=p.parts
-      return str(pp[len(pp)-1]),200
-    elif (countername == "remote_hosts"):
-      hosts=",".join(hosts_set)
-      return str(hosts),200
-    else:
-      return "Counter name: "+countername+" not found.",404
-
-
-port_number = 2222
-if len(sys.argv) >= 2:
-  if isinstance(sys.argv[1], int):
-    port_number = sys.argv[1]
-
-app.add_api('a1-openapi.yaml')
-
-app.run(port=port_number, host="127.0.0.1", threaded=False)
\ No newline at end of file
diff --git a/near-rt-ric-simulator/src/1.1.x-alpha.2/var_declaration.py b/near-rt-ric-simulator/src/1.1.x-alpha.2/var_declaration.py
deleted file mode 100644 (file)
index f64c139..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#  ============LICENSE_START===============================================
-#  Copyright (C) 2020 Nordix Foundation. All rights reserved.
-#  ========================================================================
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#  ============LICENSE_END=================================================
-#
-
-policy_instances = {}
-policy_types = {}
-policy_status = {}
-policy_type_per_instance = {}
-hosts_set=set()
index 59c47ef..6ec59ff 100644 (file)
@@ -27,6 +27,8 @@ from var_declaration import policy_instances, policy_types, policy_status, polic
 from utils import calcFingerprint
 from maincommon import extract_host_name
 
+#Constsants
+APPL_JSON='application/json'
 
 # API Function: Health check
 def get_healthcheck():
@@ -63,7 +65,7 @@ def get_policy_type(policy_type_id):
   if (policy_type_id not in policy_types.keys()):
     return (None, 404)
 
-  return Response(json.dumps(policy_types[policy_type_id]), 200, mimetype='application/json')
+  return Response(json.dumps(policy_types[policy_type_id]), 200, mimetype=APPL_JSON)
 
 # API Function: Delete a policy type
 def delete_policy_type(policy_type_id):
@@ -96,8 +98,8 @@ def create_policy_type(policy_type_id):
     return r
 
   try:
-    val=int(policy_type_id)
-  except:
+    int(policy_type_id)
+  except Exception:
     return Response("The policy type id is not an int", 400, mimetype='text/plain')
 
   policy_type_id=str(policy_type_id)
@@ -109,7 +111,7 @@ def create_policy_type(policy_type_id):
   try:
     data = request.data
     data = json.loads(data)
-  except:
+  except Exception:
     return (None, 400)
 
   if (('name' not in data.keys()) or ('description' not in data.keys()) or ('policy_type_id' not in data.keys()) or ('create_schema' not in data.keys())):
@@ -153,7 +155,7 @@ def get_policy_instance(policy_type_id, policy_instance_id):
   if (policy_instance_id not in policy_instances[policy_type_id].keys()):
     return (None, 404)
 
-  return Response(json.dumps(policy_instances[policy_type_id][policy_instance_id]), 200, mimetype='application/json')
+  return Response(json.dumps(policy_instances[policy_type_id][policy_instance_id]), 200, mimetype=APPL_JSON)
 
 # API function: Delete a policy
 def delete_policy_instance(policy_type_id, policy_instance_id):
@@ -171,8 +173,8 @@ def delete_policy_instance(policy_type_id, policy_instance_id):
   if (policy_instance_id not in policy_instances[policy_type_id].keys()):
     return (None, 404)
 
-  fpPrevious=calcFingerprint(policy_instances[policy_type_id][policy_instance_id])
-  del policy_fingerprint[fpPrevious]
+  fp_previous=calcFingerprint(policy_instances[policy_type_id][policy_instance_id])
+  del policy_fingerprint[fp_previous]
   del policy_instances[policy_type_id][policy_instance_id]
   del policy_status[policy_instance_id]
 
@@ -194,31 +196,30 @@ def create_or_replace_policy_instance(policy_type_id, policy_instance_id):
   try:
     data = request.data
     data = json.loads(data)
-  except:
+  except Exception:
     return (None, 400)
 
   try:
     validate(instance=data, schema=policy_types[policy_type_id]['create_schema'])
-  except:
+  except Exception:
     return (None, 400)
 
-  fpPrevious=None
-  retcode=201
+  fp_previous=None
   if policy_instance_id in policy_instances[policy_type_id].keys():
     retcode=200
-    fpPrevious=calcFingerprint(policy_instances[policy_type_id][policy_instance_id])
+    fp_previous=calcFingerprint(policy_instances[policy_type_id][policy_instance_id])
   else:
     if (policy_instance_id in policy_fingerprint.values()):
       return (None, 400)
 
   fp=calcFingerprint(data)
   if (fp in policy_fingerprint.keys()):
-    id=policy_fingerprint[fp]
-    if (id != policy_instance_id):
+    p_id=policy_fingerprint[fp]
+    if (p_id != policy_instance_id):
       return (None, 400)
 
-  if (fpPrevious is not None):
-    del policy_fingerprint[fpPrevious]
+  if (fp_previous is not None):
+    del policy_fingerprint[fp_previous]
 
   policy_fingerprint[fp]=policy_instance_id
 
@@ -246,7 +247,7 @@ def get_policy_instance_status(policy_type_id, policy_instance_id):
   if (policy_instance_id not in policy_instances[policy_type_id].keys()):
     return (None, 404)
 
-  return Response(json.dumps(policy_status[policy_instance_id]), 200, mimetype='application/json')
+  return Response(json.dumps(policy_status[policy_instance_id]), 200, mimetype=APPL_JSON)
 
 # Helper: Create a response object if forced http response code is set
 def get_forced_response():
@@ -264,7 +265,7 @@ def do_delay():
     try:
       val=int(forced_settings['delay'])
       time.sleep(val)
-    except:
+    except Exception:
       return
   return
 
index 1bc6128..48fbe91 100644 (file)
@@ -25,9 +25,11 @@ from pathlib import Path
 from flask import Flask, escape, request, Response, jsonify
 from jsonschema import validate
 from var_declaration import policy_instances, policy_types, policy_status, policy_fingerprint, forced_settings, hosts_set
-from maincommon import *
+from maincommon import check_apipath, apipath, get_supported_interfaces_response, extract_host_name
 from time import sleep
 
+#Constants
+TEXT_PLAIN='text/plain'
 
 check_apipath()
 
@@ -37,7 +39,7 @@ app = connexion.FlaskApp(__name__, specification_dir=apipath)
 @app.route('/', methods=['GET'])
 def test():
 
-    return Response("OK", 200, mimetype='text/plain')
+    return Response("OK", 200, mimetype=TEXT_PLAIN)
 
 @app.route('/ip', methods=['GET'])
 def get_ip():
@@ -64,7 +66,7 @@ def deleteinstances():
   forced_settings['code']=None
   forced_settings['delay']=None
   policy_fingerprint.clear()
-  return Response("All policy instances deleted", 200, mimetype='text/plain')
+  return Response("All policy instances deleted", 200, mimetype=TEXT_PLAIN)
 
 #Delete all - all reset
 @app.route('/deleteall', methods=['POST'])
@@ -76,59 +78,59 @@ def deleteall():
   forced_settings['code']=None
   forced_settings['delay']=None
   policy_fingerprint.clear()
-  return Response("All policy instances and types deleted", 200, mimetype='text/plain')
+  return Response("All policy instances and types deleted", 200, mimetype=TEXT_PLAIN)
 
 #Load a policy type
 @app.route('/policytype', methods=['PUT'])
 def policytype():
 
-  policyTypeId=request.args.get('id')
-  if (policyTypeId is None):
-    return Response('Parameter <id> missing in request', status=400, mimetype='text/plain')
+  policy_type_id=request.args.get('id')
+  if (policy_type_id is None):
+    return Response('Parameter <id> missing in request', status=400, mimetype=TEXT_PLAIN)
   try:
-    val=int(policyTypeId)
-  except:
-    return Response("The policy type id is not an int", 400, mimetype='text/plain')
+    int(policy_type_id)
+  except Exception:
+    return Response("The policy type id is not an int", 400, mimetype=TEXT_PLAIN)
   try:
     data = request.data
     data = json.loads(data)
-  except:
-    return Response("The policy type is corrupt or missing", 400, mimetype='text/plain')
+  except Exception:
+    return Response("The policy type is corrupt or missing", 400, mimetype=TEXT_PLAIN)
 
   if ('name' not in data.keys() or 'description' not in data.keys() or 'policy_type_id' not in data.keys() or'create_schema' not in data.keys()):
-    return Response("The policy type missing atributes", 400, mimetype='text/plain')
+    return Response("The policy type missing atributes", 400, mimetype=TEXT_PLAIN)
 
   retcode=201
-  if (policyTypeId in policy_types.keys()):
+  if (policy_type_id in policy_types.keys()):
     retcode=200
-    if (len(policy_instances[policyTypeId]) > 0):
-      return Response("The policy type already exists and instances exists", 400, mimetype='text/plain')
+    if (len(policy_instances[policy_type_id]) > 0):
+      return Response("The policy type already exists and instances exists", 400, mimetype=TEXT_PLAIN)
 
-  policy_types[policyTypeId]=data
-  policy_instances[policyTypeId]={}
-  return Response("Policy type " + policyTypeId + " is OK.", retcode, mimetype='text/plain')
+  policy_types[policy_type_id]=data
+  policy_instances[policy_type_id]={}
+  return Response("Policy type " + policy_type_id + " is OK.", retcode, mimetype=TEXT_PLAIN)
 
 #Delete a policy type
 @app.route('/policytype', methods=['DELETE'])
 def del_policytype():
 
-  policyTypeId=request.args.get('id')
-  if (policyTypeId is None):
-    return Response('Parameter <id> missing in request', status=400, mimetype='text/plain')
+  policy_type_id=request.args.get('id')
+  if (policy_type_id is None):
+    return Response('Parameter <id> missing in request', status=400, mimetype=TEXT_PLAIN)
   try:
-    val=int(policyTypeId)
-  except:
-    return Response("The policy type id is not an int", 400, mimetype='text/plain')
+    int(policy_type_id)
+  except Exception:
+    return Response("The policy type id is not an int", 400, mimetype=TEXT_PLAIN)
 
-  if (policyTypeId in policy_types.keys()):
-    if (len(policy_instances[policyTypeId]) > 0):
-      return Response("The policy type already exists and instances exists", 400, mimetype='text/plain')
+  if (policy_type_id in policy_types.keys()):
+    if (len(policy_instances[policy_type_id]) > 0):
+      return Response("The policy type already exists and instances exists", 400, mimetype=TEXT_PLAIN)
 
-    del policy_types[policyTypeId]
-    del policy_instances[policyTypeId]
-    return Response("Policy type " + policyTypeId + " is OK.", 204, mimetype='text/plain')
+    del policy_types[policy_type_id]
+    del policy_instances[policy_type_id]
+    return Response("Policy type " + policy_type_id + " is OK.", 204, mimetype=TEXT_PLAIN)
 
-  return Response("Policy type " + policyTypeId + " not found.", 204, mimetype='text/plain')
+  return Response("Policy type " + policy_type_id + " not found.", 204, mimetype=TEXT_PLAIN)
 
 
 # Get all policy type ids
@@ -144,9 +146,9 @@ def forceresponse():
 
   try:
     forced_settings['code']=int(request.args.get('code'))
-  except:
+  except Exception:
     forced_settings['code']=None
-  return Response("Force response code: " + str(forced_settings['code']) + " set for one single A1 response", 200, mimetype='text/plain')
+  return Response("Force response code: " + str(forced_settings['code']) + " set for one single A1 response", 200, mimetype=TEXT_PLAIN)
 
 #Set force delay response, in seconds, for all A1 responses
 #/froceesponse?delay=<seconds>
@@ -155,9 +157,9 @@ def forcedelay():
 
   try:
     forced_settings['delay']=int(request.args.get('delay'))
-  except:
+  except Exception:
     forced_settings['delay']=None
-  return Response("Force delay: " + str(forced_settings['delay']) + " sec set for all A1 responses", 200, mimetype='text/plain')
+  return Response("Force delay: " + str(forced_settings['delay']) + " sec set for all A1 responses", 200, mimetype=TEXT_PLAIN)
 
 
 #Set status and reason
@@ -165,53 +167,54 @@ def forcedelay():
 @app.route('/status', methods=['PUT'])
 def setstatus():
 
-  policyId=request.args.get('policyid')
-  if (policyId is None):
-    return Response('Parameter <policyid> missing in request', status=400, mimetype='text/plain')
+  policy_id=request.args.get('policyid')
+  if (policy_id is None):
+    return Response('Parameter <policyid> missing in request', status=400, mimetype=TEXT_PLAIN)
 
-  if policyId not in policy_status.keys():
-    return Response('Policyid: '+policyId+' not found.', status=404, mimetype='text/plain')
+  if policy_id not in policy_status.keys():
+    return Response('Policyid: '+policy_id+' not found.', status=404, mimetype=TEXT_PLAIN)
   status=request.args.get('status')
   if (status is None):
-    return Response('Parameter <status> missing in request', status=400, mimetype='text/plain')
-  policy_status[policyId]["instance_status"]=status
+    return Response('Parameter <status> missing in request', status=400, mimetype=TEXT_PLAIN)
+  policy_status[policy_id]["instance_status"]=status
   msg = "Status set to "+status
   deleted_policy=request.args.get('deleted')
   if (deleted_policy is not None):
-    policy_status[policyId]["has_been_deleted"]=deleted_policy
+    policy_status[policy_id]["has_been_deleted"]=deleted_policy
     msg = msg + " and has_been_deleted set to "+deleted_policy
   created_at = request.args.get('created_at')
   if (created_at is not None):
-    policy_status[policyId]["created_at"]=created_at
+    policy_status[policy_id]["created_at"]=created_at
     msg = msg + " and created_at set to "+created_at
-  msg=msg + " for policy: " + policyId
-  return Response(msg, 200, mimetype='text/plain')
+  msg=msg + " for policy: " + policy_id
+  return Response(msg, 200, mimetype=TEXT_PLAIN)
 
 
 #Metrics function
 #Get a named counter
 @app.route('/counter/<string:countername>', methods=['GET'])
-def getCounter(countername):
+def getcounter(countername):
 
   if (countername == "num_instances"):
-    return Response(str(len(policy_fingerprint)), 200, mimetype='text/plain')
+    return Response(str(len(policy_fingerprint)), 200, mimetype=TEXT_PLAIN)
   elif (countername == "num_types"):
-    return Response(str(len(policy_instances)),200, mimetype='text/plain')
+    return Response(str(len(policy_instances)),200, mimetype=TEXT_PLAIN)
   elif (countername == "interface"):
     p=Path(os.getcwd())
     pp=p.parts
-    return Response(str(pp[len(pp)-1]),200, mimetype='text/plain')
+    return Response(str(pp[len(pp)-1]),200, mimetype=TEXT_PLAIN)
   elif (countername == "remote_hosts"):
     hosts=",".join(hosts_set)
     return str(hosts),200
   else:
-    return Response("Counter name: "+countername+" not found.",404, mimetype='text/plain')
+    return Response("Counter name: "+countername+" not found.",404, mimetype=TEXT_PLAIN)
 
 port_number = 2222
-if len(sys.argv) >= 2:
+if len(sys.argv) >= 2 :
   if isinstance(sys.argv[1], int):
     port_number = sys.argv[1]
 
 app.add_api('openapi.yaml')
 
-app.run(port=port_number, host="127.0.0.1", threaded=False)
\ No newline at end of file
+if __name__ == '__main__':
+  app.run(port=port_number, host="127.0.0.1", threaded=False)
\ No newline at end of file
index d234327..d7169b1 100644 (file)
@@ -26,11 +26,16 @@ from connexion import NoContent
 from flask import Flask, escape, request, Response, make_response
 from var_declaration import policy_instances, policy_status, callbacks, forced_settings, policy_fingerprint, hosts_set
 from utils import calcFingerprint
-from maincommon import *
+from maincommon import check_apipath, apipath, get_supported_interfaces_response, extract_host_name
+
+#Constsants
+APPL_JSON='application/json'
+APPL_PROB_JSON='application/problem+json'
 
 # API Function: Get all policy ids
 def get_all_policy_identities():
 
+  extract_host_name(hosts_set, request)
 
   if ((r := check_modified_response()) is not None):
     return r
@@ -48,25 +53,25 @@ def put_policy(policyId):
   try:
     data = request.data
     data = json.loads(data)
-  except:
+  except Exception:
     pjson=create_problem_json(None, "The policy is corrupt or missing.", 400, None, policyId)
-    return Response(json.dumps(pjson), 400, mimetype='application/problem+json')
+    return Response(json.dumps(pjson), 400, mimetype=APPL_PROB_JSON)
 
-  fpPrevious=None
+  fp_previous=None
   retcode=201
   if policyId in policy_instances.keys():
     retcode=200
-    fpPrevious=calcFingerprint(policy_instances[policyId])
+    fp_previous=calcFingerprint(policy_instances[policyId])
 
   fp=calcFingerprint(data)
   if (fp in policy_fingerprint.keys()):
-    id=policy_fingerprint[fp]
-    if (id != policyId):
+    p_id=policy_fingerprint[fp]
+    if (p_id != policyId):
       pjson=create_problem_json(None, "The policy json already exists.", 400, None, policyId)
-      return Response(json.dumps(pjson), 400, mimetype='application/problem+json')
+      return Response(json.dumps(pjson), 400, mimetype=APPL_PROB_JSON)
 
-  if (fpPrevious is not None):
-    del policy_fingerprint[fpPrevious]
+  if (fp_previous is not None):
+    del policy_fingerprint[fp_previous]
 
   policy_fingerprint[fp]=policyId
 
@@ -79,11 +84,11 @@ def put_policy(policyId):
   policy_status[policyId]=ps
 
   if (retcode == 200):
-    return Response(json.dumps(data), 200, mimetype='application/json')
+    return Response(json.dumps(data), 200, mimetype=APPL_JSON)
   else:
     headers={}
     headers['Location']='/A1-P/v1/policies/' + policyId
-    return Response(json.dumps(data), 201, headers=headers, mimetype='application/json')
+    return Response(json.dumps(data), 201, headers=headers, mimetype=APPL_JSON)
 
 # API Function: Get a policy
 def get_policy(policyId):
@@ -94,10 +99,10 @@ def get_policy(policyId):
     return r
 
   if policyId in policy_instances.keys():
-    return Response(json.dumps(policy_instances[policyId]), 200, mimetype='application/json')
+    return Response(json.dumps(policy_instances[policyId]), 200, mimetype=APPL_JSON)
 
   pjson=create_problem_json(None, "The requested policy does not exist.", 404, None, policyId)
-  return Response(json.dumps(pjson), 404, mimetype='application/problem+json')
+  return Response(json.dumps(pjson), 404, mimetype=APPL_PROB_JSON)
 
 # API Function: Delete a policy
 def delete_policy(policyId):
@@ -108,15 +113,15 @@ def delete_policy(policyId):
     return r
 
   if policyId in policy_instances.keys():
-    fpPrevious=calcFingerprint(policy_instances[policyId])
-    policy_fingerprint.pop(fpPrevious)
+    fp_previous=calcFingerprint(policy_instances[policyId])
+    policy_fingerprint.pop(fp_previous)
     policy_instances.pop(policyId)
     policy_status.pop(policyId)
     callbacks.pop(policyId)
-    return Response('', 204, mimetype='application/json')
+    return Response('', 204, mimetype=APPL_JSON)
 
   pjson=create_problem_json(None, "The policy identity does not exist.", 404, "No policy instance has been deleted.", policyId)
-  return Response(json.dumps(pjson), 404, mimetype='application/problem+json')
+  return Response(json.dumps(pjson), 404, mimetype=APPL_PROB_JSON)
 
 # API Function: Get status for a policy
 def get_policy_status(policyId):
@@ -127,17 +132,17 @@ def get_policy_status(policyId):
     return r
 
   if policyId in policy_instances.keys():
-    return Response(json.dumps(policy_status[policyId]), status=200, mimetype='application/json')
+    return Response(json.dumps(policy_status[policyId]), status=200, mimetype=APPL_JSON)
 
   pjson=create_problem_json(None, "The policy identity does not exist.", 404, "There is no existing policy instance with the identity: " + policyId, policyId)
-  return Response(json.dumps(pjson), 404, mimetype='application/problem+json')
+  return Response(json.dumps(pjson), 404, mimetype=APPL_PROB_JSON)
 
 # Helper: Create a response object if forced http response code is set
 def get_forced_response():
   if (forced_settings['code'] is not None):
     pjson=create_error_response(forced_settings['code'])
     forced_settings['code']=None
-    return Response(json.dumps(pjson), pjson['status'], mimetype='application/problem+json')
+    return Response(json.dumps(pjson), pjson['status'], mimetype=APPL_PROB_JSON)
   return None
 
 # Helper: Delay if delayed response code is set
@@ -146,9 +151,8 @@ def do_delay():
     try:
       val=int(forced_settings['delay'])
       time.sleep(val)
-    except:
+    except Exception:
       return
-  return
 
 # Helper: Check if response shall be delayed or a forced response shall be sent
 def check_modified_response():
index 728c8da..0e8e416 100644 (file)
@@ -18,7 +18,7 @@
 import json
 from flask import Flask, request, Response
 
-app = Flask(__name__)
+app = Flask(__name__) #NOSONAR
 
 #Check alive function
 @app.route('/', methods=['GET'])
@@ -33,7 +33,7 @@ def statustest():
   try:
     data = request.data
     data = json.loads(data)
-  except:
+  except Exception:
     return Response("The status data is corrupt or missing.", 400, mimetype='text/plain')
 
   return Response(json.dumps(data), 200, mimetype='application/json')
index ce0854e..b7ecdcd 100644 (file)
@@ -26,8 +26,10 @@ from pathlib import Path
 from flask import Flask, escape, request, Response
 from jsonschema import validate
 from var_declaration import policy_instances, policy_status, callbacks, forced_settings, policy_fingerprint, hosts_set
-from maincommon import *
+from maincommon import check_apipath, apipath, get_supported_interfaces_response, extract_host_name
 
+#Constants
+TEXT_PLAIN='text/plain'
 
 check_apipath()
 
@@ -37,7 +39,7 @@ app = connexion.App(__name__, specification_dir=apipath)
 @app.route('/', methods=['GET'])
 def test():
 
-  return Response("OK", 200, mimetype='text/plain')
+  return Response("OK", 200, mimetype=TEXT_PLAIN)
 
 #Return the current and all supported yamls for the this container
 @app.route('/container_interfaces', methods=['GET'])
@@ -55,7 +57,7 @@ def delete_instances():
   forced_settings['code']=None
   forced_settings['delay']=None
   policy_fingerprint.clear()
-  return Response("All policy instances deleted", 200, mimetype='text/plain')
+  return Response("All policy instances deleted", 200, mimetype=TEXT_PLAIN)
 
 #Delete all - all reset
 #(same as delete_instances but kept to in order to use the same interface as other version of the simulator)
@@ -70,9 +72,9 @@ def forceresponse():
 
   try:
     forced_settings['code']=request.args.get('code')
-  except:
+  except Exception:
     forced_settings['code']=None
-  return Response("Force response code: " + str(forced_settings['code']) + " set for one single A1 response", 200, mimetype='text/plain')
+  return Response("Force response code: " + str(forced_settings['code']) + " set for one single A1 response", 200, mimetype=TEXT_PLAIN)
 
 #Set force delay response, in seconds, for all A1 responses
 #/froceesponse?delay=<seconds>
@@ -81,9 +83,9 @@ def forcedelay():
 
   try:
     forced_settings['delay']=request.args.get('delay')
-  except:
+  except Exception:
     forced_settings['delay']=None
-  return Response("Force delay: " + str(forced_settings['delay']) + " sec set for all A1 responses", 200, mimetype='text/plain')
+  return Response("Force delay: " + str(forced_settings['delay']) + " sec set for all A1 responses", 200, mimetype=TEXT_PLAIN)
 
 
 #Set status and reason
@@ -91,14 +93,14 @@ def forcedelay():
 @app.route('/status', methods=['PUT'])
 def setstatus():
 
-  policyId=request.args.get('policyid')
-  if (policyId is None):
-    return Response('Parameter <policyid> missing in request', status=400, mimetype='text/plain')
-  if policyId not in policy_instances.keys():
-    return Response('Policyid: '+policyId+' not found.', status=404, mimetype='text/plain')
+  policy_id=request.args.get('policyid')
+  if (policy_id is None):
+    return Response('Parameter <policyid> missing in request', status=400, mimetype=TEXT_PLAIN)
+  if policy_id not in policy_instances.keys():
+    return Response('Policyid: '+policy_id+' not found.', status=404, mimetype=TEXT_PLAIN)
   status=request.args.get('status')
   if (status is None):
-    return Response('Parameter <status> missing in request', status=400, mimetype='text/plain')
+    return Response('Parameter <status> missing in request', status=400, mimetype=TEXT_PLAIN)
   reason=request.args.get('reason')
   ps = {}
   ps["enforceStatus"] = status
@@ -106,9 +108,9 @@ def setstatus():
   if (reason is not None):
     ps["enforceReason"] = reason
     msg=msg+" and "+reason
-  policy_status[policyId] = ps
-  msg=msg+" for policy: " + policyId
-  return Response(msg, 200, mimetype='text/plain')
+  policy_status[policy_id] = ps
+  msg=msg+" for policy: " + policy_id
+  return Response(msg, 200, mimetype=TEXT_PLAIN)
 
 #Send status
 #/status?policyid=<policyid>
@@ -116,19 +118,19 @@ def setstatus():
 def sendstatus():
   policyid=request.args.get('policyid')
   if (policyid is None):
-    return Response('Parameter <policyid> missing in request', status=400, mimetype='text/plain')
+    return Response('Parameter <policyid> missing in request', status=400, mimetype=TEXT_PLAIN)
 
   if (policyid not in policy_status.keys()):
-    return Response('Policyid: '+policyid+' not found.', status=404, mimetype='text/plain')
+    return Response('Policyid: '+policyid+' not found.', status=404, mimetype=TEXT_PLAIN)
 
   ps=policy_status[policyid]
   cb=callbacks[policyid]
   try:
-    resp=requests.post(cb,json=json.dumps(ps), verify=False)
+    resp=requests.post(cb,json=json.dumps(ps), verify=False) # NOSONAR
   except:
-    return Response('Post status failed, could not send to: '+str(cb), status=500, mimetype='text/plain')
+    return Response('Post status failed, could not send to: '+str(cb), status=500, mimetype=TEXT_PLAIN)
   if (resp.status_code<199 & resp.status_code > 299):
-    return Response('Post status failed with code: '+resp.status_code, status=500, mimetype='text/plain')
+    return Response('Post status failed with code: '+resp.status_code, status=500, mimetype=TEXT_PLAIN)
 
   data = resp.json()
   return Response(data, 200, mimetype='application/json')
@@ -140,29 +142,29 @@ def statustest():
   try:
     data = request.data
     data = json.loads(data)
-  except:
-    return Response("The status data is corrupt or missing.", 400, mimetype='text/plain')
+  except Exception:
+    return Response("The status data is corrupt or missing.", 400, mimetype=TEXT_PLAIN)
 
   return Response(json.dumps(data), 200, mimetype='application/json')
 
 #Metrics function
 #Get a named counter
 @app.route('/counter/<string:countername>', methods=['GET'])
-def getCounter(countername):
+def getcounter(countername):
 
   if (countername == "num_instances"):
-    return Response(str(len(policy_instances)), 200, mimetype='text/plain')
+    return Response(str(len(policy_instances)), 200, mimetype=TEXT_PLAIN)
   elif (countername == "num_types"):
-    return Response("0",200, mimetype='text/plain')
+    return Response("0",200, mimetype=TEXT_PLAIN)
   elif (countername == "interface"):
     p=Path(os.getcwd())
     pp=p.parts
-    return Response(str(pp[len(pp)-1]),200, mimetype='text/plain')
+    return Response(str(pp[len(pp)-1]),200, mimetype=TEXT_PLAIN)
   elif (countername == "remote_hosts"):
     hosts=",".join(hosts_set)
     return str(hosts),200
   else:
-    return Response("Counter name: "+countername+" not found.",404, mimetype='text/plain')
+    return Response("Counter name: "+countername+" not found.",404, mimetype=TEXT_PLAIN)
 
 port_number = 2222
 if len(sys.argv) >= 2:
@@ -171,4 +173,5 @@ if len(sys.argv) >= 2:
 
 app.add_api('STD_A1.yaml')
 
-app.run(port=port_number, host="127.0.0.1", threaded=False)
\ No newline at end of file
+if __name__ == '__main__':
+  app.run(port=port_number, host="127.0.0.1", threaded=False)
\ No newline at end of file
index 94a0b6d..7dc8024 100644 (file)
@@ -56,7 +56,7 @@ def extract_host_name(hosts_set, request):
         try:
             name, alias, addresslist = socket.gethostbyaddr(host_ip)
             hosts_set.add(name)
-        except Exception as e:
+        except Exception:
             hosts_set.add(host_ip)
     else:
         hosts_set.add("logging_of_remote_host_names_not_enabled")
diff --git a/near-rt-ric-simulator/test/1.1.x-alpha.2/build_and_start.sh b/near-rt-ric-simulator/test/1.1.x-alpha.2/build_and_start.sh
deleted file mode 100755 (executable)
index 8b8da57..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/bash
-
-#  ============LICENSE_START===============================================
-#  Copyright (C) 2020 Nordix Foundation. All rights reserved.
-#  ========================================================================
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#  ============LICENSE_END=================================================
-#
-
-# Script to build and start the container
-
-echo "Building image"
-cd ../../
-
-#Build the image
-docker build -t a1test .
-
-echo "Starting $1 mode"
-#Run the container in interactive mode, unsecure port 8085, secure port 8185.
-docker run -it -p 8085:8085 -p 8185:8185 -e A1_VERSION=1.1.x-alpha.2 -e ALLOW_HTTP=true -e REMOTE_HOSTS_LOGGING=1 --volume "$PWD/certificate:/usr/src/app/cert" a1test
-
-
diff --git a/near-rt-ric-simulator/test/1.1.x-alpha.2/commands.sh b/near-rt-ric-simulator/test/1.1.x-alpha.2/commands.sh
deleted file mode 100755 (executable)
index 2527898..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/bin/bash
-#  ============LICENSE_START===============================================
-#  Copyright (C) 2020 Nordix Foundation. All rights reserved.
-#  ========================================================================
-#  Licensed under the Apache License, Version 2.0 (the "License");
-#  you may not use this file except in compliance with the License.
-#  You may obtain a copy of the License at
-#
-#       http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing, software
-#  distributed under the License is distributed on an "AS IS" BASIS,
-#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#  See the License for the specific language governing permissions and
-#  limitations under the License.
-#  ============LICENSE_END=================================================
-#
-
-# Different commands for the simulator.
-# By running this, nothing should return an error.
-
-# Run the build_and_start with the same arg as this script
-if [ $# -ne 1 ]; then
-    echo "Usage: ./commands.sh nonsecure|secure"
-    exit 1
-fi
-if [ "$1" != "nonsecure" ] && [ "$1" != "secure" ]; then
-    echo "Usage: ./commands.sh nonsecure|secure"
-    exit 1
-fi
-
-if [ $1 == "nonsecure" ]; then
-    #Default http port for the simulator
-    PORT=8085
-    # Set http protocol
-    HTTPX="http"
-else
-    #Default https port for the simulator
-    PORT=8185
-    # Set https protocol
-    HTTPX="https"
-fi
-
-# Make a test
-curl -vk "$HTTPX://localhost:$PORT/"
-
-# PUT a policy type STD_QoSNudging_0.2.0
-curl -X PUT -vk "$HTTPX://localhost:$PORT/policytypes/STD_QoSNudging_0.2.0" -H "accept: application/json" -H "Content-Type: application/json" --data-binary @example_files/policy_type_STD_QoSNudging_0.2.0.json
-
-# GET policy types
-curl -vk "$HTTPX://localhost:$PORT/A1-P/v1/policytypes"
-
-# GET policy type STD_QoSNudging_0.2.0
-curl -vk "$HTTPX://localhost:$PORT/A1-P/v1/policytypes/STD_QoSNudging_0.2.0"
-
-# PUT a policy instance pi1
-curl -X PUT -vk "$HTTPX://localhost:$PORT/A1-P/v1/policies/pi1?policyTypeId=STD_QoSNudging_0.2.0" -H "accept: application/json" -H "Content-Type: application/json" --data-binary @example_files/policy_instance_1_STD_QoSNudging_0.2.0.json
-
-# PUT a policy instance pi2
-curl -X PUT -vk "$HTTPX://localhost:$PORT/A1-P/v1/policies/pi2?policyTypeId=STD_QoSNudging_0.2.0" -H "accept: application/json" -H "Content-Type: application/json" --data-binary @example_files/policy_instance_2_STD_QoSNudging_0.2.0.json
-
-# SET status for pi1 and pi2
-curl -X PUT -vk "$HTTPX://localhost:$PORT/pi1/NOT_ENFORCED/300"
-curl -X PUT -vk "$HTTPX://localhost:$PORT/pi2/ENFORCED"
-
-# GET policies
-curl -vk "$HTTPX://localhost:$PORT/A1-P/v1/policies"
-
-# DELETE policy instance pi2
-curl -X DELETE -vk "$HTTPX://localhost:$PORT/A1-P/v1/policies/pi2"
-
-# PUT a different policy instance pi1 (i.e. update it)
-curl -X PUT -vk "$HTTPX://localhost:$PORT/A1-P/v1/policies/pi1?policyTypeId=STD_QoSNudging_0.2.0" -H "accept: application/json" -H "Content-Type: application/json" --data-binary @example_files/policy_instance_1_bis_STD_QoSNudging_0.2.0.json
-
-# GET policy instance pi1
-curl -vk "$HTTPX://localhost:$PORT/A1-P/v1/policies/pi1"
-
-# GET policy status for pi1
-curl -vk "$HTTPX://localhost:$PORT/A1-P/v1/policystatus/pi1"
diff --git a/near-rt-ric-simulator/test/1.1.x-alpha.2/example_files/policy_instance_1_STD_QoSNudging_0.2.0.json b/near-rt-ric-simulator/test/1.1.x-alpha.2/example_files/policy_instance_1_STD_QoSNudging_0.2.0.json
deleted file mode 100644 (file)
index 74f22c7..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-  "scope": {
-    "ueId": "ue1",
-    "groupId": "group1",
-    "sliceId": "slice1",
-    "qosId": "qos1",
-    "cellId": "cell1"
-  },
-  "statement": {
-    "priorityLevel": 5
-  }
-}
-
diff --git a/near-rt-ric-simulator/test/1.1.x-alpha.2/example_files/policy_instance_1_bis_STD_QoSNudging_0.2.0.json b/near-rt-ric-simulator/test/1.1.x-alpha.2/example_files/policy_instance_1_bis_STD_QoSNudging_0.2.0.json
deleted file mode 100644 (file)
index 8d2e985..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "scope": {
-    "ueId": "ue1",
-    "groupId": "group1",
-    "sliceId": "slice1",
-    "qosId": "qos1",
-    "cellId": "cell1"},
-  "statement": {
-    "priorityLevel": 4
-  }
-}
diff --git a/near-rt-ric-simulator/test/1.1.x-alpha.2/example_files/policy_instance_2_STD_QoSNudging_0.2.0.json b/near-rt-ric-simulator/test/1.1.x-alpha.2/example_files/policy_instance_2_STD_QoSNudging_0.2.0.json
deleted file mode 100644 (file)
index 257298c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "scope": {
-    "ueId": "ue2",
-    "groupId": "group2",
-    "sliceId": "slice2",
-    "qosId": "qos2",
-    "cellId": "cell2"
-  },
-  "statement": {
-    "priorityLevel": 5
-  }
-}
diff --git a/near-rt-ric-simulator/test/1.1.x-alpha.2/example_files/policy_type_STD_QoSNudging_0.2.0.json b/near-rt-ric-simulator/test/1.1.x-alpha.2/example_files/policy_type_STD_QoSNudging_0.2.0.json
deleted file mode 100644 (file)
index baf1bbe..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-{
-  "policySchema": {
-    "$schema": "http://json-schema.org/draft-07/schema#",
-    "title": "STD_QoSNudging_0.2.0",
-    "description": "QoS policy type",
-    "type": "object",
-    "properties": {
-      "scope": {
-        "type": "object",
-        "properties": {
-          "ueId": {"type": "string"},
-          "qosId": {"type": "string"}
-        },
-        "additionalProperties": true,
-        "required": ["ueId", "qosId"]
-      },
-      "statement": {
-        "type": "object",
-        "properties": {
-          "priorityLevel": {"type": "number"}
-        },
-        "additionalProperties": false,
-        "required": ["priorityLevel"]
-      }
-    }
-  },
-  "statusSchema": {
-    "$schema": "http://json-schema.org/draft-07/schema#",
-    "title": "statusSchema",
-    "description": "statusSchema",
-    "type": "object",
-    "properties": {
-      "enforceStatus": {
-        "type": "string",
-        "enum": ["UNDEFINED", "ENFORCED", "NOT_ENFORCED"]
-      },
-      "enforceReason": {
-        "type": "string",
-        "enum": ["100", "200", "300", "800"]
-      },
-      "additionalProperties": false
-    },
-    "if": {"properties": {"enforceStatus": {"const": "NOT_ENFORCED"}}},
-    "then": {"required": ["enforceReason"]}
-  }
-}
index 9fd2352..41ff2d1 100755 (executable)
@@ -47,7 +47,7 @@ RESULT="OK"
 do_curl GET / 200
 
 echo "=== Check used and implemented interfaces ==="
-RESULT="Current interface: OSC_2.1.0 All supported A1 interface yamls in this container: ['1.1.x-alpha.2', 'OSC_2.1.0', 'STD_1.1.3']"
+RESULT="Current interface: OSC_2.1.0 All supported A1 interface yamls in this container: ['OSC_2.1.0', 'STD_1.1.3']"
 do_curl GET /container_interfaces 200
 
 echo "=== Reset simulator instances ==="
@@ -136,11 +136,11 @@ do_curl GET '/a1-p/policytypes/1/policies/pi1/status' 200
 
 echo "=== Load a policy type: 2 ==="
 RESULT="Policy type 2 is OK."
-do_curl PUT '/policytype?id=2' 201 jsonfiles/pt1.json
+do_curl PUT '/policytype?id=2' 201 jsonfiles/pt2.json
 
 echo "=== Load a policy type: 2 again. ==="
 RESULT="Policy type 2 is OK."
-do_curl PUT '/policytype?id=2' 200 jsonfiles/pt1.json
+do_curl PUT '/policytype?id=2' 200 jsonfiles/pt2.json
 
 echo "=== API: Get policy type ids, shall contain type 1 and 2 =="
 RESULT="json:[ 1, 2 ]"
@@ -151,12 +151,12 @@ RESULT="json:[\"1\", \"2\"]"
 do_curl GET /policytypes 200
 
 echo "=== API: Get policy type 2 =="
-RESULT="json:{\"name\": \"pt1\", \"description\": \"pt1 policy type\", \"policy_type_id\": 1, \"create_schema\": {\"\$schema\": \"http://json-schema.org/draft-07/schema#\", \"title\": \"STD_QoSNudging_0.2.0\", \"description\": \"QoS policy type\", \"type\": \"object\", \"properties\": {\"scope\": {\"type\": \"object\", \"properties\": {\"ueId\": {\"type\": \"string\"}, \"qosId\": {\"type\": \"string\"}}, \"additionalProperties\": false, \"required\": [\"ueId\", \"qosId\"]}, \"statement\": {\"type\": \"object\", \"properties\": {\"priorityLevel\": {\"type\": \"number\"}}, \"additionalProperties\": false, \"required\": [\"priorityLevel\"]}}}}"
+RESULT="json:{\"name\": \"pt2\", \"description\": \"pt2 policy type\", \"policy_type_id\": 2, \"create_schema\": {\"\$schema\": \"http://json-schema.org/draft-07/schema#\", \"title\": \"STD_QoSNudging_0.2.0\", \"description\": \"QoS policy type\", \"type\": \"object\", \"properties\": {\"scope\": {\"type\": \"object\", \"properties\": {\"ueId\": {\"type\": \"string\"}, \"qosId\": {\"type\": \"string\"}}, \"additionalProperties\": false, \"required\": [\"ueId\", \"qosId\"]}, \"statement\": {\"type\": \"object\", \"properties\": {\"priorityLevel\": {\"type\": \"number\"}}, \"additionalProperties\": false, \"required\": [\"priorityLevel\"]}}}}"
 do_curl GET /a1-p/policytypes/2 200
 
 echo "=== Delete policy type: 2 ==="
 RESULT=""
-do_curl DELETE '/policytype?id=2' 204 jsonfiles/pt1.json
+do_curl DELETE '/policytype?id=2' 204 jsonfiles/pt2.json
 
 echo "=== API: Get policy type ids, shall contain type 1 =="
 RESULT="json:[ 1 ]"
@@ -167,8 +167,8 @@ RESULT="Policy type 2 is OK."
 do_curl PUT '/policytype?id=2' 201 jsonfiles/pt2.json
 
 echo "=== API: Get policy type 2 =="
-RESULT="json:{\"name\": \"pt1\", \"description\": \"pt1 policy type\", \"policy_type_id\": 1, \"create_schema\": {\"\$schema\": \"http://json-schema.org/draft-07/schema#\", \"title\": \"STD_QoSNudging_0.2.0\", \"description\": \"QoS policy type\", \"type\": \"object\", \"properties\": {\"scope\": {\"type\": \"object\", \"properties\": {\"ueId\": {\"type\": \"string\"}, \"qosId\": {\"type\": \"string\"}}, \"additionalProperties\": false, \"required\": [\"ueId\", \"qosId\"]}, \"statement\": {\"type\": \"object\", \"properties\": {\"priorityLevel\": {\"type\": \"number\"}}, \"additionalProperties\": false, \"required\": [\"priorityLevel\"]}}}}"
-do_curl GET /a1-p/policytypes/1 200
+RESULT="json:{\"name\": \"pt2\", \"description\": \"pt2 policy type\", \"policy_type_id\": 2, \"create_schema\": {\"\$schema\": \"http://json-schema.org/draft-07/schema#\", \"title\": \"STD_QoSNudging_0.2.0\", \"description\": \"QoS policy type\", \"type\": \"object\", \"properties\": {\"scope\": {\"type\": \"object\", \"properties\": {\"ueId\": {\"type\": \"string\"}, \"qosId\": {\"type\": \"string\"}}, \"additionalProperties\": false, \"required\": [\"ueId\", \"qosId\"]}, \"statement\": {\"type\": \"object\", \"properties\": {\"priorityLevel\": {\"type\": \"number\"}}, \"additionalProperties\": false, \"required\": [\"priorityLevel\"]}}}}"
+do_curl GET /a1-p/policytypes/2 200
 
 echo "=== API: Get instances for type 2, shall be empty ==="
 RESULT="json:[]"
index bcf25da..77f10a6 100755 (executable)
@@ -48,7 +48,7 @@ RESULT="OK"
 do_curl GET / 200
 
 echo "=== Check used and implemented interfaces ==="
-RESULT="Current interface: STD_1.1.3 All supported A1 interface yamls in this container: ['1.1.x-alpha.2', 'OSC_2.1.0', 'STD_1.1.3']"
+RESULT="Current interface: STD_1.1.3 All supported A1 interface yamls in this container: ['OSC_2.1.0', 'STD_1.1.3']"
 do_curl GET /container_interfaces 200
 
 echo "=== Reset simulator instances ==="
index 5766622..22c993d 100644 (file)
@@ -91,23 +91,37 @@ def compare_json(obj1, obj2):
     return True
 
 
-try:
-    #Read the input file and compare the two json (target->result)
-    jsonTarget = json.loads(sys.argv[1])
-    jsonResult = json.loads(sys.argv[2])
-    res1=compare_json(jsonTarget, jsonResult)
-
-    #Read the json again (in case the previous calls has re-arranged the jsons)
-    jsonTarget = json.loads(sys.argv[1])
-    jsonResult = json.loads(sys.argv[2])
-    #Compare the opposite order (result->target) to catch special duplicate json key cases
-    res2=compare_json(jsonResult, jsonTarget)
-
-    if (res1 and res2):
-        print (0)
-    else:
-        print (1)
+# Compare two json object. Returns true if equal, false if not equal
+# This function is intended to be used from other python scipts using json object (instead of files)
+def compare(target, result):
+    try:
+        res1=compare_json(target, result)
+        res2=compare_json(target, result)
+        if (res1 and res2):
+            return True
+        else:
+            return False
+    except Exception:
+        return False
 
-except Exception as e:
-    print (1)
-sys.exit()
\ No newline at end of file
+if __name__ == '__main__':
+    try:
+        #Read the input file and compare the two json (target->result)
+        jsonTarget = json.loads(sys.argv[1])
+        jsonResult = json.loads(sys.argv[2])
+        res1=compare_json(jsonTarget, jsonResult)
+
+        #Read the json again (in case the previous calls has re-arranged the jsons)
+        jsonTarget = json.loads(sys.argv[1])
+        jsonResult = json.loads(sys.argv[2])
+        #Compare the opposite order (result->target) to catch special duplicate json key cases
+        res2=compare_json(jsonResult, jsonTarget)
+
+        if (res1 and res2):
+            print (0)
+        else:
+            print (1)
+
+    except Exception:
+        print (1)
+    sys.exit()
\ No newline at end of file
diff --git a/near-rt-ric-simulator/tests/OSC_2.1.0/test_osc_2_1_0.py b/near-rt-ric-simulator/tests/OSC_2.1.0/test_osc_2_1_0.py
new file mode 100644 (file)
index 0000000..5b8be30
--- /dev/null
@@ -0,0 +1,546 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2020 Nordix Foundation. All rights reserved.
+#  ========================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#  ============LICENSE_END=================================================
+#
+
+# This test case test the OSC_2.1.0 version of the simulator
+
+from unittest import TestCase
+import sys
+import os
+import threading
+import requests
+import json
+
+
+#Constants for the test case
+INTERFACE_VERSION="OSC_2.1.0"
+PORT_NUMBER=2222
+HOST_IP="127.0.0.1"
+SERVER_URL="http://127.0.0.1:"+str(PORT_NUMBER)+"/"
+
+cwd=os.getcwd()+"/"
+# Env TESTS_BASE_PATH is set when executed via tox.ini
+# If basic test is executed from cmd line, that env var is not needed
+if 'TESTS_BASE_PATH' in os.environ:
+     cwd=os.environ['TESTS_BASE_PATH']+"/"+INTERFACE_VERSION+"/"
+TESTDATA=cwd+"/../../test/"+INTERFACE_VERSION+"/jsonfiles/"
+
+#Env var to setup version and host logging
+os.environ['APIPATH'] = cwd+"/../../api/"+INTERFACE_VERSION
+os.environ['REMOTE_HOSTS_LOGGING'] = "ON"
+
+# Paths need to run the sim, including needed source file dirs
+sys.path.append(os.path.abspath(cwd+'../../src/common'))
+sys.path.append(os.path.abspath(cwd+'../../test/common'))
+sys.path.append(os.path.abspath(cwd+'../../src/'+INTERFACE_VERSION))
+os.chdir(cwd+"../../src/"+INTERFACE_VERSION)
+
+import main
+from compare_json import compare
+
+class TestCase1(TestCase):
+    from main import app
+    server = None
+
+    def startServer(self):
+        self.app.run(port=PORT_NUMBER, host=HOST_IP, threaded=True)
+
+    def setUp(self):
+        self.server=threading.Thread(target=self.startServer, args=())
+        self.server.daemon = True
+        self.server.start()
+
+    # executed after each test
+    def tearDown(self):
+        self.server.killed=True
+
+    def test_apis(self):
+
+        # Header for json payload
+        header = {
+            "Content-Type" : "application/json"
+        }
+
+        # Simulator hello world
+        response=requests.get(SERVER_URL)
+        self.assertEqual(response.status_code, 200)
+
+        # Check used and implemented interfaces
+        response=requests.get(SERVER_URL+'container_interfaces')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "Current interface: OSC_2.1.0  All supported A1 interface yamls in this container: ['OSC_2.1.0', 'STD_1.1.3']")
+
+        # Reset simulator instances
+        response=requests.post(SERVER_URL+'deleteinstances')
+        self.assertEqual(response.status_code, 200)
+
+        # Reset simulator, all
+        response=requests.post(SERVER_URL+'deleteall')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Healthcheck
+        response=requests.get(SERVER_URL+'a1-p/healthcheck')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy types, shall be empty
+        data_policytypes_get = [ ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policytypes_get, result)
+        self.assertEqual(res, True)
+
+        # API: Delete a policy type, shall fail
+        response=requests.delete(SERVER_URL+'a1-p/policytypes/1')
+        self.assertEqual(response.status_code, 404)
+
+        # API: Get policy instances for type 1, shall fail
+        response=requests.get(SERVER_URL+'a1-p/policytypes/1/policies')
+        self.assertEqual(response.status_code, 404)
+
+        # API: Put a policy type: 1
+        with open(TESTDATA+'pt1.json') as json_file:
+            policytype_1 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/1', headers=header, data=json.dumps(policytype_1))
+            self.assertEqual(response.status_code, 201)
+
+        # API: Put a policy type: 1 again
+        with open(TESTDATA+'pt1.json') as json_file:
+            policytype_1 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/1', headers=header, data=json.dumps(policytype_1))
+            self.assertEqual(response.status_code, 201)
+
+        # API: Delete a policy type
+        response=requests.delete(SERVER_URL+'a1-p/policytypes/1')
+        self.assertEqual(response.status_code, 204)
+
+        # API: Get policy type ids, shall be empty
+        data_policytypes_get = [ ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policytypes_get, result)
+        self.assertEqual(res, True)
+
+        # API: Put a policy type: 1
+        with open(TESTDATA+'pt1.json') as json_file:
+            policytype_1 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/1', headers=header, data=json.dumps(policytype_1))
+            self.assertEqual(response.status_code, 201)
+
+        # API: Get policy type ids, shall contain '1'
+        data_policytypes_get = [ 1 ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policytypes_get, result)
+        self.assertEqual(res, True)
+
+        # API: Get instances for type 1, shall be empty
+        data_policies_get = [ ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes/1/policies')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policies_get, result)
+        self.assertEqual(res, True)
+
+        # API: Create policy instance pi1 of type: 1
+        with open(TESTDATA+'pi1.json') as json_file:
+            policy_1 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/1/policies/pi1', headers=header, data=json.dumps(policy_1))
+            self.assertEqual(response.status_code, 202)
+
+        # API: Get policy instance pi1 of type: 1
+        with open(TESTDATA+'pi1.json') as json_file:
+            policy_1 = json.load(json_file)
+            response=requests.get(SERVER_URL+'a1-p/policytypes/1/policies/pi1')
+            self.assertEqual(response.status_code, 200)
+            result=json.loads(response.text)
+            res=compare(policy_1, result)
+            self.assertEqual(res, True)
+
+        # API: Update policy instance pi1 of type: 1
+        with open(TESTDATA+'pi1.json') as json_file:
+            policy_1 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/1/policies/pi1', headers=header, data=json.dumps(policy_1))
+            self.assertEqual(response.status_code, 202)
+
+        # API: Update policy type: 1, shall fail
+        with open(TESTDATA+'pt1.json') as json_file:
+            policytype_1 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/1', headers=header, data=json.dumps(policytype_1))
+            self.assertEqual(response.status_code, 400)
+
+        # API: Get instances for type 1, shall contain 'pi1'
+        data_policies_get = [ "pi1" ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes/1/policies')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policies_get, result)
+        self.assertEqual(res, True)
+
+        # API: Create policy instance pi2 (copy of pi1) of type: 1. Shall fail
+        with open(TESTDATA+'pi1.json') as json_file:
+            policy_2 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/1/policies/pi2', headers=header, data=json.dumps(policy_2))
+            self.assertEqual(response.status_code, 400)
+
+        # Set force response code 401
+        response=requests.post(SERVER_URL+'forceresponse?code=401')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy type 1. Shall fail with forced code
+        response=requests.get(SERVER_URL+'a1-p/policytypes/1')
+        self.assertEqual(response.status_code, 401)
+
+        # API: Get policy status
+        policy_status = {
+            "instance_status" : "NOT IN EFFECT",
+            "has_been_deleted" : "false",
+            "created_at" : "????"
+        }
+        response=requests.get(SERVER_URL+'a1-p/policytypes/1/policies/pi1/status')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(policy_status, result)
+        self.assertEqual(res, True)
+
+        # Load a policy type: 2
+        with open(TESTDATA+'pt2.json') as json_file:
+            policytype_2 = json.load(json_file)
+            response=requests.put(SERVER_URL+'policytype?id=2', headers=header, data=json.dumps(policytype_2))
+            self.assertEqual(response.status_code, 201)
+            self.assertEqual(response.text, "Policy type 2 is OK.")
+
+        # Load a policy type: 2, again
+        with open(TESTDATA+'pt2.json') as json_file:
+            policytype_2 = json.load(json_file)
+            response=requests.put(SERVER_URL+'policytype?id=2', headers=header, data=json.dumps(policytype_2))
+            self.assertEqual(response.status_code, 200)
+            self.assertEqual(response.text, "Policy type 2 is OK.")
+
+        # API: Get policy type ids, shall contain '1' and '2'
+        data_policytypes_get = [ 1,2 ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policytypes_get, result)
+        self.assertEqual(res, True)
+
+        # Get policy type ids, shall contain type 1 and 2 =="
+        data_policytypes_get = [ "1","2" ]
+        response=requests.get(SERVER_URL+'policytypes')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policytypes_get, result)
+        self.assertEqual(res, True)
+
+        # API: Get policy type 2
+        with open(TESTDATA+'pt2.json') as json_file:
+            policytype_2 = json.load(json_file)
+            response=requests.get(SERVER_URL+'a1-p/policytypes/2')
+            self.assertEqual(response.status_code, 200)
+            result=json.loads(response.text)
+            res=compare(policytype_2, result)
+            self.assertEqual(res, True)
+
+        # Delete a policy type
+        response=requests.delete(SERVER_URL+'policytype?id=2')
+        self.assertEqual(response.status_code, 204)
+
+        # API: Get policy type ids, shall contain '1'
+        data_policytypes_get = [ 1]
+        response=requests.get(SERVER_URL+'a1-p/policytypes')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policytypes_get, result)
+        self.assertEqual(res, True)
+
+        # Load a policy type: 2
+        with open(TESTDATA+'pt2.json') as json_file:
+            policytype_2 = json.load(json_file)
+            response=requests.put(SERVER_URL+'policytype?id=2', headers=header, data=json.dumps(policytype_2))
+            self.assertEqual(response.status_code, 201)
+            self.assertEqual(response.text, "Policy type 2 is OK.")
+
+        # API: Get policy type 2
+        with open(TESTDATA+'pt2.json') as json_file:
+            policytype_2 = json.load(json_file)
+            response=requests.get(SERVER_URL+'a1-p/policytypes/2')
+            self.assertEqual(response.status_code, 200)
+            result=json.loads(response.text)
+            res=compare(policytype_2, result)
+            self.assertEqual(res, True)
+
+        # API: Get instances for type 2, shall be empty
+        data_policies_get = [ ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes/2/policies')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policies_get, result)
+        self.assertEqual(res, True)
+
+        # API: Create policy instance pi1 of type: 2, shall fail
+        with open(TESTDATA+'pi1.json') as json_file:
+            policy_1 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/2/policies/pi1', headers=header, data=json.dumps(policy_1))
+            self.assertEqual(response.status_code, 400)
+
+        # API: Create policy instance pi2 of type: 2. Missing param, shall fail
+        with open(TESTDATA+'pi2_missing_param.json') as json_file:
+            policy_2 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/2/policies/pi1', headers=header, data=json.dumps(policy_2))
+            self.assertEqual(response.status_code, 400)
+
+        # API: Create policy instance pi2 of type: 2
+        with open(TESTDATA+'pi2.json') as json_file:
+            policy_2 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/2/policies/pi2', headers=header, data=json.dumps(policy_2))
+            self.assertEqual(response.status_code, 202)
+
+        with open(TESTDATA+'pi2.json') as json_file:
+            policy_2 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/2/policies/pi2', headers=header, data=json.dumps(policy_2))
+            self.assertEqual(response.status_code, 202)
+
+        # API: Get instances for type 1, shall contain pi1
+        data_policies_get = [ "pi1" ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes/1/policies')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policies_get, result)
+        self.assertEqual(res, True)
+
+        # API: Get instances for type 2, shall contain pi2
+        data_policies_get = ["pi2" ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes/2/policies')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policies_get, result)
+        self.assertEqual(res, True)
+
+        # API: Create policy instance pi11 (copy of pi1) of type: 1. Shall fail
+        with open(TESTDATA+'pi1.json') as json_file:
+            policy_1 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/1/policies/pi11', headers=header, data=json.dumps(policy_1))
+            self.assertEqual(response.status_code, 400)
+
+        # Set force response code 409. ==="
+        response=requests.post(SERVER_URL+'forceresponse?code=401')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy status for pi1, shall fail
+        response=requests.get(SERVER_URL+'a1-p/policytypes/1/policies/pi1/status')
+        self.assertEqual(response.status_code, 401)
+
+        # Set force delay 10
+        response=requests.post(SERVER_URL+'forcedelay?delay=10')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "Force delay: 10 sec set for all A1 responses")
+
+        # API: Get policy status for pi1. Shall delay 10 sec
+        policy_status = {
+            "instance_status" : "NOT IN EFFECT",
+            "has_been_deleted" : "false",
+            "created_at" : "????"
+        }
+        response=requests.get(SERVER_URL+'a1-p/policytypes/1/policies/pi1/status')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(policy_status, result)
+        self.assertEqual(res, True)
+
+        # Reset force delay
+        response=requests.post(SERVER_URL+'forcedelay')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "Force delay: None sec set for all A1 responses")
+
+        #  Set status for pi1
+        response=requests.put(SERVER_URL+'status?policyid=pi1&status=IN%20EFFECT')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy status for pi1
+        policy_status = {
+            "instance_status" : "IN EFFECT",
+            "has_been_deleted" : "false",
+            "created_at" : "????"
+        }
+        response=requests.get(SERVER_URL+'a1-p/policytypes/1/policies/pi1/status')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(policy_status, result)
+        self.assertEqual(res, True)
+
+        #  Set status for pi1
+        response=requests.put(SERVER_URL+'status?policyid=pi1&status=IN%20EFFECT&deleted=true&created_at=2020-03-30%2012:00:00')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy status for pi1
+        policy_status = {
+            "instance_status" : "IN EFFECT",
+            "has_been_deleted" : "true",
+            "created_at" : "????"
+        }
+        response=requests.get(SERVER_URL+'a1-p/policytypes/1/policies/pi1/status')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(policy_status, result)
+        self.assertEqual(res, True)
+
+        # Get counter: intstance
+        response=requests.get(SERVER_URL+'counter/num_instances')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "2")
+
+        # Get counter: types (shall be 2)
+        response=requests.get(SERVER_URL+'counter/num_types')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "2")
+
+        # Get counter: interface
+        response=requests.get(SERVER_URL+'counter/interface')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "OSC_2.1.0")
+
+        # Get counter: remote hosts
+        response=requests.get(SERVER_URL+'counter/remote_hosts')
+        self.assertEqual(response.status_code, 200)
+
+        # Get counter: test, shall fail
+        response=requests.get(SERVER_URL+'counter/test')
+        self.assertEqual(response.status_code, 404)
+
+        # API: DELETE policy instance pi1
+        response=requests.delete(SERVER_URL+'a1-p/policytypes/1/policies/pi1')
+        self.assertEqual(response.status_code, 202)
+
+        # API: Get instances for type 1, shall be empty
+        data_policies_get = [ ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes/1/policies')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policies_get, result)
+        self.assertEqual(res, True)
+
+        # API: Get instances for type 2, shall contain pi2
+        data_policies_get = ["pi2" ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes/2/policies')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policies_get, result)
+        self.assertEqual(res, True)
+
+        # Get counter: instances
+        response=requests.get(SERVER_URL+'counter/num_instances')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "1")
+
+
+        ### Tests to increase code coverage
+
+        # Set force response code 500
+        response=requests.post(SERVER_URL+'forceresponse?code=500')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Healthcheck
+        response=requests.get(SERVER_URL+'a1-p/healthcheck')
+        self.assertEqual(response.status_code, 500)
+
+        # Set force response code 501
+        response=requests.post(SERVER_URL+'forceresponse?code=501')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy types
+        data_policytypes_get = [ ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes')
+        self.assertEqual(response.status_code, 501)
+
+        # Set force response code 502
+        response=requests.post(SERVER_URL+'forceresponse?code=502')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Delete a policy type, shall fail
+        response=requests.delete(SERVER_URL+'a1-p/policytypes/55')
+        self.assertEqual(response.status_code, 502)
+
+        # Set force response code 503. ==="
+        response=requests.post(SERVER_URL+'forceresponse?code=503')
+        self.assertEqual(response.status_code, 200)
+
+        with open(TESTDATA+'pi1.json') as json_file:
+            policy_1 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/1/policies/pi11', headers=header, data=json.dumps(policy_1))
+            self.assertEqual(response.status_code, 503)
+
+        # Set force response code 504
+        response=requests.post(SERVER_URL+'forceresponse?code=504')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get instances for type 1, shall fail
+        data_policies_get = [ ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes/1/policies')
+        self.assertEqual(response.status_code, 504)
+
+        # Set force response code 505. ==="
+        response=requests.post(SERVER_URL+'forceresponse?code=505')
+        self.assertEqual(response.status_code, 200)
+
+        # API: delete instance pi1, shall fail
+        response=requests.delete(SERVER_URL+'a1-p/policytypes/1/policies/pi1')
+        self.assertEqual(response.status_code, 505)
+
+        # API: Delete a policy type having instances, shall fail
+        response=requests.delete(SERVER_URL+'a1-p/policytypes/2')
+        self.assertEqual(response.status_code, 400)
+
+        # API: delete instance pi1 in type 5, shall fail
+        response=requests.delete(SERVER_URL+'a1-p/policytypes/5/policies/pi1')
+        self.assertEqual(response.status_code, 404)
+
+        # API: delete instance pi99 in type 1, shall fail
+        response=requests.delete(SERVER_URL+'a1-p/policytypes/1/policies/pi99')
+        self.assertEqual(response.status_code, 404)
+
+        # API: Create policy instance pi80 of type: 5
+        with open(TESTDATA+'pi1.json') as json_file:
+            policy_80 = json.load(json_file)
+            response=requests.put(SERVER_URL+'a1-p/policytypes/5/policies/pi80', headers=header, data=json.dumps(policy_80))
+            self.assertEqual(response.status_code, 404)
+
+        # API: Get policy type
+        data_policytypes_get = [ ]
+        response=requests.get(SERVER_URL+'a1-p/policytypes/55')
+        self.assertEqual(response.status_code, 404)
+
+        # API: Get status, bad type - shall fail
+        response=requests.get(SERVER_URL+'a1-p/policytypes/99/policies/pi1/status')
+        self.assertEqual(response.status_code, 404)
+
+        # API: Get status, bad instance - shall fail
+        response=requests.get(SERVER_URL+'a1-p/policytypes/1/policies/pi111/status')
+        self.assertEqual(response.status_code, 404)
+
+        # Load policy type, no type in url - shall faill
+        with open(TESTDATA+'pt2.json') as json_file:
+            policytype_2 = json.load(json_file)
+            response=requests.put(SERVER_URL+'policytype', headers=header, data=json.dumps(policytype_2))
+            self.assertEqual(response.status_code, 400)
+
+        # Load policy type - duplicatee - shall faill
+        with open(TESTDATA+'pt1.json') as json_file:
+            policytype_1 = json.load(json_file)
+            response=requests.put(SERVER_URL+'policytype?id=2', headers=header, data=json.dumps(policytype_1))
+            self.assertEqual(response.status_code, 400)
diff --git a/near-rt-ric-simulator/tests/STD_1.1.3/test_std_1_1_3.py b/near-rt-ric-simulator/tests/STD_1.1.3/test_std_1_1_3.py
new file mode 100644 (file)
index 0000000..483d964
--- /dev/null
@@ -0,0 +1,494 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2020 Nordix Foundation. All rights reserved.
+#  ========================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#  ============LICENSE_END=================================================
+#
+
+# This test case test the STD_1.1.3 version of the simulator
+
+from unittest import TestCase
+import sys
+import os
+import threading
+import requests
+import json
+
+#Constants for the test case
+INTERFACE_VERSION="STD_1.1.3"
+PORT_NUMBER=2224
+HOST_IP="127.0.0.1"
+SERVER_URL="http://127.0.0.1:"+str(PORT_NUMBER)+"/"
+
+cwd=os.getcwd()+"/"
+# Env TESTS_BASE_PATH is set when executed via tox.ini
+# If basic test is executed from cmd line, that env var is not needed
+if 'TESTS_BASE_PATH' in os.environ:
+     cwd=os.environ['TESTS_BASE_PATH']+"/"+INTERFACE_VERSION+"/"
+TESTDATA=cwd+"/../../test/"+INTERFACE_VERSION+"/jsonfiles/"
+
+#Env var to setup api version and host logging
+os.environ['APIPATH'] = cwd+"/../../api/"+INTERFACE_VERSION
+os.environ['REMOTE_HOSTS_LOGGING'] = "ON"
+
+# Paths need to run the sim, including needed source file dirs
+sys.path.append(os.path.abspath(cwd+'../../src/common'))
+sys.path.append(os.path.abspath(cwd+'../../test/common'))
+sys.path.append(os.path.abspath(cwd+'../../src/'+INTERFACE_VERSION))
+os.chdir(cwd+"../../src/"+INTERFACE_VERSION)
+
+import main
+from compare_json import compare
+
+class TestCase1(TestCase):
+    from main import app
+    server = None
+
+    def startServer(self):
+        self.app.run(port=PORT_NUMBER, host=HOST_IP, threaded=True)
+
+    def setUp(self):
+        self.server=threading.Thread(target=self.startServer, args=())
+        self.server.daemon = True
+        self.server.start()
+
+    # executed after each test
+    def tearDown(self):
+        self.server.killed=True
+
+    #from main import app
+    def test_apis(self):
+
+        # header for json payload
+        header = {
+            "Content-Type" : "application/json"
+        }
+
+        # Simulator hello world
+        response=requests.get(SERVER_URL)
+        self.assertEqual(response.status_code, 200)
+
+        # Check used and implemented interfaces
+        response=requests.get(SERVER_URL+'container_interfaces')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "Current interface: STD_1.1.3  All supported A1 interface yamls in this container: ['OSC_2.1.0', 'STD_1.1.3']")
+
+        # Reset simulator instances
+        response=requests.post(SERVER_URL+'deleteinstances')
+        self.assertEqual(response.status_code, 200)
+
+        # Reset simulator, all
+        response=requests.post(SERVER_URL+'deleteall')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy instances, shall be empty
+        data_policy_get = [ ]
+        response=requests.get(SERVER_URL+'A1-P/v1/policies')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policy_get, result)
+        self.assertEqual(res, True)
+
+        #API: Create policy instance pi1
+        data_pi1 = {
+            "scope": {
+                "ueId": "ue1",
+                "groupId": "group1",
+                "sliceId": "slice1",
+                "qosId": "qos1",
+                "cellId": "cell1"
+                },
+            "statement": {
+                "priorityLevel": 5
+            }
+        }
+        response=requests.put(SERVER_URL+'A1-P/v1/policies/pi1', headers=header, data=json.dumps(data_pi1))
+        self.assertEqual(response.status_code, 201)
+        result=json.loads(response.text)
+        res=compare(data_pi1, result)
+        self.assertEqual(res, True)
+
+        #API: Update policy instance pi1
+        data_pi1_updated = {
+            "scope": {
+                "ueId": "ue1",
+                "groupId": "group1",
+                "sliceId": "slice1",
+                "qosId": "qos1",
+                "cellId": "cell1"
+                },
+            "statement": {
+                "priorityLevel": 6
+            }
+        }
+        response=requests.put(SERVER_URL+'A1-P/v1/policies/pi1', headers=header, data=json.dumps(data_pi1_updated))
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_pi1_updated, result)
+        self.assertEqual(res, True)
+
+        #API: Create policy instance pi9, bad json
+        response=requests.put(SERVER_URL+'A1-P/v1/policies/pi9', headers=header, data="test")
+        self.assertEqual(response.status_code, 400)
+
+        # API: Get policy instances, shall contain pi1
+        data_policy_get = [ "pi1" ]
+        response=requests.get(SERVER_URL+'A1-P/v1/policies')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policy_get, result)
+        self.assertEqual(res, True)
+
+        # API: Create policy instance pi2 (copy of pi1). Shall fail
+        data_create_errror_pi1 = {
+            "title" : "The policy json already exists.",
+            "status" : 400,
+            "instance" : "pi2"
+        }
+        response=requests.put(SERVER_URL+'A1-P/v1/policies/pi2', headers=header, data=json.dumps(data_pi1_updated))
+        self.assertEqual(response.status_code, 400)
+        result=json.loads(response.text)
+        res=compare(data_create_errror_pi1, result)
+        self.assertEqual(res, True)
+
+        # Set force response code 409. ==="
+        response=requests.post(SERVER_URL+'forceresponse?code=409')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy instances, shall fail
+        data_get_errror = {
+            "title" : "Conflict",
+            "status" : 409,
+            "detail" : "Request could not be processed in the current state of the resource"
+        }
+        response=requests.get(SERVER_URL+'A1-P/v1/policies')
+        self.assertEqual(response.status_code, 409)
+        result=json.loads(response.text)
+        res=compare(data_get_errror, result)
+        self.assertEqual(res, True)
+
+        # Reset force response
+        response=requests.post(SERVER_URL+'forceresponse')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "Force response code: None set for one single A1 response")
+
+        ###
+        ### Repeating the above two test for code coverage
+        ###
+        # Set force response code 400
+        response=requests.post(SERVER_URL+'forceresponse?code=400')
+        self.assertEqual(response.status_code, 200)
+
+        #API: Create policy instance pi3, shall fail
+        data_pi3 = {
+            "scope": {
+                "ueId": "ue3"
+                },
+            "statement": {
+                "priorityLevel": 5
+            }
+        }
+        data_get_errror = {
+            "title" : "Bad request",
+            "status" : 400,
+            "detail" : "Object in payload not properly formulated or not related to the method"
+        }
+        response=requests.put(SERVER_URL+'A1-P/v1/policies/pi3', headers=header, data=json.dumps(data_pi3))
+        self.assertEqual(response.status_code, 400)
+        result=json.loads(response.text)
+        res=compare(data_get_errror, result)
+        self.assertEqual(res, True)
+
+        # Set force response code 404
+        response=requests.post(SERVER_URL+'forceresponse?code=404')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy instance pi1, shall fail =="
+        data_get_errror = {
+            "title" : "Not found",
+            "status" : 404,
+            "detail" : "No resource found at the URI"
+        }
+        response=requests.get(SERVER_URL+'A1-P/v1/policies/pi1')
+        self.assertEqual(response.status_code, 404)
+        result=json.loads(response.text)
+        res=compare(data_get_errror, result)
+        self.assertEqual(res, True)
+
+        # Set force response code 405
+        response=requests.post(SERVER_URL+'forceresponse?code=405')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Delete policy instances pi1, shall fail =="
+        data_get_errror = {
+            "title" : "Method not allowed",
+            "status" : 405,
+            "detail" : "Method not allowed for the URI"
+        }
+        response=requests.delete(SERVER_URL+'A1-P/v1/policies/pi1')
+        self.assertEqual(response.status_code, 405)
+        result=json.loads(response.text)
+        res=compare(data_get_errror, result)
+        self.assertEqual(res, True)
+
+        # Set force response code 429
+        response=requests.post(SERVER_URL+'forceresponse?code=429')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy status pi3, shall fail =="
+        data_get_errror = {
+            "title" : "Too many requests",
+            "status" : 429,
+            "detail" : "Too many requests have been sent in a given amount of time"
+        }
+        response=requests.get(SERVER_URL+'A1-P/v1/policies/pi3/status')
+        self.assertEqual(response.status_code, 429)
+        result=json.loads(response.text)
+        res=compare(data_get_errror, result)
+        self.assertEqual(res, True)
+
+        # Set force response code 507
+        response=requests.post(SERVER_URL+'forceresponse?code=507')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy instances, shall fail
+        data_get_errror = {
+            "title" : "Insufficient storage",
+            "status" : 507,
+            "detail" : "The method could not be performed on the resource because the provider is unable to store the representation needed to successfully complete the request"
+        }
+        response=requests.get(SERVER_URL+'A1-P/v1/policies')
+        self.assertEqual(response.status_code, 507)
+        result=json.loads(response.text)
+        res=compare(data_get_errror, result)
+        self.assertEqual(res, True)
+
+        # Set force response code 503. ==="
+        response=requests.post(SERVER_URL+'forceresponse?code=503')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy instances, shall fail
+        data_get_errror = {
+            "title" : "Service unavailable",
+            "status" : 503,
+            "detail" : "The provider is currently unable to handle the request due to a temporary overload"
+        }
+        response=requests.get(SERVER_URL+'A1-P/v1/policies')
+        self.assertEqual(response.status_code, 503)
+        result=json.loads(response.text)
+        res=compare(data_get_errror, result)
+        self.assertEqual(res, True)
+
+        # Set force response code 555. ==="
+        response=requests.post(SERVER_URL+'forceresponse?code=555')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy instances, shall fail
+        data_get_errror = {
+            "title" : "Unknown",
+            "status" : "555",
+            "detail" : "Not implemented response code"
+        }
+        response=requests.get(SERVER_URL+'A1-P/v1/policies')
+        self.assertEqual(response.status_code, 555)
+        result=json.loads(response.text)
+        res=compare(data_get_errror, result)
+        self.assertEqual(res, True)
+
+        ###
+        ### End of repeated test
+        ###
+
+
+        # API: Get policy status
+        data_policy_status = {
+            "enforceStatus" : "UNDEFINED"
+        }
+        response=requests.get(SERVER_URL+'A1-P/v1/policies/pi1/status')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policy_status, result)
+        self.assertEqual(res, True)
+
+        # API: Create policy instance pi2
+        data_pi2 = {
+            "scope": {
+                "ueId": "ue2",
+                "groupId": "group2",
+                "sliceId": "slice2",
+                "qosId": "qos2",
+                "cellId": "cell2"
+                },
+            "statement": {
+                "priorityLevel": 10
+            }
+        }
+        response=requests.put(SERVER_URL+'A1-P/v1/policies/pi2', headers=header, data=json.dumps(data_pi2))
+        self.assertEqual(response.status_code, 201)
+        result=json.loads(response.text)
+        res=compare(data_pi2, result)
+        self.assertEqual(res, True)
+
+
+        # API: Update policy instance pi2
+        # Reuse same policy data
+        response=requests.put(SERVER_URL+'A1-P/v1/policies/pi2?notificationDestination=http://localhost:2224/statustest', headers=header, data=json.dumps(data_pi2))
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_pi2, result)
+        self.assertEqual(res, True)
+
+        # API: Get policy instances, shall contain pi1 and pi2
+        data_policy_get = [ "pi1", "pi2" ]
+        response=requests.get(SERVER_URL+'A1-P/v1/policies')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policy_get, result)
+        self.assertEqual(res, True)
+
+        # Set force delay 10
+        response=requests.post(SERVER_URL+'forcedelay?delay=10')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "Force delay: 10 sec set for all A1 responses")
+
+        # API: Get policy instances, shall contain pi1 and pi2 and delayed 10 sec
+        data_policy_get = [ "pi1", "pi2" ]
+        response=requests.get(SERVER_URL+'A1-P/v1/policies')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_policy_get, result)
+        self.assertEqual(res, True)
+
+        # Reset force delay
+        response=requests.post(SERVER_URL+'forcedelay')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "Force delay: None sec set for all A1 responses")
+
+        # API: GET policy instance pi1
+        response=requests.get(SERVER_URL+'A1-P/v1/policies/pi1')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_pi1_updated, result)
+        self.assertEqual(res, True)
+
+        # API: GET policy instance pi2
+        response=requests.get(SERVER_URL+'A1-P/v1/policies/pi2')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_pi2, result)
+        self.assertEqual(res, True)
+
+        # API: GET policy instance pi9, shall fail
+        response=requests.get(SERVER_URL+'A1-P/v1/policies/pi9')
+        self.assertEqual(response.status_code, 404)
+
+        # API: DELETE policy instance pi1
+        response=requests.delete(SERVER_URL+'A1-P/v1/policies/pi1')
+        self.assertEqual(response.status_code, 204)
+
+        # API: DELETE policy instance pi9, shall fail
+        response=requests.delete(SERVER_URL+'A1-P/v1/policies/pi9')
+        self.assertEqual(response.status_code, 404)
+
+        # API: Get policy status for pi1, shall fail
+        data_get_errror = {
+            "title" : "The policy identity does not exist.",
+            "status" : 404,
+            "detail" : "There is no existing policy instance with the identity: pi1",
+            "instance" : "pi1"
+        }
+        response=requests.get(SERVER_URL+'A1-P/v1/policies/pi1/status')
+        self.assertEqual(response.status_code, 404)
+        result=json.loads(response.text)
+        res=compare(data_get_errror, result)
+        self.assertEqual(res, True)
+
+        # Set status for policy instance pi2
+        response=requests.put(SERVER_URL+'status?policyid=pi2&status=OK')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy status for pi2
+        data_get_status = {
+            "enforceStatus" : "OK"
+        }
+        response=requests.get(SERVER_URL+'A1-P/v1/policies/pi2/status')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_get_status, result)
+        self.assertEqual(res, True)
+
+        # Set status for policy instance pi2
+        response=requests.put(SERVER_URL+'status?policyid=pi2&status=NOTOK&reason=notok_reason')
+        self.assertEqual(response.status_code, 200)
+
+        # API: Get policy status for pi2
+        data_get_status = {
+            "enforceStatus" : "NOTOK",
+            "enforceReason" : "notok_reason"
+        }
+        response=requests.get(SERVER_URL+'A1-P/v1/policies/pi2/status')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_get_status, result)
+        self.assertEqual(res, True)
+
+        # Send status for pi2
+        response=requests.post(SERVER_URL+'sendstatus?policyid=pi2')
+        self.assertEqual(response.status_code, 200)
+        result=json.loads(response.text)
+        res=compare(data_get_status, result)
+        self.assertEqual(res, True)
+
+        # Send status, shall fail
+        response=requests.post(SERVER_URL+'sendstatus')
+        self.assertEqual(response.status_code, 400)
+
+        # Send status pi9, shall fail
+        response=requests.post(SERVER_URL+'sendstatus?policyid=pi9')
+        self.assertEqual(response.status_code, 404)
+
+        # Set status for policy instance , shall fail
+        response=requests.put(SERVER_URL+'status')
+        self.assertEqual(response.status_code, 400)
+
+        # Set status for policy instance pi9, shall fail
+        response=requests.put(SERVER_URL+'status?policyid=pi9')
+        self.assertEqual(response.status_code, 404)
+
+        # Set status for policy instance pi2, shall fail
+        response=requests.put(SERVER_URL+'status?policyid=pi2')
+        self.assertEqual(response.status_code, 400)
+
+
+        # Get counter: intstance
+        response=requests.get(SERVER_URL+'counter/num_instances')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "1")
+
+        # Get counter: types (shall be 0)
+        response=requests.get(SERVER_URL+'counter/num_types')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "0")
+
+        # Get counter: interface
+        response=requests.get(SERVER_URL+'counter/interface')
+        self.assertEqual(response.status_code, 200)
+        self.assertEqual(response.text,  "STD_1.1.3")
+
+        # Get counter: remote hosts
+        response=requests.get(SERVER_URL+'counter/remote_hosts')
+        self.assertEqual(response.status_code, 200)
+
+        # Get counter: test, shall fail
+        response=requests.get(SERVER_URL+'counter/test')
+        self.assertEqual(response.status_code, 404)
diff --git a/tox.ini b/tox.ini
index 80839a2..9936af4 100644 (file)
--- a/tox.ini
+++ b/tox.ini
 # ==================================================================================
 
 [tox]
-envlist = docs,docs-linkcheck
+envlist = code,docs,docs-linkcheck
 minversion = 2.0
 skipsdist = true
 
+; basic test and coverage jobs
+[testenv:code]
+basepython = python3.8
+deps=
+    pytest
+    coverage
+    pytest-cov
+    requests
+    connexion
+
+setenv =
+    TESTS_BASE_PATH = {toxinidir}/near-rt-ric-simulator/tests
+commands =
+; Two test execution with pytest is needed as each simulator version need to be started separately. In addtion, each simulator need
+; environment setup that would cause interference if both simulator are executed in the same pytest run.
+; Each pytest run also need to point to the specific test case file for the reasons mentioned above.
+; Note that the second pytest (additional pytest added in the future) uses the 'append' flag to combine the coverage data
+; from the previous tests. The first pytest shall not have the 'append' since the it is supposed to erase previous coverage data
+; from earlier tox run.
+    pytest --cov {toxinidir}/near-rt-ric-simulator --cov-report xml --cov-report term-missing --cov-report html --cov-fail-under=70 \
+    {toxinidir}/near-rt-ric-simulator/tests/OSC_2.1.0/test_osc_2_1_0.py
+    pytest --cov-append --cov {toxinidir}/near-rt-ric-simulator --cov-report xml --cov-report term-missing --cov-report html \
+    --cov-fail-under=70 {toxinidir}/near-rt-ric-simulator/tests/STD_1.1.3/test_std_1_1_3.py
+    coverage xml -i
+
 # doc jobs
 [testenv:docs]
 whitelist_externals = echo