test_scheduler_base.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. # -*- coding:utf-8 -*-
  2. """
  3. Unit tests for ddns.scheduler._base module
  4. @author: NewFuture
  5. """
  6. from __init__ import patch, unittest
  7. from ddns.scheduler._base import BaseScheduler
  8. class MockScheduler(BaseScheduler):
  9. """Mock scheduler for testing base functionality"""
  10. SCHEDULER_NAME = "mock"
  11. def get_status(self):
  12. return {"scheduler": "mock", "installed": False, "enabled": None, "interval": None}
  13. def is_installed(self):
  14. return False
  15. def install(self, interval, ddns_args=None):
  16. return True
  17. def uninstall(self):
  18. return True
  19. def enable(self):
  20. return True
  21. def disable(self):
  22. return True
  23. class TestBaseScheduler(unittest.TestCase):
  24. """Test BaseScheduler functionality"""
  25. def setUp(self):
  26. """Set up test fixtures"""
  27. self.scheduler = MockScheduler()
  28. def test_scheduler_name_property(self):
  29. """Test scheduler name property"""
  30. self.assertEqual(self.scheduler.SCHEDULER_NAME, "mock")
  31. def test_abstract_methods_exist(self):
  32. """Test that all abstract methods are implemented"""
  33. required_methods = ["get_status", "is_installed", "install", "uninstall", "enable", "disable"]
  34. for method_name in required_methods:
  35. self.assertTrue(hasattr(self.scheduler, method_name))
  36. method = getattr(self.scheduler, method_name)
  37. self.assertTrue(callable(method))
  38. def test_build_ddns_command_basic(self):
  39. """Test _build_ddns_command with basic arguments"""
  40. ddns_args = {"dns": "debug", "ipv4": ["test.example.com"]}
  41. command = self.scheduler._build_ddns_command(ddns_args)
  42. self.assertIsInstance(command, list)
  43. command_str = " ".join(command)
  44. self.assertIn("python", command_str.lower())
  45. self.assertIn("-m", command)
  46. self.assertIn("ddns", command)
  47. self.assertIn("--dns", command)
  48. self.assertIn("debug", command)
  49. self.assertIn("--ipv4", command)
  50. self.assertIn("test.example.com", command)
  51. def test_build_ddns_command_with_config(self):
  52. """Test _build_ddns_command with config files"""
  53. ddns_args = {"dns": "cloudflare", "config": ["config1.json", "config2.json"]}
  54. command = self.scheduler._build_ddns_command(ddns_args)
  55. self.assertIn("--config", command)
  56. self.assertIn("config1.json", command)
  57. self.assertIn("config2.json", command)
  58. def test_build_ddns_command_with_lists(self):
  59. """Test _build_ddns_command with list arguments"""
  60. ddns_args = {
  61. "dns": "debug",
  62. "ipv4": ["domain1.com", "domain2.com"],
  63. "ipv6": ["ipv6domain.com"],
  64. "proxy": ["http://proxy1:8080", "http://proxy2:8080"],
  65. }
  66. command = self.scheduler._build_ddns_command(ddns_args)
  67. self.assertIn("domain1.com", command)
  68. self.assertIn("domain2.com", command)
  69. self.assertIn("ipv6domain.com", command)
  70. self.assertIn("http://proxy1:8080", command)
  71. def test_build_ddns_command_with_boolean_flags(self):
  72. """Test _build_ddns_command with boolean flags"""
  73. ddns_args = {"dns": "debug", "ipv4": ["test.com"], "debug": True, "cache": True}
  74. command = self.scheduler._build_ddns_command(ddns_args)
  75. self.assertIn("--debug", command)
  76. self.assertIn("true", command)
  77. self.assertIn("--cache", command)
  78. def test_build_ddns_command_filters_debug_false(self):
  79. """Test _build_ddns_command filters out debug=False"""
  80. ddns_args = {"dns": "debug", "ipv4": ["test.com"], "debug": False, "cache": True} # This should be filtered out
  81. command = self.scheduler._build_ddns_command(ddns_args)
  82. command_str = " ".join(command)
  83. self.assertNotIn("--debug false", command_str)
  84. self.assertIn("--cache", command)
  85. self.assertIn("true", command)
  86. def test_build_ddns_command_with_single_values(self):
  87. """Test _build_ddns_command with single value arguments"""
  88. ddns_args = {"dns": "alidns", "id": "test_id", "token": "test_token", "ttl": 600, "log_level": "INFO"}
  89. command = self.scheduler._build_ddns_command(ddns_args)
  90. self.assertIn("--id", command)
  91. self.assertIn("test_id", command)
  92. self.assertIn("--token", command)
  93. self.assertIn("test_token", command)
  94. self.assertIn("--ttl", command)
  95. self.assertIn("600", command)
  96. def test_build_ddns_command_excludes_none_values(self):
  97. """Test _build_ddns_command behavior with None values"""
  98. ddns_args = {"dns": "debug", "ipv4": ["test.com"], "ttl": None, "line": None}
  99. command = self.scheduler._build_ddns_command(ddns_args)
  100. # The current implementation includes None values as strings
  101. # This test verifies the actual behavior
  102. self.assertIn("--ttl", command)
  103. self.assertIn("None", command)
  104. self.assertIn("--line", command)
  105. def test_build_ddns_command_excludes_empty_lists(self):
  106. """Test _build_ddns_command excludes empty lists"""
  107. ddns_args = {"dns": "debug", "ipv4": ["test.com"], "ipv6": [], "config": []}
  108. command = self.scheduler._build_ddns_command(ddns_args)
  109. # Should not include empty list arguments
  110. self.assertIn("--ipv4", command)
  111. self.assertNotIn("--ipv6", command)
  112. self.assertNotIn("--config", command)
  113. @patch("sys.executable", "/usr/bin/python3.9")
  114. def test_build_ddns_command_uses_current_python(self):
  115. """Test _build_ddns_command uses current Python executable"""
  116. ddns_args = {"dns": "debug", "ipv4": ["test.com"]}
  117. command = self.scheduler._build_ddns_command(ddns_args)
  118. # Should use sys.executable for Python path
  119. command_str = " ".join(command)
  120. self.assertIn("python", command_str.lower())
  121. def test_build_ddns_command_with_special_characters(self):
  122. """Test _build_ddns_command handles special characters"""
  123. ddns_args = {"dns": "debug", "ipv4": ["test-domain.example.com"], "token": "test_token_with_special_chars!@#"}
  124. command = self.scheduler._build_ddns_command(ddns_args)
  125. self.assertIsInstance(command, list)
  126. self.assertIn("test-domain.example.com", command)
  127. self.assertIn("test_token_with_special_chars!@#", command)
  128. def test_all_scheduler_interface_methods(self):
  129. """Test that scheduler implements all interface methods correctly"""
  130. # Test get_status
  131. status = self.scheduler.get_status()
  132. self.assertIsInstance(status, dict)
  133. self.assertIn("scheduler", status)
  134. # Test is_installed
  135. installed = self.scheduler.is_installed()
  136. self.assertIsInstance(installed, bool)
  137. # Test install
  138. result = self.scheduler.install(5, {"dns": "debug"})
  139. self.assertIsInstance(result, bool)
  140. # Test uninstall
  141. result = self.scheduler.uninstall()
  142. self.assertIsInstance(result, bool)
  143. # Test enable
  144. result = self.scheduler.enable()
  145. self.assertIsInstance(result, bool)
  146. # Test disable
  147. result = self.scheduler.disable()
  148. self.assertIsInstance(result, bool)
  149. def test_quote_command_array(self):
  150. """Test _quote_command_array method"""
  151. # Test basic functionality
  152. cmd_array = ["python", "script.py"]
  153. result = self.scheduler._quote_command_array(cmd_array)
  154. self.assertEqual(result, "python script.py")
  155. # Test with spaces
  156. cmd_array = ["python", "script with spaces.py", "normal_arg"]
  157. result = self.scheduler._quote_command_array(cmd_array)
  158. self.assertEqual(result, 'python "script with spaces.py" normal_arg')
  159. # Test with multiple spaced arguments
  160. cmd_array = ["python", "-m", "ddns", "--config", "config file.json"]
  161. result = self.scheduler._quote_command_array(cmd_array)
  162. self.assertEqual(result, 'python -m ddns --config "config file.json"')
  163. # Test empty array
  164. result = self.scheduler._quote_command_array([])
  165. self.assertEqual(result, "")
  166. if __name__ == "__main__":
  167. unittest.main()