loadzone_test.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. # Copyright (C) 2012 Internet Systems Consortium.
  2. #
  3. # Permission to use, copy, modify, and distribute this software for any
  4. # purpose with or without fee is hereby granted, provided that the above
  5. # copyright notice and this permission notice appear in all copies.
  6. #
  7. # THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
  8. # DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
  9. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
  10. # INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  12. # FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  13. # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  14. # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. '''Tests for the loadzone module'''
  16. import unittest
  17. from loadzone import *
  18. from isc.dns import *
  19. from isc.datasrc import *
  20. import isc.log
  21. import os
  22. import shutil
  23. # Some common test parameters
  24. TESTDATA_PATH = os.environ['TESTDATA_PATH'] + os.sep
  25. READ_ZONE_DB_FILE = TESTDATA_PATH + "rwtest.sqlite3" # original, to be copied
  26. LOCAL_TESTDATA_PATH = os.environ['LOCAL_TESTDATA_PATH'] + os.sep
  27. READ_ZONE_DB_FILE = TESTDATA_PATH + "rwtest.sqlite3" # original, to be copied
  28. NEW_ZONE_TXT_FILE = LOCAL_TESTDATA_PATH + "example.org.zone"
  29. ALT_NEW_ZONE_TXT_FILE = TESTDATA_PATH + "example.com.zone"
  30. TESTDATA_WRITE_PATH = os.environ['TESTDATA_WRITE_PATH'] + os.sep
  31. WRITE_ZONE_DB_FILE = TESTDATA_WRITE_PATH + "rwtest.sqlite3.copied"
  32. TEST_ZONE_NAME = Name('example.org')
  33. DATASRC_CONFIG = '{"database_file": "' + WRITE_ZONE_DB_FILE + '"}'
  34. # before/after SOAs: different in mname and serial
  35. ORIG_SOA_TXT = 'example.org. 3600 IN SOA ns1.example.org. ' +\
  36. 'admin.example.org. 1234 3600 1800 2419200 7200\n'
  37. NEW_SOA_TXT = 'example.org. 3600 IN SOA ns.example.org. ' +\
  38. 'admin.example.org. 1235 3600 1800 2419200 7200\n'
  39. # This is the brandnew SOA for a newly created zone
  40. ALT_NEW_SOA_TXT = 'example.com. 3600 IN SOA ns.example.com. ' +\
  41. 'admin.example.com. 1234 3600 1800 2419200 7200\n'
  42. class TestLoadZoneRunner(unittest.TestCase):
  43. def setUp(self):
  44. shutil.copyfile(READ_ZONE_DB_FILE, WRITE_ZONE_DB_FILE)
  45. # default command line arguments
  46. self.__args = ['-c', DATASRC_CONFIG, 'example.org', 'example.zone']
  47. self.__runner = LoadZoneRunner(self.__args)
  48. def tearDown(self):
  49. # Delete the used DB file; if some of the tests unexpectedly fail
  50. # unexpectedly in the middle of updating the DB, a lock could stay
  51. # there and would affect the other tests that would otherwise succeed.
  52. os.unlink(WRITE_ZONE_DB_FILE)
  53. def test_init(self):
  54. '''
  55. Test the old socket file is removed (if any) and a new socket
  56. is created when the ddns server is created.
  57. '''
  58. self.assertIsNone(self.__runner._zone_class)
  59. self.assertIsNone(self.__runner._zone_name)
  60. def test_parse_args(self):
  61. self.__runner._parse_args()
  62. self.assertEqual(TEST_ZONE_NAME, self.__runner._zone_name)
  63. self.assertEqual('example.zone', self.__runner._zone_file)
  64. self.assertEqual(DATASRC_CONFIG, self.__runner._datasrc_config)
  65. self.assertEqual('sqlite3', self.__runner._datasrc_type) # default
  66. def test_parse_bad_args(self):
  67. # -c cannot be omitted (right now)
  68. self.assertRaises(BadArgument,
  69. LoadZoneRunner(['example', 'example.zone']).
  70. _parse_args)
  71. # There must be exactly 2 non-option arguments: zone name and zone file
  72. copt = ['-c', '0']
  73. self.assertRaises(BadArgument, LoadZoneRunner(copt)._parse_args)
  74. self.assertRaises(BadArgument, LoadZoneRunner(copt + ['example']).
  75. _parse_args)
  76. self.assertRaises(BadArgument, LoadZoneRunner(self.__args + ['0']).
  77. _parse_args)
  78. # Bad zone name
  79. self.assertRaises(BadArgument,
  80. LoadZoneRunner(copt + ['bad..name', 'example.zone']).
  81. _parse_args)
  82. def __common_load_setup(self):
  83. self.__runner._zone_class = RRClass.IN()
  84. self.__runner._zone_name = TEST_ZONE_NAME
  85. self.__runner._zone_file = NEW_ZONE_TXT_FILE
  86. self.__runner._datasrc_type = 'sqlite3'
  87. self.__runner._datasrc_config = DATASRC_CONFIG
  88. def __check_zone_soa(self, soa_txt, zone_name=TEST_ZONE_NAME):
  89. """Check that the given SOA RR exists and matches the expected string
  90. If soa_txt is None, the zone is expected to be non-existent.
  91. """
  92. client = DataSourceClient('sqlite3', DATASRC_CONFIG)
  93. result, finder = client.find_zone(zone_name)
  94. if soa_txt is None:
  95. self.assertEqual(client.NOTFOUND, result)
  96. return
  97. self.assertEqual(client.SUCCESS, result)
  98. result, rrset, _ = finder.find(zone_name, RRType.SOA())
  99. self.assertEqual(finder.SUCCESS, result)
  100. self.assertEqual(soa_txt, rrset.to_text())
  101. def test_load_update(self):
  102. '''successful case to loading new contents to an existing zone.'''
  103. self.__common_load_setup()
  104. self.__check_zone_soa(ORIG_SOA_TXT)
  105. self.__runner._do_load()
  106. self.__check_zone_soa(NEW_SOA_TXT)
  107. def test_create_and_load(self):
  108. '''successful case to loading contents to a new zone (created).'''
  109. self.__common_load_setup()
  110. self.__runner._zone_name = Name('example.com')
  111. self.__runner._zone_file = ALT_NEW_ZONE_TXT_FILE
  112. self.__check_zone_soa(None, zone_name=Name('example.com'))
  113. self.__runner._do_load()
  114. self.__check_zone_soa(ALT_NEW_SOA_TXT, zone_name=Name('example.com'))
  115. def test_load_fail_badconfig(self):
  116. '''Load attempt fails due to broken datasrc config.'''
  117. self.__common_load_setup()
  118. self.__runner._datasrc_config = "invalid config"
  119. self.__check_zone_soa(ORIG_SOA_TXT)
  120. self.assertRaises(LoadFailure, self.__runner._do_load)
  121. self.__check_zone_soa(ORIG_SOA_TXT) # no change to the zone
  122. def test_load_fail_badzone(self):
  123. '''Load attempt fails due to broken zone file.'''
  124. self.__common_load_setup()
  125. self.__runner._zone_file = \
  126. LOCAL_TESTDATA_PATH + '/broken-example.org.zone'
  127. self.__check_zone_soa(ORIG_SOA_TXT)
  128. self.assertRaises(LoadFailure, self.__runner._do_load)
  129. self.__check_zone_soa(ORIG_SOA_TXT)
  130. def test_load_fail_noloader(self):
  131. '''Load attempt fails because loading isn't supported'''
  132. self.__common_load_setup()
  133. self.__runner._datasrc_type = 'memory'
  134. self.__runner._datasrc_config = '{"type": "memory"}'
  135. self.__check_zone_soa(ORIG_SOA_TXT)
  136. self.assertRaises(LoadFailure, self.__runner._do_load)
  137. self.__check_zone_soa(ORIG_SOA_TXT)
  138. def test_load_fail_create_cancel(self):
  139. '''Load attempt fails and new creation of zone is canceled'''
  140. self.__common_load_setup()
  141. self.__runner._zone_name = Name('example.com')
  142. self.__runner._zone_file = 'no-such-file'
  143. self.__check_zone_soa(None, zone_name=Name('example.com'))
  144. self.assertRaises(LoadFailure, self.__runner._do_load)
  145. # _do_load() should have once created the zone but then canceled it.
  146. self.__check_zone_soa(None, zone_name=Name('example.com'))
  147. if __name__== "__main__":
  148. isc.log.resetUnitTestRootLogger()
  149. unittest.main()