Loading src/device/.gitlab-ci.yml +47 −44 Original line number Diff line number Diff line Loading @@ -38,63 +38,65 @@ build device: - manifests/${IMAGE_NAME}service.yaml - .gitlab-ci.yml ## Start Mock QKD Nodes before unit testing #start_mock_nodes: # stage: deploy # script: # - bash src/tests/tools/mock_qkd_nodes/start.sh & # - sleep 10 # wait for nodes to spin up # artifacts: # paths: # - mock_nodes.log # rules: # - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' # - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' ## Prepare Scenario (Start NBI, mock services) #prepare_scenario: # stage: deploy # script: # - pytest src/tests/qkd/unit/PrepareScenario.py # needs: # - start_mock_nodes # rules: # - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' # - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' # Deploy mock QKD nodes deploy_mock_qkd_nodes: stage: prepare script: - echo "Starting mock QKD nodes deployment..." - > if docker network list | grep -q teraflowbridge; then echo "teraflowbridge network is already created"; else docker network create -d bridge teraflowbridge; fi - > for port in 11111 22222 33333; do if lsof -i:$port >/dev/null 2>&1; then echo "Freeing up port $port..."; fuser -k $port/tcp; fi done - MOCK_NODES_DIR="/home/cttc-docker/tfs-ctrl/src/tests/tools/mock_qkd_nodes" - if [ -d "$MOCK_NODES_DIR" ]; then cd "$MOCK_NODES_DIR" && ./start.sh & else echo "Error: Mock QKD nodes directory '$MOCK_NODES_DIR' not found." && exit 1; fi rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' - changes: - src/common/**/*.py - proto/*.proto - src/device/**/*.{py,in,yml} - src/device/Dockerfile - src/device/tests/*.py - src/tests/tools/mock_qkd_nodes/** - .gitlab-ci.yml # Apply unit test to the component unit_test device: unit_test_device: variables: IMAGE_NAME: 'device' # name of the microservice IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) stage: unit_test needs: - build device #- start_mock_nodes #- prepare_scenario - build_device - deploy_mock_qkd_nodes before_script: - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - > if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - > if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME image is not in the system"; fi script: - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" - docker run --name $IMAGE_NAME -d -p 2020:2020 -v "$PWD/src/$IMAGE_NAME/tests:/opt/results" --network=teraflowbridge $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG - docker run --name $IMAGE_NAME --network="host" -d -p 2020:2020 -v "$PWD/src/$IMAGE_NAME/tests:/opt/results" -e PYTHONPATH="/var/teraflow:/var/teraflow/device:/var/teraflow/tests/tools/mock_qkd_nodes:/var/teraflow/tests" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" - sleep 5 - docker ps -a - docker logs $IMAGE_NAME - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/test_unitary_emulated.py --junitxml=/opt/results/${IMAGE_NAME}_report_emulated.xml" - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/test_unitary_ietf_actn.py --junitxml=/opt/results/${IMAGE_NAME}_report_ietf_actn.xml" #- docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/qkd/unit/test_*.py" - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose device/tests/qkd/unit/test_qkd_mock_connectivity.py" - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose device/tests/qkd/unit/test_qkd_compliance.py" - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose device/tests/qkd/unit/test_mock_qkd_node.py" - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose device/tests/qkd/unit/test_qkd_error_handling.py" - docker exec -i $IMAGE_NAME bash -c "coverage report --include='${IMAGE_NAME}/*' --show-missing" coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' after_script: Loading @@ -110,6 +112,7 @@ unit_test device: - src/$IMAGE_NAME/Dockerfile - src/$IMAGE_NAME/tests/*.py - src/$IMAGE_NAME/tests/Dockerfile - src/tests/tools/mock_qkd_nodes/** - manifests/${IMAGE_NAME}service.yaml - .gitlab-ci.yml artifacts: Loading src/device/tests/qkd/unit/test_mock_qkd_node.py +7 −3 Original line number Diff line number Diff line Loading @@ -16,15 +16,19 @@ import pytest import requests from requests.exceptions import ConnectionError MOCK_QKD_ADDRESS = '127.0.0.1' MOCK_PORT = 11111 def test_mock_qkd_node_responses(): response = requests.get('http://127.0.0.1:11111/restconf/data/etsi-qkd-sdn-node:qkd_node') response = requests.get(f'http://{MOCK_QKD_ADDRESS}:{MOCK_PORT}/restconf/data/etsi-qkd-sdn-node:qkd_node') assert response.status_code == 200 data = response.json() assert 'qkd_node' in data def test_mock_node_failure_scenarios(): try: response = requests.get('http://127.0.0.1:12345/restconf/data/etsi-qkd-sdn-node:qkd_node') response = requests.get(f'http://{MOCK_QKD_ADDRESS}:12345/restconf/data/etsi-qkd-sdn-node:qkd_node') except ConnectionError as e: assert isinstance(e, ConnectionError) else: Loading src/device/tests/qkd/unit/test_qkd_compliance.py +11 −3 Original line number Diff line number Diff line Loading @@ -15,10 +15,18 @@ import pytest import requests from requests.exceptions import HTTPError from tests.tools.mock_qkd_nodes.YangValidator import YangValidator def test_compliance_with_yang_models(): validator = YangValidator('etsi-qkd-sdn-node', ['etsi-qkd-node-types']) try: response = requests.get('http://127.0.0.1:11111/restconf/data/etsi-qkd-sdn-node:qkd_node') response.raise_for_status() data = response.json() assert validator.parse_to_dict(data) is not None assert validator.parse_to_dict(data) is not None, "Data validation failed against YANG model." except HTTPError as e: pytest.fail(f"HTTP error occurred: {e}") except Exception as e: pytest.fail(f"Unexpected error occurred: {e}") src/device/tests/qkd/unit/test_qkd_error_hanling.py→src/device/tests/qkd/unit/test_qkd_error_handling.py +1 −1 Original line number Diff line number Diff line Loading @@ -40,7 +40,7 @@ def test_invalid_operations_on_network_links(qkd_driver): try: # Attempt to perform an invalid operation (simulate wrong resource key) response = requests.post(f'http://{qkd_driver.address}/invalid_resource', json=invalid_payload) response = requests.post(f'http://{qkd_driver.address}:{qkd_driver.port}/invalid_resource', json=invalid_payload) response.raise_for_status() except HTTPError as e: Loading src/device/tests/qkd/unit/test_qkd_mock_connectivity.py +25 −7 Original line number Diff line number Diff line Loading @@ -12,16 +12,35 @@ # See the License for the specific language governing permissions and # limitations under the License. import pytest, requests import pytest import requests import time import socket from unittest.mock import patch from device.service.drivers.qkd.QKDDriver import QKDDriver from device.service.drivers.qkd.QKDDriver2 import QKDDriver MOCK_QKD_ADDRRESS = '127.0.0.1' MOCK_QKD_ADDRESS = '127.0.0.1' # Use localhost to connect to the mock node in the Docker container MOCK_PORT = 11111 @pytest.fixture(scope="module") def wait_for_mock_node(): """ Fixture to wait for the mock QKD node to be ready before running tests. """ timeout = 30 # seconds start_time = time.time() while True: try: with socket.create_connection((MOCK_QKD_ADDRESS, MOCK_PORT), timeout=1): break # Success except (socket.timeout, socket.error): if time.time() - start_time > timeout: raise RuntimeError("Timed out waiting for mock QKD node to be ready.") time.sleep(1) @pytest.fixture def qkd_driver(): return QKDDriver(address=MOCK_QKD_ADDRRESS, port=MOCK_PORT, username='user', password='pass') def qkd_driver(wait_for_mock_node): return QKDDriver(address=MOCK_QKD_ADDRESS, port=MOCK_PORT, username='user', password='pass') # Deliverable Test ID: SBI_Test_01 def test_qkd_driver_connection(qkd_driver): Loading @@ -29,7 +48,7 @@ def test_qkd_driver_connection(qkd_driver): # Deliverable Test ID: SBI_Test_01 def test_qkd_driver_invalid_connection(): qkd_driver = QKDDriver(address='127.0.0.1', port=12345, username='user', password='pass') # Use invalid port directly qkd_driver = QKDDriver(address=MOCK_QKD_ADDRESS, port=12345, username='user', password='pass') # Use invalid port directly assert qkd_driver.Connect() is False # Deliverable Test ID: SBI_Test_10 Loading @@ -38,4 +57,3 @@ def test_qkd_driver_timeout_connection(mock_get, qkd_driver): mock_get.side_effect = requests.exceptions.Timeout qkd_driver.timeout = 0.001 # Simulate very short timeout assert qkd_driver.Connect() is False Loading
src/device/.gitlab-ci.yml +47 −44 Original line number Diff line number Diff line Loading @@ -38,63 +38,65 @@ build device: - manifests/${IMAGE_NAME}service.yaml - .gitlab-ci.yml ## Start Mock QKD Nodes before unit testing #start_mock_nodes: # stage: deploy # script: # - bash src/tests/tools/mock_qkd_nodes/start.sh & # - sleep 10 # wait for nodes to spin up # artifacts: # paths: # - mock_nodes.log # rules: # - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' # - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' ## Prepare Scenario (Start NBI, mock services) #prepare_scenario: # stage: deploy # script: # - pytest src/tests/qkd/unit/PrepareScenario.py # needs: # - start_mock_nodes # rules: # - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' # - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' # Deploy mock QKD nodes deploy_mock_qkd_nodes: stage: prepare script: - echo "Starting mock QKD nodes deployment..." - > if docker network list | grep -q teraflowbridge; then echo "teraflowbridge network is already created"; else docker network create -d bridge teraflowbridge; fi - > for port in 11111 22222 33333; do if lsof -i:$port >/dev/null 2>&1; then echo "Freeing up port $port..."; fuser -k $port/tcp; fi done - MOCK_NODES_DIR="/home/cttc-docker/tfs-ctrl/src/tests/tools/mock_qkd_nodes" - if [ -d "$MOCK_NODES_DIR" ]; then cd "$MOCK_NODES_DIR" && ./start.sh & else echo "Error: Mock QKD nodes directory '$MOCK_NODES_DIR' not found." && exit 1; fi rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' - changes: - src/common/**/*.py - proto/*.proto - src/device/**/*.{py,in,yml} - src/device/Dockerfile - src/device/tests/*.py - src/tests/tools/mock_qkd_nodes/** - .gitlab-ci.yml # Apply unit test to the component unit_test device: unit_test_device: variables: IMAGE_NAME: 'device' # name of the microservice IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) stage: unit_test needs: - build device #- start_mock_nodes #- prepare_scenario - build_device - deploy_mock_qkd_nodes before_script: - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - > if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - > if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME image is not in the system"; fi script: - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" - docker run --name $IMAGE_NAME -d -p 2020:2020 -v "$PWD/src/$IMAGE_NAME/tests:/opt/results" --network=teraflowbridge $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG - docker run --name $IMAGE_NAME --network="host" -d -p 2020:2020 -v "$PWD/src/$IMAGE_NAME/tests:/opt/results" -e PYTHONPATH="/var/teraflow:/var/teraflow/device:/var/teraflow/tests/tools/mock_qkd_nodes:/var/teraflow/tests" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" - sleep 5 - docker ps -a - docker logs $IMAGE_NAME - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/test_unitary_emulated.py --junitxml=/opt/results/${IMAGE_NAME}_report_emulated.xml" - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/test_unitary_ietf_actn.py --junitxml=/opt/results/${IMAGE_NAME}_report_ietf_actn.xml" #- docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/qkd/unit/test_*.py" - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose device/tests/qkd/unit/test_qkd_mock_connectivity.py" - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose device/tests/qkd/unit/test_qkd_compliance.py" - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose device/tests/qkd/unit/test_mock_qkd_node.py" - docker exec -i $IMAGE_NAME bash -c "coverage run --append -m pytest --log-level=INFO --verbose device/tests/qkd/unit/test_qkd_error_handling.py" - docker exec -i $IMAGE_NAME bash -c "coverage report --include='${IMAGE_NAME}/*' --show-missing" coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' after_script: Loading @@ -110,6 +112,7 @@ unit_test device: - src/$IMAGE_NAME/Dockerfile - src/$IMAGE_NAME/tests/*.py - src/$IMAGE_NAME/tests/Dockerfile - src/tests/tools/mock_qkd_nodes/** - manifests/${IMAGE_NAME}service.yaml - .gitlab-ci.yml artifacts: Loading
src/device/tests/qkd/unit/test_mock_qkd_node.py +7 −3 Original line number Diff line number Diff line Loading @@ -16,15 +16,19 @@ import pytest import requests from requests.exceptions import ConnectionError MOCK_QKD_ADDRESS = '127.0.0.1' MOCK_PORT = 11111 def test_mock_qkd_node_responses(): response = requests.get('http://127.0.0.1:11111/restconf/data/etsi-qkd-sdn-node:qkd_node') response = requests.get(f'http://{MOCK_QKD_ADDRESS}:{MOCK_PORT}/restconf/data/etsi-qkd-sdn-node:qkd_node') assert response.status_code == 200 data = response.json() assert 'qkd_node' in data def test_mock_node_failure_scenarios(): try: response = requests.get('http://127.0.0.1:12345/restconf/data/etsi-qkd-sdn-node:qkd_node') response = requests.get(f'http://{MOCK_QKD_ADDRESS}:12345/restconf/data/etsi-qkd-sdn-node:qkd_node') except ConnectionError as e: assert isinstance(e, ConnectionError) else: Loading
src/device/tests/qkd/unit/test_qkd_compliance.py +11 −3 Original line number Diff line number Diff line Loading @@ -15,10 +15,18 @@ import pytest import requests from requests.exceptions import HTTPError from tests.tools.mock_qkd_nodes.YangValidator import YangValidator def test_compliance_with_yang_models(): validator = YangValidator('etsi-qkd-sdn-node', ['etsi-qkd-node-types']) try: response = requests.get('http://127.0.0.1:11111/restconf/data/etsi-qkd-sdn-node:qkd_node') response.raise_for_status() data = response.json() assert validator.parse_to_dict(data) is not None assert validator.parse_to_dict(data) is not None, "Data validation failed against YANG model." except HTTPError as e: pytest.fail(f"HTTP error occurred: {e}") except Exception as e: pytest.fail(f"Unexpected error occurred: {e}")
src/device/tests/qkd/unit/test_qkd_error_hanling.py→src/device/tests/qkd/unit/test_qkd_error_handling.py +1 −1 Original line number Diff line number Diff line Loading @@ -40,7 +40,7 @@ def test_invalid_operations_on_network_links(qkd_driver): try: # Attempt to perform an invalid operation (simulate wrong resource key) response = requests.post(f'http://{qkd_driver.address}/invalid_resource', json=invalid_payload) response = requests.post(f'http://{qkd_driver.address}:{qkd_driver.port}/invalid_resource', json=invalid_payload) response.raise_for_status() except HTTPError as e: Loading
src/device/tests/qkd/unit/test_qkd_mock_connectivity.py +25 −7 Original line number Diff line number Diff line Loading @@ -12,16 +12,35 @@ # See the License for the specific language governing permissions and # limitations under the License. import pytest, requests import pytest import requests import time import socket from unittest.mock import patch from device.service.drivers.qkd.QKDDriver import QKDDriver from device.service.drivers.qkd.QKDDriver2 import QKDDriver MOCK_QKD_ADDRRESS = '127.0.0.1' MOCK_QKD_ADDRESS = '127.0.0.1' # Use localhost to connect to the mock node in the Docker container MOCK_PORT = 11111 @pytest.fixture(scope="module") def wait_for_mock_node(): """ Fixture to wait for the mock QKD node to be ready before running tests. """ timeout = 30 # seconds start_time = time.time() while True: try: with socket.create_connection((MOCK_QKD_ADDRESS, MOCK_PORT), timeout=1): break # Success except (socket.timeout, socket.error): if time.time() - start_time > timeout: raise RuntimeError("Timed out waiting for mock QKD node to be ready.") time.sleep(1) @pytest.fixture def qkd_driver(): return QKDDriver(address=MOCK_QKD_ADDRRESS, port=MOCK_PORT, username='user', password='pass') def qkd_driver(wait_for_mock_node): return QKDDriver(address=MOCK_QKD_ADDRESS, port=MOCK_PORT, username='user', password='pass') # Deliverable Test ID: SBI_Test_01 def test_qkd_driver_connection(qkd_driver): Loading @@ -29,7 +48,7 @@ def test_qkd_driver_connection(qkd_driver): # Deliverable Test ID: SBI_Test_01 def test_qkd_driver_invalid_connection(): qkd_driver = QKDDriver(address='127.0.0.1', port=12345, username='user', password='pass') # Use invalid port directly qkd_driver = QKDDriver(address=MOCK_QKD_ADDRESS, port=12345, username='user', password='pass') # Use invalid port directly assert qkd_driver.Connect() is False # Deliverable Test ID: SBI_Test_10 Loading @@ -38,4 +57,3 @@ def test_qkd_driver_timeout_connection(mock_get, qkd_driver): mock_get.side_effect = requests.exceptions.Timeout qkd_driver.timeout = 0.001 # Simulate very short timeout assert qkd_driver.Connect() is False