from unittest.mock import patch import pytest from orchestrator.types import SubscriptionLifecycle from gso.products import Router from gso.products.product_blocks.iptrunk import IptrunkInterfaceBlock from gso.products.product_blocks.router import RouterRole from gso.types.tt_number import validate_tt_number from gso.utils.helpers import ( available_interfaces_choices_including_current_members, generate_inventory_for_active_routers, ) from gso.utils.shared_enums import Vendor @pytest.fixture() def mock_router(): """Fixture to mock the Router class.""" with patch("gso.utils.helpers.Router") as mock: yield mock @pytest.fixture() def mock_netbox_client(): """Fixture to mock the NetboxClient class.""" with patch("gso.utils.helpers.NetboxClient") as mock: yield mock @pytest.fixture() def generate_tt_numbers(faker, request): """Get a Generator for valid and invalid tt numbers.""" valid_count = request.param.get("valid", 0) invalid_count = request.param.get("invalid", 0) valid_data = [(faker.tt_number(), True) for _ in range(valid_count)] invalid_data = [(faker.sentence(), False) for _ in range(invalid_count)] return valid_data + invalid_data def test_non_nokia_router_returns_none(mock_router, faker): mock_router.from_subscription.return_value.router.vendor = Vendor.JUNIPER result = available_interfaces_choices_including_current_members(faker.uuid4(), "10G", []) assert result is None def test_nokia_router_with_no_interfaces_returns_empty_choice(mock_router, mock_netbox_client, faker): mock_router.from_subscription.return_value.router.vendor = Vendor.NOKIA mock_netbox_client().get_available_interfaces.return_value = iter([]) result = available_interfaces_choices_including_current_members(faker.uuid4(), "10G", []) assert len(result) == 0 def test_nokia_router_with_interfaces_returns_choice(mock_router, mock_netbox_client, faker): mock_router.from_subscription.return_value.router.vendor = Vendor.NOKIA mock_netbox_client().get_available_interfaces.return_value = iter( [ {"name": "interface1", "module": {"display": "module1"}, "description": "desc1"}, {"name": "interface2", "module": {"display": "module2"}, "description": "desc2"}, ], ) mock_netbox_client().get_interface_by_name_and_device.return_value = { "name": "interface3", "module": {"display": "module3"}, "description": "desc3", } interfaces = [ IptrunkInterfaceBlock( interface_name="interface3", interface_description="desc3", owner_subscription_id=faker.uuid4(), subscription_instance_id=faker.uuid4(), ), ] result = available_interfaces_choices_including_current_members(faker.uuid4(), "10G", interfaces) assert len(result) == 3 assert hasattr(result, "interface1") assert hasattr(result, "interface2") assert hasattr(result, "interface3") @pytest.mark.parametrize("generate_tt_numbers", [{"valid": 5, "invalid": 3}], indirect=True) def test_tt_number(generate_tt_numbers): """Test different TT numbers.""" for tt_number, is_valid in generate_tt_numbers: if is_valid: assert validate_tt_number(tt_number) == tt_number else: err_msg = ( f"The given TT number: {tt_number} is not valid. " f" A valid TT number starts with 'TT#' followed by 16 digits." ) with pytest.raises(ValueError, match=err_msg): validate_tt_number(tt_number) def test_generate_inventory_for_active_routers_with_single_active_router(nokia_router_subscription_factory): """Test the generation of inventory for a single active P router.""" router = Router.from_subscription(nokia_router_subscription_factory(router_role=RouterRole.P)) expected_result = { "all": { "hosts": { router.router.router_fqdn: { "lo4": str(router.router.router_lo_ipv4_address), "lo6": str(router.router.router_lo_ipv6_address), "vendor": str(router.router.vendor), } } } } assert generate_inventory_for_active_routers(RouterRole.P) == expected_result def test_generate_inventory_for_active_routers_with_multiple_routers(nokia_router_subscription_factory): """Test the generation of inventory for multiple active P and PE routers""" for _ in range(5): nokia_router_subscription_factory(router_role=RouterRole.P) for _ in range(3): nokia_router_subscription_factory(router_role=RouterRole.PE) nokia_router_subscription_factory(status=SubscriptionLifecycle.TERMINATED) nokia_router_subscription_factory(status=SubscriptionLifecycle.INITIAL) # Test the generation of inventory for multiple active P routers. inventory = generate_inventory_for_active_routers(RouterRole.P) assert len(inventory["all"]["hosts"]) == 5 inventory = generate_inventory_for_active_routers(RouterRole.PE) assert len(inventory["all"]["hosts"]) == 3 def test_generate_inventory_for_active_routers_with_excluded_router(nokia_router_subscription_factory): """Test the generation of inventory for active P routers with an excluded router.""" for _ in range(5): nokia_router_subscription_factory(router_role=RouterRole.P) router = nokia_router_subscription_factory(router_role=RouterRole.P) excluded_routers = [Router.from_subscription(router).router.router_fqdn] inventory = generate_inventory_for_active_routers(RouterRole.P, exclude_routers=excluded_routers) assert len(inventory["all"]["hosts"]) == 5 # 6 P routers, the last one is excluded, so 5 P routers are left.