Compare commits

...

10 Commits

Author SHA1 Message Date
IluaAir
686cd6d715 Remove main execution block from Quasar model and add configuration files for testing
- Eliminated the main execution block from the Quasar model for cleaner code.
- Introduced new configuration files `config_1.conf` and `config_2.conf` for Quasar devices, detailing interface settings and IP configurations.
- Added expected output JSON files `config_1.expected.json` and `config_2.expected.json` to validate the parsing of Quasar configurations against expected results.
2026-06-07 09:12:47 +03:00
IluaAir
acb3a6291c Add expected configuration output for Mikrotik devices
- Introduced a new JSON file `config.expected.json` containing expected system and interface configurations for Mikrotik devices, including model, serial number, IP addresses, and VLAN details.
- This addition facilitates testing and validation of the parsing functionality for Mikrotik configurations.
2026-06-07 09:07:17 +03:00
IluaAir
9c90279868 Add normalization method for TTP group results in BaseDevice class
- Introduced a static method `_as_list` to normalize TTP group results, ensuring consistent list output regardless of input type (dict or list).
- Updated the `_validate_contract` method to utilize `_as_list` for processing interfaces and VLANs, improving code clarity and reliability.
2026-06-07 09:06:52 +03:00
IluaAir
2ea056aa17 Refactor Mikrotik model and update TTP template for improved configuration handling
- Removed unused imports and main execution block from the Mikrotik model for cleaner code.
- Updated the Mikrotik TTP template to adjust the order of parameters in the 'add' command, enhancing clarity in the generated configurations.
- Added a new configuration file `config.conf` for Mikrotik devices to facilitate testing and validation of parsing functionality.
2026-06-07 09:06:24 +03:00
IluaAir
a617bd6ecd Add description fields to Eltex interface template
- Updated the Eltex TTP template to include 'name' and 'description' fields for interfaces, enhancing clarity and detail in the generated configurations.
2026-06-07 08:47:51 +03:00
IluaAir
0ef5e7798a Refactor Qtech model to utilize centralized VLAN range expansion utility
- Replaced the internal `_expand_vlan_range` function in the `Qtech` class with the new `expand_vlan_range` utility from `utils.py` for improved code maintainability.
- Added new configuration files `config_1.conf` and `config_2.conf` for Qtech devices to facilitate testing.
- Introduced expected output JSON files `config_1.expected.json` and `config_2.expected.json` to validate the parsing of Qtech configurations against expected results.
2026-06-07 08:47:08 +03:00
IluaAir
1bc01c9c1b Add Huawei configuration files for testing
- Introduced a new configuration file `config.conf` for Huawei devices, detailing interface settings and VLAN configurations.
- Added an expected output JSON file `config.expected.json` to validate the parsing of Huawei configurations against expected results, including system model, serial number, and interface details.
2026-06-07 08:44:35 +03:00
IluaAir
170a2ebf85 Refactor Eltex model to use centralized VLAN range expansion utility
- Replaced the internal `_expand_vlan_range` function in the `Eltex` class with the new `expand_vlan_range` utility from `utils.py` for improved code maintainability.
- Added a new configuration file `config.conf` for Eltex devices to facilitate testing.
- Introduced an expected output JSON file `config.expected.json` to validate the parsing of Eltex configurations against expected results.
2026-06-07 08:42:58 +03:00
IluaAir
168111e23c Refactor Keenetic model to utilize centralized UTF-8 decoding utility
- Removed the internal `_decode_utf` method from the `Keenetic` class and replaced its usage with the new `decode_utf` utility function for decoding interface descriptions.
- Added a new configuration file `config.conf` for Keenetic devices to facilitate testing.
- Introduced an expected output JSON file `config.expected.json` to validate the parsing of Keenetic configurations against expected results.
2026-06-07 08:41:59 +03:00
IluaAir
d329ddc4ad Add unit tests for device registry model parsing
- Introduced a new test file `test_models.py` to implement unit tests for various device models in the `device_registry`.
- Added parameterized tests to validate the parsing of device configurations against expected JSON outputs and to ensure required sections are present in the parsed models.
- Enhanced test coverage for multiple device types including Mikrotik, Keenetic, Qtech, Huawei, Eltex, and Quasar.
2026-06-06 13:55:51 +03:00
26 changed files with 1741 additions and 120 deletions

View File

@@ -67,6 +67,19 @@ class BaseDevice(ABC):
"""
return self.raw.get("system", None)
@staticmethod
def _as_list(data) -> list:
"""Normalize a TTP group result to a list.
TTP returns a single dict when a group matches exactly one entry and a
list when it matches several. Callers always expect a list.
"""
if data is None:
return []
if isinstance(data, dict):
return [data]
return data
def _validate_contract(self) -> dict:
if self.raw is None:
msg = (
@@ -76,7 +89,7 @@ class BaseDevice(ABC):
)
raise OxiAPIError(msg, status_code=404)
system_data = self.system()
interfaces_data = self.interfaces() or []
interfaces_data = self._as_list(self.interfaces())
result = {
"system": System(**system_data),
"interfaces": [Interfaces(**item) for item in interfaces_data],
@@ -89,7 +102,7 @@ class BaseDevice(ABC):
f"{self.__class__.__name__}: template '{self.template}' declares optional group "
f"'vlans', but TTP did not return it."
)
vlans_data = self.vlans() or []
vlans_data = self._as_list(self.vlans())
result["vlans"] = [Vlans(**item) for item in vlans_data]
return result

View File

@@ -1,29 +1,6 @@
from oxi.interfaces import register_parser
from oxi.interfaces.base import BaseDevice
def _expand_vlan_range(value: str | list[str]) -> list[str]:
if isinstance(value, list):
value = ",".join(str(item) for item in value)
result: list[str] = []
for part in value.split(","):
part = part.strip()
if not part:
continue
if "-" not in part:
result.append(part)
continue
start_s, end_s = part.split("-", 1)
try:
start, end = int(start_s), int(end_s)
except ValueError:
result.append(part)
continue
if start > end:
start, end = end, start
result.extend(str(vlan_id) for vlan_id in range(start, end + 1))
return result
from oxi.interfaces.utils import expand_vlan_range
@register_parser("eltex")
@@ -54,15 +31,8 @@ class Eltex(BaseDevice):
tail = item.get("vlan_tail")
if tail:
ids = [*ids, tail] if isinstance(ids, list) else f"{ids},{tail}"
for vid in _expand_vlan_range(ids):
for vid in expand_vlan_range(ids):
if vid in named_vlan:
continue
vlans.append({"vlan_id": vid})
return vlans
if __name__ == "__main__":
with open("./test_not_found.txt") as file:
data = file.read()
eltex = Eltex(data)
print(eltex.parse())

View File

@@ -1,24 +1,13 @@
from ipaddress import ip_interface
from oxi.interfaces import register_parser
from oxi.interfaces.base import BaseDevice
from oxi.interfaces.utils import decode_utf
@register_parser(["NDMS", "keenetic", "KeeneticOS"])
class Keenetic(BaseDevice):
template = "keenetic.ttp"
def _decode_utf(self, text: str):
if "\\x" in text:
desc = text.strip('"')
decoded = (
desc.encode("utf-8")
.decode("unicode_escape")
.encode("latin1")
.decode("utf-8")
)
return decoded
return text
def interfaces(self):
interfaces: list[dict] = self.raw["interfaces"]
for item in interfaces:
@@ -29,7 +18,7 @@ class Keenetic(BaseDevice):
item["mask"] = ipaddress.network.prefixlen
item.pop("netmask", "Key not found")
if item.get("description"):
decoded = self._decode_utf(item.get("description", ""))
decoded = decode_utf(item.get("description", ""))
item["description"] = decoded
return interfaces
@@ -37,13 +26,6 @@ class Keenetic(BaseDevice):
vlans = self.raw["vlans"]
for item in vlans:
if item.get("description"):
decoded = self._decode_utf(item.get("description", ""))
decoded = decode_utf(item.get("description", ""))
item["description"] = decoded
return vlans
if __name__ == "__main__":
with open("./test2.txt") as file:
data = file.read()
mikr = Keenetic(data)
print(mikr.parse().model_dump_json())

View File

@@ -1,4 +1,3 @@
import os
from oxi.interfaces import register_parser
from oxi.interfaces.base import BaseDevice
@@ -6,11 +5,3 @@ from oxi.interfaces.base import BaseDevice
@register_parser(["routeros", "ros", "mikrotik"])
class Mikrotik(BaseDevice):
template = "mikrotik.ttp"
if __name__ == "__main__":
print(os.path.abspath(os.curdir))
with open("./test.txt") as file:
data = file.read()
mikr = Mikrotik(data)
print(mikr.parse().json())

View File

@@ -1,32 +1,6 @@
from oxi.interfaces import register_parser
from oxi.interfaces.base import BaseDevice
def _expand_vlan_range(value: str | list[str]) -> list[str]:
"""Expand values like '1,7,14-15' into individual VLAN IDs."""
if isinstance(value, list):
value = ",".join(str(item) for item in value)
result: list[str] = []
if not value:
return result
for part in value.split(","):
part = part.strip()
if not part:
continue
if "-" in part:
start_s, end_s = part.split("-", 1)
try:
start, end = int(start_s), int(end_s)
except ValueError:
result.append(part)
continue
if start > end:
start, end = end, start
result.extend(str(i) for i in range(start, end + 1))
else:
result.append(part)
return result
from oxi.interfaces.utils import expand_vlan_range
@register_parser(["QTECH"])
@@ -48,21 +22,8 @@ class Qtech(BaseDevice):
tail = item.get("vlan_tail")
if tail:
ids = [*ids, tail] if isinstance(ids, list) else f"{ids},{tail}"
for vid in _expand_vlan_range(ids):
for vid in expand_vlan_range(ids):
if vid in named_vlan:
continue
vlans.append({"vlan_id": vid})
return vlans
if __name__ == "__main__":
with open("./test3.txt") as file:
data = file.read()
qtech = Qtech(data)
qt = qtech.parse()
print(qt)
with open("./test3-1.txt") as file:
data = file.read()
qtech = Qtech(data)
qt = qtech.parse()
print(qt)

View File

@@ -21,17 +21,3 @@ class Quasar(BaseDevice):
if ether_interface:
interfaces.append(ether_interface)
return interfaces
if __name__ == "__main__":
with open("./test7.txt") as file:
data = file.read()
quasar = Quasar(data)
qt = quasar.parse()
print(qt)
print()
with open("./test8.txt") as file:
data = file.read()
quasar = Quasar(data)
qt = quasar.parse()
print(qt)

View File

@@ -26,6 +26,8 @@ Active-image: {{ ignore }} {{ _start_ }}
<group name="interfaces">
interface {{ interface | ORPHRASE }}
ip address {{ ip_address }} {{ mask | to_cidr }}
name {{ description }}
description {{ description }}
</group>
<group name="vlans">

View File

@@ -42,6 +42,6 @@ add comment={{ comment | _start_ | ORPHRASE | exclude("disabled=") | strip('"')}
## disabled with comment with/without quotes
add comment={{ comment | _start_ | ORPHRASE | exclude("disabled=") | strip('"')}} disabled={{ disabled | replace("yes","True") | strip('"') }} interface={{ interface }} name={{ name | ORPHRASE | strip('"') }} vlan-id={{ vlan_id }}
## disabled no comment
add interface={{ interface | _start_ }} name={{ name | ORPHRASE | strip('"') }} vlan-id={{ vlan_id }} disabled={{ disabled | replace("yes","True") | strip('"') }}
add disabled={{ disabled | _start_ | replace("yes","True") | strip('"') }} interface={{ interface }} name={{ name | ORPHRASE | strip('"') }} vlan-id={{ vlan_id }}
</group>

55
tests/fixtures/eltex/config.conf vendored Normal file
View File

@@ -0,0 +1,55 @@
!
Active-image: flash://system/images/mes3300-669-3R3.ros
! Version: 6.6.9.3
! Commit: 3a5c2e39
! Build: 3 (master)
! MD5 Digest: 7bc289cc18be560954bd5cb0afd9b2d5
! Date: 22-Sep-2025
! Time: 12:38:20
! Inactive-image: flash://system/images/_image1.bin
! Version: 6.6.2
! Commit: 3ebc7503
! Build: 5 (master)
! MD5 Digest: a3f15a788c97c71e07e90d84c0ff3b12
! Date: 20-Nov-2023
! Time: 16:39:20
!
! Unit MAC address Hardware version Serial number
! ---- ----------------- ---------------- -------------
! 1 90:54:b7:6b:9d:40 01.01.01 ESG7007778
! 2 90:54:b7:6b:bb:80 01.01.01 ESG7007777
!
!
!
interface TenGigabitEthernet1/0/2
shutdown
description FREE
storm-control broadcast pps 3000
storm-control multicast pps 3000
exit
!
interface TenGigabitEthernet1/0/11
shutdown
description FREE
storm-control broadcast pps 3000
storm-control multicast pps 3000
exit
!
interface vlan 1700
name sw-test_HW
ip address 13.36.8.1 255.255.255.0
exit
!
vlan database
vlan 114-115,120,130,414,610,999-1000,1701-1703,1705,1801,2001,2011
vlan 2021-2022,3157-3158,3333-3334
exit
!
interface vlan 666
name test
exit
!
interface vlan 777
name test2
exit
!

View File

@@ -0,0 +1,137 @@
{
"system": {
"model": "",
"serial_number": "ESG7007778",
"version": "6.6.9.3"
},
"interfaces": [
{
"interface": "TenGigabitEthernet1/0/2",
"ip_address": null,
"mask": null,
"description": "FREE"
},
{
"interface": "TenGigabitEthernet1/0/11",
"ip_address": null,
"mask": null,
"description": "FREE"
},
{
"interface": "vlan 1700",
"ip_address": "13.36.8.1",
"mask": 24,
"description": "sw-test_HW"
},
{
"interface": "vlan 666",
"ip_address": null,
"mask": null,
"description": "test"
},
{
"interface": "vlan 777",
"ip_address": null,
"mask": null,
"description": "test2"
}
],
"vlans": [
{
"vlan_id": 1700,
"description": "sw-test_HW"
},
{
"vlan_id": 114,
"description": null
},
{
"vlan_id": 115,
"description": null
},
{
"vlan_id": 120,
"description": null
},
{
"vlan_id": 130,
"description": null
},
{
"vlan_id": 414,
"description": null
},
{
"vlan_id": 610,
"description": null
},
{
"vlan_id": 999,
"description": null
},
{
"vlan_id": 1000,
"description": null
},
{
"vlan_id": 1701,
"description": null
},
{
"vlan_id": 1702,
"description": null
},
{
"vlan_id": 1703,
"description": null
},
{
"vlan_id": 1705,
"description": null
},
{
"vlan_id": 1801,
"description": null
},
{
"vlan_id": 2001,
"description": null
},
{
"vlan_id": 2011,
"description": null
},
{
"vlan_id": 2021,
"description": null
},
{
"vlan_id": 2022,
"description": null
},
{
"vlan_id": 3157,
"description": null
},
{
"vlan_id": 3158,
"description": null
},
{
"vlan_id": 3333,
"description": null
},
{
"vlan_id": 3334,
"description": null
},
{
"vlan_id": 666,
"description": "test"
},
{
"vlan_id": 777,
"description": "test2"
}
]
}

1
tests/fixtures/eltex/not_found.conf vendored Normal file
View File

@@ -0,0 +1 @@
node not found

38
tests/fixtures/huawei/config.conf vendored Normal file
View File

@@ -0,0 +1,38 @@
# Huawei Versatile Routing Platform Software
# VRP (R) software, Version 5.170 (S5731 V200R019C00SPC500)
# Copyright (C) 2000-2019 HUAWEI TECH Co., Ltd.
#
# DDR Memory Size : 4096 M bytes
# FLASH Total Memory Size : 1024 M bytes
# FLASH Available Memory Size : 739 M bytes
# Pcb Version : VER.B
# BootROM Version : 0000.04e4
# BootLoad Version : 0213.0000
# CPLD Version : 0104
# Software Version : VRP (R) Software, Version 5.170 (V200R019C00SPC500)
# FLASH Version : 0000.0000
# PWR1 information
# Pcb Version : PWR VER.D
# PWR2 information
# Pcb Version : PWR VER.D
# FAN1 information
# Pcb Version : NA
# FAN2 information
# Pcb Version : NA
# ESN of slot 1: 102266666666
# ESN of slot 2: 102288888888
interface GigabitEthernet0/0/33
port link-type access
port default vlan 101
loopback-detect enable
stp disable
storm-control broadcast min-rate 1500 max-rate 2500
storm-control multicast min-rate 1000 max-rate 2000
storm-control action error-down
#
interface Vlanif120
description SSH
ip address 10.26.196.254 255.255.255.0
#
vlan batch 13 26 101 to 103 110 120 130 201 to 204 209 to 212 350 360
#

View File

@@ -0,0 +1,95 @@
{
"system": {
"model": "S5731",
"serial_number": "102266666666",
"version": "5.170"
},
"interfaces": [
{
"interface": "GigabitEthernet0/0/33",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "Vlanif120",
"ip_address": "10.26.196.254",
"mask": 24,
"description": "SSH"
}
],
"vlans": [
{
"vlan_id": 13,
"description": null
},
{
"vlan_id": 26,
"description": null
},
{
"vlan_id": 101,
"description": null
},
{
"vlan_id": 102,
"description": null
},
{
"vlan_id": 103,
"description": null
},
{
"vlan_id": 110,
"description": null
},
{
"vlan_id": 120,
"description": null
},
{
"vlan_id": 130,
"description": null
},
{
"vlan_id": 201,
"description": null
},
{
"vlan_id": 202,
"description": null
},
{
"vlan_id": 203,
"description": null
},
{
"vlan_id": 204,
"description": null
},
{
"vlan_id": 209,
"description": null
},
{
"vlan_id": 210,
"description": null
},
{
"vlan_id": 211,
"description": null
},
{
"vlan_id": 212,
"description": null
},
{
"vlan_id": 350,
"description": null
},
{
"vlan_id": 360,
"description": null
}
]
}

341
tests/fixtures/keenetic/config.conf vendored Normal file
View File

@@ -0,0 +1,341 @@
!
! release: 4.03.C.6.2-7
! sandbox: stable
! title: 4.3.6.2
! arch: mips
!
! ndm:
! exact: 0-a3057529fd
! cdate: 29 Sep 2025
!
! bsp:
! exact: 0-03b50470c4
! cdate: 30 Sep 2025
!
! ndw:
! features: dual_image,led_control,wifi_button,wifi5ghz,
! vht2ghz,mimo2ghz,mimo5ghz,atf2ghz,atf5ghz,wifi6,wifi_ft,
! wpa3,hwnat
! components: base,cloudcontrol,corewireless,ddns,dhcpd,
! dns-filter,dns-https,dns-tls,dot1x,easyconfig,igmp,ip6,
! lang-en,lang-ru,miniupnpd,mws,nathelper-ftp,nathelper-
! h323,nathelper-pptp,nathelper-rtsp,nathelper-sip,ndmp,
! ndns,openvpn,pingcheck,ppe,pppoe,pptp,ssh,trafficcontrol,
! wireguard
!
! ndw3:
! version: 1.101.18.1
!
! ndw4:
! version: 4.3.C.6.2
!
! manufacturer: Keenetic Ltd.
! vendor: Keenetic
! series: KN
! model: Sprinter (KN-3710)
! hw_version: 7777777
! hw_type: router
! hw_id: KN-3710
! device: Sprinter
! region: EA
! description: Keenetic Sprinter (KN-3710)
! $$$ Agent: http/rci
! $$$ Last change: Fri, 3 Oct 2025 18:37:40 GMT
! $$$ Model: Keenetic Sprinter
! $$$ Username: admin
! $$$ Version: 2.06.1
system
set net.ipv4.ip_forward 1
set net.ipv4.neigh.default.gc_thresh1 256
set net.ipv4.neigh.default.gc_thresh2 1024
set net.ipv4.neigh.default.gc_thresh3 2048
set net.ipv4.tcp_fin_timeout 30
set net.ipv4.tcp_keepalive_time 120
set net.ipv6.conf.all.forwarding 1
set net.ipv6.neigh.default.gc_thresh1 256
set net.ipv6.neigh.default.gc_thresh2 1024
set net.ipv6.neigh.default.gc_thresh3 2048
set net.netfilter.nf_conntrack_tcp_timeout_established 1200
set vm.overcommit_memory 0
set vm.vfs_cache_pressure 1000
clock timezone Europe/Berlin
domainname WORKGROUP
hostname test_HW
caption default
description "Keenetic Sprinter (KN-3710)"
ndss dump-report disable
!
dyndns profile _WEBADMIN
!
interface GigabitEthernet0
up
!
interface GigabitEthernet0/1
rename 1
switchport mode access
switchport access vlan 1
up
!
interface GigabitEthernet0/2
rename 2
switchport mode access
switchport access vlan 1
up
!
interface GigabitEthernet0/3
rename 3
switchport mode access
switchport access vlan 1
up
!
interface GigabitEthernet0/Vlan1
description "Home VLAN"
ip dhcp client dns-routes
ip name-servers
up
!
interface GigabitEthernet0/Vlan2
rename ISP
description "\xd0\x9f\xd0\xbe\xd0\xb4\xd0\xba\xd0\xbb\xd1\x8e\xd1\x87\xd0\xb5\xd0\xbd\xd0\xb8\xd0\xb5 Ethernet"
dyndns nobind
mac address factory wan
security-level public
ip address dhcp
ip dhcp client hostname test_HW
ip dhcp client dns-routes
ip mtu 1500
ip access-group _WEBADMIN_ISP in
ip global 57342
ip no name-servers
igmp upstream
ipv6 address auto
ipv6 prefix auto
ipv6 no name-servers auto
up
!
interface GigabitEthernet0/0
rename 0
role inet for ISP
switchport mode access
switchport access vlan 2
up
!
interface GigabitEthernet0/Vlan3
dyndns nobind
ip dhcp client dns-routes
ip name-servers
up
!
interface WifiMaster0
country-code RU
compatibility BGN+AX
rekey-interval 86400
up
!
interface WifiMaster0/AccessPoint0
mac access-list type none
authentication wpa-psk ns3 7777ggggddddsss
encryption enable
encryption wpa2
ip dhcp client dns-routes
ssid test_HW_2.4G
up
!
interface WifiMaster0/AccessPoint1
mac access-list type none
security-level private
encryption no enable
ip dhcp client dns-routes
down
!
interface WifiMaster0/AccessPoint2
mac access-list type none
security-level private
encryption no enable
ip dhcp client dns-routes
down
!
interface WifiMaster0/WifiStation0
security-level public
encryption no enable
ip dhcp client dns-routes
standby enable
standby timeout 600
down
!
interface WifiMaster1
country-code RU
compatibility AN+AC+AX
channel width 40-above/80
rekey-interval 86400
up
!
interface WifiMaster1/AccessPoint0
mac access-list type none
authentication wpa-psk ns3 7777ggggddddsss
encryption enable
encryption wpa2
ip dhcp client dns-routes
ssid test_HW_5G
up
!
interface WifiMaster1/AccessPoint1
mac access-list type none
security-level private
encryption no enable
ip dhcp client dns-routes
down
!
interface WifiMaster1/AccessPoint2
mac access-list type none
security-level private
encryption no enable
ip dhcp client dns-routes
down
!
interface WifiMaster1/WifiStation0
security-level public
encryption no enable
ip dhcp client dns-routes
standby enable
standby timeout 600
down
!
interface Bridge0
rename Home
description "Home network"
dyndns nobind
include GigabitEthernet0/Vlan1
include WifiMaster0/AccessPoint0
include WifiMaster1/AccessPoint0
mac access-list type none
security-level private
ip address 17.36.1.1 255.255.255.0
ip dhcp client dns-routes
ip access-group _WEBADMIN_Home in
ip name-servers
band-steering
up
!
interface Bridge1
rename Guest
description "Guest network"
traffic-shape rate 5120
dyndns nobind
include GigabitEthernet0/Vlan3
mac access-list type none
peer-isolation
security-level protected
ip address 10.1.30.1 255.255.255.0
ip dhcp client dns-routes
ip name-servers
down
!
interface Bridge2
rename Test
mac access-list type none
security-level public
ip dhcp client dns-routes
up
!
interface OpenVPN0
description test_HW-udp
role misc
security-level public
ip dhcp client dns-routes
ip tcp adjust-mss pmtu
ip name-servers
ipv6 name-servers auto
openvpn accept-routes
openvpn connect
up
!
interface OpenVPN2
description test_HW-tcp
role misc
dyndns nobind
security-level public
ip dhcp client dns-routes
ip tcp adjust-mss pmtu
openvpn accept-routes
openvpn connect
down
!
interface Wireguard0
description test_HW
dyndns nobind
security-level public
ip address 10.3.100.1 255.255.255.0
ip mtu 1324
ip tcp adjust-mss pmtu
wireguard listen-port 65513
wireguard peer 7777ggggddddsss= !test_HW
allow-ips 0.0.0.0 0.0.0.0
connect
!
up
!
interface Wireguard1
description test_HW
dyndns nobind
security-level private
ip address 10.1.100.1 255.255.255.0
ip mtu 1324
ip access-group _WEBADMIN_Wireguard1 in
ip tcp adjust-mss pmtu
wireguard listen-port 65511
wireguard peer 7777ggggddddsss= !test_HW
allow-ips 10.1.100.0 255.255.255.0
allow-ips 17.36.3.0 255.255.255.0
allow-ips 17.36.1.0 255.255.255.0
allow-ips 0.0.0.0 0.0.0.0
connect
!
up
!
interface Wireguard2
description test_HW
dyndns nobind
security-level private
ip address 10.2.100.1 255.255.255.0
ip access-group _WEBADMIN_Wireguard2 in
ip tcp adjust-mss pmtu
wireguard listen-port 65512
wireguard peer 7777ggggddddsss= !test_HW
allow-ips 0.0.0.0 0.0.0.0
connect
!
up
!
ip ssh
port 22
security-level public
lockout-policy 5 15 3
!
ip hotspot
policy Home permit
host 7777ggggddddsss permit
host 7777ggggddddsss priority 4
!
ipv6 subnet Default
bind Home
mode slaac
prefix length 64
number 0
!
ppe software
ppe hardware
upnp lan Home
service dhcp
service dns-proxy
service http
service telnet
service ssh
service ntp
service upnp
!
easyconfig disable
components
auto-update disable
auto-update channel stable
!

View File

@@ -0,0 +1,161 @@
{
"system": {
"model": "Sprinter (KN-3710)",
"serial_number": "7777777",
"version": "4.03.C.6.2-7"
},
"interfaces": [
{
"interface": "GigabitEthernet0",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "GigabitEthernet0/1",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "GigabitEthernet0/2",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "GigabitEthernet0/3",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "GigabitEthernet0/0",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "WifiMaster0",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "WifiMaster0/AccessPoint0",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "WifiMaster0/AccessPoint1",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "WifiMaster0/AccessPoint2",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "WifiMaster0/WifiStation0",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "WifiMaster1",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "WifiMaster1/AccessPoint0",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "WifiMaster1/AccessPoint1",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "WifiMaster1/AccessPoint2",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "WifiMaster1/WifiStation0",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "Bridge0",
"ip_address": "17.36.1.1",
"mask": 24,
"description": "Home network"
},
{
"interface": "Bridge1",
"ip_address": "10.1.30.1",
"mask": 24,
"description": "Guest network"
},
{
"interface": "Bridge2",
"ip_address": null,
"mask": null,
"description": null
},
{
"interface": "OpenVPN0",
"ip_address": null,
"mask": null,
"description": "test_HW-udp"
},
{
"interface": "OpenVPN2",
"ip_address": null,
"mask": null,
"description": "test_HW-tcp"
},
{
"interface": "Wireguard0",
"ip_address": "10.3.100.1",
"mask": 24,
"description": "test_HW"
},
{
"interface": "Wireguard1",
"ip_address": "10.1.100.1",
"mask": 24,
"description": "test_HW"
},
{
"interface": "Wireguard2",
"ip_address": "10.2.100.1",
"mask": 24,
"description": "test_HW"
}
],
"vlans": [
{
"vlan_id": 1,
"description": "Home VLAN"
},
{
"vlan_id": 2,
"description": "Подключение Ethernet"
},
{
"vlan_id": 3,
"description": "Home network"
}
]
}

123
tests/fixtures/mikrotik/config.conf vendored Normal file
View File

@@ -0,0 +1,123 @@
# 2026-02-18 22:32:59 by RouterOS 7.19.3
# software id = 0V5S-56MC
# version: 7.12
# model = C52iG-5HaxD2HaxD
# serial number = HE108BBGW0B
/interface bridge
add name=bridge.LAN
/interface ethernet
set [ find default-name=ether1 ] mac-address=C4:AD:32:B2:A1:9A poe-out=off
set [ find default-name=ether4 ] comment=test
/interface vlan
add comment="super test vlan" interface=ether4 name="test vlan" vlan-id=255
add disabled=yes interface=ether5 name="test test vlan" vlan-id=254
/interface list
add name=LAN
add name=WAN
/interface wifi channel
add band=2ghz-ax disabled=no name=ch-2ghz width=20/40mhz
add band=5ghz-ax disabled=no name=ch-5ghz width=20/40mhz
/interface wifi security
add authentication-types=wpa2-psk name=common-auth wps=disable
/interface wifi configuration
add name=common-auth security=common-auth ssid=test_HW
/interface wifi
set [ find default-name=wifi1 ] channel=ch-5ghz configuration=common-auth configuration.mode=ap disabled=no
set [ find default-name=wifi2 ] channel=ch-2ghz configuration=common-auth configuration.mode=ap disabled=no
/ip pool
add name=dhcp_pool0 ranges=172.16.3.2-172.16.3.254
add name=dhcp_pool1 ranges=192.168.3.2-192.168.3.254
/ip dhcp-server
add address-pool=dhcp_pool0 interface=bridge.LAN lease-time=10h name=dhcp1
/ppp profile
add name=new_antizapret on-down="/ip dns cache flush\r\
\n" on-up="/ip dns cache flush\r\
\n"
add name=robovps on-down="/ip dns cache flush" on-up="/ip dns cache flush" use-ipv6=no
/routing table
add disabled=no fib name=test_HW_table
/interface bridge port
add bridge=bridge.LAN interface=ether2 learn=yes
add bridge=bridge.LAN interface=ether3
add bridge=bridge.LAN interface=ether4
add bridge=bridge.LAN interface=ether5
add bridge=bridge.LAN interface=wifi1
add bridge=bridge.LAN interface=wifi2
/ipv6 settings
set disable-ipv6=yes forward=no
/interface detect-internet
set detect-interface-list=all
/interface list member
add interface=bridge.LAN list=LAN
add interface=ether1 list=WAN
/interface ovpn-server server
add mac-address=FE:25:E0:B8:66:01 name=ovpn-server1
/ip address
add address=172.16.3.1/24 interface=bridge.LAN network=172.16.3.0
add address=10.38.3.245/24 interface=ether1 network=10.38.3.0
add address=10.1.100.2/24 interface=wireguard2 network=10.1.100.0
add address=100.10.10.1/24 disabled=yes interface=ether4 network=100.10.10.0
/ip dhcp-server lease
add address=172.16.3.20 client-id=1:d8:3a:dd:22:28:1d mac-address=D8:3A:DD:21:28:1D server=dhcp1
add address=172.16.3.4 client-id=1:2c:cd:29:1a:ea:6d comment=test_HW mac-address=1E:CD:29:8A:EA:6D server=dhcp1
/ip dhcp-server network
add address=172.16.3.0/24 dns-server=172.16.3.1 gateway=172.16.3.1
/ip dns
set allow-remote-requests=yes servers=217.10.44.35
/ip dns static
add address=172.16.3.20 regexp=".*\\.home\$" type=A
add address=172.16.3.20 regexp=".*\\.home.uk\$" type=A
add address=172.16.3.20 disabled=yes regexp=".*\\.home.uk\$" type=A
/ip firewall address-list
add address=172.16.3.0/24 list=test_HW
add address=172.16.2.0/24 list=test_HW
add address=172.16.1.0/24 list=test_HW
add address=255.255.255.255 list=test_HW
/ip firewall filter
add action=drop chain=forward out-interface=ether1 src-address=172.16.3.11
add action=accept chain=input src-address=255.255.255.255
add action=accept chain=forward in-interface=wireguard2
add action=accept chain=forward connection-state=established,related in-interface=ether1
add action=accept chain=input connection-state=established,related in-interface=ether1
add action=accept chain=input in-interface=bridge.LAN
add action=drop chain=input in-interface=ether1
add action=drop chain=forward in-interface=ether1
/ip firewall mangle
add action=passthrough chain=prerouting connection-mark=test_HW src-address=172.16.3.20
/ip firewall nat
add action=masquerade chain=srcnat out-interface=ether1
add action=masquerade chain=srcnat comment=test_HW out-interface=test_HW
/ip firewall service-port
set ftp disabled=yes
set tftp disabled=yes
set h323 disabled=yes
/ip route
add disabled=no distance=1 dst-address=172.16.1.0/24 gateway=10.1.100.1
add disabled=no distance=1 dst-address=172.16.2.0/24 gateway=10.1.100.1
add disabled=no distance=1 dst-address=255.255.255.255/32 gateway=10.38.3.1
add disabled=no distance=3 dst-address=0.0.0.0/0 gateway=10.38.3.1 routing-table=main scope=30 suppress-hw-offload=no target-scope=10
add disabled=yes distance=2 dst-address=0.0.0.0/0 gateway=10.38.3.1 routing-table=main scope=30 suppress-hw-offload=no target-scope=10
add comment=test_HW disabled=no distance=1 dst-address=185.255.255.255/32 gateway=10.38.3.1 routing-table=main scope=30 suppress-hw-offload=no target-scope=10
add comment=test_HW disabled=no distance=1 dst-address=192.168.255.255/32 gateway=10.38.3.1 routing-table=main scope=30 suppress-hw-offload=no target-scope=10
/ip service
set telnet disabled=yes
/system clock
set time-zone-name=Europe/Berlin
/system identity
set name=test_HW
/system logging
set 0 topics=info,!wireless
/system note
set show-at-login=no
/system ntp client
set enabled=yes
/system ntp client servers
add address=pool.ntp.org
/tool mac-server
set allowed-interface-list=LAN
/tool mac-server mac-winbox
set allowed-interface-list=LAN
/tool mac-server ping
set enabled=no
/user aaa
set default-group=full use-radius=yes

View File

@@ -0,0 +1,43 @@
{
"system": {
"model": "C52iG-5HaxD2HaxD",
"serial_number": "HE108BBGW0B",
"version": "7.12"
},
"interfaces": [
{
"interface": "bridge.LAN",
"ip_address": "172.16.3.1",
"mask": 24,
"description": null
},
{
"interface": "ether1",
"ip_address": "10.38.3.245",
"mask": 24,
"description": null
},
{
"interface": "wireguard2",
"ip_address": "10.1.100.2",
"mask": 24,
"description": null
},
{
"interface": "ether4",
"ip_address": "100.10.10.1",
"mask": 24,
"description": null
}
],
"vlans": [
{
"vlan_id": 255,
"description": "test vlan"
},
{
"vlan_id": 254,
"description": "test test vlan"
}
]
}

42
tests/fixtures/qtech/config_1.conf vendored Normal file
View File

@@ -0,0 +1,42 @@
! QTECH LLC Internetwork Operating System Software
! QSW-8330-40T-DC Series Software, Version 2.2.0C Build 96279, RELEASE SOFTWARE
! ROM: System Bootstrap, Version 0.4.7,hardware version:A
! Serial num:6060606060606060, ID num:555555555555
! System image file is "Switch.bin"
! QTECH LLC QSW-8330-40T-DC RISC
! 524288K bytes of memory,16384K bytes of flash
! Base ethernet MAC Address: 08:c6:b3:08:cf:ff
! snmp info:
! vend_ID:27514 product_ID:404 system_ID:1.3.6.1.4.1.27514
interface GigaEthernet1/0/9
shutdown
description FREE
switchport pvid 102
storm-control broadcast threshold 15
storm-control broadcast action shutdown
storm-control broadcast auto_resume 60s
storm-control multicast threshold 10
storm-control multicast action shutdown
storm-control multicast auto_resume 60s
qos policy IPP3 ingress
!
interface VLAN1
ip address 192.168.0.1 255.255.0.0
ip mtu 1500
no ip directed-broadcast
!
interface VLAN1002
description test-1002
ip address 13.36.8.1 255.255.255.0
ip mtu 1500
no ip directed-broadcast
!
vlan 772
name test
!
vlan 888
name test_super
!
vlan 1,7,14-15,44,101-102,115,117-124,130-136,139,167,200-205,772
,1607
vlan 888,2016,2085-2088

View File

@@ -0,0 +1,185 @@
{
"system": {
"model": "QSW-8330-40T-DC",
"serial_number": "6060606060606060",
"version": "96279"
},
"interfaces": [
{
"interface": "GigaEthernet1/0/9",
"ip_address": null,
"mask": null,
"description": "FREE"
},
{
"interface": "VLAN1",
"ip_address": "192.168.0.1",
"mask": 16,
"description": null
},
{
"interface": "VLAN1002",
"ip_address": "13.36.8.1",
"mask": 24,
"description": "test-1002"
}
],
"vlans": [
{
"vlan_id": 772,
"description": "test"
},
{
"vlan_id": 888,
"description": "test_super"
},
{
"vlan_id": 1,
"description": null
},
{
"vlan_id": 7,
"description": null
},
{
"vlan_id": 14,
"description": null
},
{
"vlan_id": 15,
"description": null
},
{
"vlan_id": 44,
"description": null
},
{
"vlan_id": 101,
"description": null
},
{
"vlan_id": 102,
"description": null
},
{
"vlan_id": 115,
"description": null
},
{
"vlan_id": 117,
"description": null
},
{
"vlan_id": 118,
"description": null
},
{
"vlan_id": 119,
"description": null
},
{
"vlan_id": 120,
"description": null
},
{
"vlan_id": 121,
"description": null
},
{
"vlan_id": 122,
"description": null
},
{
"vlan_id": 123,
"description": null
},
{
"vlan_id": 124,
"description": null
},
{
"vlan_id": 130,
"description": null
},
{
"vlan_id": 131,
"description": null
},
{
"vlan_id": 132,
"description": null
},
{
"vlan_id": 133,
"description": null
},
{
"vlan_id": 134,
"description": null
},
{
"vlan_id": 135,
"description": null
},
{
"vlan_id": 136,
"description": null
},
{
"vlan_id": 139,
"description": null
},
{
"vlan_id": 167,
"description": null
},
{
"vlan_id": 200,
"description": null
},
{
"vlan_id": 201,
"description": null
},
{
"vlan_id": 202,
"description": null
},
{
"vlan_id": 203,
"description": null
},
{
"vlan_id": 204,
"description": null
},
{
"vlan_id": 205,
"description": null
},
{
"vlan_id": 1607,
"description": null
},
{
"vlan_id": 2016,
"description": null
},
{
"vlan_id": 2085,
"description": null
},
{
"vlan_id": 2086,
"description": null
},
{
"vlan_id": 2087,
"description": null
},
{
"vlan_id": 2088,
"description": null
}
]
}

36
tests/fixtures/qtech/config_2.conf vendored Normal file
View File

@@ -0,0 +1,36 @@
! QTECH LLC Internetwork Operating System Software
! QSW-8330-40T-DC Series Software, Version 2.2.0C Build 96279, RELEASE SOFTWARE
! ROM: System Bootstrap, Version 0.4.7,hardware version:A
! Serial num:6060606060606060, ID num:555555555555
! System image file is "Switch.bin"
! QTECH LLC QSW-8330-40T-DC RISC
! 524288K bytes of memory,16384K bytes of flash
! Base ethernet MAC Address: 08:c6:b3:08:cf:f7
! snmp info:
! vend_ID:27514 product_ID:404 system_ID:1.3.6.1.4.1.27514
interface GigaEthernet1/0/9
shutdown
description FREE
switchport pvid 102
storm-control broadcast threshold 15
storm-control broadcast action shutdown
storm-control broadcast auto_resume 60s
storm-control multicast threshold 10
storm-control multicast action shutdown
storm-control multicast auto_resume 60s
qos policy IPP3 ingress
!
interface VLAN1
ip address 192.168.0.1 255.255.0.0
ip mtu 1500
no ip directed-broadcast
!
interface VLAN1002
description test-1002
ip address 13.36.8.1 255.255.255.0
ip mtu 1500
no ip directed-broadcast
!
vlan 1,7,14-15,44,101-102,115,117-124,130-136,139,167,200-205,772
,1607
vlan 888,2016,2085-2088

View File

@@ -0,0 +1,185 @@
{
"system": {
"model": "QSW-8330-40T-DC",
"serial_number": "6060606060606060",
"version": "96279"
},
"interfaces": [
{
"interface": "GigaEthernet1/0/9",
"ip_address": null,
"mask": null,
"description": "FREE"
},
{
"interface": "VLAN1",
"ip_address": "192.168.0.1",
"mask": 16,
"description": null
},
{
"interface": "VLAN1002",
"ip_address": "13.36.8.1",
"mask": 24,
"description": "test-1002"
}
],
"vlans": [
{
"vlan_id": 1,
"description": null
},
{
"vlan_id": 7,
"description": null
},
{
"vlan_id": 14,
"description": null
},
{
"vlan_id": 15,
"description": null
},
{
"vlan_id": 44,
"description": null
},
{
"vlan_id": 101,
"description": null
},
{
"vlan_id": 102,
"description": null
},
{
"vlan_id": 115,
"description": null
},
{
"vlan_id": 117,
"description": null
},
{
"vlan_id": 118,
"description": null
},
{
"vlan_id": 119,
"description": null
},
{
"vlan_id": 120,
"description": null
},
{
"vlan_id": 121,
"description": null
},
{
"vlan_id": 122,
"description": null
},
{
"vlan_id": 123,
"description": null
},
{
"vlan_id": 124,
"description": null
},
{
"vlan_id": 130,
"description": null
},
{
"vlan_id": 131,
"description": null
},
{
"vlan_id": 132,
"description": null
},
{
"vlan_id": 133,
"description": null
},
{
"vlan_id": 134,
"description": null
},
{
"vlan_id": 135,
"description": null
},
{
"vlan_id": 136,
"description": null
},
{
"vlan_id": 139,
"description": null
},
{
"vlan_id": 167,
"description": null
},
{
"vlan_id": 200,
"description": null
},
{
"vlan_id": 201,
"description": null
},
{
"vlan_id": 202,
"description": null
},
{
"vlan_id": 203,
"description": null
},
{
"vlan_id": 204,
"description": null
},
{
"vlan_id": 205,
"description": null
},
{
"vlan_id": 772,
"description": null
},
{
"vlan_id": 1607,
"description": null
},
{
"vlan_id": 888,
"description": null
},
{
"vlan_id": 2016,
"description": null
},
{
"vlan_id": 2085,
"description": null
},
{
"vlan_id": 2086,
"description": null
},
{
"vlan_id": 2087,
"description": null
},
{
"vlan_id": 2088,
"description": null
}
]
}

41
tests/fixtures/quasar/config_1.conf vendored Normal file
View File

@@ -0,0 +1,41 @@
# Copyright © 2021-2022, TechArgos LLC
# ----------- -----------------
# Subsystem Version
# ----------- -----------------
# Engine 0.2.17.2022-10-21
# DPlane 0.2.18.2022-05-16
# BfMonitor 1.1.2.2022-08-25
# CLI.core 1.0.3.2022-09-30
# CLI.engine 1.2.2.2022-10-12
# RConsole 0.3.4.2022-01-12
# RcAppParams 0.3.1.2022-01-12
# SNMP 0.0.11.2022-04-26
# Zabbix 0.2.13.2022-01-26
# WebUI 1.1.3.2022-10-19
# BF.core 9.3.1.2021-01-30
#
# ------------------------- ---------------
# Platform EEPROM field Value
# ------------------------- ---------------
# Product Name Quasar-T-Q-0002
# Product Number HB4NC011234M
# Local MAC N/A
# Product Serial Number WEE1C1CC0004A
# Product Version 0.0
# System Manufacturing Date 2026-06-07
config ethernet ipv4 address 25.25.1.221/24 gateway 25.25.1.254 enable
config interface 7/4 fec none mode force-up enable
config interface 8/1 fec none mode force-up enable
config interface 8/2 fec none mode force-up enable
config interface 8/3 fec none mode force-up enable
config interface 8/4 fec none mode force-up enable
config interface 9/1 fec none mode force-up enable
config interface 9/2 fec none mode force-up enable
config interface 7/4 description "IN DWDM / OUT TEST_HW_08_N0_p1"
config interface 8/1 description "IN DWDM / OUT TEST_HW_09_N1_p0"
config interface 8/2 description "IN DWDM / OUT TEST_HW_09_N0_p0"
config interface 8/3 description "IN DWDM / OUT TEST_HW_10_N1_p0"
config interface 8/4 description "IN DWDM / OUT TEST_HW_10_N0_p0"
config interface 9/1 description "IN DWDM / OUT TEST_HW_11_N0_p0"
config interface 9/2 description "IN DWDM / OUT TEST_HW_11_N0_p1"

View File

@@ -0,0 +1,58 @@
{
"system": {
"model": "Quasar-T-Q-0002",
"serial_number": "WEE1C1CC0004A",
"version": "0.2.17.2022-10-21"
},
"interfaces": [
{
"interface": "7/4",
"ip_address": null,
"mask": null,
"description": "IN DWDM / OUT TEST_HW_08_N0_p1"
},
{
"interface": "8/1",
"ip_address": null,
"mask": null,
"description": "IN DWDM / OUT TEST_HW_09_N1_p0"
},
{
"interface": "8/2",
"ip_address": null,
"mask": null,
"description": "IN DWDM / OUT TEST_HW_09_N0_p0"
},
{
"interface": "8/3",
"ip_address": null,
"mask": null,
"description": "IN DWDM / OUT TEST_HW_10_N1_p0"
},
{
"interface": "8/4",
"ip_address": null,
"mask": null,
"description": "IN DWDM / OUT TEST_HW_10_N0_p0"
},
{
"interface": "9/1",
"ip_address": null,
"mask": null,
"description": "IN DWDM / OUT TEST_HW_11_N0_p0"
},
{
"interface": "9/2",
"ip_address": null,
"mask": null,
"description": "IN DWDM / OUT TEST_HW_11_N0_p1"
},
{
"interface": "ethernet",
"ip_address": "25.25.1.221",
"mask": 24,
"description": null
}
],
"vlans": []
}

43
tests/fixtures/quasar/config_2.conf vendored Normal file
View File

@@ -0,0 +1,43 @@
# Copyright © 2021-2024, TechArgos LLC
# ----------- ------------------
# Component Version
# ----------- ------------------
# Assembly 0.2.23_9.9.1_GA
# Engine 2.23.15.2024-08-22
# DPlane 0.2.20.2023-10-17
# BfMonitor 1.4.0.2024-08-27
# CLI.core 1.0.3.2022-09-30
# CLI.engine 1.3.4.2024-08-22
# RConsole 1.0.1.2022-12-23
# RcAppParams 1.0.1.2022-12-23
# SNMP 0.3.0.2024-07-08
# Zabbix 0.2.13.2022-01-26
# WebUI 1.3.34.2024-08-30
# NMS.agent 1.2.12.2024-08-21
# SysLog 0.7.12.2024-02-02
# NTPd 0.1.5.2024-07-15
# AAA 0.0.8.2023-11-16
#
# ------------------------- --------------------
# Platform EEPROM field Value
# ------------------------- --------------------
# Product Name D5232C-T
# Part Number TA-PB-D5232C-T-AC-PI
# Local MAC N/A
# Product Serial Number WHF1C87123456A
# Product Version 0.0
# System Manufacturing Date 2026-06-07
config ethernet ipv4 address 25.25.18.19/24 gateway 25.25.18.254 enable
config interface 1/1 description "TEST_HW_1_1"
config interface 1/3 description "TEST_HW_1_3"
config interface 2/1 description "TEST_HW_2_1"
config interface 2/2 description "TEST_HW_2_2"
config interface 2/3 description "TEST_HW_2_3"
config interface 2/4 description "TEST_HW_2_4"
config interface 3/1 description "TEST_HW_3_1"
config interface 3/3 description "TEST_HW_3_3"
config interface 3/4 description "TEST_HW_3_4"
config interface 4/1 description "TEST_HW_4_1"
config interface 4/2 description "TEST_HW_4_2"
config interface 4/3 description "TEST_HW_4_3"
config interface 4/4 description "TEST_HW_4_4"

View File

@@ -0,0 +1,94 @@
{
"system": {
"model": "D5232C-T",
"serial_number": "WHF1C87123456A",
"version": "0.2.23_9.9.1_GA"
},
"interfaces": [
{
"interface": "1/1",
"ip_address": null,
"mask": null,
"description": "TEST_HW_1_1"
},
{
"interface": "1/3",
"ip_address": null,
"mask": null,
"description": "TEST_HW_1_3"
},
{
"interface": "2/1",
"ip_address": null,
"mask": null,
"description": "TEST_HW_2_1"
},
{
"interface": "2/2",
"ip_address": null,
"mask": null,
"description": "TEST_HW_2_2"
},
{
"interface": "2/3",
"ip_address": null,
"mask": null,
"description": "TEST_HW_2_3"
},
{
"interface": "2/4",
"ip_address": null,
"mask": null,
"description": "TEST_HW_2_4"
},
{
"interface": "3/1",
"ip_address": null,
"mask": null,
"description": "TEST_HW_3_1"
},
{
"interface": "3/3",
"ip_address": null,
"mask": null,
"description": "TEST_HW_3_3"
},
{
"interface": "3/4",
"ip_address": null,
"mask": null,
"description": "TEST_HW_3_4"
},
{
"interface": "4/1",
"ip_address": null,
"mask": null,
"description": "TEST_HW_4_1"
},
{
"interface": "4/2",
"ip_address": null,
"mask": null,
"description": "TEST_HW_4_2"
},
{
"interface": "4/3",
"ip_address": null,
"mask": null,
"description": "TEST_HW_4_3"
},
{
"interface": "4/4",
"ip_address": null,
"mask": null,
"description": "TEST_HW_4_4"
},
{
"interface": "ethernet",
"ip_address": "25.25.18.19",
"mask": 24,
"description": null
}
],
"vlans": []
}

38
tests/test_models.py Normal file
View File

@@ -0,0 +1,38 @@
import json
import pytest
from conftest import FIXTURES, load
from oxi.interfaces import device_registry
MODEL_CASES = [
("mikrotik", "config.conf", "config.expected.json"),
("keenetic", "config.conf", "config.expected.json"),
("qtech", "config_1.conf", "config_1.expected.json"),
("qtech", "config_2.conf", "config_2.expected.json"),
("huawei", "config.conf", "config.expected.json"),
("eltex", "config.conf", "config.expected.json"),
("quasar", "config_1.conf", "config_1.expected.json"),
("quasar", "config_2.conf", "config_2.expected.json"),
]
@pytest.mark.parametrize("model_key, fixture, expected_file", MODEL_CASES)
def test_parse_matches_golden(model_key, fixture, expected_file):
cls = device_registry[model_key]
raw = load(model_key, fixture)
parsed = cls(raw).parse().model_dump(by_alias=True, mode="json")
expected = json.loads((FIXTURES / model_key / expected_file).read_text("utf-8"))
assert parsed == expected
@pytest.mark.parametrize("model_key, fixture, _expected", MODEL_CASES)
def test_parse_has_required_sections(model_key, fixture, _expected):
cls = device_registry[model_key]
device = cls(load(model_key, fixture)).parse()
assert device.system is not None
assert isinstance(device.interfaces, list)
assert isinstance(device.vlans, list)