Fix broad test suite failures

This commit is contained in:
Herbert Wolverson committed 2026-06-14 14:36:03 -05:00
1 parent efbdcfab51
commit e9e48ab153
5 files changed
+132 -99

No files matched your search

@@ -110,7 +110,14 @@ enum MergeNetworkModeError {
fn merge_network_mode(candidate: Config) -> Result<Config, MergeNetworkModeError> {
let live = lqos_config::load_config().map_err(|_| MergeNetworkModeError::LoadLiveConfig)?;
let mut merged = (*live).clone();
merge_network_mode_with_live(&live, candidate)
}
fn merge_network_mode_with_live(
live: &Config,
candidate: Config,
) -> Result<Config, MergeNetworkModeError> {
let mut merged = live.clone();
merged.bridge = candidate.bridge;
merged.single_interface = candidate.single_interface;
merged
@@ -202,11 +209,9 @@ pub async fn apply(
MergeNetworkModeError::InvalidCandidate(message) => {
helper_validation_error_response(message)
}
MergeNetworkModeError::LoadLiveConfig => {
helper_internal_error_response(
"Unable to load the live LibreQoS configuration".to_string(),
)
}
MergeNetworkModeError::LoadLiveConfig => helper_internal_error_response(
"Unable to load the live LibreQoS configuration".to_string(),
),
};
}
};
@@ -350,86 +355,8 @@ pub async fn retry_shaping(
#[cfg(test)]
mod tests {
use super::{MergeNetworkModeError, merge_network_mode};
use crate::test_support::runtime_config_test_lock;
use super::{MergeNetworkModeError, merge_network_mode_with_live};
use lqos_config::{BridgeConfig, Config, SingleInterfaceConfig};
use std::ffi::OsString;
use std::path::{Path, PathBuf};
use std::time::{SystemTime, UNIX_EPOCH};
fn network_mode_test_runtime_dir() -> PathBuf {
let unique_suffix = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("time should move forward")
.as_nanos();
std::env::temp_dir().join(format!(
"lqosd-network-mode-test-{}-{unique_suffix}",
std::process::id()
))
}
fn write_network_mode_test_config(runtime_dir: &Path) -> PathBuf {
std::fs::create_dir_all(runtime_dir).expect("create network-mode runtime dir");
let config_path = runtime_dir.join("lqos.conf");
let runtime_dir_string = runtime_dir.display().to_string();
let state_dir_string = runtime_dir.join("state").display().to_string();
let raw = include_str!("../../../../lqos_config/src/etc/v15/example.toml")
.replace("/opt/libreqos/src", &runtime_dir_string)
.replace("/opt/libreqos/state", &state_dir_string)
.replace("node_id = \"0000-0000-0000\"", "node_id = \"node\"");
std::fs::write(&config_path, raw).expect("write network-mode test config");
config_path
}
struct NetworkModeTestContext {
_guard: std::sync::MutexGuard<'static, ()>,
old_lqos_config: Option<OsString>,
old_lqos_directory: Option<OsString>,
runtime_dir: PathBuf,
}
impl NetworkModeTestContext {
fn new() -> Self {
let guard = runtime_config_test_lock()
.lock()
.expect("network-mode env lock should not be poisoned");
let runtime_dir = network_mode_test_runtime_dir();
let config_path = write_network_mode_test_config(&runtime_dir);
let old_lqos_config = std::env::var_os("LQOS_CONFIG");
let old_lqos_directory = std::env::var_os("LQOS_DIRECTORY");
unsafe {
std::env::set_var("LQOS_CONFIG", &config_path);
std::env::set_var("LQOS_DIRECTORY", &runtime_dir);
}
lqos_config::clear_cached_config();
Self {
_guard: guard,
old_lqos_config,
old_lqos_directory,
runtime_dir,
}
}
}
impl Drop for NetworkModeTestContext {
fn drop(&mut self) {
match &self.old_lqos_config {
Some(value) => unsafe { std::env::set_var("LQOS_CONFIG", value) },
None => unsafe { std::env::remove_var("LQOS_CONFIG") },
}
match &self.old_lqos_directory {
Some(value) => unsafe { std::env::set_var("LQOS_DIRECTORY", value) },
None => unsafe { std::env::remove_var("LQOS_DIRECTORY") },
}
lqos_config::clear_cached_config();
let _ = std::fs::remove_dir_all(&self.runtime_dir);
}
}
fn with_config_env<T>(test_fn: impl FnOnce() -> T) -> T {
let _context = NetworkModeTestContext::new();
test_fn()
}
#[test]
fn merge_network_mode_rejects_invalid_bridge_mtu() {
@@ -439,8 +366,8 @@ mod tests {
..BridgeConfig::default()
});
let error =
with_config_env(|| merge_network_mode(candidate).expect_err("invalid MTU should fail"));
let error = merge_network_mode_with_live(&Config::default(), candidate)
.expect_err("invalid MTU should fail");
assert_eq!(
error,
@@ -459,8 +386,8 @@ mod tests {
..SingleInterfaceConfig::default()
});
let error =
with_config_env(|| merge_network_mode(candidate).expect_err("invalid MTU should fail"));
let error = merge_network_mode_with_live(&Config::default(), candidate)
.expect_err("invalid MTU should fail");
assert_eq!(
error,
@@ -23,6 +23,8 @@ def install_common_stubs():
lqlib.exception_cpes = lambda: []
lqlib.promote_to_root_list = lambda: []
lqlib.client_bandwidth_multiplier = lambda: 1.0
lqlib.write_compiled_topology_from_python_graph_payload = lambda *_args, **_kwargs: None
lqlib.get_libreqos_directory = lambda: "/tmp/libreqos"
sys.modules["liblqos_python"] = lqlib
@@ -105,8 +107,9 @@ class TestIntegrationCommonIgnoreSubnets(unittest.TestCase):
self.assertEqual(len(rows), 2)
self.assertEqual(rows[1][0], "client-1")
self.assertIn("203.0.113.10/32", rows[1][6])
self.assertNotIn("100.64.1.10/32", rows[1][6])
ipv4_column = rows[0].index("IPv4")
self.assertIn("203.0.113.10/32", rows[1][ipv4_column])
self.assertNotIn("100.64.1.10/32", rows[1][ipv4_column])
def test_prune_does_not_require_ip_to_be_in_allowed_subnets(self):
integrationCommon.allowed_subnets = lambda: ["10.0.0.0/8"]
@@ -131,7 +134,8 @@ class TestIntegrationCommonIgnoreSubnets(unittest.TestCase):
self.assertEqual(len(rows), 2)
self.assertEqual(rows[1][0], "client-1")
self.assertIn("203.0.113.10/32", rows[1][6])
ipv4_column = rows[0].index("IPv4")
self.assertIn("203.0.113.10/32", rows[1][ipv4_column])
if __name__ == "__main__":
+35
View File
@@ -1,6 +1,41 @@
import unittest
import sys
import types
from unittest.mock import patch
def install_visp_stubs():
lqlib = types.ModuleType("liblqos_python")
lqlib.allowed_subnets = lambda: ["0.0.0.0/0", "::/0"]
lqlib.ignore_subnets = lambda: []
lqlib.generated_pn_download_mbps = lambda: 1000
lqlib.generated_pn_upload_mbps = lambda: 1000
lqlib.circuit_name_use_address = lambda: False
lqlib.upstream_bandwidth_capacity_download_mbps = lambda: 1000
lqlib.upstream_bandwidth_capacity_upload_mbps = lambda: 1000
lqlib.find_ipv6_using_mikrotik = lambda: False
lqlib.exclude_sites = lambda: []
lqlib.bandwidth_overhead_factor = lambda: 1.0
lqlib.committed_bandwidth_multiplier = lambda: 1.0
lqlib.exception_cpes = lambda: []
lqlib.promote_to_root_list = lambda: []
lqlib.client_bandwidth_multiplier = lambda: 1.0
lqlib.write_compiled_topology_from_python_graph_payload = lambda *_args, **_kwargs: None
lqlib.get_libreqos_directory = lambda: "/tmp/libreqos"
lqlib.visp_client_id = lambda: ""
lqlib.visp_client_secret = lambda: ""
lqlib.visp_username = lambda: ""
lqlib.visp_password = lambda: ""
lqlib.visp_isp_id = lambda: ""
lqlib.visp_online_users_domain = lambda: ""
lqlib.visp_timeout_secs = lambda: 60
sys.modules["liblqos_python"] = lqlib
install_visp_stubs()
sys.modules.pop("integrationCommon", None)
sys.modules.pop("integrationVISP", None)
from integrationVISP import (
_bulk_ipv4_candidates,
_select_attachment_equipment,
+3 -7
View File
@@ -7,13 +7,9 @@ import unittest
sys.modules.setdefault("routeros_api", types.SimpleNamespace())
sys.modules.setdefault(
"liblqos_python",
types.SimpleNamespace(
load_mikrotik_ipv6_routers_json=lambda: "[]",
mikrotik_ipv6_config_path=lambda: "/etc/libreqos/mikrotik_ipv6.toml",
),
)
lqlib = sys.modules.setdefault("liblqos_python", types.SimpleNamespace())
lqlib.load_mikrotik_ipv6_routers_json = lambda: "[]"
lqlib.mikrotik_ipv6_config_path = lambda: "/etc/libreqos/mikrotik_ipv6.toml"
import mikrotikFindIPv6
from mikrotikFindIPv6 import _build_ipv4_to_ipv6_map, _mac_from_dhcpv6_duid
+71
View File
@@ -1,4 +1,75 @@
import unittest
import sys
import types
def install_libreqos_import_stubs():
python_check = types.ModuleType("pythonCheck")
python_check.checkPythonVersion = lambda: None
sys.modules["pythonCheck"] = python_check
deepdiff = types.ModuleType("deepdiff")
deepdiff.DeepDiff = lambda *_args, **_kwargs: {}
sys.modules["deepdiff"] = deepdiff
lqlib = types.ModuleType("liblqos_python")
lqlib.is_lqosd_alive = lambda: True
lqlib.clear_ip_mappings = lambda: None
lqlib.delete_ip_mapping = lambda *_args, **_kwargs: None
lqlib.validate_shaped_devices = lambda: "OK"
lqlib.is_libre_already_running = lambda: False
lqlib.create_lock_file = lambda: None
lqlib.free_lock_file = lambda: None
lqlib.add_ip_mapping = lambda *_args, **_kwargs: None
class DummyBatchedCommands:
pass
class DummyBakery:
pass
lqlib.BatchedCommands = DummyBatchedCommands
lqlib.check_config = lambda: None
lqlib.sqm = lambda: "cake"
lqlib.upstream_bandwidth_capacity_download_mbps = lambda: 1000
lqlib.upstream_bandwidth_capacity_upload_mbps = lambda: 1000
lqlib.interface_a = lambda: "eth0"
lqlib.interface_b = lambda: "eth1"
lqlib.enable_actual_shell_commands = lambda: False
lqlib.use_bin_packing_to_balance_cpu = lambda: False
lqlib.queue_mode = lambda: "shape"
lqlib.run_shell_commands_as_sudo = lambda: False
lqlib.generated_pn_download_mbps = lambda: 1000
lqlib.generated_pn_upload_mbps = lambda: 1000
lqlib.queues_available_override = lambda: 0
lqlib.on_a_stick = lambda: False
lqlib.get_tree_weights = lambda: {}
lqlib.get_weights = lambda: {}
lqlib.is_network_flat = lambda: False
lqlib.get_libreqos_directory = lambda: "/tmp/libreqos"
lqlib.enable_insight_topology = lambda: False
lqlib.is_insight_enabled = lambda: False
lqlib.scheduler_error = lambda *_args, **_kwargs: None
lqlib.xdp_ip_mapping_capacity = lambda: 1024
lqlib.overrides_circuit_adjustments_effective = lambda: []
lqlib.automatic_import_uisp = lambda: False
lqlib.automatic_import_splynx = lambda: False
lqlib.automatic_import_powercode = lambda: False
lqlib.automatic_import_sonar = lambda: False
lqlib.automatic_import_wispgate = lambda: False
lqlib.automatic_import_netzur = lambda: False
lqlib.automatic_import_visp = lambda: False
lqlib.topology_import_ingress_enabled = lambda: False
lqlib.plan_top_level_cpu_bins = lambda *_args, **_kwargs: {}
lqlib.plan_class_identities = lambda *_args, **_kwargs: {}
lqlib.fast_queues_fq_codel = lambda: False
lqlib.shaping_cpu_count = lambda: 16
lqlib.Bakery = DummyBakery
sys.modules["liblqos_python"] = lqlib
install_libreqos_import_stubs()
sys.modules.pop("LibreQoS", None)
import LibreQoS