mirror of
https://github.com/NewFuture/DDNS.git
synced 2026-10-19 16:15:45 +00:00
* feat(cache): add configurable cache max age Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * test(cache): cover cache max age integration paths Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * test(cache): fix portable regression test formatting Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * style(test): format cache max age run test Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Future New (WEILAI LIU) <weilail@microsoft.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
233 lines
8.3 KiB
Python
233 lines
8.3 KiB
Python
# -*- coding:utf-8 -*-
|
|
"""
|
|
Unit tests for ddns.scheduler._base module
|
|
@author: NewFuture
|
|
"""
|
|
|
|
from __init__ import patch, unittest
|
|
|
|
from ddns.scheduler._base import BaseScheduler
|
|
|
|
|
|
class MockScheduler(BaseScheduler):
|
|
"""Mock scheduler for testing base functionality"""
|
|
|
|
SCHEDULER_NAME = "mock"
|
|
|
|
def get_status(self):
|
|
return {"scheduler": "mock", "installed": False, "enabled": None, "interval": None}
|
|
|
|
def is_installed(self):
|
|
return False
|
|
|
|
def install(self, interval, ddns_args=None):
|
|
return True
|
|
|
|
def uninstall(self):
|
|
return True
|
|
|
|
def enable(self):
|
|
return True
|
|
|
|
def disable(self):
|
|
return True
|
|
|
|
|
|
class TestBaseScheduler(unittest.TestCase):
|
|
"""Test BaseScheduler functionality"""
|
|
|
|
def setUp(self):
|
|
"""Set up test fixtures"""
|
|
self.scheduler = MockScheduler()
|
|
|
|
def test_scheduler_name_property(self):
|
|
"""Test scheduler name property"""
|
|
self.assertEqual(self.scheduler.SCHEDULER_NAME, "mock")
|
|
|
|
def test_abstract_methods_exist(self):
|
|
"""Test that all abstract methods are implemented"""
|
|
required_methods = ["get_status", "is_installed", "install", "uninstall", "enable", "disable"]
|
|
|
|
for method_name in required_methods:
|
|
self.assertTrue(hasattr(self.scheduler, method_name))
|
|
method = getattr(self.scheduler, method_name)
|
|
self.assertTrue(callable(method))
|
|
|
|
def test_build_ddns_command_basic(self):
|
|
"""Test _build_ddns_command with basic arguments"""
|
|
ddns_args = {"dns": "debug", "ipv4": ["test.example.com"]}
|
|
|
|
command = self.scheduler._build_ddns_command(ddns_args)
|
|
|
|
self.assertIsInstance(command, list)
|
|
command_str = " ".join(command)
|
|
self.assertIn("python", command_str.lower())
|
|
self.assertIn("-m", command)
|
|
self.assertIn("ddns", command)
|
|
self.assertIn("--dns", command)
|
|
self.assertIn("debug", command)
|
|
self.assertIn("--ipv4", command)
|
|
self.assertIn("test.example.com", command)
|
|
|
|
def test_build_ddns_command_with_config(self):
|
|
"""Test _build_ddns_command with config files"""
|
|
ddns_args = {"dns": "cloudflare", "config": ["config1.json", "config2.json"]}
|
|
|
|
command = self.scheduler._build_ddns_command(ddns_args)
|
|
|
|
self.assertIn("--config", command)
|
|
self.assertIn("config1.json", command)
|
|
self.assertIn("config2.json", command)
|
|
|
|
def test_build_ddns_command_with_lists(self):
|
|
"""Test _build_ddns_command with list arguments"""
|
|
ddns_args = {
|
|
"dns": "debug",
|
|
"ipv4": ["domain1.com", "domain2.com"],
|
|
"ipv6": ["ipv6domain.com"],
|
|
"proxy": ["http://proxy1:8080", "http://proxy2:8080"],
|
|
}
|
|
|
|
command = self.scheduler._build_ddns_command(ddns_args)
|
|
|
|
self.assertIn("domain1.com", command)
|
|
self.assertIn("domain2.com", command)
|
|
self.assertIn("ipv6domain.com", command)
|
|
self.assertIn("http://proxy1:8080", command)
|
|
|
|
def test_build_ddns_command_with_boolean_flags(self):
|
|
"""Test _build_ddns_command with boolean flags"""
|
|
ddns_args = {"dns": "debug", "ipv4": ["test.com"], "debug": True, "cache": True}
|
|
|
|
command = self.scheduler._build_ddns_command(ddns_args)
|
|
|
|
self.assertIn("--debug", command)
|
|
self.assertIn("true", command)
|
|
self.assertIn("--cache", command)
|
|
|
|
def test_build_ddns_command_filters_debug_false(self):
|
|
"""Test _build_ddns_command filters out debug=False"""
|
|
ddns_args = {"dns": "debug", "ipv4": ["test.com"], "debug": False, "cache": True} # This should be filtered out
|
|
|
|
command = self.scheduler._build_ddns_command(ddns_args)
|
|
|
|
command_str = " ".join(command)
|
|
self.assertNotIn("--debug false", command_str)
|
|
self.assertIn("--cache", command)
|
|
self.assertIn("true", command)
|
|
|
|
def test_build_ddns_command_with_single_values(self):
|
|
"""Test _build_ddns_command with single value arguments"""
|
|
ddns_args = {"dns": "alidns", "id": "test_id", "token": "test_token", "ttl": 600, "log_level": "INFO"}
|
|
|
|
command = self.scheduler._build_ddns_command(ddns_args)
|
|
|
|
self.assertIn("--id", command)
|
|
self.assertIn("test_id", command)
|
|
self.assertIn("--token", command)
|
|
self.assertIn("test_token", command)
|
|
self.assertIn("--ttl", command)
|
|
self.assertIn("600", command)
|
|
|
|
def test_build_ddns_command_with_cache_max_age(self):
|
|
"""Test _build_ddns_command emits the cache max age option."""
|
|
command = self.scheduler._build_ddns_command({"cache_max_age": 86400})
|
|
|
|
self.assertIn("--cache_max_age", command)
|
|
self.assertIn("86400", command)
|
|
|
|
def test_build_ddns_command_excludes_none_values(self):
|
|
"""Test _build_ddns_command behavior with None values"""
|
|
ddns_args = {"dns": "debug", "ipv4": ["test.com"], "ttl": None, "line": None}
|
|
|
|
command = self.scheduler._build_ddns_command(ddns_args)
|
|
|
|
# The current implementation includes None values as strings
|
|
# This test verifies the actual behavior
|
|
self.assertIn("--ttl", command)
|
|
self.assertIn("None", command)
|
|
self.assertIn("--line", command)
|
|
|
|
def test_build_ddns_command_excludes_empty_lists(self):
|
|
"""Test _build_ddns_command excludes empty lists"""
|
|
ddns_args = {"dns": "debug", "ipv4": ["test.com"], "ipv6": [], "config": []}
|
|
|
|
command = self.scheduler._build_ddns_command(ddns_args)
|
|
|
|
# Should not include empty list arguments
|
|
self.assertIn("--ipv4", command)
|
|
self.assertNotIn("--ipv6", command)
|
|
self.assertNotIn("--config", command)
|
|
|
|
@patch("sys.executable", "/usr/bin/python3.9")
|
|
def test_build_ddns_command_uses_current_python(self):
|
|
"""Test _build_ddns_command uses current Python executable"""
|
|
ddns_args = {"dns": "debug", "ipv4": ["test.com"]}
|
|
command = self.scheduler._build_ddns_command(ddns_args)
|
|
|
|
# Should use sys.executable for Python path
|
|
command_str = " ".join(command)
|
|
self.assertIn("python", command_str.lower())
|
|
|
|
def test_build_ddns_command_with_special_characters(self):
|
|
"""Test _build_ddns_command handles special characters"""
|
|
ddns_args = {"dns": "debug", "ipv4": ["test-domain.example.com"], "token": "test_token_with_special_chars!@#"}
|
|
|
|
command = self.scheduler._build_ddns_command(ddns_args)
|
|
|
|
self.assertIsInstance(command, list)
|
|
self.assertIn("test-domain.example.com", command)
|
|
self.assertIn("test_token_with_special_chars!@#", command)
|
|
|
|
def test_all_scheduler_interface_methods(self):
|
|
"""Test that scheduler implements all interface methods correctly"""
|
|
# Test get_status
|
|
status = self.scheduler.get_status()
|
|
self.assertIsInstance(status, dict)
|
|
self.assertIn("scheduler", status)
|
|
|
|
# Test is_installed
|
|
installed = self.scheduler.is_installed()
|
|
self.assertIsInstance(installed, bool)
|
|
|
|
# Test install
|
|
result = self.scheduler.install(5, {"dns": "debug"})
|
|
self.assertIsInstance(result, bool)
|
|
|
|
# Test uninstall
|
|
result = self.scheduler.uninstall()
|
|
self.assertIsInstance(result, bool)
|
|
|
|
# Test enable
|
|
result = self.scheduler.enable()
|
|
self.assertIsInstance(result, bool)
|
|
|
|
# Test disable
|
|
result = self.scheduler.disable()
|
|
self.assertIsInstance(result, bool)
|
|
|
|
def test_quote_command_array(self):
|
|
"""Test _quote_command_array method"""
|
|
# Test basic functionality
|
|
cmd_array = ["python", "script.py"]
|
|
result = self.scheduler._quote_command_array(cmd_array)
|
|
self.assertEqual(result, "python script.py")
|
|
|
|
# Test with spaces
|
|
cmd_array = ["python", "script with spaces.py", "normal_arg"]
|
|
result = self.scheduler._quote_command_array(cmd_array)
|
|
self.assertEqual(result, 'python "script with spaces.py" normal_arg')
|
|
|
|
# Test with multiple spaced arguments
|
|
cmd_array = ["python", "-m", "ddns", "--config", "config file.json"]
|
|
result = self.scheduler._quote_command_array(cmd_array)
|
|
self.assertEqual(result, 'python -m ddns --config "config file.json"')
|
|
|
|
# Test empty array
|
|
result = self.scheduler._quote_command_array([])
|
|
self.assertEqual(result, "")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|