Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/route_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ def process_route_entry(prefix, route_entry):
if not route_entry.get('selected', False):
return
if not route_entry.get('offloaded', False):
missing_routes.append(prefix)
missing_routes.append({'prefix': prefix, 'protocol': route_entry.get('protocol', '')})
if route_entry.get('failed', False):
failing_routes.append(prefix)

Expand Down
53 changes: 29 additions & 24 deletions tests/fetch_routes_chunk_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
import route_check # noqa: E402


def get_missing_prefixes(result):
"""Extract prefix strings from missing_routes dicts for assertion comparison."""
return {entry['prefix'] for entry in result}


class ChunkedBytesIO:
def __init__(self, chunks):
self.chunks = chunks
Expand Down Expand Up @@ -79,7 +84,7 @@ def test_complete_json_single_chunk(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert result == (["192.168.1.0/24"], [])
assert result == ([{"prefix": "192.168.1.0/24", "protocol": "bgp"}], [])

def test_json_split_across_chunks(self):
"""Test parsing when JSON is split across multiple chunks"""
Expand Down Expand Up @@ -116,7 +121,7 @@ def test_json_split_across_chunks(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert set(result[0]) == {"10.0.0.0/8", "172.16.0.0/12"}
assert get_missing_prefixes(result[0]) == {"10.0.0.0/8", "172.16.0.0/12"}

def test_routes_with_offloaded_flag(self):
"""Test that routes with offloaded=True are not included in missing
Expand Down Expand Up @@ -144,7 +149,7 @@ def test_routes_with_offloaded_flag(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert result == (["192.168.2.0/24"], [])
assert result == ([{"prefix": "192.168.2.0/24", "protocol": "bgp"}], [])

def test_filter_connected_kernel_static_protocols(self):
"""Test that connected, kernel and static protocols are filtered out"""
Expand Down Expand Up @@ -186,7 +191,7 @@ def test_filter_connected_kernel_static_protocols(self):
result = route_check.fetch_routes()

# Only BGP route should be in the result
assert result == (["192.168.4.0/24"], [])
assert result == ([{"prefix": "192.168.4.0/24", "protocol": "bgp"}], [])

def test_filter_non_default_vrf(self):
"""Test that routes in non-default VRF are filtered out"""
Expand Down Expand Up @@ -221,7 +226,7 @@ def test_filter_non_default_vrf(self):
result = route_check.fetch_routes()

# Only default VRF route should be in the result
assert result == (["192.168.2.0/24"], [])
assert result == ([{"prefix": "192.168.2.0/24", "protocol": "bgp"}], [])

def test_filter_not_selected_routes(self):
"""Test that routes not selected as best are filtered out"""
Expand Down Expand Up @@ -249,7 +254,7 @@ def test_filter_not_selected_routes(self):
result = route_check.fetch_routes()

# Only selected route should be in the result
assert result == (["192.168.2.0/24"], [])
assert result == ([{"prefix": "192.168.2.0/24", "protocol": "bgp"}], [])

def test_empty_json_response(self):
"""Test handling of empty JSON response"""
Expand Down Expand Up @@ -297,7 +302,7 @@ def test_utf8_split_across_chunks(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert result == (["192.168.1.0/24"], [])
assert result == ([{"prefix": "192.168.1.0/24", "protocol": "bgp"}], [])

def test_very_small_chunks(self):
"""Test parsing with very small chunk sizes (byte-by-byte)"""
Expand All @@ -324,7 +329,7 @@ def test_very_small_chunks(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert result == (["10.0.0.0/8"], [])
assert result == ([{"prefix": "10.0.0.0/8", "protocol": "bgp"}], [])

def test_large_json_with_many_routes(self):
"""Test parsing large JSON with many route entries"""
Expand All @@ -350,7 +355,7 @@ def test_large_json_with_many_routes(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert set(result[0]) == set(expected_missing)
assert get_missing_prefixes(result[0]) == set(expected_missing)
assert len(result[0]) == 100

def test_ipv6_command(self):
Expand All @@ -377,7 +382,7 @@ def test_ipv6_command(self):
call_args = mock_popen.call_args[0][0]
assert call_args == ["sudo", "vtysh", "-c", "show ipv6 route json"]

assert result == (["2001:db8::/32"], [])
assert result == ([{"prefix": "2001:db8::/32", "protocol": "bgp"}], [])

def test_subprocess_non_zero_exit_code(self):
"""Test handling of subprocess with non-zero exit code"""
Expand All @@ -402,7 +407,7 @@ def test_subprocess_non_zero_exit_code(self):
result = route_check.fetch_routes()

# Should still return the parsed routes
assert result == (["192.168.1.0/24"], [])
assert result == ([{"prefix": "192.168.1.0/24", "protocol": "bgp"}], [])

def test_file_not_found_error(self):
"""Test handling of FileNotFoundError when vtysh is not found"""
Expand Down Expand Up @@ -469,7 +474,7 @@ def test_json_with_nested_objects(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert result == (["192.168.1.0/24"], [])
assert result == ([{"prefix": "192.168.1.0/24", "protocol": "bgp"}], [])

def test_variable_chunk_boundary(self):
"""Test when chunk boundary falls at variious locations"""
Expand Down Expand Up @@ -500,7 +505,7 @@ def test_variable_chunk_boundary(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert result == (["192.168.1.0/24"], [])
assert result == ([{"prefix": "192.168.1.0/24", "protocol": "bgp"}], [])

def test_chunk_boundary_in_string_value(self):
"""Test when chunk boundary falls in the middle of a string value"""
Expand Down Expand Up @@ -532,7 +537,7 @@ def test_chunk_boundary_in_string_value(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert result == (["192.168.1.0/24"], [])
assert result == ([{"prefix": "192.168.1.0/24", "protocol": "bgp"}], [])

def test_escaped_quotes_in_json(self):
"""Test handling of escaped quotes in JSON strings"""
Expand All @@ -553,7 +558,7 @@ def test_escaped_quotes_in_json(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert result == (["192.168.1.0/24"], [])
assert result == ([{"prefix": "192.168.1.0/24", "protocol": "bgp"}], [])

def test_whitespace_handling(self):
"""Test handling of JSON with various whitespace"""
Expand All @@ -576,7 +581,7 @@ def test_whitespace_handling(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert result == (["192.168.1.0/24"], [])
assert result == ([{"prefix": "192.168.1.0/24", "protocol": "bgp"}], [])

def test_mixed_ipv4_and_ipv6_routes(self):
"""Test parsing JSON with both IPv4 and IPv6 routes"""
Expand All @@ -603,7 +608,7 @@ def test_mixed_ipv4_and_ipv6_routes(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert set(result[0]) == {"192.168.1.0/24", "2001:db8::/32"}
assert get_missing_prefixes(result[0]) == {"192.168.1.0/24", "2001:db8::/32"}

def test_malformed_json_in_buffer(self):
"""Test handling of malformed JSON that cannot be parsed"""
Expand Down Expand Up @@ -649,7 +654,7 @@ def test_incremental_parsing_multiple_prefixes(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert set(result[0]) == {"192.168.1.0/24",
assert get_missing_prefixes(result[0]) == {"192.168.1.0/24",
"192.168.2.0/24",
"192.168.3.0/24"}

Expand Down Expand Up @@ -693,7 +698,7 @@ def test_incremental_parsing_prefix_split_across_chunks(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert set(result[0]) == {"192.168.1.0/24", "192.168.2.0/24"}
assert get_missing_prefixes(result[0]) == {"192.168.1.0/24", "192.168.2.0/24"}

def test_incremental_parsing_across_multiple_chunks(self):
# Create a large JSON with many prefixes
Expand Down Expand Up @@ -727,7 +732,7 @@ def test_incremental_parsing_across_multiple_chunks(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert set(result[0]) == set(expected_missing)
assert get_missing_prefixes(result[0]) == set(expected_missing)
assert len(result[0]) == 50

def test_incremental_parsing_prefix_boundary_at_comma(self):
Expand Down Expand Up @@ -766,7 +771,7 @@ def test_incremental_parsing_prefix_boundary_at_comma(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert set(result[0]) == {"192.168.1.0/24", "192.168.2.0/24"}
assert get_missing_prefixes(result[0]) == {"192.168.1.0/24", "192.168.2.0/24"}

def test_incremental_parsing_mixed_offloaded_states(self):
"""Test incremental parsing with mixed offloaded states across multiple prefixes"""
Expand Down Expand Up @@ -808,7 +813,7 @@ def test_incremental_parsing_mixed_offloaded_states(self):
result = route_check.fetch_routes()

# Only the non-offloaded routes should be in the result
assert set(result[0]) == {"192.168.2.0/24", "192.168.4.0/24"}
assert get_missing_prefixes(result[0]) == {"192.168.2.0/24", "192.168.4.0/24"}

def test_incremental_parsing_with_whitespace_variations(self):
"""Test incremental parsing with various whitespace formatting"""
Expand Down Expand Up @@ -840,7 +845,7 @@ def test_incremental_parsing_with_whitespace_variations(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert set(result[0]) == {"192.168.1.0/24", "192.168.2.0/24"}
assert get_missing_prefixes(result[0]) == {"192.168.1.0/24", "192.168.2.0/24"}

def test_incremental_parsing_prefix_with_special_characters(self):
"""Test incremental parsing of prefixes with special characters in descriptions"""
Expand Down Expand Up @@ -869,4 +874,4 @@ def test_incremental_parsing_prefix_with_special_characters(self):
with patch('route_check.subprocess.Popen', return_value=mock_proc):
result = route_check.fetch_routes()

assert set(result[0]) == {"192.168.1.0/24", "192.168.2.0/24"}
assert get_missing_prefixes(result[0]) == {"192.168.1.0/24", "192.168.2.0/24"}
2 changes: 1 addition & 1 deletion tests/route_check_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ def mock_fetch_routes(self, ct_data, *args, **kwargs):
if not e.get('selected', False):
continue
if not e.get('offloaded', False):
missed_route_list.append(r)
missed_route_list.append({'prefix': r, 'protocol': e.get('protocol', '')})
if e.get('failed', False):
failed_route_list.append(r)
return missed_route_list, failed_route_list # Return tuple of (missed_routes, failed_routes)
Expand Down
10 changes: 5 additions & 5 deletions tests/route_check_test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@
},
},
RESULT: {
DEFAULTNS: {"missed_FRR_routes": ['10.10.196.12/31']}
DEFAULTNS: {"missed_FRR_routes": [{"prefix": "10.10.196.12/31", "protocol": "bgp"}]}
},
RET: -1,
},
Expand Down Expand Up @@ -971,7 +971,7 @@
},
},
RESULT: {
ASIC1: {"missed_FRR_routes": ['10.10.196.12/31']},
ASIC1: {"missed_FRR_routes": [{"prefix": "10.10.196.12/31", "protocol": "bgp"}]},
},
RET: -1,
},
Expand Down Expand Up @@ -1497,7 +1497,7 @@
RESULT: {
ASIC0: {
"missed_FRR_routes": [
"10.10.196.20/31"
{"prefix": "10.10.196.20/31", "protocol": "bgp"}
],
"failed_FRR_routes": [
"10.10.196.12/31",
Expand Down Expand Up @@ -1590,8 +1590,8 @@
RESULT: {
DEFAULTNS: {
"missed_FRR_routes": [
"10.10.196.12/31",
"192.168.1.0/24"
{"prefix": "10.10.196.12/31", "protocol": "bgp"},
{"prefix": "192.168.1.0/24", "protocol": "bgp"}
],
"failed_FRR_routes": [
"10.10.196.20/31",
Expand Down
Loading