Loading src/pathcompextended/Dockerfile +4 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,10 @@ COPY src/context/__init__.py context/__init__.py COPY src/context/client/. context/client/ COPY src/device/__init__.py device/__init__.py COPY src/device/client/. device/client/ # Perform the testing # Requires entire Forecaster component for the tests # TODO: Improve testing framework COPY src/forecaster/. forecaster/ Loading src/pathcompextended/tests/model_validation/README.md 0 → 100644 +59 −0 Original line number Diff line number Diff line # Model Validation Tests This directory contains standalone tests for validating Pydantic models using example JSON files. ## Purpose These tests validate that: 1. Models can parse example JSON files correctly 2. Models can serialize back to JSON with proper aliases 3. Model validation works as expected 4. Round-trip serialization preserves data integrity ## Running the Tests ### Run all tests: ```bash pytest src/pathcompextended/tests/model_validation/ ``` ### Run specific test class: ```bash pytest src/pathcompextended/tests/model_validation/test_pydantic_models.py::TestNetworkContextModels ``` ### Run with verbose output: ```bash pytest src/pathcompextended/tests/model_validation/ -v ``` ### Run directly: ```bash python src/pathcompextended/tests/model_validation/test_pydantic_models.py ``` ## Test Structure - **TestNetworkContextModels**: Tests for Network Context requests and responses - **TestTransportOpticalSliceModels**: Tests for Transport Optical Slice models - **TestTransportNetworkSliceL3Models**: Tests for Transport Network Slice L3 models - **TestHealthCheckModels**: Tests for Health Check responses - **TestIetfNetworkSliceModels**: Tests for IETF Network Slice base models - **TestModelIntegration**: Integration tests for round-trip serialization ## Example Files The tests use example JSON files from `src/pathcompextended/example/`: - `network_context/post/request.json` and `response.json` - `transport_optical_slice/post/request.json` and `response.json` - `transport_network_slice_l3/post/request.json` and `response.json` - `health_check/get/response.json` - And other response examples ## Adding New Tests When adding new models or example files: 1. Add a new test class or extend an existing one 2. Use `load_json_file()` helper to load example JSONs 3. Test both parsing and serialization 4. Include round-trip tests for complex models src/pathcompextended/tests/model_validation/__init__.py 0 → 100644 +13 −0 Original line number Diff line number Diff line # Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # 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. src/pathcompextended/tests/model_validation/example_usage.py 0 → 100644 +183 −0 Original line number Diff line number Diff line # Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # 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. """ Example usage of Pydantic models for H-RAT API. This script demonstrates how to: 1. Create models from JSON data 2. Serialize models back to JSON 3. Validate model data """ import json from pathlib import Path # Import models from pathcompextended.model import ( NetworkContextRequest, TransportOpticalSliceRequest, TransportNetworkSliceL3Request, Topology, ) from pathcompextended.connector.hrat import ( NetworkContextPostRequest, TransportOpticalSlicePostRequest, TransportNetworkSliceL3PostRequest, NetworkContextPostResponse, TransportOpticalSliceResponse, TransportNetworkSliceL3Response, ) # Get example directory EXAMPLE_DIR = Path(__file__).parent.parent.parent / "example" def example_network_context(): """Example: Create and use NetworkContextRequest.""" print("=" * 60) print("Example: Network Context Request") print("=" * 60) # Create a network context request request = NetworkContextPostRequest( topologies=[ Topology( topology_id="topology-1", controller_id="controller-1", topology_type="TAPI", raw_json_topology='{"nodes": [], "links": []}' ) ] ) # Serialize to JSON with aliases json_data = request.model_dump(by_alias=True, exclude_none=True) print("\nSerialized JSON:") print(json.dumps(json_data, indent=2)) # Parse response response_data = { "message": "Network context created successfully", "total-topologies": 1 } response = NetworkContextPostResponse(**response_data) print(f"\nResponse: {response.message}") print(f"Total topologies: {response.total_topologies}") def example_transport_optical_slice(): """Example: Create and use TransportOpticalSliceRequest.""" print("\n" + "=" * 60) print("Example: Transport Optical Slice Request") print("=" * 60) # Load example request example_file = EXAMPLE_DIR / "transport_optical_slice" / "post" / "request.json" with open(example_file, 'r') as f: request_data = json.load(f) # Create model from JSON request = TransportOpticalSlicePostRequest(**request_data) # Access nested data services = request.ietf_network_slice_service_network_slice_services print(f"\nNumber of slice services: {len(services.slice_service)}") print(f"Number of SLO/SLE templates: {len(services.slo_sle_templates.slo_sle_template)}") if services.slice_service: print(f"First slice service ID: {services.slice_service[0].id}") # Serialize back to JSON json_data = request.model_dump(by_alias=True, exclude_none=True) print("\nModel validated successfully!") print(f"Serialized JSON keys: {list(json_data.keys())}") def example_transport_network_slice_l3(): """Example: Create and use TransportNetworkSliceL3Request.""" print("\n" + "=" * 60) print("Example: Transport Network Slice L3 Request") print("=" * 60) # Load example request example_file = EXAMPLE_DIR / "transport_network_slice_l3" / "post" / "request.json" with open(example_file, 'r') as f: request_data = json.load(f) # Create model from JSON request = TransportNetworkSliceL3PostRequest(**request_data) # Access nested data services = request.ietf_network_slice_service_network_slice_services print(f"\nNumber of slice services: {len(services.slice_service)}") if services.slice_service: slice_service = services.slice_service[0] print(f"Slice service ID: {slice_service.id}") print(f"Description: {slice_service.description}") if slice_service.sdps and slice_service.sdps.sdp: print(f"Number of SDPs: {len(slice_service.sdps.sdp)}") print("\nModel validated successfully!") def example_response_parsing(): """Example: Parse response JSON.""" print("\n" + "=" * 60) print("Example: Parsing Response JSON") print("=" * 60) # Load example response example_file = EXAMPLE_DIR / "transport_optical_slice" / "post" / "response.json" with open(example_file, 'r') as f: response_data = json.load(f) # Create model from JSON response = TransportOpticalSliceResponse(**response_data) print(f"\nOptical Slice UUID: {response.optical_slice_uuid}") print(f"Viability: {response.viability}") print(f"Number of actions: {len(response.actions)}") if response.actions: action = response.actions[0] print(f"\nFirst action:") print(f" Type: {action.type}") print(f" Layer: {action.layer}") print(f" Controller UUID: {action.controller_uuid}") if hasattr(action.content, 'tenant_uuid'): print(f" Tenant UUID: {action.content.tenant_uuid}") if __name__ == "__main__": print("\n" + "=" * 60) print("Pydantic Models Usage Examples") print("=" * 60) try: example_network_context() example_transport_optical_slice() example_transport_network_slice_l3() example_response_parsing() print("\n" + "=" * 60) print("All examples completed successfully!") print("=" * 60) except Exception as e: print(f"\nError: {e}") import traceback traceback.print_exc() src/pathcompextended/tests/model_validation/run_tests.sh 0 → 100755 +33 −0 Original line number Diff line number Diff line #!/bin/bash # Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # 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. # Script to run Pydantic model validation tests set -e # Get the directory where this script is located SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" PROJECT_ROOT="$( cd "$SCRIPT_DIR/../../.." && pwd )" echo "Running Pydantic model validation tests..." echo "Project root: $PROJECT_ROOT" echo "" # Run pytest with verbose output cd "$PROJECT_ROOT" python -m pytest "$SCRIPT_DIR/test_pydantic_models.py" -v --tb=short echo "" echo "Tests completed!" Loading
src/pathcompextended/Dockerfile +4 −0 Original line number Diff line number Diff line Loading @@ -68,6 +68,10 @@ COPY src/context/__init__.py context/__init__.py COPY src/context/client/. context/client/ COPY src/device/__init__.py device/__init__.py COPY src/device/client/. device/client/ # Perform the testing # Requires entire Forecaster component for the tests # TODO: Improve testing framework COPY src/forecaster/. forecaster/ Loading
src/pathcompextended/tests/model_validation/README.md 0 → 100644 +59 −0 Original line number Diff line number Diff line # Model Validation Tests This directory contains standalone tests for validating Pydantic models using example JSON files. ## Purpose These tests validate that: 1. Models can parse example JSON files correctly 2. Models can serialize back to JSON with proper aliases 3. Model validation works as expected 4. Round-trip serialization preserves data integrity ## Running the Tests ### Run all tests: ```bash pytest src/pathcompextended/tests/model_validation/ ``` ### Run specific test class: ```bash pytest src/pathcompextended/tests/model_validation/test_pydantic_models.py::TestNetworkContextModels ``` ### Run with verbose output: ```bash pytest src/pathcompextended/tests/model_validation/ -v ``` ### Run directly: ```bash python src/pathcompextended/tests/model_validation/test_pydantic_models.py ``` ## Test Structure - **TestNetworkContextModels**: Tests for Network Context requests and responses - **TestTransportOpticalSliceModels**: Tests for Transport Optical Slice models - **TestTransportNetworkSliceL3Models**: Tests for Transport Network Slice L3 models - **TestHealthCheckModels**: Tests for Health Check responses - **TestIetfNetworkSliceModels**: Tests for IETF Network Slice base models - **TestModelIntegration**: Integration tests for round-trip serialization ## Example Files The tests use example JSON files from `src/pathcompextended/example/`: - `network_context/post/request.json` and `response.json` - `transport_optical_slice/post/request.json` and `response.json` - `transport_network_slice_l3/post/request.json` and `response.json` - `health_check/get/response.json` - And other response examples ## Adding New Tests When adding new models or example files: 1. Add a new test class or extend an existing one 2. Use `load_json_file()` helper to load example JSONs 3. Test both parsing and serialization 4. Include round-trip tests for complex models
src/pathcompextended/tests/model_validation/__init__.py 0 → 100644 +13 −0 Original line number Diff line number Diff line # Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # 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.
src/pathcompextended/tests/model_validation/example_usage.py 0 → 100644 +183 −0 Original line number Diff line number Diff line # Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # 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. """ Example usage of Pydantic models for H-RAT API. This script demonstrates how to: 1. Create models from JSON data 2. Serialize models back to JSON 3. Validate model data """ import json from pathlib import Path # Import models from pathcompextended.model import ( NetworkContextRequest, TransportOpticalSliceRequest, TransportNetworkSliceL3Request, Topology, ) from pathcompextended.connector.hrat import ( NetworkContextPostRequest, TransportOpticalSlicePostRequest, TransportNetworkSliceL3PostRequest, NetworkContextPostResponse, TransportOpticalSliceResponse, TransportNetworkSliceL3Response, ) # Get example directory EXAMPLE_DIR = Path(__file__).parent.parent.parent / "example" def example_network_context(): """Example: Create and use NetworkContextRequest.""" print("=" * 60) print("Example: Network Context Request") print("=" * 60) # Create a network context request request = NetworkContextPostRequest( topologies=[ Topology( topology_id="topology-1", controller_id="controller-1", topology_type="TAPI", raw_json_topology='{"nodes": [], "links": []}' ) ] ) # Serialize to JSON with aliases json_data = request.model_dump(by_alias=True, exclude_none=True) print("\nSerialized JSON:") print(json.dumps(json_data, indent=2)) # Parse response response_data = { "message": "Network context created successfully", "total-topologies": 1 } response = NetworkContextPostResponse(**response_data) print(f"\nResponse: {response.message}") print(f"Total topologies: {response.total_topologies}") def example_transport_optical_slice(): """Example: Create and use TransportOpticalSliceRequest.""" print("\n" + "=" * 60) print("Example: Transport Optical Slice Request") print("=" * 60) # Load example request example_file = EXAMPLE_DIR / "transport_optical_slice" / "post" / "request.json" with open(example_file, 'r') as f: request_data = json.load(f) # Create model from JSON request = TransportOpticalSlicePostRequest(**request_data) # Access nested data services = request.ietf_network_slice_service_network_slice_services print(f"\nNumber of slice services: {len(services.slice_service)}") print(f"Number of SLO/SLE templates: {len(services.slo_sle_templates.slo_sle_template)}") if services.slice_service: print(f"First slice service ID: {services.slice_service[0].id}") # Serialize back to JSON json_data = request.model_dump(by_alias=True, exclude_none=True) print("\nModel validated successfully!") print(f"Serialized JSON keys: {list(json_data.keys())}") def example_transport_network_slice_l3(): """Example: Create and use TransportNetworkSliceL3Request.""" print("\n" + "=" * 60) print("Example: Transport Network Slice L3 Request") print("=" * 60) # Load example request example_file = EXAMPLE_DIR / "transport_network_slice_l3" / "post" / "request.json" with open(example_file, 'r') as f: request_data = json.load(f) # Create model from JSON request = TransportNetworkSliceL3PostRequest(**request_data) # Access nested data services = request.ietf_network_slice_service_network_slice_services print(f"\nNumber of slice services: {len(services.slice_service)}") if services.slice_service: slice_service = services.slice_service[0] print(f"Slice service ID: {slice_service.id}") print(f"Description: {slice_service.description}") if slice_service.sdps and slice_service.sdps.sdp: print(f"Number of SDPs: {len(slice_service.sdps.sdp)}") print("\nModel validated successfully!") def example_response_parsing(): """Example: Parse response JSON.""" print("\n" + "=" * 60) print("Example: Parsing Response JSON") print("=" * 60) # Load example response example_file = EXAMPLE_DIR / "transport_optical_slice" / "post" / "response.json" with open(example_file, 'r') as f: response_data = json.load(f) # Create model from JSON response = TransportOpticalSliceResponse(**response_data) print(f"\nOptical Slice UUID: {response.optical_slice_uuid}") print(f"Viability: {response.viability}") print(f"Number of actions: {len(response.actions)}") if response.actions: action = response.actions[0] print(f"\nFirst action:") print(f" Type: {action.type}") print(f" Layer: {action.layer}") print(f" Controller UUID: {action.controller_uuid}") if hasattr(action.content, 'tenant_uuid'): print(f" Tenant UUID: {action.content.tenant_uuid}") if __name__ == "__main__": print("\n" + "=" * 60) print("Pydantic Models Usage Examples") print("=" * 60) try: example_network_context() example_transport_optical_slice() example_transport_network_slice_l3() example_response_parsing() print("\n" + "=" * 60) print("All examples completed successfully!") print("=" * 60) except Exception as e: print(f"\nError: {e}") import traceback traceback.print_exc()
src/pathcompextended/tests/model_validation/run_tests.sh 0 → 100755 +33 −0 Original line number Diff line number Diff line #!/bin/bash # Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # 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. # Script to run Pydantic model validation tests set -e # Get the directory where this script is located SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" PROJECT_ROOT="$( cd "$SCRIPT_DIR/../../.." && pwd )" echo "Running Pydantic model validation tests..." echo "Project root: $PROJECT_ROOT" echo "" # Run pytest with verbose output cd "$PROJECT_ROOT" python -m pytest "$SCRIPT_DIR/test_pydantic_models.py" -v --tb=short echo "" echo "Tests completed!"