1 # Copyright 2019 Exentrique Solutions Ltd
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
20 from assertpy import assert_that
21 from mock.mock import patch, call
23 from nipio.backend import DynamicBackend
26 class DynamicBackendTest(unittest.TestCase):
28 self.mock_sys_patcher = patch("nipio.backend.sys")
29 self.mock_sys = self.mock_sys_patcher.start()
31 self.mock_sys.stderr.write = sys.stderr.write
34 nipio.backend._is_debug = lambda: True
39 self.mock_sys_patcher.stop()
41 def test_backend_ends_response_to_ANY_request_if_ip_is_blacklisted(self):
42 self._send_commands(["Q", "subdomain.127.0.0.2.lcl.io", "IN", "ANY", "1", "127.0.0.1"])
46 self._assert_expected_responses(["LOG", "Blacklisted: 127.0.0.2"])
48 def test_backend_ends_response_to_A_request_if_ip_is_blacklisted(self):
49 self._send_commands(["Q", "subdomain.127.0.0.2.lcl.io", "IN", "A", "1", "127.0.0.1"])
53 self._assert_expected_responses(
54 ["LOG", "Blacklisted: 127.0.0.2"]
57 def test_backend_responds_to_ANY_request_with_valid_ip(self):
58 self._send_commands(["Q", "subdomain.127.0.0.1.lcl.io", "IN", "ANY", "1", "127.0.0.1"])
62 self._assert_expected_responses(
63 ["DATA", "subdomain.127.0.0.1.lcl.io", "IN", "A", "200", "22", "127.0.0.1"],
64 ["DATA", "subdomain.127.0.0.1.lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
65 ["DATA", "subdomain.127.0.0.1.lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
68 def test_backend_responds_to_A_request_with_valid_ip(self):
69 self._send_commands(["Q", "subdomain.127.0.0.1.lcl.io", "IN", "A", "1", "127.0.0.1"])
73 self._assert_expected_responses(
74 ["DATA", "subdomain.127.0.0.1.lcl.io", "IN", "A", "200", "22", "127.0.0.1"],
75 ["DATA", "subdomain.127.0.0.1.lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
76 ["DATA", "subdomain.127.0.0.1.lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
79 def test_backend_responds_to_invalid_ip_in_ANY_request_with_self_ip(self):
80 self._send_commands(["Q", "subdomain.127.0.1.lcl.io", "IN", "ANY", "1", "127.0.0.1"])
84 self._assert_expected_responses(
85 ["DATA", "subdomain.127.0.1.lcl.io", "IN", "A", "200", "22", "127.0.0.33"],
86 ["DATA", "subdomain.127.0.1.lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
87 ["DATA", "subdomain.127.0.1.lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
90 def test_backend_responds_to_invalid_ip_in_A_request_with_self(self):
91 self._send_commands(["Q", "subdomain.127.0.1.lcl.io", "IN", "A", "1", "127.0.0.1"])
95 self._assert_expected_responses(
96 ["DATA", "subdomain.127.0.1.lcl.io", "IN", "A", "200", "22", "127.0.0.33"],
97 ["DATA", "subdomain.127.0.1.lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
98 ["DATA", "subdomain.127.0.1.lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
101 def test_backend_responds_to_short_ip_in_ANY_request_with_self_ip(self):
102 self._send_commands(["Q", "127.0.1.lcl.io", "IN", "ANY", "1", "127.0.0.1"])
106 self._assert_expected_responses(
107 ["DATA", "127.0.1.lcl.io", "IN", "A", "200", "22", "127.0.0.33"],
108 ["DATA", "127.0.1.lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
109 ["DATA", "127.0.1.lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
112 def test_backend_responds_to_short_ip_in_A_request_with_self(self):
113 self._send_commands(["Q", "127.0.1.lcl.io", "IN", "A", "1", "127.0.0.1"])
117 self._assert_expected_responses(
118 ["DATA", "127.0.1.lcl.io", "IN", "A", "200", "22", "127.0.0.33"],
119 ["DATA", "127.0.1.lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
120 ["DATA", "127.0.1.lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
123 def test_backend_responds_to_large_ip_in_ANY_request_with_self(self):
124 self._send_commands(["Q", "subdomain.127.0.300.1.lcl.io", "IN", "ANY", "1", "127.0.0.1"])
128 self._assert_expected_responses(
129 ["DATA", "subdomain.127.0.300.1.lcl.io", "IN", "A", "200", "22", "127.0.0.33"],
130 ["DATA", "subdomain.127.0.300.1.lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
131 ["DATA", "subdomain.127.0.300.1.lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
134 def test_backend_responds_to_large_ip_in_A_request_with_self(self):
135 self._send_commands(["Q", "subdomain.127.0.300.1.lcl.io", "IN", "A", "1", "127.0.0.1"])
139 self._assert_expected_responses(
140 ["DATA", "subdomain.127.0.300.1.lcl.io", "IN", "A", "200", "22", "127.0.0.33"],
141 ["DATA", "subdomain.127.0.300.1.lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
142 ["DATA", "subdomain.127.0.300.1.lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
145 def test_backend_responds_to_string_in_ip_in_ANY_request_with_self(self):
146 self._send_commands(["Q", "subdomain.127.0.STRING.1.lcl.io", "IN", "ANY", "1", "127.0.0.1"])
150 self._assert_expected_responses(
151 ["DATA", "subdomain.127.0.string.1.lcl.io", "IN", "A", "200", "22", "127.0.0.33"],
152 ["DATA", "subdomain.127.0.string.1.lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
153 ["DATA", "subdomain.127.0.string.1.lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
156 def test_backend_responds_to_string_in_ip_in_A_request_with_self(self):
157 self._send_commands(["Q", "subdomain.127.0.STRING.1.lcl.io", "IN", "A", "1", "127.0.0.1"])
161 self._assert_expected_responses(
162 ["DATA", "subdomain.127.0.string.1.lcl.io", "IN", "A", "200", "22", "127.0.0.33"],
163 ["DATA", "subdomain.127.0.string.1.lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
164 ["DATA", "subdomain.127.0.string.1.lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
167 def test_backend_responds_to_no_ip_in_ANY_request_with_self(self):
168 self._send_commands(["Q", "subdomain.127.0.1.lcl.io", "IN", "ANY", "1", "127.0.0.1"])
172 self._assert_expected_responses(
173 ["DATA", "subdomain.127.0.1.lcl.io", "IN", "A", "200", "22", "127.0.0.33"],
174 ["DATA", "subdomain.127.0.1.lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
175 ["DATA", "subdomain.127.0.1.lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
178 def test_backend_responds_to_no_ip_in_A_request_with_self(self):
179 self._send_commands(["Q", "subdomain.127.0.1.lcl.io", "IN", "A", "1", "127.0.0.1"])
183 self._assert_expected_responses(
184 ["DATA", "subdomain.127.0.1.lcl.io", "IN", "A", "200", "22", "127.0.0.33"],
185 ["DATA", "subdomain.127.0.1.lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
186 ["DATA", "subdomain.127.0.1.lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
189 def test_backend_responds_to_self_domain_to_A_request(self):
190 self._send_commands(["Q", "lcl.io", "IN", "A", "1", "127.0.0.1"])
194 self._assert_expected_responses(
195 ["DATA", "lcl.io", "IN", "A", "200", "22", "127.0.0.33"],
196 ["DATA", "lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
197 ["DATA", "lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
200 def test_backend_responds_to_self_domain_to_ANY_request(self):
201 self._send_commands(["Q", "lcl.io", "IN", "ANY", "1", "127.0.0.1"])
205 self._assert_expected_responses(
206 ["DATA", "lcl.io", "IN", "A", "200", "22", "127.0.0.33"],
207 ["DATA", "lcl.io", "IN", "NS", "200", "22", "ns1.lcl.io"],
208 ["DATA", "lcl.io", "IN", "NS", "200", "22", "ns2.lcl.io"],
211 def test_backend_responds_to_name_servers_A_request_with_valid_ip(self):
212 self._send_commands(["Q", "ns1.lcl.io", "IN", "A", "1", "127.0.0.1"])
216 self._assert_expected_responses(
217 ["DATA", "ns1.lcl.io", "IN", "A", "200", "22", "127.0.0.34"],
220 def test_backend_responds_to_name_servers_ANY_request_with_valid_ip(self):
221 self._send_commands(["Q", "ns2.lcl.io", "IN", "ANY", "1", "127.0.0.1"])
225 self._assert_expected_responses(
226 ["DATA", "ns2.lcl.io", "IN", "A", "200", "22", "127.0.0.35"],
229 def test_backend_responds_to_SOA_request_for_self(self):
230 self._send_commands(["Q", "lcl.io", "IN", "SOA", "1", "127.0.0.1"])
234 self._assert_expected_responses(
235 ["DATA", "lcl.io", "IN", "SOA", "200", "22", "MY_SOA"]
238 def test_backend_responds_to_SOA_request_for_valid_ip(self):
239 self._send_commands(["Q", "subdomain.127.0.0.1.lcl.io", "IN", "SOA", "1", "127.0.0.1"])
243 self._assert_expected_responses(
244 ["DATA", "subdomain.127.0.0.1.lcl.io", "IN", "SOA", "200", "22", "MY_SOA"]
247 def test_backend_responds_to_SOA_request_for_invalid_ip(self):
248 self._send_commands(["Q", "subdomain.127.0.1.lcl.io", "IN", "SOA", "1", "127.0.0.1"])
252 self._assert_expected_responses(
253 ["DATA", "subdomain.127.0.1.lcl.io", "IN", "SOA", "200", "22", "MY_SOA"]
256 def test_backend_responds_to_SOA_request_for_no_ip(self):
257 self._send_commands(["Q", "subdomain.lcl.io", "IN", "SOA", "1", "127.0.0.1"])
261 self._assert_expected_responses(
262 ["DATA", "subdomain.lcl.io", "IN", "SOA", "200", "22", "MY_SOA"]
265 def test_backend_responds_to_SOA_request_for_nameserver(self):
266 self._send_commands(["Q", "ns1.lcl.io", "IN", "SOA", "1", "127.0.0.1"])
270 self._assert_expected_responses(
271 ["DATA", "ns1.lcl.io", "IN", "SOA", "200", "22", "MY_SOA"]
274 def test_backend_responds_to_A_request_for_unknown_domain_with_invalid_response(self):
275 self._send_commands(["Q", "unknown.domain", "IN", "A", "1", "127.0.0.1"])
279 self._assert_expected_responses(
280 ["LOG", "Unknown type: A, domain: unknown.domain"]
283 def test_backend_responds_to_invalid_request_with_invalid_response(self):
284 self._send_commands(["Q", "lcl.io", "IN", "INVALID", "1", "127.0.0.1"])
288 self._assert_expected_responses(
289 ["LOG", "Unknown type: INVALID, domain: lcl.io"]
292 def test_backend_responds_to_invalid_command_with_fail(self):
293 self._send_commands(["INVALID", "COMMAND"])
307 self.mock_sys.stdout.write.assert_has_calls(calls)
308 assert_that(self.mock_sys.stdout.write.call_count).is_equal_to(len(calls))
310 assert_that(self.mock_sys.stdout.flush.call_count).is_equal_to(2)
312 def test_configure_with_full_config(self):
313 backend = self._configure_backend()
315 assert_that(backend.id).is_equal_to("55")
316 assert_that(backend.ip_address).is_equal_to("127.0.0.40")
317 assert_that(backend.domain).is_equal_to("lcl.io")
318 assert_that(backend.ttl).is_equal_to("1000")
319 assert_that(backend.name_servers).is_equal_to({"ns1.lcl.io": "127.0.0.41", "ns2.lcl.io" : "127.0.0.42"})
320 assert_that(backend.blacklisted_ips).is_equal_to(["10.0.0.100"])
321 assert_that(backend.soa).is_equal_to("ns1.lcl.io emailaddress@lcl.io 55")
323 def test_configure_with_config_missing_blacklists(self):
324 backend = self._configure_backend(filename="backend_test_no_blacklist.conf")
326 assert_that(backend.blacklisted_ips).is_empty()
328 def _run_backend(self):
329 backend = self._create_backend()
332 def _send_commands(self, *commands):
333 commands_to_send = ["HELO\t1\n"]
335 for command in commands:
336 commands_to_send.append("\t".join(command) + "\n")
338 commands_to_send.append("END\n")
340 self.mock_sys.stdin.readline.side_effect = commands_to_send
342 def _assert_expected_responses(self, *responses):
350 for response in responses:
351 tab_separated = ["\t"] * (len(response) * 2 - 1)
352 tab_separated[0::2] = response
353 tab_separated.append("\n")
355 calls.extend([call(response_item) for response_item in tab_separated])
362 self.mock_sys.stdout.write.assert_has_calls(calls)
363 assert_that(self.mock_sys.stdout.write.call_count).is_equal_to(len(calls))
365 assert_that(self.mock_sys.stdout.flush.call_count).is_equal_to(len(responses) + 2)
368 def _create_backend():
369 backend = DynamicBackend()
371 backend.soa = "MY_SOA"
372 backend.ip_address = "127.0.0.33"
374 backend.name_servers = collections.OrderedDict([
375 ("ns1.lcl.io", "127.0.0.34"),
376 ("ns2.lcl.io", "127.0.0.35"),
378 backend.domain = "lcl.io"
379 backend.blacklisted_ips = ["127.0.0.2"]
382 def _configure_backend(self, filename="backend_test.conf"):
383 backend = DynamicBackend()
384 backend._get_config_filename = lambda: self._get_test_config_filename(filename)
388 def _get_test_config_filename(self, filename):
389 return os.path.join(os.path.dirname(os.path.realpath(__file__)), filename)