From d228663b48cdf0bf20017f963e828ec77aaa6528 Mon Sep 17 00:00:00 2001
From: Katopodisv <vkatopodis@ubitech.eu>
Date: Mon, 12 Dec 2022 15:49:49 +0200
Subject: [PATCH 1/4] Policy: create benchmark tests

---
 src/tests/benchmark/policy/.gitignore         |   2 +
 .../benchmark/policy/PolicyAddService.js      |  72 ++++++
 src/tests/benchmark/policy/PolicyDelete.js    |  53 ++++
 .../benchmark/policy/PolicyUpdateService.js   |  72 ++++++
 src/tests/benchmark/policy/README.md          |  17 ++
 src/tests/benchmark/policy/__init__.py        |  14 ++
 src/tests/benchmark/policy/deploy_specs.sh    |  26 ++
 .../policy/descriptors_emulated.json          | 121 +++++++++
 .../policy/descriptors_emulated_xr.json       | 108 ++++++++
 .../benchmark/policy/run_test_01_bootstrap.sh |  17 ++
 .../policy/run_test_02_create_service.sh      |  17 ++
 .../policy/run_test_03_delete_service.sh      |  17 ++
 .../benchmark/policy/run_test_04_cleanup.sh   |  17 ++
 src/tests/benchmark/policy/run_tests.sh       |  44 ++++
 src/tests/benchmark/policy/tests/.gitignore   |   2 +
 src/tests/benchmark/policy/tests/Fixtures.py  |  28 +++
 src/tests/benchmark/policy/tests/Objects.py   |  38 +++
 src/tests/benchmark/policy/tests/ObjectsXr.py | 238 ++++++++++++++++++
 src/tests/benchmark/policy/tests/__init__.py  |  14 ++
 .../policy/tests/test_functional_bootstrap.py |  95 +++++++
 .../policy/tests/test_functional_cleanup.py   |  80 ++++++
 .../tests/test_functional_create_service.py   | 124 +++++++++
 .../test_functional_create_service_xr.py      | 129 ++++++++++
 .../tests/test_functional_delete_service.py   |  99 ++++++++
 .../test_functional_delete_service_xr.py      | 133 ++++++++++
 25 files changed, 1577 insertions(+)
 create mode 100644 src/tests/benchmark/policy/.gitignore
 create mode 100644 src/tests/benchmark/policy/PolicyAddService.js
 create mode 100644 src/tests/benchmark/policy/PolicyDelete.js
 create mode 100644 src/tests/benchmark/policy/PolicyUpdateService.js
 create mode 100644 src/tests/benchmark/policy/README.md
 create mode 100644 src/tests/benchmark/policy/__init__.py
 create mode 100644 src/tests/benchmark/policy/deploy_specs.sh
 create mode 100644 src/tests/benchmark/policy/descriptors_emulated.json
 create mode 100644 src/tests/benchmark/policy/descriptors_emulated_xr.json
 create mode 100755 src/tests/benchmark/policy/run_test_01_bootstrap.sh
 create mode 100755 src/tests/benchmark/policy/run_test_02_create_service.sh
 create mode 100755 src/tests/benchmark/policy/run_test_03_delete_service.sh
 create mode 100755 src/tests/benchmark/policy/run_test_04_cleanup.sh
 create mode 100755 src/tests/benchmark/policy/run_tests.sh
 create mode 100644 src/tests/benchmark/policy/tests/.gitignore
 create mode 100644 src/tests/benchmark/policy/tests/Fixtures.py
 create mode 100644 src/tests/benchmark/policy/tests/Objects.py
 create mode 100644 src/tests/benchmark/policy/tests/ObjectsXr.py
 create mode 100644 src/tests/benchmark/policy/tests/__init__.py
 create mode 100644 src/tests/benchmark/policy/tests/test_functional_bootstrap.py
 create mode 100644 src/tests/benchmark/policy/tests/test_functional_cleanup.py
 create mode 100644 src/tests/benchmark/policy/tests/test_functional_create_service.py
 create mode 100644 src/tests/benchmark/policy/tests/test_functional_create_service_xr.py
 create mode 100644 src/tests/benchmark/policy/tests/test_functional_delete_service.py
 create mode 100644 src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py

diff --git a/src/tests/benchmark/policy/.gitignore b/src/tests/benchmark/policy/.gitignore
new file mode 100644
index 000000000..0a3f4400d
--- /dev/null
+++ b/src/tests/benchmark/policy/.gitignore
@@ -0,0 +1,2 @@
+# Add here your files containing confidential testbed details such as IP addresses, ports, usernames, passwords, etc.
+descriptors_real.json
diff --git a/src/tests/benchmark/policy/PolicyAddService.js b/src/tests/benchmark/policy/PolicyAddService.js
new file mode 100644
index 000000000..116ce394b
--- /dev/null
+++ b/src/tests/benchmark/policy/PolicyAddService.js
@@ -0,0 +1,72 @@
+import grpc from 'k6/net/grpc';
+import exec from "k6/execution";
+import { check, sleep } from 'k6';
+
+const client = new grpc.Client();
+client.load(['../proto'], 'policy.proto');
+
+export const data = [];
+for (let i = 1; i < 2; i++) {
+  data.push(
+    {
+        "serviceId": {
+            "context_id": {
+                "context_uuid": {"uuid": "admin"}
+            },
+            "service_uuid": {
+                "uuid": "6942d780-cfa9-4dea-a946-a8a0b3f7eab2"
+            }
+        },
+        "policyRuleBasic": {
+            "policyRuleId": {"uuid": {"uuid": i.toString()}},
+            "policyRuleState": {"policyRuleState": "POLICY_ACTIVE"},
+            "priority": 0,
+            "conditionList": [{"kpiId": {"kpi_id": {"uuid": "1"}}, 
+                            "numericalOperator": "POLICYRULE_CONDITION_NUMERICAL_EQUAL",
+                            "kpiValue": {"boolVal": false}
+    
+            }],
+            "actionList": [{}],
+            "booleanOperator": "POLICYRULE_CONDITION_BOOLEAN_OR"
+        }
+    }
+  );
+};
+
+export const options = {
+  scenarios :{
+
+    "AddPolicy-scenario": {
+      executor: "shared-iterations",
+      vus: 1,
+      iterations: data.length,
+      maxDuration: "1h"
+    }
+  }
+};
+
+export default () => {
+  client.connect('10.1.255.198:6060', {
+    plaintext: true,
+//    timeout: 10000
+  });
+
+  var item = data[exec.scenario.iterationInInstance];  
+  const response = client.invoke('policy.PolicyService/PolicyAddService', item);
+
+  check(response, {
+    'status is OK': (r) => r && r.status === grpc.StatusOK,
+  });
+
+  console.log(JSON.stringify(response.message));
+
+  client.close();
+  sleep(1);
+};
+
+export function handleSummary(data) {
+
+  return {
+    'summary_add_1.json': JSON.stringify(data.metrics.grpc_req_duration.values), //the default data object
+  };
+}
diff --git a/src/tests/benchmark/policy/PolicyDelete.js b/src/tests/benchmark/policy/PolicyDelete.js
new file mode 100644
index 000000000..85946837e
--- /dev/null
+++ b/src/tests/benchmark/policy/PolicyDelete.js
@@ -0,0 +1,53 @@
+import grpc from 'k6/net/grpc';
+import exec from "k6/execution";
+import { check, sleep } from 'k6';
+
+const client = new grpc.Client();
+client.load(['../proto'], 'policy.proto');
+
+export const data = [];
+for (let i = 1; i < 2; i++) {
+  data.push(
+    {
+     "uuid": {"uuid": i.toString()}
+    }
+  );
+};
+
+export const options = {
+  scenarios :{
+
+    "AddPolicy-scenario": {
+      executor: "shared-iterations",
+      vus: 1,
+      iterations: data.length,
+      maxDuration: "1h"
+    }
+  }
+};
+
+export default () => {
+  client.connect('10.1.255.198:6060', {
+    plaintext: true,
+//    timeout: 10000
+  });
+
+  var item = data[exec.scenario.iterationInInstance];  
+  const response = client.invoke('policy.PolicyService/PolicyDelete', item);
+
+  check(response, {
+    'status is OK': (r) => r && r.status === grpc.StatusOK,
+  });
+
+  console.log(JSON.stringify(response.message));
+
+  client.close();
+  sleep(1);
+};
+
+export function handleSummary(data) {
+
+  return {
+    'summary_delete_1.json': JSON.stringify(data.metrics.grpc_req_duration.values), //the default data object
+  };
+}
diff --git a/src/tests/benchmark/policy/PolicyUpdateService.js b/src/tests/benchmark/policy/PolicyUpdateService.js
new file mode 100644
index 000000000..8a1988ea5
--- /dev/null
+++ b/src/tests/benchmark/policy/PolicyUpdateService.js
@@ -0,0 +1,72 @@
+import grpc from 'k6/net/grpc';
+import exec from "k6/execution";
+import { check, sleep } from 'k6';
+
+const client = new grpc.Client();
+client.load(['../proto'], 'policy.proto');
+
+export const data = [];
+for (let i = 1; i < 2; i++) {
+  data.push(
+    {
+        "serviceId": {
+            "context_id": {
+                "context_uuid": {"uuid": "admin"}
+            },
+            "service_uuid": {
+                "uuid": "6942d780-cfa9-4dea-a946-a8a0b3f7eab2"
+            }
+        },
+        "policyRuleBasic": {
+            "policyRuleId": {"uuid": {"uuid": i.toString()}},
+            "policyRuleState": {"policyRuleState": "POLICY_ACTIVE"},
+            "priority": 0,
+            "conditionList": [{"kpiId": {"kpi_id": {"uuid": "1"}}, 
+                            "numericalOperator": "POLICYRULE_CONDITION_NUMERICAL_EQUAL",
+                            "kpiValue": {"boolVal": false}
+    
+            }],
+            "actionList": [{}],
+            "booleanOperator": "POLICYRULE_CONDITION_BOOLEAN_OR"
+        }
+    }
+  );
+};
+
+export const options = {
+  scenarios :{
+
+    "AddPolicy-scenario": {
+      executor: "shared-iterations",
+      vus: 1,
+      iterations: data.length,
+      maxDuration: "1h"
+    }
+  }
+};
+
+export default () => {
+  client.connect('10.1.255.198:6060', {
+    plaintext: true,
+//    timeout: 10000
+  });
+
+  var item = data[exec.scenario.iterationInInstance];  
+  const response = client.invoke('policy.PolicyService/PolicyUpdateService', item);
+
+  check(response, {
+    'status is OK': (r) => r && r.status === grpc.StatusOK,
+  });
+
+  console.log(JSON.stringify(response.message));
+
+  client.close();
+  sleep(1);
+};
+
+export function handleSummary(data) {
+
+  return {
+    'summary_add_1.json': JSON.stringify(data.metrics.grpc_req_duration.values), //the default data object
+  };
+}
diff --git a/src/tests/benchmark/policy/README.md b/src/tests/benchmark/policy/README.md
new file mode 100644
index 000000000..8b5b2a01e
--- /dev/null
+++ b/src/tests/benchmark/policy/README.md
@@ -0,0 +1,17 @@
+
+# Grafana k6 load testing tool
+
+# K6 Installation Instructions on Ubuntu
+
+sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
+echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
+sudo apt-get update
+sudo apt-get install k6
+
+Or install k6 via snap:
+
+sudo apt install snapd
+sudo snap install k6
+
+# Running K6 
+k6 run script.js
\ No newline at end of file
diff --git a/src/tests/benchmark/policy/__init__.py b/src/tests/benchmark/policy/__init__.py
new file mode 100644
index 000000000..70a332512
--- /dev/null
+++ b/src/tests/benchmark/policy/__init__.py
@@ -0,0 +1,14 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
diff --git a/src/tests/benchmark/policy/deploy_specs.sh b/src/tests/benchmark/policy/deploy_specs.sh
new file mode 100644
index 000000000..ffd91da35
--- /dev/null
+++ b/src/tests/benchmark/policy/deploy_specs.sh
@@ -0,0 +1,26 @@
+# Set the URL of your local Docker registry where the images will be uploaded to.
+export TFS_REGISTRY_IMAGE="http://localhost:32000/tfs/"
+
+# Set the list of components, separated by spaces, you want to build images for, and deploy.
+# Supported components are:
+#   context device automation policy service compute monitoring webui
+#   interdomain slice pathcomp dlt
+#   dbscanserving opticalattackmitigator opticalattackdetector
+#   l3_attackmitigator l3_centralizedattackdetector l3_distributedattackdetector
+export TFS_COMPONENTS="context device automation monitoring pathcomp service slice compute webui"
+
+# Set the tag you want to use for your images.
+export TFS_IMAGE_TAG="dev"
+
+# Set the name of the Kubernetes namespace to deploy to.
+export TFS_K8S_NAMESPACE="tfs"
+
+# Set additional manifest files to be applied after the deployment
+export TFS_EXTRA_MANIFESTS="manifests/nginx_ingress_http.yaml"
+
+# Set the new Grafana admin password
+export TFS_GRAFANA_PASSWORD="admin123+"
+
+# If not already set, disable skip-build flag.
+# If TFS_SKIP_BUILD is "YES", the containers are not rebuilt-retagged-repushed and existing ones are used.
+export TFS_SKIP_BUILD=${TFS_SKIP_BUILD:-""}
diff --git a/src/tests/benchmark/policy/descriptors_emulated.json b/src/tests/benchmark/policy/descriptors_emulated.json
new file mode 100644
index 000000000..a71d454f4
--- /dev/null
+++ b/src/tests/benchmark/policy/descriptors_emulated.json
@@ -0,0 +1,121 @@
+{
+    "contexts": [
+        {
+            "context_id": {"context_uuid": {"uuid": "admin"}},
+            "topology_ids": [],
+            "service_ids": []
+        }
+    ],
+    "topologies": [
+        {
+            "topology_id": {"topology_uuid": {"uuid": "admin"}, "context_id": {"context_uuid": {"uuid": "admin"}}},
+            "device_ids": [
+                {"device_uuid": {"uuid": "R1-EMU"}},
+                {"device_uuid": {"uuid": "R2-EMU"}},
+                {"device_uuid": {"uuid": "R3-EMU"}},
+                {"device_uuid": {"uuid": "R4-EMU"}},
+                {"device_uuid": {"uuid": "O1-OLS"}}                
+            ],
+            "link_ids": [
+                {"link_uuid": {"uuid": "R1-EMU/13/0/0==O1-OLS/aade6001-f00b-5e2f-a357-6a0a9d3de870"}},
+                {"link_uuid": {"uuid": "R2-EMU/13/0/0==O1-OLS/eb287d83-f05e-53ec-ab5a-adf6bd2b5418"}},
+                {"link_uuid": {"uuid": "R3-EMU/13/0/0==O1-OLS/0ef74f99-1acc-57bd-ab9d-4b958b06c513"}},
+                {"link_uuid": {"uuid": "R4-EMU/13/0/0==O1-OLS/50296d99-58cc-5ce7-82f5-fc8ee4eec2ec"}}
+            ]
+        }
+    ],
+    "devices": [
+        {
+            "device_id": {"device_uuid": {"uuid": "R1-EMU"}}, "device_type": "emu-packet-router",
+            "device_operational_status": 1, "device_drivers": [0], "device_endpoints": [],
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [
+                    {"uuid": "13/0/0", "type": "optical", "sample_types": []},
+                    {"uuid": "13/1/2", "type": "copper",  "sample_types": [101, 102, 201, 202]}
+                ]}}}
+            ]}
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "R2-EMU"}}, "device_type": "emu-packet-router",
+            "device_operational_status": 1, "device_drivers": [0], "device_endpoints": [],
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [
+                    {"uuid": "13/0/0", "type": "optical", "sample_types": []},
+                    {"uuid": "13/1/2", "type": "copper",  "sample_types": [101, 102, 201, 202]}
+                ]}}}
+            ]}
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "R3-EMU"}}, "device_type": "emu-packet-router",
+            "device_operational_status": 1, "device_drivers": [0], "device_endpoints": [],
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [
+                    {"uuid": "13/0/0", "type": "optical", "sample_types": []},
+                    {"uuid": "13/1/2", "type": "copper",  "sample_types": [101, 102, 201, 202]}
+                ]}}}
+            ]}
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "R4-EMU"}}, "device_type": "emu-packet-router",
+            "device_operational_status": 1, "device_drivers": [0], "device_endpoints": [],
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [
+                    {"uuid": "13/0/0", "type": "optical", "sample_types": []},
+                    {"uuid": "13/1/2", "type": "copper",  "sample_types": [101, 102, 201, 202]}
+                ]}}}
+            ]}
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "O1-OLS"}}, "device_type": "emu-open-line-system",
+            "device_operational_status": 1, "device_drivers": [0], "device_endpoints": [],
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [
+                    {"uuid": "aade6001-f00b-5e2f-a357-6a0a9d3de870", "type": "optical", "sample_types": []},
+                    {"uuid": "eb287d83-f05e-53ec-ab5a-adf6bd2b5418", "type": "optical", "sample_types": []},
+                    {"uuid": "0ef74f99-1acc-57bd-ab9d-4b958b06c513", "type": "optical", "sample_types": []},
+                    {"uuid": "50296d99-58cc-5ce7-82f5-fc8ee4eec2ec", "type": "optical", "sample_types": []}
+                ]}}}
+            ]}
+        }
+    ],
+    "links": [
+        {
+            "link_id": {"link_uuid": {"uuid": "R1-EMU/13/0/0==O1-OLS/aade6001-f00b-5e2f-a357-6a0a9d3de870"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R1-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "O1-OLS"}}, "endpoint_uuid": {"uuid": "aade6001-f00b-5e2f-a357-6a0a9d3de870"}}
+            ]
+        },
+        {
+            "link_id": {"link_uuid": {"uuid": "R2-EMU/13/0/0==O1-OLS/eb287d83-f05e-53ec-ab5a-adf6bd2b5418"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R2-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "O1-OLS"}}, "endpoint_uuid": {"uuid": "eb287d83-f05e-53ec-ab5a-adf6bd2b5418"}}
+            ]
+        },
+        {
+            "link_id": {"link_uuid": {"uuid": "R3-EMU/13/0/0==O1-OLS/0ef74f99-1acc-57bd-ab9d-4b958b06c513"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R3-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "O1-OLS"}}, "endpoint_uuid": {"uuid": "0ef74f99-1acc-57bd-ab9d-4b958b06c513"}}
+            ]
+        },
+        {
+            "link_id": {"link_uuid": {"uuid": "R4-EMU/13/0/0==O1-OLS/50296d99-58cc-5ce7-82f5-fc8ee4eec2ec"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R4-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "O1-OLS"}}, "endpoint_uuid": {"uuid": "50296d99-58cc-5ce7-82f5-fc8ee4eec2ec"}}
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/tests/benchmark/policy/descriptors_emulated_xr.json b/src/tests/benchmark/policy/descriptors_emulated_xr.json
new file mode 100644
index 000000000..30bd97ddd
--- /dev/null
+++ b/src/tests/benchmark/policy/descriptors_emulated_xr.json
@@ -0,0 +1,108 @@
+{
+    "contexts": [
+        {
+            "context_id": {"context_uuid": {"uuid": "admin"}},
+            "topology_ids": [],
+            "service_ids": []
+        }
+    ],
+    "topologies": [
+        {
+            "topology_id": {"topology_uuid": {"uuid": "admin"}, "context_id": {"context_uuid": {"uuid": "admin"}}},
+            "device_ids": [],
+            "link_ids": []
+        }
+    ],
+    "devices": [
+        {
+            "device_id": {"device_uuid": {"uuid": "R1-EMU"}},
+            "device_type": "emu-packet-router",
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
+            ]},
+            "device_operational_status": 1,
+            "device_drivers": [0],
+            "device_endpoints": []
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "R2-EMU"}},
+            "device_type": "emu-packet-router",
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
+            ]},
+            "device_operational_status": 1,
+            "device_drivers": [0],
+            "device_endpoints": []
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "R3-EMU"}},
+            "device_type": "emu-packet-router",
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
+            ]},
+            "device_operational_status": 1,
+            "device_drivers": [0],
+            "device_endpoints": []
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "R4-EMU"}},
+            "device_type": "emu-packet-router",
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
+            ]},
+            "device_operational_status": 1,
+            "device_drivers": [0],
+            "device_endpoints": []
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}},
+            "device_type": "xr-constellation",
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.19.219.44"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "443"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"username\": \"xr-user-1\", \"password\": \"xr-user-1\", \"hub_module_name\": \"XR HUB 1\"}"}}
+            ]},
+            "device_operational_status": 1,
+            "device_drivers": [6],
+            "device_endpoints": []
+        }
+    ],
+    "links": [
+        {
+            "link_id": {"link_uuid": {"uuid": "R1-EMU/13/0/0==XR HUB 1|XR-T4"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R1-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR HUB 1|XR-T4"}}
+            ]
+        },
+        {
+            "link_id": {"link_uuid": {"uuid": "R2-EMU/13/0/0==XR HUB 1|XR-T3"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R2-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR HUB 1|XR-T3"}}
+            ]
+        },
+        {
+            "link_id": {"link_uuid": {"uuid": "R3-EMU/13/0/0==XR1-XR LEAF 1|XR-T1"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R3-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR LEAF 1|XR-T1"}}
+            ]
+        },
+        {
+            "link_id": {"link_uuid": {"uuid": "R4-EMU/13/0/0==XR LEAF 2|XR-T1"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R4-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR LEAF 2|XR-T1"}}
+            ]
+        }
+    ]
+}
diff --git a/src/tests/benchmark/policy/run_test_01_bootstrap.sh b/src/tests/benchmark/policy/run_test_01_bootstrap.sh
new file mode 100755
index 000000000..fc15d2d9a
--- /dev/null
+++ b/src/tests/benchmark/policy/run_test_01_bootstrap.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+source tfs_runtime_env_vars.sh
+pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policytest_functional_bootstrap.py
diff --git a/src/tests/benchmark/policy/run_test_02_create_service.sh b/src/tests/benchmark/policy/run_test_02_create_service.sh
new file mode 100755
index 000000000..c14e19f53
--- /dev/null
+++ b/src/tests/benchmark/policy/run_test_02_create_service.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+source tfs_runtime_env_vars.sh
+pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policy/test_functional_create_service.py
diff --git a/src/tests/benchmark/policy/run_test_03_delete_service.sh b/src/tests/benchmark/policy/run_test_03_delete_service.sh
new file mode 100755
index 000000000..904f6161c
--- /dev/null
+++ b/src/tests/benchmark/policy/run_test_03_delete_service.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+source tfs_runtime_env_vars.sh
+pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policy/test_functional_delete_service.py
diff --git a/src/tests/benchmark/policy/run_test_04_cleanup.sh b/src/tests/benchmark/policy/run_test_04_cleanup.sh
new file mode 100755
index 000000000..ea3fcb61b
--- /dev/null
+++ b/src/tests/benchmark/policy/run_test_04_cleanup.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+source tfs_runtime_env_vars.sh
+pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policy/test_functional_cleanup.py
diff --git a/src/tests/benchmark/policy/run_tests.sh b/src/tests/benchmark/policy/run_tests.sh
new file mode 100755
index 000000000..0ad4be313
--- /dev/null
+++ b/src/tests/benchmark/policy/run_tests.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+
+PROJECTDIR=`pwd`
+
+RCFILE=$PROJECTDIR/coverage/.coveragerc
+COVERAGEFILE=$PROJECTDIR/coverage/.coverage
+
+# Configure the correct folder on the .coveragerc file
+cat $PROJECTDIR/coverage/.coveragerc.template | sed s+~/teraflow/controller+$PROJECTDIR/src+g > $RCFILE
+
+# Destroy old coverage file
+rm -f $COVERAGEFILE
+
+source tfs_runtime_env_vars.sh
+
+# Force a flush of Context database
+kubectl --namespace $TFS_K8S_NAMESPACE exec -it deployment/contextservice --container redis -- redis-cli FLUSHALL
+
+# Run functional tests
+pytest --log-level=INFO --verbose \
+    src/tests/ofc22/tests/test_functional_bootstrap.py
+
+pytest --log-level=INFO --verbose \
+    src/tests/ofc22/tests/test_functional_create_service.py
+
+pytest --log-level=INFO --verbose \
+    src/tests/ofc22/tests/test_functional_delete_service.py
+
+pytest --log-level=INFO --verbose \
+    src/tests/ofc22/tests/test_functional_cleanup.py
diff --git a/src/tests/benchmark/policy/tests/.gitignore b/src/tests/benchmark/policy/tests/.gitignore
new file mode 100644
index 000000000..76cb708d1
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/.gitignore
@@ -0,0 +1,2 @@
+# Add here your files containing confidential testbed details such as IP addresses, ports, usernames, passwords, etc.
+Credentials.py
diff --git a/src/tests/benchmark/policy/tests/Fixtures.py b/src/tests/benchmark/policy/tests/Fixtures.py
new file mode 100644
index 000000000..3b35a12e2
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/Fixtures.py
@@ -0,0 +1,28 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import pytest, logging
+from common.Settings import get_setting
+from tests.tools.mock_osm.Constants import WIM_PASSWORD, WIM_USERNAME
+from tests.tools.mock_osm.MockOSM import MockOSM
+from .Objects import WIM_MAPPING
+
+LOGGER = logging.getLogger(__name__)
+
+@pytest.fixture(scope='session')
+def osm_wim():
+    wim_url = 'http://{:s}:{:s}'.format(
+        get_setting('COMPUTESERVICE_SERVICE_HOST'), str(get_setting('COMPUTESERVICE_SERVICE_PORT_HTTP')))
+    LOGGER.info('WIM_MAPPING = {:s}'.format(str(WIM_MAPPING)))
+    return MockOSM(wim_url, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
diff --git a/src/tests/benchmark/policy/tests/Objects.py b/src/tests/benchmark/policy/tests/Objects.py
new file mode 100644
index 000000000..7bfbe9fce
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/Objects.py
@@ -0,0 +1,38 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+from common.tools.object_factory.Device import json_device_id
+from common.tools.object_factory.EndPoint import json_endpoint_id
+from tests.tools.mock_osm.Tools import connection_point, wim_mapping
+
+# ----- WIM Service Settings -------------------------------------------------------------------------------------------
+
+WIM_DC1_SITE_ID     = '1'
+WIM_DC1_DEVICE_ID   = json_device_id('R1-EMU')
+WIM_DC1_ENDPOINT_ID = json_endpoint_id(WIM_DC1_DEVICE_ID, '13/1/2')
+
+WIM_DC2_SITE_ID     = '2'
+WIM_DC2_DEVICE_ID   = json_device_id('R3-EMU')
+WIM_DC2_ENDPOINT_ID = json_endpoint_id(WIM_DC2_DEVICE_ID, '13/1/2')
+
+WIM_SEP_DC1, WIM_MAP_DC1 = wim_mapping(WIM_DC1_SITE_ID, WIM_DC1_ENDPOINT_ID)
+WIM_SEP_DC2, WIM_MAP_DC2 = wim_mapping(WIM_DC2_SITE_ID, WIM_DC2_ENDPOINT_ID)
+WIM_MAPPING  = [WIM_MAP_DC1, WIM_MAP_DC2]
+
+WIM_SRV_VLAN_ID = 300
+WIM_SERVICE_TYPE = 'ELINE'
+WIM_SERVICE_CONNECTION_POINTS = [
+    connection_point(WIM_SEP_DC1, 'dot1q', WIM_SRV_VLAN_ID),
+    connection_point(WIM_SEP_DC2, 'dot1q', WIM_SRV_VLAN_ID),
+]
diff --git a/src/tests/benchmark/policy/tests/ObjectsXr.py b/src/tests/benchmark/policy/tests/ObjectsXr.py
new file mode 100644
index 000000000..0cb223de2
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/ObjectsXr.py
@@ -0,0 +1,238 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+from typing import Dict, List, Tuple
+from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID
+from common.tools.object_factory.Context import json_context, json_context_id
+from common.tools.object_factory.Device import (
+    json_device_connect_rules, json_device_emulated_connect_rules, json_device_emulated_packet_router_disabled,
+    json_device_emulated_tapi_disabled, json_device_id, json_device_packetrouter_disabled, json_device_tapi_disabled)
+from common.tools.object_factory.EndPoint import json_endpoint, json_endpoint_id
+from common.tools.object_factory.Link import json_link, json_link_id
+from common.tools.object_factory.Topology import json_topology, json_topology_id
+from common.proto.kpi_sample_types_pb2 import KpiSampleType
+
+# ----- Context --------------------------------------------------------------------------------------------------------
+CONTEXT_ID = json_context_id(DEFAULT_CONTEXT_UUID)
+CONTEXT    = json_context(DEFAULT_CONTEXT_UUID)
+
+# ----- Topology -------------------------------------------------------------------------------------------------------
+TOPOLOGY_ID = json_topology_id(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
+TOPOLOGY    = json_topology(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
+
+# ----- Monitoring Samples ---------------------------------------------------------------------------------------------
+PACKET_PORT_SAMPLE_TYPES = [
+    KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED,
+    KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED,
+    KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED,
+    KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED,
+]
+
+# ----- Device Credentials and Settings --------------------------------------------------------------------------------
+try:
+    from .Credentials import DEVICE_R1_ADDRESS, DEVICE_R1_PORT, DEVICE_R1_USERNAME, DEVICE_R1_PASSWORD
+    from .Credentials import DEVICE_R3_ADDRESS, DEVICE_R3_PORT, DEVICE_R3_USERNAME, DEVICE_R3_PASSWORD
+    #from .Credentials import DEVICE_O1_ADDRESS, DEVICE_O1_PORT
+    USE_REAL_DEVICES = True     # Use real devices
+except ImportError:
+    USE_REAL_DEVICES = False    # Use emulated devices
+
+    DEVICE_R1_ADDRESS  = '0.0.0.0'
+    DEVICE_R1_PORT     = 830
+    DEVICE_R1_USERNAME = 'admin'
+    DEVICE_R1_PASSWORD = 'admin'
+
+    DEVICE_R3_ADDRESS  = '0.0.0.0'
+    DEVICE_R3_PORT     = 830
+    DEVICE_R3_USERNAME = 'admin'
+    DEVICE_R3_PASSWORD = 'admin'
+
+DEVICE_X1_ADDRESS  = '172.19.219.44'
+DEVICE_X1_PORT     = 443
+
+#USE_REAL_DEVICES = False     # Uncomment to force to use emulated devices
+
+def json_endpoint_ids(device_id : Dict, endpoint_descriptors : List[Tuple[str, str, List[int]]]):
+    return [
+        json_endpoint_id(device_id, ep_uuid, topology_id=None)
+        for ep_uuid, _, _ in endpoint_descriptors
+    ]
+
+def json_endpoints(device_id : Dict, endpoint_descriptors : List[Tuple[str, str, List[int]]]):
+    return [
+        json_endpoint(device_id, ep_uuid, ep_type, topology_id=None, kpi_sample_types=ep_sample_types)
+        for ep_uuid, ep_type, ep_sample_types in endpoint_descriptors
+    ]
+
+def get_link_uuid(a_device_id : Dict, a_endpoint_id : Dict, z_device_id : Dict, z_endpoint_id : Dict) -> str:
+    return '{:s}/{:s}=={:s}/{:s}'.format(
+        a_device_id['device_uuid']['uuid'], a_endpoint_id['endpoint_uuid']['uuid'],
+        z_device_id['device_uuid']['uuid'], z_endpoint_id['endpoint_uuid']['uuid'])
+
+
+# ----- Devices --------------------------------------------------------------------------------------------------------
+if not USE_REAL_DEVICES:
+    json_device_packetrouter_disabled = json_device_emulated_packet_router_disabled
+    json_device_tapi_disabled         = json_device_emulated_tapi_disabled
+
+DEVICE_R1_UUID          = 'R1-EMU'
+DEVICE_R1_TIMEOUT       = 120
+DEVICE_R1_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
+DEVICE_R1_ID            = json_device_id(DEVICE_R1_UUID)
+#DEVICE_R1_ENDPOINTS     = json_endpoints(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
+DEVICE_R1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
+DEVICE_R1               = json_device_packetrouter_disabled(DEVICE_R1_UUID)
+ENDPOINT_ID_R1_13_0_0   = DEVICE_R1_ENDPOINT_IDS[0]
+ENDPOINT_ID_R1_13_1_2   = DEVICE_R1_ENDPOINT_IDS[1]
+DEVICE_R1_CONNECT_RULES = json_device_connect_rules(DEVICE_R1_ADDRESS, DEVICE_R1_PORT, {
+    'username': DEVICE_R1_USERNAME,
+    'password': DEVICE_R1_PASSWORD,
+    'timeout' : DEVICE_R1_TIMEOUT,
+}) if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_R1_ENDPOINT_DEFS)
+
+
+DEVICE_R2_UUID          = 'R2-EMU'
+DEVICE_R2_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
+DEVICE_R2_ID            = json_device_id(DEVICE_R2_UUID)
+#DEVICE_R2_ENDPOINTS     = json_endpoints(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
+DEVICE_R2_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
+DEVICE_R2               = json_device_emulated_packet_router_disabled(DEVICE_R2_UUID)
+ENDPOINT_ID_R2_13_0_0   = DEVICE_R2_ENDPOINT_IDS[0]
+ENDPOINT_ID_R2_13_1_2   = DEVICE_R2_ENDPOINT_IDS[1]
+DEVICE_R2_CONNECT_RULES = json_device_emulated_connect_rules(DEVICE_R2_ENDPOINT_DEFS)
+
+
+DEVICE_R3_UUID          = 'R3-EMU'
+DEVICE_R3_TIMEOUT       = 120
+DEVICE_R3_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
+DEVICE_R3_ID            = json_device_id(DEVICE_R3_UUID)
+#DEVICE_R3_ENDPOINTS     = json_endpoints(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS)
+DEVICE_R3_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS)
+DEVICE_R3               = json_device_packetrouter_disabled(DEVICE_R3_UUID)
+ENDPOINT_ID_R3_13_0_0   = DEVICE_R3_ENDPOINT_IDS[0]
+ENDPOINT_ID_R3_13_1_2   = DEVICE_R3_ENDPOINT_IDS[1]
+DEVICE_R3_CONNECT_RULES = json_device_connect_rules(DEVICE_R3_ADDRESS, DEVICE_R3_PORT, {
+    'username': DEVICE_R3_USERNAME,
+    'password': DEVICE_R3_PASSWORD,
+    'timeout' : DEVICE_R3_TIMEOUT,
+}) if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_R3_ENDPOINT_DEFS)
+
+
+DEVICE_R4_UUID          = 'R4-EMU'
+DEVICE_R4_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
+DEVICE_R4_ID            = json_device_id(DEVICE_R4_UUID)
+#DEVICE_R4_ENDPOINTS     = json_endpoints(DEVICE_R4_ID, DEVICE_R4_ENDPOINT_DEFS)
+DEVICE_R4_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R4_ID, DEVICE_R4_ENDPOINT_DEFS)
+DEVICE_R4               = json_device_emulated_packet_router_disabled(DEVICE_R4_UUID)
+ENDPOINT_ID_R4_13_0_0   = DEVICE_R4_ENDPOINT_IDS[0]
+ENDPOINT_ID_R4_13_1_2   = DEVICE_R4_ENDPOINT_IDS[1]
+DEVICE_R4_CONNECT_RULES = json_device_emulated_connect_rules(DEVICE_R4_ENDPOINT_DEFS)
+
+
+DEVICE_X1_UUID          = 'X1-XR-CONSTELLATION'
+DEVICE_X1_TIMEOUT       = 120
+DEVICE_X1_ENDPOINT_DEFS = [
+    ('XR HUB 1|XR-T1', 'optical', []),
+    ('XR HUB 1|XR-T2', 'optical', []),
+    ('XR HUB 1|XR-T3', 'optical', []),
+    ('XR HUB 1|XR-T4', 'optical', []),
+    ('XR LEAF 1|XR-T1', 'optical', []),
+    ('XR LEAF 2|XR-T1', 'optical', []),
+]
+DEVICE_X1_ID            = json_device_id(DEVICE_X1_UUID)
+DEVICE_X1               = json_device_tapi_disabled(DEVICE_X1_UUID)
+DEVICE_X1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_X1_ID, DEVICE_X1_ENDPOINT_DEFS)
+# These match JSON, hence indexes are what theyt are
+ENDPOINT_ID_X1_EP1      = DEVICE_X1_ENDPOINT_IDS[3]
+ENDPOINT_ID_X1_EP2      = DEVICE_X1_ENDPOINT_IDS[2]
+ENDPOINT_ID_X1_EP3      = DEVICE_X1_ENDPOINT_IDS[4]
+ENDPOINT_ID_X1_EP4      = DEVICE_X1_ENDPOINT_IDS[5]
+DEVICE_X1_CONNECT_RULES = json_device_connect_rules(DEVICE_X1_ADDRESS, DEVICE_X1_PORT, {
+    'timeout' : DEVICE_X1_TIMEOUT,
+    "username": "xr-user-1",
+    "password": "xr-user-1",
+    "hub_module_name": "XR HUB 1"
+})
+# Always using real device (CM, whether CM has emulated backend is another story)
+#if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_X1_ENDPOINT_DEFS)
+
+
+# ----- Links ----------------------------------------------------------------------------------------------------------
+LINK_R1_X1_UUID = get_link_uuid(DEVICE_R1_ID, ENDPOINT_ID_R1_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP1)
+LINK_R1_X1_ID   = json_link_id(LINK_R1_X1_UUID)
+LINK_R1_X1      = json_link(LINK_R1_X1_UUID, [ENDPOINT_ID_R1_13_0_0, ENDPOINT_ID_X1_EP1])
+
+LINK_R2_X1_UUID = get_link_uuid(DEVICE_R2_ID, ENDPOINT_ID_R2_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP2)
+LINK_R2_X1_ID   = json_link_id(LINK_R2_X1_UUID)
+LINK_R2_X1      = json_link(LINK_R2_X1_UUID, [ENDPOINT_ID_R2_13_0_0, ENDPOINT_ID_X1_EP2])
+
+LINK_R3_X1_UUID = get_link_uuid(DEVICE_R3_ID, ENDPOINT_ID_R3_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP3)
+LINK_R3_X1_ID   = json_link_id(LINK_R3_X1_UUID)
+LINK_R3_X1      = json_link(LINK_R3_X1_UUID, [ENDPOINT_ID_R3_13_0_0, ENDPOINT_ID_X1_EP3])
+
+LINK_R4_X1_UUID = get_link_uuid(DEVICE_R4_ID, ENDPOINT_ID_R4_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP4)
+LINK_R4_X1_ID   = json_link_id(LINK_R4_X1_UUID)
+LINK_R4_X1      = json_link(LINK_R4_X1_UUID, [ENDPOINT_ID_R4_13_0_0, ENDPOINT_ID_X1_EP4])
+
+
+# ----- WIM Service Settings -------------------------------------------------------------------------------------------
+
+def compose_service_endpoint_id(endpoint_id):
+    device_uuid = endpoint_id['device_id']['device_uuid']['uuid']
+    endpoint_uuid = endpoint_id['endpoint_uuid']['uuid']
+    return ':'.join([device_uuid, endpoint_uuid])
+
+WIM_SEP_R1_ID      = compose_service_endpoint_id(ENDPOINT_ID_R1_13_1_2)
+WIM_SEP_R1_SITE_ID = '1'
+WIM_SEP_R1_BEARER  = WIM_SEP_R1_ID
+WIM_SRV_R1_VLAN_ID = 400
+
+WIM_SEP_R3_ID      = compose_service_endpoint_id(ENDPOINT_ID_R3_13_1_2)
+WIM_SEP_R3_SITE_ID = '2'
+WIM_SEP_R3_BEARER  = WIM_SEP_R3_ID
+WIM_SRV_R3_VLAN_ID = 500
+
+WIM_USERNAME = 'admin'
+WIM_PASSWORD = 'admin'
+
+WIM_MAPPING  = [
+    {'device-id': DEVICE_R1_UUID, 'service_endpoint_id': WIM_SEP_R1_ID,
+     'service_mapping_info': {'bearer': {'bearer-reference': WIM_SEP_R1_BEARER}, 'site-id': WIM_SEP_R1_SITE_ID}},
+    {'device-id': DEVICE_R3_UUID, 'service_endpoint_id': WIM_SEP_R3_ID,
+     'service_mapping_info': {'bearer': {'bearer-reference': WIM_SEP_R3_BEARER}, 'site-id': WIM_SEP_R3_SITE_ID}},
+]
+WIM_SERVICE_TYPE = 'ELINE'
+WIM_SERVICE_CONNECTION_POINTS = [
+    {'service_endpoint_id': WIM_SEP_R1_ID,
+        'service_endpoint_encapsulation_type': 'dot1q',
+        'service_endpoint_encapsulation_info': {'vlan': WIM_SRV_R1_VLAN_ID}},
+    {'service_endpoint_id': WIM_SEP_R3_ID,
+        'service_endpoint_encapsulation_type': 'dot1q',
+        'service_endpoint_encapsulation_info': {'vlan': WIM_SRV_R3_VLAN_ID}},
+]
+
+# ----- Object Collections ---------------------------------------------------------------------------------------------
+
+CONTEXTS = [CONTEXT]
+TOPOLOGIES = [TOPOLOGY]
+
+DEVICES = [
+    (DEVICE_R1, DEVICE_R1_CONNECT_RULES),
+    (DEVICE_R2, DEVICE_R2_CONNECT_RULES),
+    (DEVICE_R3, DEVICE_R3_CONNECT_RULES),
+    (DEVICE_R4, DEVICE_R4_CONNECT_RULES),
+    (DEVICE_X1, DEVICE_X1_CONNECT_RULES),
+]
+
+LINKS = [LINK_R1_X1, LINK_R2_X1, LINK_R3_X1, LINK_R4_X1]
diff --git a/src/tests/benchmark/policy/tests/__init__.py b/src/tests/benchmark/policy/tests/__init__.py
new file mode 100644
index 000000000..70a332512
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/__init__.py
@@ -0,0 +1,14 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
diff --git a/src/tests/benchmark/policy/tests/test_functional_bootstrap.py b/src/tests/benchmark/policy/tests/test_functional_bootstrap.py
new file mode 100644
index 000000000..71deb9d59
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/test_functional_bootstrap.py
@@ -0,0 +1,95 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import logging, time
+from common.proto.context_pb2 import ContextId, Empty
+from common.proto.monitoring_pb2 import KpiDescriptorList
+from common.tests.LoadScenario import load_scenario_from_descriptor
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from common.tools.object_factory.Context import json_context_id
+from context.client.ContextClient import ContextClient
+from device.client.DeviceClient import DeviceClient
+from monitoring.client.MonitoringClient import MonitoringClient
+from tests.Fixtures import context_client, device_client, monitoring_client # pylint: disable=unused-import
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
+
+def test_scenario_bootstrap(
+    context_client : ContextClient, # pylint: disable=redefined-outer-name
+    device_client : DeviceClient,   # pylint: disable=redefined-outer-name
+) -> None:
+    # ----- List entities - Ensure database is empty -------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == 0
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == 0
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == 0
+
+
+    # ----- Load Scenario ----------------------------------------------------------------------------------------------
+    descriptor_loader = load_scenario_from_descriptor(
+        DESCRIPTOR_FILE, context_client, device_client, None, None)
+
+
+    # ----- List entities - Ensure scenario is ready -------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == descriptor_loader.num_contexts
+
+    for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
+        response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
+        assert len(response.topologies) == num_topologies
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == descriptor_loader.num_devices
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == descriptor_loader.num_links
+
+    for context_uuid, _ in descriptor_loader.num_services.items():
+        response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
+        assert len(response.services) == 0
+
+def test_scenario_kpis_created(
+    context_client : ContextClient,         # pylint: disable=redefined-outer-name
+    monitoring_client: MonitoringClient,    # pylint: disable=redefined-outer-name
+) -> None:
+    """
+    This test validates that KPIs related to the service/device/endpoint were created
+    during the service creation process.
+    """
+    response = context_client.ListDevices(Empty())
+    kpis_expected = set()
+    for device in response.devices:
+        device_uuid = device.device_id.device_uuid.uuid
+        for endpoint in device.device_endpoints:
+            endpoint_uuid = endpoint.endpoint_id.endpoint_uuid.uuid
+            for kpi_sample_type in endpoint.kpi_sample_types:
+                kpis_expected.add((device_uuid, endpoint_uuid, kpi_sample_type))
+    num_kpis_expected = len(kpis_expected)
+    LOGGER.info('Num KPIs expected: {:d}'.format(num_kpis_expected))
+
+    num_kpis_created, num_retry = 0, 0
+    while (num_kpis_created != num_kpis_expected) and (num_retry < 5):
+        response: KpiDescriptorList = monitoring_client.GetKpiDescriptorList(Empty())
+        num_kpis_created = len(response.kpi_descriptor_list)
+        LOGGER.info('Num KPIs created: {:d}'.format(num_kpis_created))
+        time.sleep(0.5)
+        num_retry += 1
+    assert num_kpis_created == num_kpis_expected
diff --git a/src/tests/benchmark/policy/tests/test_functional_cleanup.py b/src/tests/benchmark/policy/tests/test_functional_cleanup.py
new file mode 100644
index 000000000..be807eaa0
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/test_functional_cleanup.py
@@ -0,0 +1,80 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import logging
+from common.tools.descriptor.Loader import DescriptorLoader
+from common.tools.object_factory.Context import json_context_id
+from common.proto.context_pb2 import ContextId, DeviceId, Empty, LinkId, TopologyId
+from context.client.ContextClient import ContextClient
+from device.client.DeviceClient import DeviceClient
+from tests.Fixtures import context_client, device_client    # pylint: disable=unused-import
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
+
+
+def test_services_removed(
+    context_client : ContextClient, # pylint: disable=redefined-outer-name
+    device_client : DeviceClient,   # pylint: disable=redefined-outer-name
+) -> None:
+    # ----- List entities - Ensure service is removed ------------------------------------------------------------------
+    with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f:
+        descriptors = f.read()
+
+    descriptor_loader = DescriptorLoader(descriptors)
+
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == descriptor_loader.num_contexts
+
+    for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
+        response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
+        assert len(response.topologies) == num_topologies
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == descriptor_loader.num_devices
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == descriptor_loader.num_links
+
+    for context_uuid, _ in descriptor_loader.num_services.items():
+        response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
+        assert len(response.services) == 0
+
+
+    # ----- Delete Links, Devices, Topologies, Contexts ----------------------------------------------------------------
+    for link in descriptor_loader.links:
+        context_client.RemoveLink(LinkId(**link['link_id']))
+
+    for device in descriptor_loader.devices:
+        device_client .DeleteDevice(DeviceId(**device['device_id']))
+
+    for context_uuid, topology_list in descriptor_loader.topologies.items():
+        for topology in topology_list:
+            context_client.RemoveTopology(TopologyId(**topology['topology_id']))
+
+    for context in descriptor_loader.contexts:
+        context_client.RemoveContext(ContextId(**context['context_id']))
+
+
+    # ----- List entities - Ensure database is empty again -------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == 0
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == 0
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == 0
diff --git a/src/tests/benchmark/policy/tests/test_functional_create_service.py b/src/tests/benchmark/policy/tests/test_functional_create_service.py
new file mode 100644
index 000000000..e606d060d
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/test_functional_create_service.py
@@ -0,0 +1,124 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import logging, random
+from common.DeviceTypes import DeviceTypeEnum
+from common.proto.context_pb2 import ContextId, Empty
+from common.proto.kpi_sample_types_pb2 import KpiSampleType
+from common.tools.descriptor.Loader import DescriptorLoader
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from common.tools.object_factory.Context import json_context_id
+from context.client.ContextClient import ContextClient
+from monitoring.client.MonitoringClient import MonitoringClient
+from tests.Fixtures import context_client, device_client, monitoring_client # pylint: disable=unused-import
+from tests.tools.mock_osm.MockOSM import MockOSM
+from .Fixtures import osm_wim # pylint: disable=unused-import
+from .Objects import WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
+DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM.value
+
+DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
+
+def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure scenario is ready -------------------------------------------------------------------
+    with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f:
+        descriptors = f.read()
+
+    descriptor_loader = DescriptorLoader(descriptors)
+
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == descriptor_loader.num_contexts
+
+    for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
+        response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
+        assert len(response.topologies) == num_topologies
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == descriptor_loader.num_devices
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == descriptor_loader.num_links
+
+    for context_uuid, num_services in descriptor_loader.num_services.items():
+        response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
+        assert len(response.services) == 0
+
+
+    # ----- Create Service ---------------------------------------------------------------------------------------------
+    service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS)
+    osm_wim.get_connectivity_service_status(service_uuid)
+
+
+    # ----- List entities - Ensure service is created ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == descriptor_loader.num_contexts
+
+    for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
+        response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
+        assert len(response.topologies) == num_topologies
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == descriptor_loader.num_devices
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == descriptor_loader.num_links
+
+    for context_uuid, num_services in descriptor_loader.num_services.items():
+        response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
+        LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
+        assert len(response.services) == 2*num_services # OLS & L3NM => (L3NM + TAPI)
+
+        for service in response.services:
+            service_id = service.service_id
+            response = context_client.ListConnections(service_id)
+            LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
+                grpc_message_to_json_string(service_id), len(response.connections),
+                grpc_message_to_json_string(response)))
+            assert len(response.connections) == 1 # one connection per service
+
+
+def test_scenario_kpi_values_created(
+    monitoring_client: MonitoringClient,    # pylint: disable=redefined-outer-name
+) -> None:
+    """
+    This test validates that KPI values have been inserted into the monitoring database.
+    We short k KPI descriptors to test.
+    """
+    response = monitoring_client.GetKpiDescriptorList(Empty())
+    kpi_descriptors = random.choices(response.kpi_descriptor_list, k=2)
+
+    for kpi_descriptor in kpi_descriptors:
+        MSG = 'KPI(kpi_uuid={:s}, device_uuid={:s}, endpoint_uuid={:s}, service_uuid={:s}, kpi_sample_type={:s})...'
+        LOGGER.info(MSG.format(
+            str(kpi_descriptor.kpi_id.kpi_id.uuid), str(kpi_descriptor.device_id.device_uuid.uuid),
+            str(kpi_descriptor.endpoint_id.endpoint_uuid.uuid), str(kpi_descriptor.service_id.service_uuid.uuid),
+            str(KpiSampleType.Name(kpi_descriptor.kpi_sample_type))))
+        response = monitoring_client.GetInstantKpi(kpi_descriptor.kpi_id)
+        kpi_uuid = response.kpi_id.kpi_id.uuid
+        assert kpi_uuid == kpi_descriptor.kpi_id.kpi_id.uuid
+        kpi_value_type = response.kpi_value.WhichOneof('value')
+        if kpi_value_type is None:
+            MSG = '  KPI({:s}): No instant value found'
+            LOGGER.warning(MSG.format(str(kpi_uuid)))
+        else:
+            kpi_timestamp = response.timestamp.timestamp
+            assert kpi_timestamp > 0
+            assert kpi_value_type == 'floatVal'
+            kpi_value = getattr(response.kpi_value, kpi_value_type)
+            MSG = '  KPI({:s}): timestamp={:s} value_type={:s} value={:s}'
+            LOGGER.info(MSG.format(str(kpi_uuid), str(kpi_timestamp), str(kpi_value_type), str(kpi_value)))
diff --git a/src/tests/benchmark/policy/tests/test_functional_create_service_xr.py b/src/tests/benchmark/policy/tests/test_functional_create_service_xr.py
new file mode 100644
index 000000000..bb78abc1e
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/test_functional_create_service_xr.py
@@ -0,0 +1,129 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import logging, pytest
+from common.DeviceTypes import DeviceTypeEnum
+from common.Settings import get_setting
+from common.tests.EventTools import EVENT_CREATE, EVENT_UPDATE, check_events
+from common.tools.object_factory.Connection import json_connection_id
+from common.tools.object_factory.Device import json_device_id
+from common.tools.object_factory.Service import json_service_id
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from compute.tests.mock_osm.MockOSM import MockOSM
+from context.client.ContextClient import ContextClient
+from context.client.EventsCollector import EventsCollector
+from common.proto.context_pb2 import ContextId, Empty
+from .ObjectsXr import (
+    CONTEXT_ID, CONTEXTS, DEVICE_X1_UUID, DEVICE_R1_UUID, DEVICE_R3_UUID, DEVICES, LINKS, TOPOLOGIES,
+    WIM_MAPPING, WIM_PASSWORD, WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE, WIM_USERNAME)
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
+DEVTYPE_XR_CONSTELLATION = DeviceTypeEnum.XR_CONSTELLATION.value
+
+
+@pytest.fixture(scope='session')
+def context_client():
+    _client = ContextClient(get_setting('CONTEXTSERVICE_SERVICE_HOST'), get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC'))
+    yield _client
+    _client.close()
+
+
+@pytest.fixture(scope='session')
+def osm_wim():
+    wim_url = 'http://{:s}:{:s}'.format(
+        get_setting('COMPUTESERVICE_SERVICE_HOST'), str(get_setting('COMPUTESERVICE_SERVICE_PORT_HTTP')))
+    return MockOSM(wim_url, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
+
+
+def test_scenario_is_correct(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure links are created -------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    assert len(response.services) == 0
+
+
+def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
+    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
+    # events_collector = EventsCollector(context_client, log_events_received=True)
+    # events_collector.start()
+
+    # ----- Create Service ---------------------------------------------------------------------------------------------
+    service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS)
+    osm_wim.get_connectivity_service_status(service_uuid)
+
+    # ----- Validate collected events ----------------------------------------------------------------------------------
+
+    # packet_connection_uuid = '{:s}:{:s}'.format(service_uuid, DEVTYPE_EMU_PR)
+    # optical_connection_uuid = '{:s}:optical:{:s}'.format(service_uuid, DEVTYPE_XR_CONSTELLATION)
+    # optical_service_uuid = '{:s}:optical'.format(service_uuid)
+
+    # expected_events = [
+    #     # Create packet service and add first endpoint
+    #     ('ServiceEvent',    EVENT_CREATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
+    #     ('ServiceEvent',    EVENT_UPDATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
+
+    #     # Configure OLS controller, create optical service, create optical connection
+    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_X1_UUID)),
+    #     ('ServiceEvent',    EVENT_CREATE, json_service_id(optical_service_uuid, context_id=CONTEXT_ID)),
+    #     ('ConnectionEvent', EVENT_CREATE, json_connection_id(optical_connection_uuid)),
+
+    #     # Configure endpoint packet devices, add second endpoint to service, create connection
+    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R1_UUID)),
+    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R3_UUID)),
+    #     ('ServiceEvent',    EVENT_UPDATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
+    #     ('ConnectionEvent', EVENT_CREATE, json_connection_id(packet_connection_uuid)),
+    # ]
+    # check_events(events_collector, expected_events)
+
+    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
+    # events_collector.stop()
+
+
+def test_scenario_service_created(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure service is created ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
+    assert len(response.services) == 2 # L3NM + TAPI
+    for service in response.services:
+        service_id = service.service_id
+        response = context_client.ListConnections(service_id)
+        LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
+            grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
+        assert len(response.connections) == 1 # one connection per service
diff --git a/src/tests/benchmark/policy/tests/test_functional_delete_service.py b/src/tests/benchmark/policy/tests/test_functional_delete_service.py
new file mode 100644
index 000000000..0f8d08801
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/test_functional_delete_service.py
@@ -0,0 +1,99 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import logging
+from common.Constants import DEFAULT_CONTEXT_UUID
+from common.DeviceTypes import DeviceTypeEnum
+from common.proto.context_pb2 import ContextId, Empty, ServiceTypeEnum
+from common.tools.descriptor.Loader import DescriptorLoader
+from common.tools.object_factory.Context import json_context_id
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from context.client.ContextClient import ContextClient
+from tests.Fixtures import context_client   # pylint: disable=unused-import
+from tests.tools.mock_osm.MockOSM import MockOSM
+from .Fixtures import osm_wim # pylint: disable=unused-import
+
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
+DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM.value
+
+DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
+
+
+def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure service is created ------------------------------------------------------------------
+    with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f:
+        descriptors = f.read()
+
+    descriptor_loader = DescriptorLoader(descriptors)
+
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == descriptor_loader.num_contexts
+
+    for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
+        response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
+        assert len(response.topologies) == num_topologies
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == descriptor_loader.num_devices
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == descriptor_loader.num_links
+
+    l3nm_service_uuids = set()
+    response = context_client.ListServices(ContextId(**json_context_id(DEFAULT_CONTEXT_UUID)))
+    assert len(response.services) == 2 # OLS & L3NM => (L3NM + TAPI)
+    for service in response.services:
+        service_id = service.service_id
+
+        if service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM:
+            service_uuid = service_id.service_uuid.uuid
+            l3nm_service_uuids.add(service_uuid)
+            osm_wim.conn_info[service_uuid] = {}
+
+        response = context_client.ListConnections(service_id)
+        LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
+            grpc_message_to_json_string(service_id), len(response.connections),
+            grpc_message_to_json_string(response)))
+        assert len(response.connections) == 1 # one connection per service
+
+    # Identify service to delete
+    assert len(l3nm_service_uuids) == 1  # assume a single L3NM service has been created
+    l3nm_service_uuid = set(l3nm_service_uuids).pop()
+
+
+    # ----- Delete Service ---------------------------------------------------------------------------------------------
+    osm_wim.delete_connectivity_service(l3nm_service_uuid)
+
+
+    # ----- List entities - Ensure service is removed ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == descriptor_loader.num_contexts
+
+    for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
+        response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
+        assert len(response.topologies) == num_topologies
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == descriptor_loader.num_devices
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == descriptor_loader.num_links
+
+    for context_uuid, num_services in descriptor_loader.num_services.items():
+        response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
+        assert len(response.services) == 0
diff --git a/src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py b/src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py
new file mode 100644
index 000000000..f28828be0
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py
@@ -0,0 +1,133 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import logging, pytest
+from common.DeviceTypes import DeviceTypeEnum
+from common.Settings import get_setting
+from common.tests.EventTools import EVENT_REMOVE, EVENT_UPDATE, check_events
+from common.tools.object_factory.Connection import json_connection_id
+from common.tools.object_factory.Device import json_device_id
+from common.tools.object_factory.Service import json_service_id
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from compute.tests.mock_osm.MockOSM import MockOSM
+from context.client.ContextClient import ContextClient
+from context.client.EventsCollector import EventsCollector
+from common.proto.context_pb2 import ContextId, Empty, ServiceTypeEnum
+from .ObjectsXr import (
+    CONTEXT_ID, CONTEXTS, DEVICE_X1_UUID, DEVICE_R1_UUID, DEVICE_R3_UUID, DEVICES, LINKS, TOPOLOGIES, WIM_MAPPING,
+    WIM_PASSWORD, WIM_USERNAME)
+
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
+DEVTYPE_XR_CONSTELLATION = DeviceTypeEnum.XR_CONSTELLATION.value
+
+@pytest.fixture(scope='session')
+def context_client():
+    _client = ContextClient(get_setting('CONTEXTSERVICE_SERVICE_HOST'), get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC'))
+    yield _client
+    _client.close()
+
+
+@pytest.fixture(scope='session')
+def osm_wim():
+    wim_url = 'http://{:s}:{:s}'.format(
+        get_setting('COMPUTESERVICE_SERVICE_HOST'), str(get_setting('COMPUTESERVICE_SERVICE_PORT_HTTP')))
+    return MockOSM(wim_url, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
+
+
+def test_scenario_is_correct(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure service is created ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
+    assert len(response.services) == 2 # L3NM + TAPI
+    for service in response.services:
+        service_id = service.service_id
+        response = context_client.ListConnections(service_id)
+        LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
+            grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
+        assert len(response.connections) == 1 # one connection per service
+
+
+def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
+    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
+    events_collector = EventsCollector(context_client, log_events_received=True)
+    events_collector.start()
+
+    # ----- Delete Service ---------------------------------------------------------------------------------------------
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
+    assert len(response.services) == 2 # L3NM + TAPI
+    service_uuids = set()
+    for service in response.services:
+        if service.service_type != ServiceTypeEnum.SERVICETYPE_L3NM: continue
+        service_uuid = service.service_id.service_uuid.uuid
+        service_uuids.add(service_uuid)
+        osm_wim.conn_info[service_uuid] = {}
+
+    assert len(service_uuids) == 1  # assume a single service has been created
+    service_uuid = set(service_uuids).pop()
+
+    osm_wim.delete_connectivity_service(service_uuid)
+
+    # ----- Validate collected events ----------------------------------------------------------------------------------
+    # packet_connection_uuid = '{:s}:{:s}'.format(service_uuid, DEVTYPE_EMU_PR)
+    # optical_connection_uuid = '{:s}:optical:{:s}'.format(service_uuid, DEVTYPE_XR_CONSTELLATION)
+    # optical_service_uuid = '{:s}:optical'.format(service_uuid)
+
+    # expected_events = [
+    #     ('ConnectionEvent', EVENT_REMOVE, json_connection_id(packet_connection_uuid)),
+    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R1_UUID)),
+    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R3_UUID)),
+    #     ('ServiceEvent',    EVENT_REMOVE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
+    #     ('ConnectionEvent', EVENT_REMOVE, json_connection_id(optical_connection_uuid)),
+    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_X1_UUID)),
+    #     ('ServiceEvent',    EVENT_REMOVE, json_service_id(optical_service_uuid, context_id=CONTEXT_ID)),
+    # ]
+    # check_events(events_collector, expected_events)
+
+    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
+    # events_collector.stop()
+
+
+def test_services_removed(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure service is removed ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    assert len(response.services) == 0
-- 
GitLab


From f5ab1a58da0b7a6ff76c0b34f5bdcd45a47a8baf Mon Sep 17 00:00:00 2001
From: Katopodisv <vkatopodis@ubitech.eu>
Date: Tue, 13 Dec 2022 14:01:29 +0200
Subject: [PATCH 2/4] Fix policy benchmark tests

---
 .../benchmark/policy/PolicyAddService.js      |   4 +-
 .../benchmark/policy/PolicyUpdateService.js   |   4 +-
 .../policy/descriptors_emulated_xr.json       | 108 --------
 .../benchmark/policy/run_test_01_bootstrap.sh |   2 +-
 .../policy/run_test_02_create_service.sh      |   2 +-
 .../policy/run_test_03_delete_service.sh      |   2 +-
 .../benchmark/policy/run_test_04_cleanup.sh   |   2 +-
 src/tests/benchmark/policy/run_tests.sh       |  44 ----
 src/tests/benchmark/policy/tests/ObjectsXr.py | 238 ------------------
 .../test_functional_create_service_xr.py      | 129 ----------
 .../test_functional_delete_service_xr.py      | 133 ----------
 11 files changed, 8 insertions(+), 660 deletions(-)
 delete mode 100644 src/tests/benchmark/policy/descriptors_emulated_xr.json
 delete mode 100755 src/tests/benchmark/policy/run_tests.sh
 delete mode 100644 src/tests/benchmark/policy/tests/ObjectsXr.py
 delete mode 100644 src/tests/benchmark/policy/tests/test_functional_create_service_xr.py
 delete mode 100644 src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py

diff --git a/src/tests/benchmark/policy/PolicyAddService.js b/src/tests/benchmark/policy/PolicyAddService.js
index 116ce394b..708209ba0 100644
--- a/src/tests/benchmark/policy/PolicyAddService.js
+++ b/src/tests/benchmark/policy/PolicyAddService.js
@@ -19,7 +19,7 @@ for (let i = 1; i < 2; i++) {
         },
         "policyRuleBasic": {
             "policyRuleId": {"uuid": {"uuid": i.toString()}},
-            "policyRuleState": {"policyRuleState": "POLICY_ACTIVE"},
+            "policyRuleState": {"policyRuleState": "POLICY_UNDEFINED"},
             "priority": 0,
             "conditionList": [{"kpiId": {"kpi_id": {"uuid": "1"}}, 
                             "numericalOperator": "POLICYRULE_CONDITION_NUMERICAL_EQUAL",
@@ -27,7 +27,7 @@ for (let i = 1; i < 2; i++) {
     
             }],
             "actionList": [{}],
-            "booleanOperator": "POLICYRULE_CONDITION_BOOLEAN_OR"
+            "booleanOperator": "POLICYRULE_CONDITION_BOOLEAN_UNDEFINED"
         }
     }
   );
diff --git a/src/tests/benchmark/policy/PolicyUpdateService.js b/src/tests/benchmark/policy/PolicyUpdateService.js
index 8a1988ea5..a3774f9da 100644
--- a/src/tests/benchmark/policy/PolicyUpdateService.js
+++ b/src/tests/benchmark/policy/PolicyUpdateService.js
@@ -19,7 +19,7 @@ for (let i = 1; i < 2; i++) {
         },
         "policyRuleBasic": {
             "policyRuleId": {"uuid": {"uuid": i.toString()}},
-            "policyRuleState": {"policyRuleState": "POLICY_ACTIVE"},
+            "policyRuleState": {"policyRuleState": "POLICY_UNDEFINED"},
             "priority": 0,
             "conditionList": [{"kpiId": {"kpi_id": {"uuid": "1"}}, 
                             "numericalOperator": "POLICYRULE_CONDITION_NUMERICAL_EQUAL",
@@ -27,7 +27,7 @@ for (let i = 1; i < 2; i++) {
     
             }],
             "actionList": [{}],
-            "booleanOperator": "POLICYRULE_CONDITION_BOOLEAN_OR"
+            "booleanOperator": "POLICYRULE_CONDITION_BOOLEAN_UNDEFINED"
         }
     }
   );
diff --git a/src/tests/benchmark/policy/descriptors_emulated_xr.json b/src/tests/benchmark/policy/descriptors_emulated_xr.json
deleted file mode 100644
index 30bd97ddd..000000000
--- a/src/tests/benchmark/policy/descriptors_emulated_xr.json
+++ /dev/null
@@ -1,108 +0,0 @@
-{
-    "contexts": [
-        {
-            "context_id": {"context_uuid": {"uuid": "admin"}},
-            "topology_ids": [],
-            "service_ids": []
-        }
-    ],
-    "topologies": [
-        {
-            "topology_id": {"topology_uuid": {"uuid": "admin"}, "context_id": {"context_uuid": {"uuid": "admin"}}},
-            "device_ids": [],
-            "link_ids": []
-        }
-    ],
-    "devices": [
-        {
-            "device_id": {"device_uuid": {"uuid": "R1-EMU"}},
-            "device_type": "emu-packet-router",
-            "device_config": {"config_rules": [
-                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
-                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
-                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
-            ]},
-            "device_operational_status": 1,
-            "device_drivers": [0],
-            "device_endpoints": []
-        },
-        {
-            "device_id": {"device_uuid": {"uuid": "R2-EMU"}},
-            "device_type": "emu-packet-router",
-            "device_config": {"config_rules": [
-                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
-                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
-                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
-            ]},
-            "device_operational_status": 1,
-            "device_drivers": [0],
-            "device_endpoints": []
-        },
-        {
-            "device_id": {"device_uuid": {"uuid": "R3-EMU"}},
-            "device_type": "emu-packet-router",
-            "device_config": {"config_rules": [
-                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
-                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
-                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
-            ]},
-            "device_operational_status": 1,
-            "device_drivers": [0],
-            "device_endpoints": []
-        },
-        {
-            "device_id": {"device_uuid": {"uuid": "R4-EMU"}},
-            "device_type": "emu-packet-router",
-            "device_config": {"config_rules": [
-                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
-                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
-                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
-            ]},
-            "device_operational_status": 1,
-            "device_drivers": [0],
-            "device_endpoints": []
-        },
-        {
-            "device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}},
-            "device_type": "xr-constellation",
-            "device_config": {"config_rules": [
-                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.19.219.44"}},
-                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "443"}},
-                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"username\": \"xr-user-1\", \"password\": \"xr-user-1\", \"hub_module_name\": \"XR HUB 1\"}"}}
-            ]},
-            "device_operational_status": 1,
-            "device_drivers": [6],
-            "device_endpoints": []
-        }
-    ],
-    "links": [
-        {
-            "link_id": {"link_uuid": {"uuid": "R1-EMU/13/0/0==XR HUB 1|XR-T4"}},
-            "link_endpoint_ids": [
-                {"device_id": {"device_uuid": {"uuid": "R1-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
-                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR HUB 1|XR-T4"}}
-            ]
-        },
-        {
-            "link_id": {"link_uuid": {"uuid": "R2-EMU/13/0/0==XR HUB 1|XR-T3"}},
-            "link_endpoint_ids": [
-                {"device_id": {"device_uuid": {"uuid": "R2-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
-                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR HUB 1|XR-T3"}}
-            ]
-        },
-        {
-            "link_id": {"link_uuid": {"uuid": "R3-EMU/13/0/0==XR1-XR LEAF 1|XR-T1"}},
-            "link_endpoint_ids": [
-                {"device_id": {"device_uuid": {"uuid": "R3-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
-                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR LEAF 1|XR-T1"}}
-            ]
-        },
-        {
-            "link_id": {"link_uuid": {"uuid": "R4-EMU/13/0/0==XR LEAF 2|XR-T1"}},
-            "link_endpoint_ids": [
-                {"device_id": {"device_uuid": {"uuid": "R4-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
-                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR LEAF 2|XR-T1"}}
-            ]
-        }
-    ]
-}
diff --git a/src/tests/benchmark/policy/run_test_01_bootstrap.sh b/src/tests/benchmark/policy/run_test_01_bootstrap.sh
index fc15d2d9a..10b18257b 100755
--- a/src/tests/benchmark/policy/run_test_01_bootstrap.sh
+++ b/src/tests/benchmark/policy/run_test_01_bootstrap.sh
@@ -14,4 +14,4 @@
 # limitations under the License.
 
 source tfs_runtime_env_vars.sh
-pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policytest_functional_bootstrap.py
+pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policy/tests/test_functional_bootstrap.py
diff --git a/src/tests/benchmark/policy/run_test_02_create_service.sh b/src/tests/benchmark/policy/run_test_02_create_service.sh
index c14e19f53..2f61bcf97 100755
--- a/src/tests/benchmark/policy/run_test_02_create_service.sh
+++ b/src/tests/benchmark/policy/run_test_02_create_service.sh
@@ -14,4 +14,4 @@
 # limitations under the License.
 
 source tfs_runtime_env_vars.sh
-pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policy/test_functional_create_service.py
+pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO tests/tests/test_functional_create_service.py
diff --git a/src/tests/benchmark/policy/run_test_03_delete_service.sh b/src/tests/benchmark/policy/run_test_03_delete_service.sh
index 904f6161c..2e78c8b7e 100755
--- a/src/tests/benchmark/policy/run_test_03_delete_service.sh
+++ b/src/tests/benchmark/policy/run_test_03_delete_service.sh
@@ -14,4 +14,4 @@
 # limitations under the License.
 
 source tfs_runtime_env_vars.sh
-pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policy/test_functional_delete_service.py
+pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO tests/tests/test_functional_delete_service.py
diff --git a/src/tests/benchmark/policy/run_test_04_cleanup.sh b/src/tests/benchmark/policy/run_test_04_cleanup.sh
index ea3fcb61b..a2be265de 100755
--- a/src/tests/benchmark/policy/run_test_04_cleanup.sh
+++ b/src/tests/benchmark/policy/run_test_04_cleanup.sh
@@ -14,4 +14,4 @@
 # limitations under the License.
 
 source tfs_runtime_env_vars.sh
-pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policy/test_functional_cleanup.py
+pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policy/tests/test_functional_cleanup.py
diff --git a/src/tests/benchmark/policy/run_tests.sh b/src/tests/benchmark/policy/run_tests.sh
deleted file mode 100755
index 0ad4be313..000000000
--- a/src/tests/benchmark/policy/run_tests.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/bash
-# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
-#
-# 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.
-
-
-PROJECTDIR=`pwd`
-
-RCFILE=$PROJECTDIR/coverage/.coveragerc
-COVERAGEFILE=$PROJECTDIR/coverage/.coverage
-
-# Configure the correct folder on the .coveragerc file
-cat $PROJECTDIR/coverage/.coveragerc.template | sed s+~/teraflow/controller+$PROJECTDIR/src+g > $RCFILE
-
-# Destroy old coverage file
-rm -f $COVERAGEFILE
-
-source tfs_runtime_env_vars.sh
-
-# Force a flush of Context database
-kubectl --namespace $TFS_K8S_NAMESPACE exec -it deployment/contextservice --container redis -- redis-cli FLUSHALL
-
-# Run functional tests
-pytest --log-level=INFO --verbose \
-    src/tests/ofc22/tests/test_functional_bootstrap.py
-
-pytest --log-level=INFO --verbose \
-    src/tests/ofc22/tests/test_functional_create_service.py
-
-pytest --log-level=INFO --verbose \
-    src/tests/ofc22/tests/test_functional_delete_service.py
-
-pytest --log-level=INFO --verbose \
-    src/tests/ofc22/tests/test_functional_cleanup.py
diff --git a/src/tests/benchmark/policy/tests/ObjectsXr.py b/src/tests/benchmark/policy/tests/ObjectsXr.py
deleted file mode 100644
index 0cb223de2..000000000
--- a/src/tests/benchmark/policy/tests/ObjectsXr.py
+++ /dev/null
@@ -1,238 +0,0 @@
-# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
-#
-# 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.
-
-from typing import Dict, List, Tuple
-from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID
-from common.tools.object_factory.Context import json_context, json_context_id
-from common.tools.object_factory.Device import (
-    json_device_connect_rules, json_device_emulated_connect_rules, json_device_emulated_packet_router_disabled,
-    json_device_emulated_tapi_disabled, json_device_id, json_device_packetrouter_disabled, json_device_tapi_disabled)
-from common.tools.object_factory.EndPoint import json_endpoint, json_endpoint_id
-from common.tools.object_factory.Link import json_link, json_link_id
-from common.tools.object_factory.Topology import json_topology, json_topology_id
-from common.proto.kpi_sample_types_pb2 import KpiSampleType
-
-# ----- Context --------------------------------------------------------------------------------------------------------
-CONTEXT_ID = json_context_id(DEFAULT_CONTEXT_UUID)
-CONTEXT    = json_context(DEFAULT_CONTEXT_UUID)
-
-# ----- Topology -------------------------------------------------------------------------------------------------------
-TOPOLOGY_ID = json_topology_id(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
-TOPOLOGY    = json_topology(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
-
-# ----- Monitoring Samples ---------------------------------------------------------------------------------------------
-PACKET_PORT_SAMPLE_TYPES = [
-    KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED,
-    KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED,
-    KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED,
-    KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED,
-]
-
-# ----- Device Credentials and Settings --------------------------------------------------------------------------------
-try:
-    from .Credentials import DEVICE_R1_ADDRESS, DEVICE_R1_PORT, DEVICE_R1_USERNAME, DEVICE_R1_PASSWORD
-    from .Credentials import DEVICE_R3_ADDRESS, DEVICE_R3_PORT, DEVICE_R3_USERNAME, DEVICE_R3_PASSWORD
-    #from .Credentials import DEVICE_O1_ADDRESS, DEVICE_O1_PORT
-    USE_REAL_DEVICES = True     # Use real devices
-except ImportError:
-    USE_REAL_DEVICES = False    # Use emulated devices
-
-    DEVICE_R1_ADDRESS  = '0.0.0.0'
-    DEVICE_R1_PORT     = 830
-    DEVICE_R1_USERNAME = 'admin'
-    DEVICE_R1_PASSWORD = 'admin'
-
-    DEVICE_R3_ADDRESS  = '0.0.0.0'
-    DEVICE_R3_PORT     = 830
-    DEVICE_R3_USERNAME = 'admin'
-    DEVICE_R3_PASSWORD = 'admin'
-
-DEVICE_X1_ADDRESS  = '172.19.219.44'
-DEVICE_X1_PORT     = 443
-
-#USE_REAL_DEVICES = False     # Uncomment to force to use emulated devices
-
-def json_endpoint_ids(device_id : Dict, endpoint_descriptors : List[Tuple[str, str, List[int]]]):
-    return [
-        json_endpoint_id(device_id, ep_uuid, topology_id=None)
-        for ep_uuid, _, _ in endpoint_descriptors
-    ]
-
-def json_endpoints(device_id : Dict, endpoint_descriptors : List[Tuple[str, str, List[int]]]):
-    return [
-        json_endpoint(device_id, ep_uuid, ep_type, topology_id=None, kpi_sample_types=ep_sample_types)
-        for ep_uuid, ep_type, ep_sample_types in endpoint_descriptors
-    ]
-
-def get_link_uuid(a_device_id : Dict, a_endpoint_id : Dict, z_device_id : Dict, z_endpoint_id : Dict) -> str:
-    return '{:s}/{:s}=={:s}/{:s}'.format(
-        a_device_id['device_uuid']['uuid'], a_endpoint_id['endpoint_uuid']['uuid'],
-        z_device_id['device_uuid']['uuid'], z_endpoint_id['endpoint_uuid']['uuid'])
-
-
-# ----- Devices --------------------------------------------------------------------------------------------------------
-if not USE_REAL_DEVICES:
-    json_device_packetrouter_disabled = json_device_emulated_packet_router_disabled
-    json_device_tapi_disabled         = json_device_emulated_tapi_disabled
-
-DEVICE_R1_UUID          = 'R1-EMU'
-DEVICE_R1_TIMEOUT       = 120
-DEVICE_R1_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
-DEVICE_R1_ID            = json_device_id(DEVICE_R1_UUID)
-#DEVICE_R1_ENDPOINTS     = json_endpoints(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
-DEVICE_R1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
-DEVICE_R1               = json_device_packetrouter_disabled(DEVICE_R1_UUID)
-ENDPOINT_ID_R1_13_0_0   = DEVICE_R1_ENDPOINT_IDS[0]
-ENDPOINT_ID_R1_13_1_2   = DEVICE_R1_ENDPOINT_IDS[1]
-DEVICE_R1_CONNECT_RULES = json_device_connect_rules(DEVICE_R1_ADDRESS, DEVICE_R1_PORT, {
-    'username': DEVICE_R1_USERNAME,
-    'password': DEVICE_R1_PASSWORD,
-    'timeout' : DEVICE_R1_TIMEOUT,
-}) if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_R1_ENDPOINT_DEFS)
-
-
-DEVICE_R2_UUID          = 'R2-EMU'
-DEVICE_R2_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
-DEVICE_R2_ID            = json_device_id(DEVICE_R2_UUID)
-#DEVICE_R2_ENDPOINTS     = json_endpoints(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
-DEVICE_R2_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
-DEVICE_R2               = json_device_emulated_packet_router_disabled(DEVICE_R2_UUID)
-ENDPOINT_ID_R2_13_0_0   = DEVICE_R2_ENDPOINT_IDS[0]
-ENDPOINT_ID_R2_13_1_2   = DEVICE_R2_ENDPOINT_IDS[1]
-DEVICE_R2_CONNECT_RULES = json_device_emulated_connect_rules(DEVICE_R2_ENDPOINT_DEFS)
-
-
-DEVICE_R3_UUID          = 'R3-EMU'
-DEVICE_R3_TIMEOUT       = 120
-DEVICE_R3_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
-DEVICE_R3_ID            = json_device_id(DEVICE_R3_UUID)
-#DEVICE_R3_ENDPOINTS     = json_endpoints(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS)
-DEVICE_R3_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS)
-DEVICE_R3               = json_device_packetrouter_disabled(DEVICE_R3_UUID)
-ENDPOINT_ID_R3_13_0_0   = DEVICE_R3_ENDPOINT_IDS[0]
-ENDPOINT_ID_R3_13_1_2   = DEVICE_R3_ENDPOINT_IDS[1]
-DEVICE_R3_CONNECT_RULES = json_device_connect_rules(DEVICE_R3_ADDRESS, DEVICE_R3_PORT, {
-    'username': DEVICE_R3_USERNAME,
-    'password': DEVICE_R3_PASSWORD,
-    'timeout' : DEVICE_R3_TIMEOUT,
-}) if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_R3_ENDPOINT_DEFS)
-
-
-DEVICE_R4_UUID          = 'R4-EMU'
-DEVICE_R4_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
-DEVICE_R4_ID            = json_device_id(DEVICE_R4_UUID)
-#DEVICE_R4_ENDPOINTS     = json_endpoints(DEVICE_R4_ID, DEVICE_R4_ENDPOINT_DEFS)
-DEVICE_R4_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R4_ID, DEVICE_R4_ENDPOINT_DEFS)
-DEVICE_R4               = json_device_emulated_packet_router_disabled(DEVICE_R4_UUID)
-ENDPOINT_ID_R4_13_0_0   = DEVICE_R4_ENDPOINT_IDS[0]
-ENDPOINT_ID_R4_13_1_2   = DEVICE_R4_ENDPOINT_IDS[1]
-DEVICE_R4_CONNECT_RULES = json_device_emulated_connect_rules(DEVICE_R4_ENDPOINT_DEFS)
-
-
-DEVICE_X1_UUID          = 'X1-XR-CONSTELLATION'
-DEVICE_X1_TIMEOUT       = 120
-DEVICE_X1_ENDPOINT_DEFS = [
-    ('XR HUB 1|XR-T1', 'optical', []),
-    ('XR HUB 1|XR-T2', 'optical', []),
-    ('XR HUB 1|XR-T3', 'optical', []),
-    ('XR HUB 1|XR-T4', 'optical', []),
-    ('XR LEAF 1|XR-T1', 'optical', []),
-    ('XR LEAF 2|XR-T1', 'optical', []),
-]
-DEVICE_X1_ID            = json_device_id(DEVICE_X1_UUID)
-DEVICE_X1               = json_device_tapi_disabled(DEVICE_X1_UUID)
-DEVICE_X1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_X1_ID, DEVICE_X1_ENDPOINT_DEFS)
-# These match JSON, hence indexes are what theyt are
-ENDPOINT_ID_X1_EP1      = DEVICE_X1_ENDPOINT_IDS[3]
-ENDPOINT_ID_X1_EP2      = DEVICE_X1_ENDPOINT_IDS[2]
-ENDPOINT_ID_X1_EP3      = DEVICE_X1_ENDPOINT_IDS[4]
-ENDPOINT_ID_X1_EP4      = DEVICE_X1_ENDPOINT_IDS[5]
-DEVICE_X1_CONNECT_RULES = json_device_connect_rules(DEVICE_X1_ADDRESS, DEVICE_X1_PORT, {
-    'timeout' : DEVICE_X1_TIMEOUT,
-    "username": "xr-user-1",
-    "password": "xr-user-1",
-    "hub_module_name": "XR HUB 1"
-})
-# Always using real device (CM, whether CM has emulated backend is another story)
-#if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_X1_ENDPOINT_DEFS)
-
-
-# ----- Links ----------------------------------------------------------------------------------------------------------
-LINK_R1_X1_UUID = get_link_uuid(DEVICE_R1_ID, ENDPOINT_ID_R1_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP1)
-LINK_R1_X1_ID   = json_link_id(LINK_R1_X1_UUID)
-LINK_R1_X1      = json_link(LINK_R1_X1_UUID, [ENDPOINT_ID_R1_13_0_0, ENDPOINT_ID_X1_EP1])
-
-LINK_R2_X1_UUID = get_link_uuid(DEVICE_R2_ID, ENDPOINT_ID_R2_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP2)
-LINK_R2_X1_ID   = json_link_id(LINK_R2_X1_UUID)
-LINK_R2_X1      = json_link(LINK_R2_X1_UUID, [ENDPOINT_ID_R2_13_0_0, ENDPOINT_ID_X1_EP2])
-
-LINK_R3_X1_UUID = get_link_uuid(DEVICE_R3_ID, ENDPOINT_ID_R3_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP3)
-LINK_R3_X1_ID   = json_link_id(LINK_R3_X1_UUID)
-LINK_R3_X1      = json_link(LINK_R3_X1_UUID, [ENDPOINT_ID_R3_13_0_0, ENDPOINT_ID_X1_EP3])
-
-LINK_R4_X1_UUID = get_link_uuid(DEVICE_R4_ID, ENDPOINT_ID_R4_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP4)
-LINK_R4_X1_ID   = json_link_id(LINK_R4_X1_UUID)
-LINK_R4_X1      = json_link(LINK_R4_X1_UUID, [ENDPOINT_ID_R4_13_0_0, ENDPOINT_ID_X1_EP4])
-
-
-# ----- WIM Service Settings -------------------------------------------------------------------------------------------
-
-def compose_service_endpoint_id(endpoint_id):
-    device_uuid = endpoint_id['device_id']['device_uuid']['uuid']
-    endpoint_uuid = endpoint_id['endpoint_uuid']['uuid']
-    return ':'.join([device_uuid, endpoint_uuid])
-
-WIM_SEP_R1_ID      = compose_service_endpoint_id(ENDPOINT_ID_R1_13_1_2)
-WIM_SEP_R1_SITE_ID = '1'
-WIM_SEP_R1_BEARER  = WIM_SEP_R1_ID
-WIM_SRV_R1_VLAN_ID = 400
-
-WIM_SEP_R3_ID      = compose_service_endpoint_id(ENDPOINT_ID_R3_13_1_2)
-WIM_SEP_R3_SITE_ID = '2'
-WIM_SEP_R3_BEARER  = WIM_SEP_R3_ID
-WIM_SRV_R3_VLAN_ID = 500
-
-WIM_USERNAME = 'admin'
-WIM_PASSWORD = 'admin'
-
-WIM_MAPPING  = [
-    {'device-id': DEVICE_R1_UUID, 'service_endpoint_id': WIM_SEP_R1_ID,
-     'service_mapping_info': {'bearer': {'bearer-reference': WIM_SEP_R1_BEARER}, 'site-id': WIM_SEP_R1_SITE_ID}},
-    {'device-id': DEVICE_R3_UUID, 'service_endpoint_id': WIM_SEP_R3_ID,
-     'service_mapping_info': {'bearer': {'bearer-reference': WIM_SEP_R3_BEARER}, 'site-id': WIM_SEP_R3_SITE_ID}},
-]
-WIM_SERVICE_TYPE = 'ELINE'
-WIM_SERVICE_CONNECTION_POINTS = [
-    {'service_endpoint_id': WIM_SEP_R1_ID,
-        'service_endpoint_encapsulation_type': 'dot1q',
-        'service_endpoint_encapsulation_info': {'vlan': WIM_SRV_R1_VLAN_ID}},
-    {'service_endpoint_id': WIM_SEP_R3_ID,
-        'service_endpoint_encapsulation_type': 'dot1q',
-        'service_endpoint_encapsulation_info': {'vlan': WIM_SRV_R3_VLAN_ID}},
-]
-
-# ----- Object Collections ---------------------------------------------------------------------------------------------
-
-CONTEXTS = [CONTEXT]
-TOPOLOGIES = [TOPOLOGY]
-
-DEVICES = [
-    (DEVICE_R1, DEVICE_R1_CONNECT_RULES),
-    (DEVICE_R2, DEVICE_R2_CONNECT_RULES),
-    (DEVICE_R3, DEVICE_R3_CONNECT_RULES),
-    (DEVICE_R4, DEVICE_R4_CONNECT_RULES),
-    (DEVICE_X1, DEVICE_X1_CONNECT_RULES),
-]
-
-LINKS = [LINK_R1_X1, LINK_R2_X1, LINK_R3_X1, LINK_R4_X1]
diff --git a/src/tests/benchmark/policy/tests/test_functional_create_service_xr.py b/src/tests/benchmark/policy/tests/test_functional_create_service_xr.py
deleted file mode 100644
index bb78abc1e..000000000
--- a/src/tests/benchmark/policy/tests/test_functional_create_service_xr.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
-#
-# 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.
-
-import logging, pytest
-from common.DeviceTypes import DeviceTypeEnum
-from common.Settings import get_setting
-from common.tests.EventTools import EVENT_CREATE, EVENT_UPDATE, check_events
-from common.tools.object_factory.Connection import json_connection_id
-from common.tools.object_factory.Device import json_device_id
-from common.tools.object_factory.Service import json_service_id
-from common.tools.grpc.Tools import grpc_message_to_json_string
-from compute.tests.mock_osm.MockOSM import MockOSM
-from context.client.ContextClient import ContextClient
-from context.client.EventsCollector import EventsCollector
-from common.proto.context_pb2 import ContextId, Empty
-from .ObjectsXr import (
-    CONTEXT_ID, CONTEXTS, DEVICE_X1_UUID, DEVICE_R1_UUID, DEVICE_R3_UUID, DEVICES, LINKS, TOPOLOGIES,
-    WIM_MAPPING, WIM_PASSWORD, WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE, WIM_USERNAME)
-
-LOGGER = logging.getLogger(__name__)
-LOGGER.setLevel(logging.DEBUG)
-
-DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
-DEVTYPE_XR_CONSTELLATION = DeviceTypeEnum.XR_CONSTELLATION.value
-
-
-@pytest.fixture(scope='session')
-def context_client():
-    _client = ContextClient(get_setting('CONTEXTSERVICE_SERVICE_HOST'), get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC'))
-    yield _client
-    _client.close()
-
-
-@pytest.fixture(scope='session')
-def osm_wim():
-    wim_url = 'http://{:s}:{:s}'.format(
-        get_setting('COMPUTESERVICE_SERVICE_HOST'), str(get_setting('COMPUTESERVICE_SERVICE_PORT_HTTP')))
-    return MockOSM(wim_url, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
-
-
-def test_scenario_is_correct(context_client : ContextClient):  # pylint: disable=redefined-outer-name
-    # ----- List entities - Ensure links are created -------------------------------------------------------------------
-    response = context_client.ListContexts(Empty())
-    assert len(response.contexts) == len(CONTEXTS)
-
-    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
-    assert len(response.topologies) == len(TOPOLOGIES)
-
-    response = context_client.ListDevices(Empty())
-    assert len(response.devices) == len(DEVICES)
-
-    response = context_client.ListLinks(Empty())
-    assert len(response.links) == len(LINKS)
-
-    response = context_client.ListServices(ContextId(**CONTEXT_ID))
-    assert len(response.services) == 0
-
-
-def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
-    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
-    # events_collector = EventsCollector(context_client, log_events_received=True)
-    # events_collector.start()
-
-    # ----- Create Service ---------------------------------------------------------------------------------------------
-    service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS)
-    osm_wim.get_connectivity_service_status(service_uuid)
-
-    # ----- Validate collected events ----------------------------------------------------------------------------------
-
-    # packet_connection_uuid = '{:s}:{:s}'.format(service_uuid, DEVTYPE_EMU_PR)
-    # optical_connection_uuid = '{:s}:optical:{:s}'.format(service_uuid, DEVTYPE_XR_CONSTELLATION)
-    # optical_service_uuid = '{:s}:optical'.format(service_uuid)
-
-    # expected_events = [
-    #     # Create packet service and add first endpoint
-    #     ('ServiceEvent',    EVENT_CREATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
-    #     ('ServiceEvent',    EVENT_UPDATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
-
-    #     # Configure OLS controller, create optical service, create optical connection
-    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_X1_UUID)),
-    #     ('ServiceEvent',    EVENT_CREATE, json_service_id(optical_service_uuid, context_id=CONTEXT_ID)),
-    #     ('ConnectionEvent', EVENT_CREATE, json_connection_id(optical_connection_uuid)),
-
-    #     # Configure endpoint packet devices, add second endpoint to service, create connection
-    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R1_UUID)),
-    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R3_UUID)),
-    #     ('ServiceEvent',    EVENT_UPDATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
-    #     ('ConnectionEvent', EVENT_CREATE, json_connection_id(packet_connection_uuid)),
-    # ]
-    # check_events(events_collector, expected_events)
-
-    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
-    # events_collector.stop()
-
-
-def test_scenario_service_created(context_client : ContextClient):  # pylint: disable=redefined-outer-name
-    # ----- List entities - Ensure service is created ------------------------------------------------------------------
-    response = context_client.ListContexts(Empty())
-    assert len(response.contexts) == len(CONTEXTS)
-
-    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
-    assert len(response.topologies) == len(TOPOLOGIES)
-
-    response = context_client.ListDevices(Empty())
-    assert len(response.devices) == len(DEVICES)
-
-    response = context_client.ListLinks(Empty())
-    assert len(response.links) == len(LINKS)
-
-    response = context_client.ListServices(ContextId(**CONTEXT_ID))
-    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
-    assert len(response.services) == 2 # L3NM + TAPI
-    for service in response.services:
-        service_id = service.service_id
-        response = context_client.ListConnections(service_id)
-        LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
-            grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
-        assert len(response.connections) == 1 # one connection per service
diff --git a/src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py b/src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py
deleted file mode 100644
index f28828be0..000000000
--- a/src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
-#
-# 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.
-
-import logging, pytest
-from common.DeviceTypes import DeviceTypeEnum
-from common.Settings import get_setting
-from common.tests.EventTools import EVENT_REMOVE, EVENT_UPDATE, check_events
-from common.tools.object_factory.Connection import json_connection_id
-from common.tools.object_factory.Device import json_device_id
-from common.tools.object_factory.Service import json_service_id
-from common.tools.grpc.Tools import grpc_message_to_json_string
-from compute.tests.mock_osm.MockOSM import MockOSM
-from context.client.ContextClient import ContextClient
-from context.client.EventsCollector import EventsCollector
-from common.proto.context_pb2 import ContextId, Empty, ServiceTypeEnum
-from .ObjectsXr import (
-    CONTEXT_ID, CONTEXTS, DEVICE_X1_UUID, DEVICE_R1_UUID, DEVICE_R3_UUID, DEVICES, LINKS, TOPOLOGIES, WIM_MAPPING,
-    WIM_PASSWORD, WIM_USERNAME)
-
-
-LOGGER = logging.getLogger(__name__)
-LOGGER.setLevel(logging.DEBUG)
-
-DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
-DEVTYPE_XR_CONSTELLATION = DeviceTypeEnum.XR_CONSTELLATION.value
-
-@pytest.fixture(scope='session')
-def context_client():
-    _client = ContextClient(get_setting('CONTEXTSERVICE_SERVICE_HOST'), get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC'))
-    yield _client
-    _client.close()
-
-
-@pytest.fixture(scope='session')
-def osm_wim():
-    wim_url = 'http://{:s}:{:s}'.format(
-        get_setting('COMPUTESERVICE_SERVICE_HOST'), str(get_setting('COMPUTESERVICE_SERVICE_PORT_HTTP')))
-    return MockOSM(wim_url, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
-
-
-def test_scenario_is_correct(context_client : ContextClient):  # pylint: disable=redefined-outer-name
-    # ----- List entities - Ensure service is created ------------------------------------------------------------------
-    response = context_client.ListContexts(Empty())
-    assert len(response.contexts) == len(CONTEXTS)
-
-    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
-    assert len(response.topologies) == len(TOPOLOGIES)
-
-    response = context_client.ListDevices(Empty())
-    assert len(response.devices) == len(DEVICES)
-
-    response = context_client.ListLinks(Empty())
-    assert len(response.links) == len(LINKS)
-
-    response = context_client.ListServices(ContextId(**CONTEXT_ID))
-    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
-    assert len(response.services) == 2 # L3NM + TAPI
-    for service in response.services:
-        service_id = service.service_id
-        response = context_client.ListConnections(service_id)
-        LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
-            grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
-        assert len(response.connections) == 1 # one connection per service
-
-
-def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
-    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
-    events_collector = EventsCollector(context_client, log_events_received=True)
-    events_collector.start()
-
-    # ----- Delete Service ---------------------------------------------------------------------------------------------
-    response = context_client.ListServices(ContextId(**CONTEXT_ID))
-    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
-    assert len(response.services) == 2 # L3NM + TAPI
-    service_uuids = set()
-    for service in response.services:
-        if service.service_type != ServiceTypeEnum.SERVICETYPE_L3NM: continue
-        service_uuid = service.service_id.service_uuid.uuid
-        service_uuids.add(service_uuid)
-        osm_wim.conn_info[service_uuid] = {}
-
-    assert len(service_uuids) == 1  # assume a single service has been created
-    service_uuid = set(service_uuids).pop()
-
-    osm_wim.delete_connectivity_service(service_uuid)
-
-    # ----- Validate collected events ----------------------------------------------------------------------------------
-    # packet_connection_uuid = '{:s}:{:s}'.format(service_uuid, DEVTYPE_EMU_PR)
-    # optical_connection_uuid = '{:s}:optical:{:s}'.format(service_uuid, DEVTYPE_XR_CONSTELLATION)
-    # optical_service_uuid = '{:s}:optical'.format(service_uuid)
-
-    # expected_events = [
-    #     ('ConnectionEvent', EVENT_REMOVE, json_connection_id(packet_connection_uuid)),
-    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R1_UUID)),
-    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R3_UUID)),
-    #     ('ServiceEvent',    EVENT_REMOVE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
-    #     ('ConnectionEvent', EVENT_REMOVE, json_connection_id(optical_connection_uuid)),
-    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_X1_UUID)),
-    #     ('ServiceEvent',    EVENT_REMOVE, json_service_id(optical_service_uuid, context_id=CONTEXT_ID)),
-    # ]
-    # check_events(events_collector, expected_events)
-
-    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
-    # events_collector.stop()
-
-
-def test_services_removed(context_client : ContextClient):  # pylint: disable=redefined-outer-name
-    # ----- List entities - Ensure service is removed ------------------------------------------------------------------
-    response = context_client.ListContexts(Empty())
-    assert len(response.contexts) == len(CONTEXTS)
-
-    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
-    assert len(response.topologies) == len(TOPOLOGIES)
-
-    response = context_client.ListDevices(Empty())
-    assert len(response.devices) == len(DEVICES)
-
-    response = context_client.ListLinks(Empty())
-    assert len(response.links) == len(LINKS)
-
-    response = context_client.ListServices(ContextId(**CONTEXT_ID))
-    assert len(response.services) == 0
-- 
GitLab


From 7e07eea358c2403e0c84466b5c0a55d5e121f54b Mon Sep 17 00:00:00 2001
From: Katopodisv <vkatopodis@ubitech.eu>
Date: Mon, 12 Dec 2022 15:49:49 +0200
Subject: [PATCH 3/4] Policy: create benchmark tests

---
 src/tests/benchmark/policy/.gitignore         |   2 +
 .../benchmark/policy/PolicyAddService.js      |  72 ++++++
 src/tests/benchmark/policy/PolicyDelete.js    |  53 ++++
 .../benchmark/policy/PolicyUpdateService.js   |  72 ++++++
 src/tests/benchmark/policy/README.md          |  17 ++
 src/tests/benchmark/policy/__init__.py        |  14 ++
 src/tests/benchmark/policy/deploy_specs.sh    |  26 ++
 .../policy/descriptors_emulated.json          | 121 +++++++++
 .../policy/descriptors_emulated_xr.json       | 108 ++++++++
 .../benchmark/policy/run_test_01_bootstrap.sh |  17 ++
 .../policy/run_test_02_create_service.sh      |  17 ++
 .../policy/run_test_03_delete_service.sh      |  17 ++
 .../benchmark/policy/run_test_04_cleanup.sh   |  17 ++
 src/tests/benchmark/policy/run_tests.sh       |  44 ++++
 src/tests/benchmark/policy/tests/.gitignore   |   2 +
 src/tests/benchmark/policy/tests/Fixtures.py  |  28 +++
 src/tests/benchmark/policy/tests/Objects.py   |  38 +++
 src/tests/benchmark/policy/tests/ObjectsXr.py | 238 ++++++++++++++++++
 src/tests/benchmark/policy/tests/__init__.py  |  14 ++
 .../policy/tests/test_functional_bootstrap.py |  95 +++++++
 .../policy/tests/test_functional_cleanup.py   |  80 ++++++
 .../tests/test_functional_create_service.py   | 124 +++++++++
 .../test_functional_create_service_xr.py      | 129 ++++++++++
 .../tests/test_functional_delete_service.py   |  99 ++++++++
 .../test_functional_delete_service_xr.py      | 133 ++++++++++
 25 files changed, 1577 insertions(+)
 create mode 100644 src/tests/benchmark/policy/.gitignore
 create mode 100644 src/tests/benchmark/policy/PolicyAddService.js
 create mode 100644 src/tests/benchmark/policy/PolicyDelete.js
 create mode 100644 src/tests/benchmark/policy/PolicyUpdateService.js
 create mode 100644 src/tests/benchmark/policy/README.md
 create mode 100644 src/tests/benchmark/policy/__init__.py
 create mode 100644 src/tests/benchmark/policy/deploy_specs.sh
 create mode 100644 src/tests/benchmark/policy/descriptors_emulated.json
 create mode 100644 src/tests/benchmark/policy/descriptors_emulated_xr.json
 create mode 100755 src/tests/benchmark/policy/run_test_01_bootstrap.sh
 create mode 100755 src/tests/benchmark/policy/run_test_02_create_service.sh
 create mode 100755 src/tests/benchmark/policy/run_test_03_delete_service.sh
 create mode 100755 src/tests/benchmark/policy/run_test_04_cleanup.sh
 create mode 100755 src/tests/benchmark/policy/run_tests.sh
 create mode 100644 src/tests/benchmark/policy/tests/.gitignore
 create mode 100644 src/tests/benchmark/policy/tests/Fixtures.py
 create mode 100644 src/tests/benchmark/policy/tests/Objects.py
 create mode 100644 src/tests/benchmark/policy/tests/ObjectsXr.py
 create mode 100644 src/tests/benchmark/policy/tests/__init__.py
 create mode 100644 src/tests/benchmark/policy/tests/test_functional_bootstrap.py
 create mode 100644 src/tests/benchmark/policy/tests/test_functional_cleanup.py
 create mode 100644 src/tests/benchmark/policy/tests/test_functional_create_service.py
 create mode 100644 src/tests/benchmark/policy/tests/test_functional_create_service_xr.py
 create mode 100644 src/tests/benchmark/policy/tests/test_functional_delete_service.py
 create mode 100644 src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py

diff --git a/src/tests/benchmark/policy/.gitignore b/src/tests/benchmark/policy/.gitignore
new file mode 100644
index 000000000..0a3f4400d
--- /dev/null
+++ b/src/tests/benchmark/policy/.gitignore
@@ -0,0 +1,2 @@
+# Add here your files containing confidential testbed details such as IP addresses, ports, usernames, passwords, etc.
+descriptors_real.json
diff --git a/src/tests/benchmark/policy/PolicyAddService.js b/src/tests/benchmark/policy/PolicyAddService.js
new file mode 100644
index 000000000..116ce394b
--- /dev/null
+++ b/src/tests/benchmark/policy/PolicyAddService.js
@@ -0,0 +1,72 @@
+import grpc from 'k6/net/grpc';
+import exec from "k6/execution";
+import { check, sleep } from 'k6';
+
+const client = new grpc.Client();
+client.load(['../proto'], 'policy.proto');
+
+export const data = [];
+for (let i = 1; i < 2; i++) {
+  data.push(
+    {
+        "serviceId": {
+            "context_id": {
+                "context_uuid": {"uuid": "admin"}
+            },
+            "service_uuid": {
+                "uuid": "6942d780-cfa9-4dea-a946-a8a0b3f7eab2"
+            }
+        },
+        "policyRuleBasic": {
+            "policyRuleId": {"uuid": {"uuid": i.toString()}},
+            "policyRuleState": {"policyRuleState": "POLICY_ACTIVE"},
+            "priority": 0,
+            "conditionList": [{"kpiId": {"kpi_id": {"uuid": "1"}}, 
+                            "numericalOperator": "POLICYRULE_CONDITION_NUMERICAL_EQUAL",
+                            "kpiValue": {"boolVal": false}
+    
+            }],
+            "actionList": [{}],
+            "booleanOperator": "POLICYRULE_CONDITION_BOOLEAN_OR"
+        }
+    }
+  );
+};
+
+export const options = {
+  scenarios :{
+
+    "AddPolicy-scenario": {
+      executor: "shared-iterations",
+      vus: 1,
+      iterations: data.length,
+      maxDuration: "1h"
+    }
+  }
+};
+
+export default () => {
+  client.connect('10.1.255.198:6060', {
+    plaintext: true,
+//    timeout: 10000
+  });
+
+  var item = data[exec.scenario.iterationInInstance];  
+  const response = client.invoke('policy.PolicyService/PolicyAddService', item);
+
+  check(response, {
+    'status is OK': (r) => r && r.status === grpc.StatusOK,
+  });
+
+  console.log(JSON.stringify(response.message));
+
+  client.close();
+  sleep(1);
+};
+
+export function handleSummary(data) {
+
+  return {
+    'summary_add_1.json': JSON.stringify(data.metrics.grpc_req_duration.values), //the default data object
+  };
+}
diff --git a/src/tests/benchmark/policy/PolicyDelete.js b/src/tests/benchmark/policy/PolicyDelete.js
new file mode 100644
index 000000000..85946837e
--- /dev/null
+++ b/src/tests/benchmark/policy/PolicyDelete.js
@@ -0,0 +1,53 @@
+import grpc from 'k6/net/grpc';
+import exec from "k6/execution";
+import { check, sleep } from 'k6';
+
+const client = new grpc.Client();
+client.load(['../proto'], 'policy.proto');
+
+export const data = [];
+for (let i = 1; i < 2; i++) {
+  data.push(
+    {
+     "uuid": {"uuid": i.toString()}
+    }
+  );
+};
+
+export const options = {
+  scenarios :{
+
+    "AddPolicy-scenario": {
+      executor: "shared-iterations",
+      vus: 1,
+      iterations: data.length,
+      maxDuration: "1h"
+    }
+  }
+};
+
+export default () => {
+  client.connect('10.1.255.198:6060', {
+    plaintext: true,
+//    timeout: 10000
+  });
+
+  var item = data[exec.scenario.iterationInInstance];  
+  const response = client.invoke('policy.PolicyService/PolicyDelete', item);
+
+  check(response, {
+    'status is OK': (r) => r && r.status === grpc.StatusOK,
+  });
+
+  console.log(JSON.stringify(response.message));
+
+  client.close();
+  sleep(1);
+};
+
+export function handleSummary(data) {
+
+  return {
+    'summary_delete_1.json': JSON.stringify(data.metrics.grpc_req_duration.values), //the default data object
+  };
+}
diff --git a/src/tests/benchmark/policy/PolicyUpdateService.js b/src/tests/benchmark/policy/PolicyUpdateService.js
new file mode 100644
index 000000000..8a1988ea5
--- /dev/null
+++ b/src/tests/benchmark/policy/PolicyUpdateService.js
@@ -0,0 +1,72 @@
+import grpc from 'k6/net/grpc';
+import exec from "k6/execution";
+import { check, sleep } from 'k6';
+
+const client = new grpc.Client();
+client.load(['../proto'], 'policy.proto');
+
+export const data = [];
+for (let i = 1; i < 2; i++) {
+  data.push(
+    {
+        "serviceId": {
+            "context_id": {
+                "context_uuid": {"uuid": "admin"}
+            },
+            "service_uuid": {
+                "uuid": "6942d780-cfa9-4dea-a946-a8a0b3f7eab2"
+            }
+        },
+        "policyRuleBasic": {
+            "policyRuleId": {"uuid": {"uuid": i.toString()}},
+            "policyRuleState": {"policyRuleState": "POLICY_ACTIVE"},
+            "priority": 0,
+            "conditionList": [{"kpiId": {"kpi_id": {"uuid": "1"}}, 
+                            "numericalOperator": "POLICYRULE_CONDITION_NUMERICAL_EQUAL",
+                            "kpiValue": {"boolVal": false}
+    
+            }],
+            "actionList": [{}],
+            "booleanOperator": "POLICYRULE_CONDITION_BOOLEAN_OR"
+        }
+    }
+  );
+};
+
+export const options = {
+  scenarios :{
+
+    "AddPolicy-scenario": {
+      executor: "shared-iterations",
+      vus: 1,
+      iterations: data.length,
+      maxDuration: "1h"
+    }
+  }
+};
+
+export default () => {
+  client.connect('10.1.255.198:6060', {
+    plaintext: true,
+//    timeout: 10000
+  });
+
+  var item = data[exec.scenario.iterationInInstance];  
+  const response = client.invoke('policy.PolicyService/PolicyUpdateService', item);
+
+  check(response, {
+    'status is OK': (r) => r && r.status === grpc.StatusOK,
+  });
+
+  console.log(JSON.stringify(response.message));
+
+  client.close();
+  sleep(1);
+};
+
+export function handleSummary(data) {
+
+  return {
+    'summary_add_1.json': JSON.stringify(data.metrics.grpc_req_duration.values), //the default data object
+  };
+}
diff --git a/src/tests/benchmark/policy/README.md b/src/tests/benchmark/policy/README.md
new file mode 100644
index 000000000..8b5b2a01e
--- /dev/null
+++ b/src/tests/benchmark/policy/README.md
@@ -0,0 +1,17 @@
+
+# Grafana k6 load testing tool
+
+# K6 Installation Instructions on Ubuntu
+
+sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
+echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
+sudo apt-get update
+sudo apt-get install k6
+
+Or install k6 via snap:
+
+sudo apt install snapd
+sudo snap install k6
+
+# Running K6 
+k6 run script.js
\ No newline at end of file
diff --git a/src/tests/benchmark/policy/__init__.py b/src/tests/benchmark/policy/__init__.py
new file mode 100644
index 000000000..70a332512
--- /dev/null
+++ b/src/tests/benchmark/policy/__init__.py
@@ -0,0 +1,14 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
diff --git a/src/tests/benchmark/policy/deploy_specs.sh b/src/tests/benchmark/policy/deploy_specs.sh
new file mode 100644
index 000000000..ffd91da35
--- /dev/null
+++ b/src/tests/benchmark/policy/deploy_specs.sh
@@ -0,0 +1,26 @@
+# Set the URL of your local Docker registry where the images will be uploaded to.
+export TFS_REGISTRY_IMAGE="http://localhost:32000/tfs/"
+
+# Set the list of components, separated by spaces, you want to build images for, and deploy.
+# Supported components are:
+#   context device automation policy service compute monitoring webui
+#   interdomain slice pathcomp dlt
+#   dbscanserving opticalattackmitigator opticalattackdetector
+#   l3_attackmitigator l3_centralizedattackdetector l3_distributedattackdetector
+export TFS_COMPONENTS="context device automation monitoring pathcomp service slice compute webui"
+
+# Set the tag you want to use for your images.
+export TFS_IMAGE_TAG="dev"
+
+# Set the name of the Kubernetes namespace to deploy to.
+export TFS_K8S_NAMESPACE="tfs"
+
+# Set additional manifest files to be applied after the deployment
+export TFS_EXTRA_MANIFESTS="manifests/nginx_ingress_http.yaml"
+
+# Set the new Grafana admin password
+export TFS_GRAFANA_PASSWORD="admin123+"
+
+# If not already set, disable skip-build flag.
+# If TFS_SKIP_BUILD is "YES", the containers are not rebuilt-retagged-repushed and existing ones are used.
+export TFS_SKIP_BUILD=${TFS_SKIP_BUILD:-""}
diff --git a/src/tests/benchmark/policy/descriptors_emulated.json b/src/tests/benchmark/policy/descriptors_emulated.json
new file mode 100644
index 000000000..a71d454f4
--- /dev/null
+++ b/src/tests/benchmark/policy/descriptors_emulated.json
@@ -0,0 +1,121 @@
+{
+    "contexts": [
+        {
+            "context_id": {"context_uuid": {"uuid": "admin"}},
+            "topology_ids": [],
+            "service_ids": []
+        }
+    ],
+    "topologies": [
+        {
+            "topology_id": {"topology_uuid": {"uuid": "admin"}, "context_id": {"context_uuid": {"uuid": "admin"}}},
+            "device_ids": [
+                {"device_uuid": {"uuid": "R1-EMU"}},
+                {"device_uuid": {"uuid": "R2-EMU"}},
+                {"device_uuid": {"uuid": "R3-EMU"}},
+                {"device_uuid": {"uuid": "R4-EMU"}},
+                {"device_uuid": {"uuid": "O1-OLS"}}                
+            ],
+            "link_ids": [
+                {"link_uuid": {"uuid": "R1-EMU/13/0/0==O1-OLS/aade6001-f00b-5e2f-a357-6a0a9d3de870"}},
+                {"link_uuid": {"uuid": "R2-EMU/13/0/0==O1-OLS/eb287d83-f05e-53ec-ab5a-adf6bd2b5418"}},
+                {"link_uuid": {"uuid": "R3-EMU/13/0/0==O1-OLS/0ef74f99-1acc-57bd-ab9d-4b958b06c513"}},
+                {"link_uuid": {"uuid": "R4-EMU/13/0/0==O1-OLS/50296d99-58cc-5ce7-82f5-fc8ee4eec2ec"}}
+            ]
+        }
+    ],
+    "devices": [
+        {
+            "device_id": {"device_uuid": {"uuid": "R1-EMU"}}, "device_type": "emu-packet-router",
+            "device_operational_status": 1, "device_drivers": [0], "device_endpoints": [],
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [
+                    {"uuid": "13/0/0", "type": "optical", "sample_types": []},
+                    {"uuid": "13/1/2", "type": "copper",  "sample_types": [101, 102, 201, 202]}
+                ]}}}
+            ]}
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "R2-EMU"}}, "device_type": "emu-packet-router",
+            "device_operational_status": 1, "device_drivers": [0], "device_endpoints": [],
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [
+                    {"uuid": "13/0/0", "type": "optical", "sample_types": []},
+                    {"uuid": "13/1/2", "type": "copper",  "sample_types": [101, 102, 201, 202]}
+                ]}}}
+            ]}
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "R3-EMU"}}, "device_type": "emu-packet-router",
+            "device_operational_status": 1, "device_drivers": [0], "device_endpoints": [],
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [
+                    {"uuid": "13/0/0", "type": "optical", "sample_types": []},
+                    {"uuid": "13/1/2", "type": "copper",  "sample_types": [101, 102, 201, 202]}
+                ]}}}
+            ]}
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "R4-EMU"}}, "device_type": "emu-packet-router",
+            "device_operational_status": 1, "device_drivers": [0], "device_endpoints": [],
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [
+                    {"uuid": "13/0/0", "type": "optical", "sample_types": []},
+                    {"uuid": "13/1/2", "type": "copper",  "sample_types": [101, 102, 201, 202]}
+                ]}}}
+            ]}
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "O1-OLS"}}, "device_type": "emu-open-line-system",
+            "device_operational_status": 1, "device_drivers": [0], "device_endpoints": [],
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {"endpoints": [
+                    {"uuid": "aade6001-f00b-5e2f-a357-6a0a9d3de870", "type": "optical", "sample_types": []},
+                    {"uuid": "eb287d83-f05e-53ec-ab5a-adf6bd2b5418", "type": "optical", "sample_types": []},
+                    {"uuid": "0ef74f99-1acc-57bd-ab9d-4b958b06c513", "type": "optical", "sample_types": []},
+                    {"uuid": "50296d99-58cc-5ce7-82f5-fc8ee4eec2ec", "type": "optical", "sample_types": []}
+                ]}}}
+            ]}
+        }
+    ],
+    "links": [
+        {
+            "link_id": {"link_uuid": {"uuid": "R1-EMU/13/0/0==O1-OLS/aade6001-f00b-5e2f-a357-6a0a9d3de870"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R1-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "O1-OLS"}}, "endpoint_uuid": {"uuid": "aade6001-f00b-5e2f-a357-6a0a9d3de870"}}
+            ]
+        },
+        {
+            "link_id": {"link_uuid": {"uuid": "R2-EMU/13/0/0==O1-OLS/eb287d83-f05e-53ec-ab5a-adf6bd2b5418"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R2-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "O1-OLS"}}, "endpoint_uuid": {"uuid": "eb287d83-f05e-53ec-ab5a-adf6bd2b5418"}}
+            ]
+        },
+        {
+            "link_id": {"link_uuid": {"uuid": "R3-EMU/13/0/0==O1-OLS/0ef74f99-1acc-57bd-ab9d-4b958b06c513"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R3-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "O1-OLS"}}, "endpoint_uuid": {"uuid": "0ef74f99-1acc-57bd-ab9d-4b958b06c513"}}
+            ]
+        },
+        {
+            "link_id": {"link_uuid": {"uuid": "R4-EMU/13/0/0==O1-OLS/50296d99-58cc-5ce7-82f5-fc8ee4eec2ec"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R4-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "O1-OLS"}}, "endpoint_uuid": {"uuid": "50296d99-58cc-5ce7-82f5-fc8ee4eec2ec"}}
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/tests/benchmark/policy/descriptors_emulated_xr.json b/src/tests/benchmark/policy/descriptors_emulated_xr.json
new file mode 100644
index 000000000..30bd97ddd
--- /dev/null
+++ b/src/tests/benchmark/policy/descriptors_emulated_xr.json
@@ -0,0 +1,108 @@
+{
+    "contexts": [
+        {
+            "context_id": {"context_uuid": {"uuid": "admin"}},
+            "topology_ids": [],
+            "service_ids": []
+        }
+    ],
+    "topologies": [
+        {
+            "topology_id": {"topology_uuid": {"uuid": "admin"}, "context_id": {"context_uuid": {"uuid": "admin"}}},
+            "device_ids": [],
+            "link_ids": []
+        }
+    ],
+    "devices": [
+        {
+            "device_id": {"device_uuid": {"uuid": "R1-EMU"}},
+            "device_type": "emu-packet-router",
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
+            ]},
+            "device_operational_status": 1,
+            "device_drivers": [0],
+            "device_endpoints": []
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "R2-EMU"}},
+            "device_type": "emu-packet-router",
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
+            ]},
+            "device_operational_status": 1,
+            "device_drivers": [0],
+            "device_endpoints": []
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "R3-EMU"}},
+            "device_type": "emu-packet-router",
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
+            ]},
+            "device_operational_status": 1,
+            "device_drivers": [0],
+            "device_endpoints": []
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "R4-EMU"}},
+            "device_type": "emu-packet-router",
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
+            ]},
+            "device_operational_status": 1,
+            "device_drivers": [0],
+            "device_endpoints": []
+        },
+        {
+            "device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}},
+            "device_type": "xr-constellation",
+            "device_config": {"config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.19.219.44"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "443"}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"username\": \"xr-user-1\", \"password\": \"xr-user-1\", \"hub_module_name\": \"XR HUB 1\"}"}}
+            ]},
+            "device_operational_status": 1,
+            "device_drivers": [6],
+            "device_endpoints": []
+        }
+    ],
+    "links": [
+        {
+            "link_id": {"link_uuid": {"uuid": "R1-EMU/13/0/0==XR HUB 1|XR-T4"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R1-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR HUB 1|XR-T4"}}
+            ]
+        },
+        {
+            "link_id": {"link_uuid": {"uuid": "R2-EMU/13/0/0==XR HUB 1|XR-T3"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R2-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR HUB 1|XR-T3"}}
+            ]
+        },
+        {
+            "link_id": {"link_uuid": {"uuid": "R3-EMU/13/0/0==XR1-XR LEAF 1|XR-T1"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R3-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR LEAF 1|XR-T1"}}
+            ]
+        },
+        {
+            "link_id": {"link_uuid": {"uuid": "R4-EMU/13/0/0==XR LEAF 2|XR-T1"}},
+            "link_endpoint_ids": [
+                {"device_id": {"device_uuid": {"uuid": "R4-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
+                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR LEAF 2|XR-T1"}}
+            ]
+        }
+    ]
+}
diff --git a/src/tests/benchmark/policy/run_test_01_bootstrap.sh b/src/tests/benchmark/policy/run_test_01_bootstrap.sh
new file mode 100755
index 000000000..fc15d2d9a
--- /dev/null
+++ b/src/tests/benchmark/policy/run_test_01_bootstrap.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+source tfs_runtime_env_vars.sh
+pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policytest_functional_bootstrap.py
diff --git a/src/tests/benchmark/policy/run_test_02_create_service.sh b/src/tests/benchmark/policy/run_test_02_create_service.sh
new file mode 100755
index 000000000..c14e19f53
--- /dev/null
+++ b/src/tests/benchmark/policy/run_test_02_create_service.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+source tfs_runtime_env_vars.sh
+pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policy/test_functional_create_service.py
diff --git a/src/tests/benchmark/policy/run_test_03_delete_service.sh b/src/tests/benchmark/policy/run_test_03_delete_service.sh
new file mode 100755
index 000000000..904f6161c
--- /dev/null
+++ b/src/tests/benchmark/policy/run_test_03_delete_service.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+source tfs_runtime_env_vars.sh
+pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policy/test_functional_delete_service.py
diff --git a/src/tests/benchmark/policy/run_test_04_cleanup.sh b/src/tests/benchmark/policy/run_test_04_cleanup.sh
new file mode 100755
index 000000000..ea3fcb61b
--- /dev/null
+++ b/src/tests/benchmark/policy/run_test_04_cleanup.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+source tfs_runtime_env_vars.sh
+pytest --verbose --log-level=INFO -o log_cli=true -o log_cli_level=INFO src/tests/benchmark/policy/test_functional_cleanup.py
diff --git a/src/tests/benchmark/policy/run_tests.sh b/src/tests/benchmark/policy/run_tests.sh
new file mode 100755
index 000000000..0ad4be313
--- /dev/null
+++ b/src/tests/benchmark/policy/run_tests.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+
+PROJECTDIR=`pwd`
+
+RCFILE=$PROJECTDIR/coverage/.coveragerc
+COVERAGEFILE=$PROJECTDIR/coverage/.coverage
+
+# Configure the correct folder on the .coveragerc file
+cat $PROJECTDIR/coverage/.coveragerc.template | sed s+~/teraflow/controller+$PROJECTDIR/src+g > $RCFILE
+
+# Destroy old coverage file
+rm -f $COVERAGEFILE
+
+source tfs_runtime_env_vars.sh
+
+# Force a flush of Context database
+kubectl --namespace $TFS_K8S_NAMESPACE exec -it deployment/contextservice --container redis -- redis-cli FLUSHALL
+
+# Run functional tests
+pytest --log-level=INFO --verbose \
+    src/tests/ofc22/tests/test_functional_bootstrap.py
+
+pytest --log-level=INFO --verbose \
+    src/tests/ofc22/tests/test_functional_create_service.py
+
+pytest --log-level=INFO --verbose \
+    src/tests/ofc22/tests/test_functional_delete_service.py
+
+pytest --log-level=INFO --verbose \
+    src/tests/ofc22/tests/test_functional_cleanup.py
diff --git a/src/tests/benchmark/policy/tests/.gitignore b/src/tests/benchmark/policy/tests/.gitignore
new file mode 100644
index 000000000..76cb708d1
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/.gitignore
@@ -0,0 +1,2 @@
+# Add here your files containing confidential testbed details such as IP addresses, ports, usernames, passwords, etc.
+Credentials.py
diff --git a/src/tests/benchmark/policy/tests/Fixtures.py b/src/tests/benchmark/policy/tests/Fixtures.py
new file mode 100644
index 000000000..3b35a12e2
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/Fixtures.py
@@ -0,0 +1,28 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import pytest, logging
+from common.Settings import get_setting
+from tests.tools.mock_osm.Constants import WIM_PASSWORD, WIM_USERNAME
+from tests.tools.mock_osm.MockOSM import MockOSM
+from .Objects import WIM_MAPPING
+
+LOGGER = logging.getLogger(__name__)
+
+@pytest.fixture(scope='session')
+def osm_wim():
+    wim_url = 'http://{:s}:{:s}'.format(
+        get_setting('COMPUTESERVICE_SERVICE_HOST'), str(get_setting('COMPUTESERVICE_SERVICE_PORT_HTTP')))
+    LOGGER.info('WIM_MAPPING = {:s}'.format(str(WIM_MAPPING)))
+    return MockOSM(wim_url, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
diff --git a/src/tests/benchmark/policy/tests/Objects.py b/src/tests/benchmark/policy/tests/Objects.py
new file mode 100644
index 000000000..7bfbe9fce
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/Objects.py
@@ -0,0 +1,38 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+from common.tools.object_factory.Device import json_device_id
+from common.tools.object_factory.EndPoint import json_endpoint_id
+from tests.tools.mock_osm.Tools import connection_point, wim_mapping
+
+# ----- WIM Service Settings -------------------------------------------------------------------------------------------
+
+WIM_DC1_SITE_ID     = '1'
+WIM_DC1_DEVICE_ID   = json_device_id('R1-EMU')
+WIM_DC1_ENDPOINT_ID = json_endpoint_id(WIM_DC1_DEVICE_ID, '13/1/2')
+
+WIM_DC2_SITE_ID     = '2'
+WIM_DC2_DEVICE_ID   = json_device_id('R3-EMU')
+WIM_DC2_ENDPOINT_ID = json_endpoint_id(WIM_DC2_DEVICE_ID, '13/1/2')
+
+WIM_SEP_DC1, WIM_MAP_DC1 = wim_mapping(WIM_DC1_SITE_ID, WIM_DC1_ENDPOINT_ID)
+WIM_SEP_DC2, WIM_MAP_DC2 = wim_mapping(WIM_DC2_SITE_ID, WIM_DC2_ENDPOINT_ID)
+WIM_MAPPING  = [WIM_MAP_DC1, WIM_MAP_DC2]
+
+WIM_SRV_VLAN_ID = 300
+WIM_SERVICE_TYPE = 'ELINE'
+WIM_SERVICE_CONNECTION_POINTS = [
+    connection_point(WIM_SEP_DC1, 'dot1q', WIM_SRV_VLAN_ID),
+    connection_point(WIM_SEP_DC2, 'dot1q', WIM_SRV_VLAN_ID),
+]
diff --git a/src/tests/benchmark/policy/tests/ObjectsXr.py b/src/tests/benchmark/policy/tests/ObjectsXr.py
new file mode 100644
index 000000000..0cb223de2
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/ObjectsXr.py
@@ -0,0 +1,238 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+from typing import Dict, List, Tuple
+from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID
+from common.tools.object_factory.Context import json_context, json_context_id
+from common.tools.object_factory.Device import (
+    json_device_connect_rules, json_device_emulated_connect_rules, json_device_emulated_packet_router_disabled,
+    json_device_emulated_tapi_disabled, json_device_id, json_device_packetrouter_disabled, json_device_tapi_disabled)
+from common.tools.object_factory.EndPoint import json_endpoint, json_endpoint_id
+from common.tools.object_factory.Link import json_link, json_link_id
+from common.tools.object_factory.Topology import json_topology, json_topology_id
+from common.proto.kpi_sample_types_pb2 import KpiSampleType
+
+# ----- Context --------------------------------------------------------------------------------------------------------
+CONTEXT_ID = json_context_id(DEFAULT_CONTEXT_UUID)
+CONTEXT    = json_context(DEFAULT_CONTEXT_UUID)
+
+# ----- Topology -------------------------------------------------------------------------------------------------------
+TOPOLOGY_ID = json_topology_id(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
+TOPOLOGY    = json_topology(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
+
+# ----- Monitoring Samples ---------------------------------------------------------------------------------------------
+PACKET_PORT_SAMPLE_TYPES = [
+    KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED,
+    KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED,
+    KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED,
+    KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED,
+]
+
+# ----- Device Credentials and Settings --------------------------------------------------------------------------------
+try:
+    from .Credentials import DEVICE_R1_ADDRESS, DEVICE_R1_PORT, DEVICE_R1_USERNAME, DEVICE_R1_PASSWORD
+    from .Credentials import DEVICE_R3_ADDRESS, DEVICE_R3_PORT, DEVICE_R3_USERNAME, DEVICE_R3_PASSWORD
+    #from .Credentials import DEVICE_O1_ADDRESS, DEVICE_O1_PORT
+    USE_REAL_DEVICES = True     # Use real devices
+except ImportError:
+    USE_REAL_DEVICES = False    # Use emulated devices
+
+    DEVICE_R1_ADDRESS  = '0.0.0.0'
+    DEVICE_R1_PORT     = 830
+    DEVICE_R1_USERNAME = 'admin'
+    DEVICE_R1_PASSWORD = 'admin'
+
+    DEVICE_R3_ADDRESS  = '0.0.0.0'
+    DEVICE_R3_PORT     = 830
+    DEVICE_R3_USERNAME = 'admin'
+    DEVICE_R3_PASSWORD = 'admin'
+
+DEVICE_X1_ADDRESS  = '172.19.219.44'
+DEVICE_X1_PORT     = 443
+
+#USE_REAL_DEVICES = False     # Uncomment to force to use emulated devices
+
+def json_endpoint_ids(device_id : Dict, endpoint_descriptors : List[Tuple[str, str, List[int]]]):
+    return [
+        json_endpoint_id(device_id, ep_uuid, topology_id=None)
+        for ep_uuid, _, _ in endpoint_descriptors
+    ]
+
+def json_endpoints(device_id : Dict, endpoint_descriptors : List[Tuple[str, str, List[int]]]):
+    return [
+        json_endpoint(device_id, ep_uuid, ep_type, topology_id=None, kpi_sample_types=ep_sample_types)
+        for ep_uuid, ep_type, ep_sample_types in endpoint_descriptors
+    ]
+
+def get_link_uuid(a_device_id : Dict, a_endpoint_id : Dict, z_device_id : Dict, z_endpoint_id : Dict) -> str:
+    return '{:s}/{:s}=={:s}/{:s}'.format(
+        a_device_id['device_uuid']['uuid'], a_endpoint_id['endpoint_uuid']['uuid'],
+        z_device_id['device_uuid']['uuid'], z_endpoint_id['endpoint_uuid']['uuid'])
+
+
+# ----- Devices --------------------------------------------------------------------------------------------------------
+if not USE_REAL_DEVICES:
+    json_device_packetrouter_disabled = json_device_emulated_packet_router_disabled
+    json_device_tapi_disabled         = json_device_emulated_tapi_disabled
+
+DEVICE_R1_UUID          = 'R1-EMU'
+DEVICE_R1_TIMEOUT       = 120
+DEVICE_R1_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
+DEVICE_R1_ID            = json_device_id(DEVICE_R1_UUID)
+#DEVICE_R1_ENDPOINTS     = json_endpoints(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
+DEVICE_R1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
+DEVICE_R1               = json_device_packetrouter_disabled(DEVICE_R1_UUID)
+ENDPOINT_ID_R1_13_0_0   = DEVICE_R1_ENDPOINT_IDS[0]
+ENDPOINT_ID_R1_13_1_2   = DEVICE_R1_ENDPOINT_IDS[1]
+DEVICE_R1_CONNECT_RULES = json_device_connect_rules(DEVICE_R1_ADDRESS, DEVICE_R1_PORT, {
+    'username': DEVICE_R1_USERNAME,
+    'password': DEVICE_R1_PASSWORD,
+    'timeout' : DEVICE_R1_TIMEOUT,
+}) if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_R1_ENDPOINT_DEFS)
+
+
+DEVICE_R2_UUID          = 'R2-EMU'
+DEVICE_R2_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
+DEVICE_R2_ID            = json_device_id(DEVICE_R2_UUID)
+#DEVICE_R2_ENDPOINTS     = json_endpoints(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
+DEVICE_R2_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
+DEVICE_R2               = json_device_emulated_packet_router_disabled(DEVICE_R2_UUID)
+ENDPOINT_ID_R2_13_0_0   = DEVICE_R2_ENDPOINT_IDS[0]
+ENDPOINT_ID_R2_13_1_2   = DEVICE_R2_ENDPOINT_IDS[1]
+DEVICE_R2_CONNECT_RULES = json_device_emulated_connect_rules(DEVICE_R2_ENDPOINT_DEFS)
+
+
+DEVICE_R3_UUID          = 'R3-EMU'
+DEVICE_R3_TIMEOUT       = 120
+DEVICE_R3_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
+DEVICE_R3_ID            = json_device_id(DEVICE_R3_UUID)
+#DEVICE_R3_ENDPOINTS     = json_endpoints(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS)
+DEVICE_R3_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS)
+DEVICE_R3               = json_device_packetrouter_disabled(DEVICE_R3_UUID)
+ENDPOINT_ID_R3_13_0_0   = DEVICE_R3_ENDPOINT_IDS[0]
+ENDPOINT_ID_R3_13_1_2   = DEVICE_R3_ENDPOINT_IDS[1]
+DEVICE_R3_CONNECT_RULES = json_device_connect_rules(DEVICE_R3_ADDRESS, DEVICE_R3_PORT, {
+    'username': DEVICE_R3_USERNAME,
+    'password': DEVICE_R3_PASSWORD,
+    'timeout' : DEVICE_R3_TIMEOUT,
+}) if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_R3_ENDPOINT_DEFS)
+
+
+DEVICE_R4_UUID          = 'R4-EMU'
+DEVICE_R4_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
+DEVICE_R4_ID            = json_device_id(DEVICE_R4_UUID)
+#DEVICE_R4_ENDPOINTS     = json_endpoints(DEVICE_R4_ID, DEVICE_R4_ENDPOINT_DEFS)
+DEVICE_R4_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R4_ID, DEVICE_R4_ENDPOINT_DEFS)
+DEVICE_R4               = json_device_emulated_packet_router_disabled(DEVICE_R4_UUID)
+ENDPOINT_ID_R4_13_0_0   = DEVICE_R4_ENDPOINT_IDS[0]
+ENDPOINT_ID_R4_13_1_2   = DEVICE_R4_ENDPOINT_IDS[1]
+DEVICE_R4_CONNECT_RULES = json_device_emulated_connect_rules(DEVICE_R4_ENDPOINT_DEFS)
+
+
+DEVICE_X1_UUID          = 'X1-XR-CONSTELLATION'
+DEVICE_X1_TIMEOUT       = 120
+DEVICE_X1_ENDPOINT_DEFS = [
+    ('XR HUB 1|XR-T1', 'optical', []),
+    ('XR HUB 1|XR-T2', 'optical', []),
+    ('XR HUB 1|XR-T3', 'optical', []),
+    ('XR HUB 1|XR-T4', 'optical', []),
+    ('XR LEAF 1|XR-T1', 'optical', []),
+    ('XR LEAF 2|XR-T1', 'optical', []),
+]
+DEVICE_X1_ID            = json_device_id(DEVICE_X1_UUID)
+DEVICE_X1               = json_device_tapi_disabled(DEVICE_X1_UUID)
+DEVICE_X1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_X1_ID, DEVICE_X1_ENDPOINT_DEFS)
+# These match JSON, hence indexes are what theyt are
+ENDPOINT_ID_X1_EP1      = DEVICE_X1_ENDPOINT_IDS[3]
+ENDPOINT_ID_X1_EP2      = DEVICE_X1_ENDPOINT_IDS[2]
+ENDPOINT_ID_X1_EP3      = DEVICE_X1_ENDPOINT_IDS[4]
+ENDPOINT_ID_X1_EP4      = DEVICE_X1_ENDPOINT_IDS[5]
+DEVICE_X1_CONNECT_RULES = json_device_connect_rules(DEVICE_X1_ADDRESS, DEVICE_X1_PORT, {
+    'timeout' : DEVICE_X1_TIMEOUT,
+    "username": "xr-user-1",
+    "password": "xr-user-1",
+    "hub_module_name": "XR HUB 1"
+})
+# Always using real device (CM, whether CM has emulated backend is another story)
+#if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_X1_ENDPOINT_DEFS)
+
+
+# ----- Links ----------------------------------------------------------------------------------------------------------
+LINK_R1_X1_UUID = get_link_uuid(DEVICE_R1_ID, ENDPOINT_ID_R1_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP1)
+LINK_R1_X1_ID   = json_link_id(LINK_R1_X1_UUID)
+LINK_R1_X1      = json_link(LINK_R1_X1_UUID, [ENDPOINT_ID_R1_13_0_0, ENDPOINT_ID_X1_EP1])
+
+LINK_R2_X1_UUID = get_link_uuid(DEVICE_R2_ID, ENDPOINT_ID_R2_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP2)
+LINK_R2_X1_ID   = json_link_id(LINK_R2_X1_UUID)
+LINK_R2_X1      = json_link(LINK_R2_X1_UUID, [ENDPOINT_ID_R2_13_0_0, ENDPOINT_ID_X1_EP2])
+
+LINK_R3_X1_UUID = get_link_uuid(DEVICE_R3_ID, ENDPOINT_ID_R3_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP3)
+LINK_R3_X1_ID   = json_link_id(LINK_R3_X1_UUID)
+LINK_R3_X1      = json_link(LINK_R3_X1_UUID, [ENDPOINT_ID_R3_13_0_0, ENDPOINT_ID_X1_EP3])
+
+LINK_R4_X1_UUID = get_link_uuid(DEVICE_R4_ID, ENDPOINT_ID_R4_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP4)
+LINK_R4_X1_ID   = json_link_id(LINK_R4_X1_UUID)
+LINK_R4_X1      = json_link(LINK_R4_X1_UUID, [ENDPOINT_ID_R4_13_0_0, ENDPOINT_ID_X1_EP4])
+
+
+# ----- WIM Service Settings -------------------------------------------------------------------------------------------
+
+def compose_service_endpoint_id(endpoint_id):
+    device_uuid = endpoint_id['device_id']['device_uuid']['uuid']
+    endpoint_uuid = endpoint_id['endpoint_uuid']['uuid']
+    return ':'.join([device_uuid, endpoint_uuid])
+
+WIM_SEP_R1_ID      = compose_service_endpoint_id(ENDPOINT_ID_R1_13_1_2)
+WIM_SEP_R1_SITE_ID = '1'
+WIM_SEP_R1_BEARER  = WIM_SEP_R1_ID
+WIM_SRV_R1_VLAN_ID = 400
+
+WIM_SEP_R3_ID      = compose_service_endpoint_id(ENDPOINT_ID_R3_13_1_2)
+WIM_SEP_R3_SITE_ID = '2'
+WIM_SEP_R3_BEARER  = WIM_SEP_R3_ID
+WIM_SRV_R3_VLAN_ID = 500
+
+WIM_USERNAME = 'admin'
+WIM_PASSWORD = 'admin'
+
+WIM_MAPPING  = [
+    {'device-id': DEVICE_R1_UUID, 'service_endpoint_id': WIM_SEP_R1_ID,
+     'service_mapping_info': {'bearer': {'bearer-reference': WIM_SEP_R1_BEARER}, 'site-id': WIM_SEP_R1_SITE_ID}},
+    {'device-id': DEVICE_R3_UUID, 'service_endpoint_id': WIM_SEP_R3_ID,
+     'service_mapping_info': {'bearer': {'bearer-reference': WIM_SEP_R3_BEARER}, 'site-id': WIM_SEP_R3_SITE_ID}},
+]
+WIM_SERVICE_TYPE = 'ELINE'
+WIM_SERVICE_CONNECTION_POINTS = [
+    {'service_endpoint_id': WIM_SEP_R1_ID,
+        'service_endpoint_encapsulation_type': 'dot1q',
+        'service_endpoint_encapsulation_info': {'vlan': WIM_SRV_R1_VLAN_ID}},
+    {'service_endpoint_id': WIM_SEP_R3_ID,
+        'service_endpoint_encapsulation_type': 'dot1q',
+        'service_endpoint_encapsulation_info': {'vlan': WIM_SRV_R3_VLAN_ID}},
+]
+
+# ----- Object Collections ---------------------------------------------------------------------------------------------
+
+CONTEXTS = [CONTEXT]
+TOPOLOGIES = [TOPOLOGY]
+
+DEVICES = [
+    (DEVICE_R1, DEVICE_R1_CONNECT_RULES),
+    (DEVICE_R2, DEVICE_R2_CONNECT_RULES),
+    (DEVICE_R3, DEVICE_R3_CONNECT_RULES),
+    (DEVICE_R4, DEVICE_R4_CONNECT_RULES),
+    (DEVICE_X1, DEVICE_X1_CONNECT_RULES),
+]
+
+LINKS = [LINK_R1_X1, LINK_R2_X1, LINK_R3_X1, LINK_R4_X1]
diff --git a/src/tests/benchmark/policy/tests/__init__.py b/src/tests/benchmark/policy/tests/__init__.py
new file mode 100644
index 000000000..70a332512
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/__init__.py
@@ -0,0 +1,14 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
diff --git a/src/tests/benchmark/policy/tests/test_functional_bootstrap.py b/src/tests/benchmark/policy/tests/test_functional_bootstrap.py
new file mode 100644
index 000000000..71deb9d59
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/test_functional_bootstrap.py
@@ -0,0 +1,95 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import logging, time
+from common.proto.context_pb2 import ContextId, Empty
+from common.proto.monitoring_pb2 import KpiDescriptorList
+from common.tests.LoadScenario import load_scenario_from_descriptor
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from common.tools.object_factory.Context import json_context_id
+from context.client.ContextClient import ContextClient
+from device.client.DeviceClient import DeviceClient
+from monitoring.client.MonitoringClient import MonitoringClient
+from tests.Fixtures import context_client, device_client, monitoring_client # pylint: disable=unused-import
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
+
+def test_scenario_bootstrap(
+    context_client : ContextClient, # pylint: disable=redefined-outer-name
+    device_client : DeviceClient,   # pylint: disable=redefined-outer-name
+) -> None:
+    # ----- List entities - Ensure database is empty -------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == 0
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == 0
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == 0
+
+
+    # ----- Load Scenario ----------------------------------------------------------------------------------------------
+    descriptor_loader = load_scenario_from_descriptor(
+        DESCRIPTOR_FILE, context_client, device_client, None, None)
+
+
+    # ----- List entities - Ensure scenario is ready -------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == descriptor_loader.num_contexts
+
+    for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
+        response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
+        assert len(response.topologies) == num_topologies
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == descriptor_loader.num_devices
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == descriptor_loader.num_links
+
+    for context_uuid, _ in descriptor_loader.num_services.items():
+        response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
+        assert len(response.services) == 0
+
+def test_scenario_kpis_created(
+    context_client : ContextClient,         # pylint: disable=redefined-outer-name
+    monitoring_client: MonitoringClient,    # pylint: disable=redefined-outer-name
+) -> None:
+    """
+    This test validates that KPIs related to the service/device/endpoint were created
+    during the service creation process.
+    """
+    response = context_client.ListDevices(Empty())
+    kpis_expected = set()
+    for device in response.devices:
+        device_uuid = device.device_id.device_uuid.uuid
+        for endpoint in device.device_endpoints:
+            endpoint_uuid = endpoint.endpoint_id.endpoint_uuid.uuid
+            for kpi_sample_type in endpoint.kpi_sample_types:
+                kpis_expected.add((device_uuid, endpoint_uuid, kpi_sample_type))
+    num_kpis_expected = len(kpis_expected)
+    LOGGER.info('Num KPIs expected: {:d}'.format(num_kpis_expected))
+
+    num_kpis_created, num_retry = 0, 0
+    while (num_kpis_created != num_kpis_expected) and (num_retry < 5):
+        response: KpiDescriptorList = monitoring_client.GetKpiDescriptorList(Empty())
+        num_kpis_created = len(response.kpi_descriptor_list)
+        LOGGER.info('Num KPIs created: {:d}'.format(num_kpis_created))
+        time.sleep(0.5)
+        num_retry += 1
+    assert num_kpis_created == num_kpis_expected
diff --git a/src/tests/benchmark/policy/tests/test_functional_cleanup.py b/src/tests/benchmark/policy/tests/test_functional_cleanup.py
new file mode 100644
index 000000000..be807eaa0
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/test_functional_cleanup.py
@@ -0,0 +1,80 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import logging
+from common.tools.descriptor.Loader import DescriptorLoader
+from common.tools.object_factory.Context import json_context_id
+from common.proto.context_pb2 import ContextId, DeviceId, Empty, LinkId, TopologyId
+from context.client.ContextClient import ContextClient
+from device.client.DeviceClient import DeviceClient
+from tests.Fixtures import context_client, device_client    # pylint: disable=unused-import
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
+
+
+def test_services_removed(
+    context_client : ContextClient, # pylint: disable=redefined-outer-name
+    device_client : DeviceClient,   # pylint: disable=redefined-outer-name
+) -> None:
+    # ----- List entities - Ensure service is removed ------------------------------------------------------------------
+    with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f:
+        descriptors = f.read()
+
+    descriptor_loader = DescriptorLoader(descriptors)
+
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == descriptor_loader.num_contexts
+
+    for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
+        response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
+        assert len(response.topologies) == num_topologies
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == descriptor_loader.num_devices
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == descriptor_loader.num_links
+
+    for context_uuid, _ in descriptor_loader.num_services.items():
+        response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
+        assert len(response.services) == 0
+
+
+    # ----- Delete Links, Devices, Topologies, Contexts ----------------------------------------------------------------
+    for link in descriptor_loader.links:
+        context_client.RemoveLink(LinkId(**link['link_id']))
+
+    for device in descriptor_loader.devices:
+        device_client .DeleteDevice(DeviceId(**device['device_id']))
+
+    for context_uuid, topology_list in descriptor_loader.topologies.items():
+        for topology in topology_list:
+            context_client.RemoveTopology(TopologyId(**topology['topology_id']))
+
+    for context in descriptor_loader.contexts:
+        context_client.RemoveContext(ContextId(**context['context_id']))
+
+
+    # ----- List entities - Ensure database is empty again -------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == 0
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == 0
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == 0
diff --git a/src/tests/benchmark/policy/tests/test_functional_create_service.py b/src/tests/benchmark/policy/tests/test_functional_create_service.py
new file mode 100644
index 000000000..e606d060d
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/test_functional_create_service.py
@@ -0,0 +1,124 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import logging, random
+from common.DeviceTypes import DeviceTypeEnum
+from common.proto.context_pb2 import ContextId, Empty
+from common.proto.kpi_sample_types_pb2 import KpiSampleType
+from common.tools.descriptor.Loader import DescriptorLoader
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from common.tools.object_factory.Context import json_context_id
+from context.client.ContextClient import ContextClient
+from monitoring.client.MonitoringClient import MonitoringClient
+from tests.Fixtures import context_client, device_client, monitoring_client # pylint: disable=unused-import
+from tests.tools.mock_osm.MockOSM import MockOSM
+from .Fixtures import osm_wim # pylint: disable=unused-import
+from .Objects import WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
+DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM.value
+
+DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
+
+def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure scenario is ready -------------------------------------------------------------------
+    with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f:
+        descriptors = f.read()
+
+    descriptor_loader = DescriptorLoader(descriptors)
+
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == descriptor_loader.num_contexts
+
+    for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
+        response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
+        assert len(response.topologies) == num_topologies
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == descriptor_loader.num_devices
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == descriptor_loader.num_links
+
+    for context_uuid, num_services in descriptor_loader.num_services.items():
+        response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
+        assert len(response.services) == 0
+
+
+    # ----- Create Service ---------------------------------------------------------------------------------------------
+    service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS)
+    osm_wim.get_connectivity_service_status(service_uuid)
+
+
+    # ----- List entities - Ensure service is created ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == descriptor_loader.num_contexts
+
+    for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
+        response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
+        assert len(response.topologies) == num_topologies
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == descriptor_loader.num_devices
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == descriptor_loader.num_links
+
+    for context_uuid, num_services in descriptor_loader.num_services.items():
+        response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
+        LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
+        assert len(response.services) == 2*num_services # OLS & L3NM => (L3NM + TAPI)
+
+        for service in response.services:
+            service_id = service.service_id
+            response = context_client.ListConnections(service_id)
+            LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
+                grpc_message_to_json_string(service_id), len(response.connections),
+                grpc_message_to_json_string(response)))
+            assert len(response.connections) == 1 # one connection per service
+
+
+def test_scenario_kpi_values_created(
+    monitoring_client: MonitoringClient,    # pylint: disable=redefined-outer-name
+) -> None:
+    """
+    This test validates that KPI values have been inserted into the monitoring database.
+    We short k KPI descriptors to test.
+    """
+    response = monitoring_client.GetKpiDescriptorList(Empty())
+    kpi_descriptors = random.choices(response.kpi_descriptor_list, k=2)
+
+    for kpi_descriptor in kpi_descriptors:
+        MSG = 'KPI(kpi_uuid={:s}, device_uuid={:s}, endpoint_uuid={:s}, service_uuid={:s}, kpi_sample_type={:s})...'
+        LOGGER.info(MSG.format(
+            str(kpi_descriptor.kpi_id.kpi_id.uuid), str(kpi_descriptor.device_id.device_uuid.uuid),
+            str(kpi_descriptor.endpoint_id.endpoint_uuid.uuid), str(kpi_descriptor.service_id.service_uuid.uuid),
+            str(KpiSampleType.Name(kpi_descriptor.kpi_sample_type))))
+        response = monitoring_client.GetInstantKpi(kpi_descriptor.kpi_id)
+        kpi_uuid = response.kpi_id.kpi_id.uuid
+        assert kpi_uuid == kpi_descriptor.kpi_id.kpi_id.uuid
+        kpi_value_type = response.kpi_value.WhichOneof('value')
+        if kpi_value_type is None:
+            MSG = '  KPI({:s}): No instant value found'
+            LOGGER.warning(MSG.format(str(kpi_uuid)))
+        else:
+            kpi_timestamp = response.timestamp.timestamp
+            assert kpi_timestamp > 0
+            assert kpi_value_type == 'floatVal'
+            kpi_value = getattr(response.kpi_value, kpi_value_type)
+            MSG = '  KPI({:s}): timestamp={:s} value_type={:s} value={:s}'
+            LOGGER.info(MSG.format(str(kpi_uuid), str(kpi_timestamp), str(kpi_value_type), str(kpi_value)))
diff --git a/src/tests/benchmark/policy/tests/test_functional_create_service_xr.py b/src/tests/benchmark/policy/tests/test_functional_create_service_xr.py
new file mode 100644
index 000000000..bb78abc1e
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/test_functional_create_service_xr.py
@@ -0,0 +1,129 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import logging, pytest
+from common.DeviceTypes import DeviceTypeEnum
+from common.Settings import get_setting
+from common.tests.EventTools import EVENT_CREATE, EVENT_UPDATE, check_events
+from common.tools.object_factory.Connection import json_connection_id
+from common.tools.object_factory.Device import json_device_id
+from common.tools.object_factory.Service import json_service_id
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from compute.tests.mock_osm.MockOSM import MockOSM
+from context.client.ContextClient import ContextClient
+from context.client.EventsCollector import EventsCollector
+from common.proto.context_pb2 import ContextId, Empty
+from .ObjectsXr import (
+    CONTEXT_ID, CONTEXTS, DEVICE_X1_UUID, DEVICE_R1_UUID, DEVICE_R3_UUID, DEVICES, LINKS, TOPOLOGIES,
+    WIM_MAPPING, WIM_PASSWORD, WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE, WIM_USERNAME)
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
+DEVTYPE_XR_CONSTELLATION = DeviceTypeEnum.XR_CONSTELLATION.value
+
+
+@pytest.fixture(scope='session')
+def context_client():
+    _client = ContextClient(get_setting('CONTEXTSERVICE_SERVICE_HOST'), get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC'))
+    yield _client
+    _client.close()
+
+
+@pytest.fixture(scope='session')
+def osm_wim():
+    wim_url = 'http://{:s}:{:s}'.format(
+        get_setting('COMPUTESERVICE_SERVICE_HOST'), str(get_setting('COMPUTESERVICE_SERVICE_PORT_HTTP')))
+    return MockOSM(wim_url, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
+
+
+def test_scenario_is_correct(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure links are created -------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    assert len(response.services) == 0
+
+
+def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
+    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
+    # events_collector = EventsCollector(context_client, log_events_received=True)
+    # events_collector.start()
+
+    # ----- Create Service ---------------------------------------------------------------------------------------------
+    service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS)
+    osm_wim.get_connectivity_service_status(service_uuid)
+
+    # ----- Validate collected events ----------------------------------------------------------------------------------
+
+    # packet_connection_uuid = '{:s}:{:s}'.format(service_uuid, DEVTYPE_EMU_PR)
+    # optical_connection_uuid = '{:s}:optical:{:s}'.format(service_uuid, DEVTYPE_XR_CONSTELLATION)
+    # optical_service_uuid = '{:s}:optical'.format(service_uuid)
+
+    # expected_events = [
+    #     # Create packet service and add first endpoint
+    #     ('ServiceEvent',    EVENT_CREATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
+    #     ('ServiceEvent',    EVENT_UPDATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
+
+    #     # Configure OLS controller, create optical service, create optical connection
+    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_X1_UUID)),
+    #     ('ServiceEvent',    EVENT_CREATE, json_service_id(optical_service_uuid, context_id=CONTEXT_ID)),
+    #     ('ConnectionEvent', EVENT_CREATE, json_connection_id(optical_connection_uuid)),
+
+    #     # Configure endpoint packet devices, add second endpoint to service, create connection
+    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R1_UUID)),
+    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R3_UUID)),
+    #     ('ServiceEvent',    EVENT_UPDATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
+    #     ('ConnectionEvent', EVENT_CREATE, json_connection_id(packet_connection_uuid)),
+    # ]
+    # check_events(events_collector, expected_events)
+
+    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
+    # events_collector.stop()
+
+
+def test_scenario_service_created(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure service is created ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
+    assert len(response.services) == 2 # L3NM + TAPI
+    for service in response.services:
+        service_id = service.service_id
+        response = context_client.ListConnections(service_id)
+        LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
+            grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
+        assert len(response.connections) == 1 # one connection per service
diff --git a/src/tests/benchmark/policy/tests/test_functional_delete_service.py b/src/tests/benchmark/policy/tests/test_functional_delete_service.py
new file mode 100644
index 000000000..0f8d08801
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/test_functional_delete_service.py
@@ -0,0 +1,99 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import logging
+from common.Constants import DEFAULT_CONTEXT_UUID
+from common.DeviceTypes import DeviceTypeEnum
+from common.proto.context_pb2 import ContextId, Empty, ServiceTypeEnum
+from common.tools.descriptor.Loader import DescriptorLoader
+from common.tools.object_factory.Context import json_context_id
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from context.client.ContextClient import ContextClient
+from tests.Fixtures import context_client   # pylint: disable=unused-import
+from tests.tools.mock_osm.MockOSM import MockOSM
+from .Fixtures import osm_wim # pylint: disable=unused-import
+
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
+DEVTYPE_EMU_OLS = DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM.value
+
+DESCRIPTOR_FILE = 'ofc22/descriptors_emulated.json'
+
+
+def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure service is created ------------------------------------------------------------------
+    with open(DESCRIPTOR_FILE, 'r', encoding='UTF-8') as f:
+        descriptors = f.read()
+
+    descriptor_loader = DescriptorLoader(descriptors)
+
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == descriptor_loader.num_contexts
+
+    for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
+        response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
+        assert len(response.topologies) == num_topologies
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == descriptor_loader.num_devices
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == descriptor_loader.num_links
+
+    l3nm_service_uuids = set()
+    response = context_client.ListServices(ContextId(**json_context_id(DEFAULT_CONTEXT_UUID)))
+    assert len(response.services) == 2 # OLS & L3NM => (L3NM + TAPI)
+    for service in response.services:
+        service_id = service.service_id
+
+        if service.service_type == ServiceTypeEnum.SERVICETYPE_L3NM:
+            service_uuid = service_id.service_uuid.uuid
+            l3nm_service_uuids.add(service_uuid)
+            osm_wim.conn_info[service_uuid] = {}
+
+        response = context_client.ListConnections(service_id)
+        LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
+            grpc_message_to_json_string(service_id), len(response.connections),
+            grpc_message_to_json_string(response)))
+        assert len(response.connections) == 1 # one connection per service
+
+    # Identify service to delete
+    assert len(l3nm_service_uuids) == 1  # assume a single L3NM service has been created
+    l3nm_service_uuid = set(l3nm_service_uuids).pop()
+
+
+    # ----- Delete Service ---------------------------------------------------------------------------------------------
+    osm_wim.delete_connectivity_service(l3nm_service_uuid)
+
+
+    # ----- List entities - Ensure service is removed ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == descriptor_loader.num_contexts
+
+    for context_uuid, num_topologies in descriptor_loader.num_topologies.items():
+        response = context_client.ListTopologies(ContextId(**json_context_id(context_uuid)))
+        assert len(response.topologies) == num_topologies
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == descriptor_loader.num_devices
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == descriptor_loader.num_links
+
+    for context_uuid, num_services in descriptor_loader.num_services.items():
+        response = context_client.ListServices(ContextId(**json_context_id(context_uuid)))
+        assert len(response.services) == 0
diff --git a/src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py b/src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py
new file mode 100644
index 000000000..f28828be0
--- /dev/null
+++ b/src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py
@@ -0,0 +1,133 @@
+# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
+#
+# 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.
+
+import logging, pytest
+from common.DeviceTypes import DeviceTypeEnum
+from common.Settings import get_setting
+from common.tests.EventTools import EVENT_REMOVE, EVENT_UPDATE, check_events
+from common.tools.object_factory.Connection import json_connection_id
+from common.tools.object_factory.Device import json_device_id
+from common.tools.object_factory.Service import json_service_id
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from compute.tests.mock_osm.MockOSM import MockOSM
+from context.client.ContextClient import ContextClient
+from context.client.EventsCollector import EventsCollector
+from common.proto.context_pb2 import ContextId, Empty, ServiceTypeEnum
+from .ObjectsXr import (
+    CONTEXT_ID, CONTEXTS, DEVICE_X1_UUID, DEVICE_R1_UUID, DEVICE_R3_UUID, DEVICES, LINKS, TOPOLOGIES, WIM_MAPPING,
+    WIM_PASSWORD, WIM_USERNAME)
+
+
+LOGGER = logging.getLogger(__name__)
+LOGGER.setLevel(logging.DEBUG)
+
+DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
+DEVTYPE_XR_CONSTELLATION = DeviceTypeEnum.XR_CONSTELLATION.value
+
+@pytest.fixture(scope='session')
+def context_client():
+    _client = ContextClient(get_setting('CONTEXTSERVICE_SERVICE_HOST'), get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC'))
+    yield _client
+    _client.close()
+
+
+@pytest.fixture(scope='session')
+def osm_wim():
+    wim_url = 'http://{:s}:{:s}'.format(
+        get_setting('COMPUTESERVICE_SERVICE_HOST'), str(get_setting('COMPUTESERVICE_SERVICE_PORT_HTTP')))
+    return MockOSM(wim_url, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
+
+
+def test_scenario_is_correct(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure service is created ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
+    assert len(response.services) == 2 # L3NM + TAPI
+    for service in response.services:
+        service_id = service.service_id
+        response = context_client.ListConnections(service_id)
+        LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
+            grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
+        assert len(response.connections) == 1 # one connection per service
+
+
+def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
+    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
+    events_collector = EventsCollector(context_client, log_events_received=True)
+    events_collector.start()
+
+    # ----- Delete Service ---------------------------------------------------------------------------------------------
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
+    assert len(response.services) == 2 # L3NM + TAPI
+    service_uuids = set()
+    for service in response.services:
+        if service.service_type != ServiceTypeEnum.SERVICETYPE_L3NM: continue
+        service_uuid = service.service_id.service_uuid.uuid
+        service_uuids.add(service_uuid)
+        osm_wim.conn_info[service_uuid] = {}
+
+    assert len(service_uuids) == 1  # assume a single service has been created
+    service_uuid = set(service_uuids).pop()
+
+    osm_wim.delete_connectivity_service(service_uuid)
+
+    # ----- Validate collected events ----------------------------------------------------------------------------------
+    # packet_connection_uuid = '{:s}:{:s}'.format(service_uuid, DEVTYPE_EMU_PR)
+    # optical_connection_uuid = '{:s}:optical:{:s}'.format(service_uuid, DEVTYPE_XR_CONSTELLATION)
+    # optical_service_uuid = '{:s}:optical'.format(service_uuid)
+
+    # expected_events = [
+    #     ('ConnectionEvent', EVENT_REMOVE, json_connection_id(packet_connection_uuid)),
+    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R1_UUID)),
+    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R3_UUID)),
+    #     ('ServiceEvent',    EVENT_REMOVE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
+    #     ('ConnectionEvent', EVENT_REMOVE, json_connection_id(optical_connection_uuid)),
+    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_X1_UUID)),
+    #     ('ServiceEvent',    EVENT_REMOVE, json_service_id(optical_service_uuid, context_id=CONTEXT_ID)),
+    # ]
+    # check_events(events_collector, expected_events)
+
+    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
+    # events_collector.stop()
+
+
+def test_services_removed(context_client : ContextClient):  # pylint: disable=redefined-outer-name
+    # ----- List entities - Ensure service is removed ------------------------------------------------------------------
+    response = context_client.ListContexts(Empty())
+    assert len(response.contexts) == len(CONTEXTS)
+
+    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
+    assert len(response.topologies) == len(TOPOLOGIES)
+
+    response = context_client.ListDevices(Empty())
+    assert len(response.devices) == len(DEVICES)
+
+    response = context_client.ListLinks(Empty())
+    assert len(response.links) == len(LINKS)
+
+    response = context_client.ListServices(ContextId(**CONTEXT_ID))
+    assert len(response.services) == 0
-- 
GitLab


From 86fc1a783167f15e03700cec70ca01f6962a312a Mon Sep 17 00:00:00 2001
From: Katopodisv <vkatopodis@ubitech.eu>
Date: Wed, 14 Dec 2022 10:19:01 +0200
Subject: [PATCH 4/4] Remove not used files

---
 .../policy/descriptors_emulated_xr.json       | 108 --------
 src/tests/benchmark/policy/run_tests.sh       |  44 ----
 src/tests/benchmark/policy/tests/ObjectsXr.py | 238 ------------------
 .../test_functional_create_service_xr.py      | 129 ----------
 .../test_functional_delete_service_xr.py      | 133 ----------
 5 files changed, 652 deletions(-)
 delete mode 100644 src/tests/benchmark/policy/descriptors_emulated_xr.json
 delete mode 100755 src/tests/benchmark/policy/run_tests.sh
 delete mode 100644 src/tests/benchmark/policy/tests/ObjectsXr.py
 delete mode 100644 src/tests/benchmark/policy/tests/test_functional_create_service_xr.py
 delete mode 100644 src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py

diff --git a/src/tests/benchmark/policy/descriptors_emulated_xr.json b/src/tests/benchmark/policy/descriptors_emulated_xr.json
deleted file mode 100644
index 30bd97ddd..000000000
--- a/src/tests/benchmark/policy/descriptors_emulated_xr.json
+++ /dev/null
@@ -1,108 +0,0 @@
-{
-    "contexts": [
-        {
-            "context_id": {"context_uuid": {"uuid": "admin"}},
-            "topology_ids": [],
-            "service_ids": []
-        }
-    ],
-    "topologies": [
-        {
-            "topology_id": {"topology_uuid": {"uuid": "admin"}, "context_id": {"context_uuid": {"uuid": "admin"}}},
-            "device_ids": [],
-            "link_ids": []
-        }
-    ],
-    "devices": [
-        {
-            "device_id": {"device_uuid": {"uuid": "R1-EMU"}},
-            "device_type": "emu-packet-router",
-            "device_config": {"config_rules": [
-                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
-                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
-                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
-            ]},
-            "device_operational_status": 1,
-            "device_drivers": [0],
-            "device_endpoints": []
-        },
-        {
-            "device_id": {"device_uuid": {"uuid": "R2-EMU"}},
-            "device_type": "emu-packet-router",
-            "device_config": {"config_rules": [
-                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
-                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
-                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
-            ]},
-            "device_operational_status": 1,
-            "device_drivers": [0],
-            "device_endpoints": []
-        },
-        {
-            "device_id": {"device_uuid": {"uuid": "R3-EMU"}},
-            "device_type": "emu-packet-router",
-            "device_config": {"config_rules": [
-                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
-                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
-                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
-            ]},
-            "device_operational_status": 1,
-            "device_drivers": [0],
-            "device_endpoints": []
-        },
-        {
-            "device_id": {"device_uuid": {"uuid": "R4-EMU"}},
-            "device_type": "emu-packet-router",
-            "device_config": {"config_rules": [
-                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
-                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "0"}},
-                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"endpoints\": [{\"sample_types\": [], \"type\": \"optical\", \"uuid\": \"13/0/0\"}, {\"sample_types\": [101, 102, 201, 202], \"type\": \"copper\", \"uuid\": \"13/1/2\"}]}"}}
-            ]},
-            "device_operational_status": 1,
-            "device_drivers": [0],
-            "device_endpoints": []
-        },
-        {
-            "device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}},
-            "device_type": "xr-constellation",
-            "device_config": {"config_rules": [
-                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "172.19.219.44"}},
-                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": "443"}},
-                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": "{\"username\": \"xr-user-1\", \"password\": \"xr-user-1\", \"hub_module_name\": \"XR HUB 1\"}"}}
-            ]},
-            "device_operational_status": 1,
-            "device_drivers": [6],
-            "device_endpoints": []
-        }
-    ],
-    "links": [
-        {
-            "link_id": {"link_uuid": {"uuid": "R1-EMU/13/0/0==XR HUB 1|XR-T4"}},
-            "link_endpoint_ids": [
-                {"device_id": {"device_uuid": {"uuid": "R1-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
-                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR HUB 1|XR-T4"}}
-            ]
-        },
-        {
-            "link_id": {"link_uuid": {"uuid": "R2-EMU/13/0/0==XR HUB 1|XR-T3"}},
-            "link_endpoint_ids": [
-                {"device_id": {"device_uuid": {"uuid": "R2-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
-                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR HUB 1|XR-T3"}}
-            ]
-        },
-        {
-            "link_id": {"link_uuid": {"uuid": "R3-EMU/13/0/0==XR1-XR LEAF 1|XR-T1"}},
-            "link_endpoint_ids": [
-                {"device_id": {"device_uuid": {"uuid": "R3-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
-                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR LEAF 1|XR-T1"}}
-            ]
-        },
-        {
-            "link_id": {"link_uuid": {"uuid": "R4-EMU/13/0/0==XR LEAF 2|XR-T1"}},
-            "link_endpoint_ids": [
-                {"device_id": {"device_uuid": {"uuid": "R4-EMU"}}, "endpoint_uuid": {"uuid": "13/0/0"}},
-                {"device_id": {"device_uuid": {"uuid": "X1-XR-CONSTELLATION"}}, "endpoint_uuid": {"uuid": "XR LEAF 2|XR-T1"}}
-            ]
-        }
-    ]
-}
diff --git a/src/tests/benchmark/policy/run_tests.sh b/src/tests/benchmark/policy/run_tests.sh
deleted file mode 100755
index 0ad4be313..000000000
--- a/src/tests/benchmark/policy/run_tests.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/bash
-# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
-#
-# 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.
-
-
-PROJECTDIR=`pwd`
-
-RCFILE=$PROJECTDIR/coverage/.coveragerc
-COVERAGEFILE=$PROJECTDIR/coverage/.coverage
-
-# Configure the correct folder on the .coveragerc file
-cat $PROJECTDIR/coverage/.coveragerc.template | sed s+~/teraflow/controller+$PROJECTDIR/src+g > $RCFILE
-
-# Destroy old coverage file
-rm -f $COVERAGEFILE
-
-source tfs_runtime_env_vars.sh
-
-# Force a flush of Context database
-kubectl --namespace $TFS_K8S_NAMESPACE exec -it deployment/contextservice --container redis -- redis-cli FLUSHALL
-
-# Run functional tests
-pytest --log-level=INFO --verbose \
-    src/tests/ofc22/tests/test_functional_bootstrap.py
-
-pytest --log-level=INFO --verbose \
-    src/tests/ofc22/tests/test_functional_create_service.py
-
-pytest --log-level=INFO --verbose \
-    src/tests/ofc22/tests/test_functional_delete_service.py
-
-pytest --log-level=INFO --verbose \
-    src/tests/ofc22/tests/test_functional_cleanup.py
diff --git a/src/tests/benchmark/policy/tests/ObjectsXr.py b/src/tests/benchmark/policy/tests/ObjectsXr.py
deleted file mode 100644
index 0cb223de2..000000000
--- a/src/tests/benchmark/policy/tests/ObjectsXr.py
+++ /dev/null
@@ -1,238 +0,0 @@
-# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
-#
-# 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.
-
-from typing import Dict, List, Tuple
-from common.Constants import DEFAULT_CONTEXT_UUID, DEFAULT_TOPOLOGY_UUID
-from common.tools.object_factory.Context import json_context, json_context_id
-from common.tools.object_factory.Device import (
-    json_device_connect_rules, json_device_emulated_connect_rules, json_device_emulated_packet_router_disabled,
-    json_device_emulated_tapi_disabled, json_device_id, json_device_packetrouter_disabled, json_device_tapi_disabled)
-from common.tools.object_factory.EndPoint import json_endpoint, json_endpoint_id
-from common.tools.object_factory.Link import json_link, json_link_id
-from common.tools.object_factory.Topology import json_topology, json_topology_id
-from common.proto.kpi_sample_types_pb2 import KpiSampleType
-
-# ----- Context --------------------------------------------------------------------------------------------------------
-CONTEXT_ID = json_context_id(DEFAULT_CONTEXT_UUID)
-CONTEXT    = json_context(DEFAULT_CONTEXT_UUID)
-
-# ----- Topology -------------------------------------------------------------------------------------------------------
-TOPOLOGY_ID = json_topology_id(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
-TOPOLOGY    = json_topology(DEFAULT_TOPOLOGY_UUID, context_id=CONTEXT_ID)
-
-# ----- Monitoring Samples ---------------------------------------------------------------------------------------------
-PACKET_PORT_SAMPLE_TYPES = [
-    KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED,
-    KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED,
-    KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED,
-    KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED,
-]
-
-# ----- Device Credentials and Settings --------------------------------------------------------------------------------
-try:
-    from .Credentials import DEVICE_R1_ADDRESS, DEVICE_R1_PORT, DEVICE_R1_USERNAME, DEVICE_R1_PASSWORD
-    from .Credentials import DEVICE_R3_ADDRESS, DEVICE_R3_PORT, DEVICE_R3_USERNAME, DEVICE_R3_PASSWORD
-    #from .Credentials import DEVICE_O1_ADDRESS, DEVICE_O1_PORT
-    USE_REAL_DEVICES = True     # Use real devices
-except ImportError:
-    USE_REAL_DEVICES = False    # Use emulated devices
-
-    DEVICE_R1_ADDRESS  = '0.0.0.0'
-    DEVICE_R1_PORT     = 830
-    DEVICE_R1_USERNAME = 'admin'
-    DEVICE_R1_PASSWORD = 'admin'
-
-    DEVICE_R3_ADDRESS  = '0.0.0.0'
-    DEVICE_R3_PORT     = 830
-    DEVICE_R3_USERNAME = 'admin'
-    DEVICE_R3_PASSWORD = 'admin'
-
-DEVICE_X1_ADDRESS  = '172.19.219.44'
-DEVICE_X1_PORT     = 443
-
-#USE_REAL_DEVICES = False     # Uncomment to force to use emulated devices
-
-def json_endpoint_ids(device_id : Dict, endpoint_descriptors : List[Tuple[str, str, List[int]]]):
-    return [
-        json_endpoint_id(device_id, ep_uuid, topology_id=None)
-        for ep_uuid, _, _ in endpoint_descriptors
-    ]
-
-def json_endpoints(device_id : Dict, endpoint_descriptors : List[Tuple[str, str, List[int]]]):
-    return [
-        json_endpoint(device_id, ep_uuid, ep_type, topology_id=None, kpi_sample_types=ep_sample_types)
-        for ep_uuid, ep_type, ep_sample_types in endpoint_descriptors
-    ]
-
-def get_link_uuid(a_device_id : Dict, a_endpoint_id : Dict, z_device_id : Dict, z_endpoint_id : Dict) -> str:
-    return '{:s}/{:s}=={:s}/{:s}'.format(
-        a_device_id['device_uuid']['uuid'], a_endpoint_id['endpoint_uuid']['uuid'],
-        z_device_id['device_uuid']['uuid'], z_endpoint_id['endpoint_uuid']['uuid'])
-
-
-# ----- Devices --------------------------------------------------------------------------------------------------------
-if not USE_REAL_DEVICES:
-    json_device_packetrouter_disabled = json_device_emulated_packet_router_disabled
-    json_device_tapi_disabled         = json_device_emulated_tapi_disabled
-
-DEVICE_R1_UUID          = 'R1-EMU'
-DEVICE_R1_TIMEOUT       = 120
-DEVICE_R1_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
-DEVICE_R1_ID            = json_device_id(DEVICE_R1_UUID)
-#DEVICE_R1_ENDPOINTS     = json_endpoints(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
-DEVICE_R1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R1_ID, DEVICE_R1_ENDPOINT_DEFS)
-DEVICE_R1               = json_device_packetrouter_disabled(DEVICE_R1_UUID)
-ENDPOINT_ID_R1_13_0_0   = DEVICE_R1_ENDPOINT_IDS[0]
-ENDPOINT_ID_R1_13_1_2   = DEVICE_R1_ENDPOINT_IDS[1]
-DEVICE_R1_CONNECT_RULES = json_device_connect_rules(DEVICE_R1_ADDRESS, DEVICE_R1_PORT, {
-    'username': DEVICE_R1_USERNAME,
-    'password': DEVICE_R1_PASSWORD,
-    'timeout' : DEVICE_R1_TIMEOUT,
-}) if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_R1_ENDPOINT_DEFS)
-
-
-DEVICE_R2_UUID          = 'R2-EMU'
-DEVICE_R2_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
-DEVICE_R2_ID            = json_device_id(DEVICE_R2_UUID)
-#DEVICE_R2_ENDPOINTS     = json_endpoints(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
-DEVICE_R2_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R2_ID, DEVICE_R2_ENDPOINT_DEFS)
-DEVICE_R2               = json_device_emulated_packet_router_disabled(DEVICE_R2_UUID)
-ENDPOINT_ID_R2_13_0_0   = DEVICE_R2_ENDPOINT_IDS[0]
-ENDPOINT_ID_R2_13_1_2   = DEVICE_R2_ENDPOINT_IDS[1]
-DEVICE_R2_CONNECT_RULES = json_device_emulated_connect_rules(DEVICE_R2_ENDPOINT_DEFS)
-
-
-DEVICE_R3_UUID          = 'R3-EMU'
-DEVICE_R3_TIMEOUT       = 120
-DEVICE_R3_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
-DEVICE_R3_ID            = json_device_id(DEVICE_R3_UUID)
-#DEVICE_R3_ENDPOINTS     = json_endpoints(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS)
-DEVICE_R3_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R3_ID, DEVICE_R3_ENDPOINT_DEFS)
-DEVICE_R3               = json_device_packetrouter_disabled(DEVICE_R3_UUID)
-ENDPOINT_ID_R3_13_0_0   = DEVICE_R3_ENDPOINT_IDS[0]
-ENDPOINT_ID_R3_13_1_2   = DEVICE_R3_ENDPOINT_IDS[1]
-DEVICE_R3_CONNECT_RULES = json_device_connect_rules(DEVICE_R3_ADDRESS, DEVICE_R3_PORT, {
-    'username': DEVICE_R3_USERNAME,
-    'password': DEVICE_R3_PASSWORD,
-    'timeout' : DEVICE_R3_TIMEOUT,
-}) if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_R3_ENDPOINT_DEFS)
-
-
-DEVICE_R4_UUID          = 'R4-EMU'
-DEVICE_R4_ENDPOINT_DEFS = [('13/0/0', 'optical', []), ('13/1/2', 'copper', PACKET_PORT_SAMPLE_TYPES)]
-DEVICE_R4_ID            = json_device_id(DEVICE_R4_UUID)
-#DEVICE_R4_ENDPOINTS     = json_endpoints(DEVICE_R4_ID, DEVICE_R4_ENDPOINT_DEFS)
-DEVICE_R4_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_R4_ID, DEVICE_R4_ENDPOINT_DEFS)
-DEVICE_R4               = json_device_emulated_packet_router_disabled(DEVICE_R4_UUID)
-ENDPOINT_ID_R4_13_0_0   = DEVICE_R4_ENDPOINT_IDS[0]
-ENDPOINT_ID_R4_13_1_2   = DEVICE_R4_ENDPOINT_IDS[1]
-DEVICE_R4_CONNECT_RULES = json_device_emulated_connect_rules(DEVICE_R4_ENDPOINT_DEFS)
-
-
-DEVICE_X1_UUID          = 'X1-XR-CONSTELLATION'
-DEVICE_X1_TIMEOUT       = 120
-DEVICE_X1_ENDPOINT_DEFS = [
-    ('XR HUB 1|XR-T1', 'optical', []),
-    ('XR HUB 1|XR-T2', 'optical', []),
-    ('XR HUB 1|XR-T3', 'optical', []),
-    ('XR HUB 1|XR-T4', 'optical', []),
-    ('XR LEAF 1|XR-T1', 'optical', []),
-    ('XR LEAF 2|XR-T1', 'optical', []),
-]
-DEVICE_X1_ID            = json_device_id(DEVICE_X1_UUID)
-DEVICE_X1               = json_device_tapi_disabled(DEVICE_X1_UUID)
-DEVICE_X1_ENDPOINT_IDS  = json_endpoint_ids(DEVICE_X1_ID, DEVICE_X1_ENDPOINT_DEFS)
-# These match JSON, hence indexes are what theyt are
-ENDPOINT_ID_X1_EP1      = DEVICE_X1_ENDPOINT_IDS[3]
-ENDPOINT_ID_X1_EP2      = DEVICE_X1_ENDPOINT_IDS[2]
-ENDPOINT_ID_X1_EP3      = DEVICE_X1_ENDPOINT_IDS[4]
-ENDPOINT_ID_X1_EP4      = DEVICE_X1_ENDPOINT_IDS[5]
-DEVICE_X1_CONNECT_RULES = json_device_connect_rules(DEVICE_X1_ADDRESS, DEVICE_X1_PORT, {
-    'timeout' : DEVICE_X1_TIMEOUT,
-    "username": "xr-user-1",
-    "password": "xr-user-1",
-    "hub_module_name": "XR HUB 1"
-})
-# Always using real device (CM, whether CM has emulated backend is another story)
-#if USE_REAL_DEVICES else json_device_emulated_connect_rules(DEVICE_X1_ENDPOINT_DEFS)
-
-
-# ----- Links ----------------------------------------------------------------------------------------------------------
-LINK_R1_X1_UUID = get_link_uuid(DEVICE_R1_ID, ENDPOINT_ID_R1_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP1)
-LINK_R1_X1_ID   = json_link_id(LINK_R1_X1_UUID)
-LINK_R1_X1      = json_link(LINK_R1_X1_UUID, [ENDPOINT_ID_R1_13_0_0, ENDPOINT_ID_X1_EP1])
-
-LINK_R2_X1_UUID = get_link_uuid(DEVICE_R2_ID, ENDPOINT_ID_R2_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP2)
-LINK_R2_X1_ID   = json_link_id(LINK_R2_X1_UUID)
-LINK_R2_X1      = json_link(LINK_R2_X1_UUID, [ENDPOINT_ID_R2_13_0_0, ENDPOINT_ID_X1_EP2])
-
-LINK_R3_X1_UUID = get_link_uuid(DEVICE_R3_ID, ENDPOINT_ID_R3_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP3)
-LINK_R3_X1_ID   = json_link_id(LINK_R3_X1_UUID)
-LINK_R3_X1      = json_link(LINK_R3_X1_UUID, [ENDPOINT_ID_R3_13_0_0, ENDPOINT_ID_X1_EP3])
-
-LINK_R4_X1_UUID = get_link_uuid(DEVICE_R4_ID, ENDPOINT_ID_R4_13_0_0, DEVICE_X1_ID, ENDPOINT_ID_X1_EP4)
-LINK_R4_X1_ID   = json_link_id(LINK_R4_X1_UUID)
-LINK_R4_X1      = json_link(LINK_R4_X1_UUID, [ENDPOINT_ID_R4_13_0_0, ENDPOINT_ID_X1_EP4])
-
-
-# ----- WIM Service Settings -------------------------------------------------------------------------------------------
-
-def compose_service_endpoint_id(endpoint_id):
-    device_uuid = endpoint_id['device_id']['device_uuid']['uuid']
-    endpoint_uuid = endpoint_id['endpoint_uuid']['uuid']
-    return ':'.join([device_uuid, endpoint_uuid])
-
-WIM_SEP_R1_ID      = compose_service_endpoint_id(ENDPOINT_ID_R1_13_1_2)
-WIM_SEP_R1_SITE_ID = '1'
-WIM_SEP_R1_BEARER  = WIM_SEP_R1_ID
-WIM_SRV_R1_VLAN_ID = 400
-
-WIM_SEP_R3_ID      = compose_service_endpoint_id(ENDPOINT_ID_R3_13_1_2)
-WIM_SEP_R3_SITE_ID = '2'
-WIM_SEP_R3_BEARER  = WIM_SEP_R3_ID
-WIM_SRV_R3_VLAN_ID = 500
-
-WIM_USERNAME = 'admin'
-WIM_PASSWORD = 'admin'
-
-WIM_MAPPING  = [
-    {'device-id': DEVICE_R1_UUID, 'service_endpoint_id': WIM_SEP_R1_ID,
-     'service_mapping_info': {'bearer': {'bearer-reference': WIM_SEP_R1_BEARER}, 'site-id': WIM_SEP_R1_SITE_ID}},
-    {'device-id': DEVICE_R3_UUID, 'service_endpoint_id': WIM_SEP_R3_ID,
-     'service_mapping_info': {'bearer': {'bearer-reference': WIM_SEP_R3_BEARER}, 'site-id': WIM_SEP_R3_SITE_ID}},
-]
-WIM_SERVICE_TYPE = 'ELINE'
-WIM_SERVICE_CONNECTION_POINTS = [
-    {'service_endpoint_id': WIM_SEP_R1_ID,
-        'service_endpoint_encapsulation_type': 'dot1q',
-        'service_endpoint_encapsulation_info': {'vlan': WIM_SRV_R1_VLAN_ID}},
-    {'service_endpoint_id': WIM_SEP_R3_ID,
-        'service_endpoint_encapsulation_type': 'dot1q',
-        'service_endpoint_encapsulation_info': {'vlan': WIM_SRV_R3_VLAN_ID}},
-]
-
-# ----- Object Collections ---------------------------------------------------------------------------------------------
-
-CONTEXTS = [CONTEXT]
-TOPOLOGIES = [TOPOLOGY]
-
-DEVICES = [
-    (DEVICE_R1, DEVICE_R1_CONNECT_RULES),
-    (DEVICE_R2, DEVICE_R2_CONNECT_RULES),
-    (DEVICE_R3, DEVICE_R3_CONNECT_RULES),
-    (DEVICE_R4, DEVICE_R4_CONNECT_RULES),
-    (DEVICE_X1, DEVICE_X1_CONNECT_RULES),
-]
-
-LINKS = [LINK_R1_X1, LINK_R2_X1, LINK_R3_X1, LINK_R4_X1]
diff --git a/src/tests/benchmark/policy/tests/test_functional_create_service_xr.py b/src/tests/benchmark/policy/tests/test_functional_create_service_xr.py
deleted file mode 100644
index bb78abc1e..000000000
--- a/src/tests/benchmark/policy/tests/test_functional_create_service_xr.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
-#
-# 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.
-
-import logging, pytest
-from common.DeviceTypes import DeviceTypeEnum
-from common.Settings import get_setting
-from common.tests.EventTools import EVENT_CREATE, EVENT_UPDATE, check_events
-from common.tools.object_factory.Connection import json_connection_id
-from common.tools.object_factory.Device import json_device_id
-from common.tools.object_factory.Service import json_service_id
-from common.tools.grpc.Tools import grpc_message_to_json_string
-from compute.tests.mock_osm.MockOSM import MockOSM
-from context.client.ContextClient import ContextClient
-from context.client.EventsCollector import EventsCollector
-from common.proto.context_pb2 import ContextId, Empty
-from .ObjectsXr import (
-    CONTEXT_ID, CONTEXTS, DEVICE_X1_UUID, DEVICE_R1_UUID, DEVICE_R3_UUID, DEVICES, LINKS, TOPOLOGIES,
-    WIM_MAPPING, WIM_PASSWORD, WIM_SERVICE_CONNECTION_POINTS, WIM_SERVICE_TYPE, WIM_USERNAME)
-
-LOGGER = logging.getLogger(__name__)
-LOGGER.setLevel(logging.DEBUG)
-
-DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
-DEVTYPE_XR_CONSTELLATION = DeviceTypeEnum.XR_CONSTELLATION.value
-
-
-@pytest.fixture(scope='session')
-def context_client():
-    _client = ContextClient(get_setting('CONTEXTSERVICE_SERVICE_HOST'), get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC'))
-    yield _client
-    _client.close()
-
-
-@pytest.fixture(scope='session')
-def osm_wim():
-    wim_url = 'http://{:s}:{:s}'.format(
-        get_setting('COMPUTESERVICE_SERVICE_HOST'), str(get_setting('COMPUTESERVICE_SERVICE_PORT_HTTP')))
-    return MockOSM(wim_url, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
-
-
-def test_scenario_is_correct(context_client : ContextClient):  # pylint: disable=redefined-outer-name
-    # ----- List entities - Ensure links are created -------------------------------------------------------------------
-    response = context_client.ListContexts(Empty())
-    assert len(response.contexts) == len(CONTEXTS)
-
-    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
-    assert len(response.topologies) == len(TOPOLOGIES)
-
-    response = context_client.ListDevices(Empty())
-    assert len(response.devices) == len(DEVICES)
-
-    response = context_client.ListLinks(Empty())
-    assert len(response.links) == len(LINKS)
-
-    response = context_client.ListServices(ContextId(**CONTEXT_ID))
-    assert len(response.services) == 0
-
-
-def test_service_creation(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
-    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
-    # events_collector = EventsCollector(context_client, log_events_received=True)
-    # events_collector.start()
-
-    # ----- Create Service ---------------------------------------------------------------------------------------------
-    service_uuid = osm_wim.create_connectivity_service(WIM_SERVICE_TYPE, WIM_SERVICE_CONNECTION_POINTS)
-    osm_wim.get_connectivity_service_status(service_uuid)
-
-    # ----- Validate collected events ----------------------------------------------------------------------------------
-
-    # packet_connection_uuid = '{:s}:{:s}'.format(service_uuid, DEVTYPE_EMU_PR)
-    # optical_connection_uuid = '{:s}:optical:{:s}'.format(service_uuid, DEVTYPE_XR_CONSTELLATION)
-    # optical_service_uuid = '{:s}:optical'.format(service_uuid)
-
-    # expected_events = [
-    #     # Create packet service and add first endpoint
-    #     ('ServiceEvent',    EVENT_CREATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
-    #     ('ServiceEvent',    EVENT_UPDATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
-
-    #     # Configure OLS controller, create optical service, create optical connection
-    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_X1_UUID)),
-    #     ('ServiceEvent',    EVENT_CREATE, json_service_id(optical_service_uuid, context_id=CONTEXT_ID)),
-    #     ('ConnectionEvent', EVENT_CREATE, json_connection_id(optical_connection_uuid)),
-
-    #     # Configure endpoint packet devices, add second endpoint to service, create connection
-    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R1_UUID)),
-    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R3_UUID)),
-    #     ('ServiceEvent',    EVENT_UPDATE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
-    #     ('ConnectionEvent', EVENT_CREATE, json_connection_id(packet_connection_uuid)),
-    # ]
-    # check_events(events_collector, expected_events)
-
-    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
-    # events_collector.stop()
-
-
-def test_scenario_service_created(context_client : ContextClient):  # pylint: disable=redefined-outer-name
-    # ----- List entities - Ensure service is created ------------------------------------------------------------------
-    response = context_client.ListContexts(Empty())
-    assert len(response.contexts) == len(CONTEXTS)
-
-    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
-    assert len(response.topologies) == len(TOPOLOGIES)
-
-    response = context_client.ListDevices(Empty())
-    assert len(response.devices) == len(DEVICES)
-
-    response = context_client.ListLinks(Empty())
-    assert len(response.links) == len(LINKS)
-
-    response = context_client.ListServices(ContextId(**CONTEXT_ID))
-    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
-    assert len(response.services) == 2 # L3NM + TAPI
-    for service in response.services:
-        service_id = service.service_id
-        response = context_client.ListConnections(service_id)
-        LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
-            grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
-        assert len(response.connections) == 1 # one connection per service
diff --git a/src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py b/src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py
deleted file mode 100644
index f28828be0..000000000
--- a/src/tests/benchmark/policy/tests/test_functional_delete_service_xr.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
-#
-# 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.
-
-import logging, pytest
-from common.DeviceTypes import DeviceTypeEnum
-from common.Settings import get_setting
-from common.tests.EventTools import EVENT_REMOVE, EVENT_UPDATE, check_events
-from common.tools.object_factory.Connection import json_connection_id
-from common.tools.object_factory.Device import json_device_id
-from common.tools.object_factory.Service import json_service_id
-from common.tools.grpc.Tools import grpc_message_to_json_string
-from compute.tests.mock_osm.MockOSM import MockOSM
-from context.client.ContextClient import ContextClient
-from context.client.EventsCollector import EventsCollector
-from common.proto.context_pb2 import ContextId, Empty, ServiceTypeEnum
-from .ObjectsXr import (
-    CONTEXT_ID, CONTEXTS, DEVICE_X1_UUID, DEVICE_R1_UUID, DEVICE_R3_UUID, DEVICES, LINKS, TOPOLOGIES, WIM_MAPPING,
-    WIM_PASSWORD, WIM_USERNAME)
-
-
-LOGGER = logging.getLogger(__name__)
-LOGGER.setLevel(logging.DEBUG)
-
-DEVTYPE_EMU_PR  = DeviceTypeEnum.EMULATED_PACKET_ROUTER.value
-DEVTYPE_XR_CONSTELLATION = DeviceTypeEnum.XR_CONSTELLATION.value
-
-@pytest.fixture(scope='session')
-def context_client():
-    _client = ContextClient(get_setting('CONTEXTSERVICE_SERVICE_HOST'), get_setting('CONTEXTSERVICE_SERVICE_PORT_GRPC'))
-    yield _client
-    _client.close()
-
-
-@pytest.fixture(scope='session')
-def osm_wim():
-    wim_url = 'http://{:s}:{:s}'.format(
-        get_setting('COMPUTESERVICE_SERVICE_HOST'), str(get_setting('COMPUTESERVICE_SERVICE_PORT_HTTP')))
-    return MockOSM(wim_url, WIM_MAPPING, WIM_USERNAME, WIM_PASSWORD)
-
-
-def test_scenario_is_correct(context_client : ContextClient):  # pylint: disable=redefined-outer-name
-    # ----- List entities - Ensure service is created ------------------------------------------------------------------
-    response = context_client.ListContexts(Empty())
-    assert len(response.contexts) == len(CONTEXTS)
-
-    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
-    assert len(response.topologies) == len(TOPOLOGIES)
-
-    response = context_client.ListDevices(Empty())
-    assert len(response.devices) == len(DEVICES)
-
-    response = context_client.ListLinks(Empty())
-    assert len(response.links) == len(LINKS)
-
-    response = context_client.ListServices(ContextId(**CONTEXT_ID))
-    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
-    assert len(response.services) == 2 # L3NM + TAPI
-    for service in response.services:
-        service_id = service.service_id
-        response = context_client.ListConnections(service_id)
-        LOGGER.info('  ServiceId[{:s}] => Connections[{:d}] = {:s}'.format(
-            grpc_message_to_json_string(service_id), len(response.connections), grpc_message_to_json_string(response)))
-        assert len(response.connections) == 1 # one connection per service
-
-
-def test_service_removal(context_client : ContextClient, osm_wim : MockOSM): # pylint: disable=redefined-outer-name
-    # ----- Start the EventsCollector ----------------------------------------------------------------------------------
-    events_collector = EventsCollector(context_client, log_events_received=True)
-    events_collector.start()
-
-    # ----- Delete Service ---------------------------------------------------------------------------------------------
-    response = context_client.ListServices(ContextId(**CONTEXT_ID))
-    LOGGER.info('Services[{:d}] = {:s}'.format(len(response.services), grpc_message_to_json_string(response)))
-    assert len(response.services) == 2 # L3NM + TAPI
-    service_uuids = set()
-    for service in response.services:
-        if service.service_type != ServiceTypeEnum.SERVICETYPE_L3NM: continue
-        service_uuid = service.service_id.service_uuid.uuid
-        service_uuids.add(service_uuid)
-        osm_wim.conn_info[service_uuid] = {}
-
-    assert len(service_uuids) == 1  # assume a single service has been created
-    service_uuid = set(service_uuids).pop()
-
-    osm_wim.delete_connectivity_service(service_uuid)
-
-    # ----- Validate collected events ----------------------------------------------------------------------------------
-    # packet_connection_uuid = '{:s}:{:s}'.format(service_uuid, DEVTYPE_EMU_PR)
-    # optical_connection_uuid = '{:s}:optical:{:s}'.format(service_uuid, DEVTYPE_XR_CONSTELLATION)
-    # optical_service_uuid = '{:s}:optical'.format(service_uuid)
-
-    # expected_events = [
-    #     ('ConnectionEvent', EVENT_REMOVE, json_connection_id(packet_connection_uuid)),
-    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R1_UUID)),
-    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_R3_UUID)),
-    #     ('ServiceEvent',    EVENT_REMOVE, json_service_id(service_uuid, context_id=CONTEXT_ID)),
-    #     ('ConnectionEvent', EVENT_REMOVE, json_connection_id(optical_connection_uuid)),
-    #     ('DeviceEvent',     EVENT_UPDATE, json_device_id(DEVICE_X1_UUID)),
-    #     ('ServiceEvent',    EVENT_REMOVE, json_service_id(optical_service_uuid, context_id=CONTEXT_ID)),
-    # ]
-    # check_events(events_collector, expected_events)
-
-    # ----- Stop the EventsCollector -----------------------------------------------------------------------------------
-    # events_collector.stop()
-
-
-def test_services_removed(context_client : ContextClient):  # pylint: disable=redefined-outer-name
-    # ----- List entities - Ensure service is removed ------------------------------------------------------------------
-    response = context_client.ListContexts(Empty())
-    assert len(response.contexts) == len(CONTEXTS)
-
-    response = context_client.ListTopologies(ContextId(**CONTEXT_ID))
-    assert len(response.topologies) == len(TOPOLOGIES)
-
-    response = context_client.ListDevices(Empty())
-    assert len(response.devices) == len(DEVICES)
-
-    response = context_client.ListLinks(Empty())
-    assert len(response.links) == len(LINKS)
-
-    response = context_client.ListServices(ContextId(**CONTEXT_ID))
-    assert len(response.services) == 0
-- 
GitLab