88from pydantic import ValidationError
99
1010from input_models .models import (
11- DeviceListQuery , IntentQuery , InterfacesQuery , KBQuery ,
12- OspfQuery , TracerouteInput ,
11+ DeviceListQuery , IntentQuery , KBQuery ,
12+ OspfQuery , RoutingQuery , TracerouteInput ,
1313)
14- from platforms .platform_map import PLATFORM_MAP , _apply_vrf , get_action
14+ from platforms .platform_map import PLATFORM_MAP , _apply_vrf
1515from tools .intent import query_intent
1616from tools .inventory_tool import list_devices
1717from tools .operational import traceroute
1818from tools .ospf import get_ospf
19+ from tools .routing import get_routing
1920from tools .status import get_status
2021from transport .ssh import _build_cli , execute_ssh
2122
@@ -177,6 +178,15 @@ async def test_traceroute_source_appended():
177178 assert "source 192.168.1.1" in result ["_command" ]
178179
179180
181+ async def test_routing_full_stack_ios ():
182+ with patch ("transport.execute_ssh" , new_callable = AsyncMock ) as mock_ssh :
183+ mock_ssh .return_value = "O 10.0.0.0/24 [110/20] via 10.0.0.1"
184+ result = await get_routing (RoutingQuery (device = "R1" , query = "ip_route" ))
185+ assert result ["device" ] == "R1"
186+ assert result ["cli_style" ] == "ios"
187+ assert result ["_command" ] == "show ip route vrf VRF1"
188+
189+
180190# ── Inventory & device listing ───────────────────────────────────────────────
181191
182192def test_device_lookup_returns_dict (monkeypatch ):
@@ -201,6 +211,10 @@ async def test_status_structure():
201211 mi .exists .return_value = False
202212 result = await get_status ()
203213 assert set (result .keys ()) == {"inventory" , "intent" , "chromadb" }
214+ assert result ["inventory" ]["device_count" ] == 6
215+ assert result ["inventory" ]["source" ] == "network_json"
216+ assert result ["intent" ]["source" ] == "unavailable"
217+ assert result ["chromadb" ]["available" ] is False
204218
205219
206220async def test_intent_single_device_filter (tmp_path ):
@@ -238,7 +252,22 @@ async def test_kb_basic_query():
238252
239253# ── Adversarial input ────────────────────────────────────────────────────────
240254
241- @pytest .mark .parametrize ("bad_device" , ["; rm -rf /" , "' OR 1=1 --" , "a" * 1000 , "" ])
242- async def test_adversarial_device_name (bad_device ):
243- result = await get_ospf (OspfQuery (device = bad_device , query = "neighbors" ))
244- assert "error" in result
255+ _BAD_DEVICES = [
256+ "; rm -rf /" , "' OR 1=1 --" , "a" * 65 , "" ,
257+ "R1 extra" , "R1\n show run" , "R1;cmd" , "$(reboot)" ,
258+ "R1\x00 cmd" , "R1&& cat /etc/shadow" ,
259+ ]
260+
261+ _VALID_DEVICES = ["R1" , "my_device" , "core-rtr_01" , "A" * 64 ]
262+
263+
264+ @pytest .mark .parametrize ("bad_device" , _BAD_DEVICES )
265+ def test_adversarial_device_name_blocked (bad_device ):
266+ with pytest .raises (ValidationError ):
267+ OspfQuery (device = bad_device , query = "neighbors" )
268+
269+
270+ @pytest .mark .parametrize ("good_device" , _VALID_DEVICES )
271+ def test_valid_device_names_accepted (good_device ):
272+ q = OspfQuery (device = good_device , query = "neighbors" )
273+ assert q .device == good_device
0 commit comments