173 )), |
173 )), |
174 ]) |
174 ]) |
175 |
175 |
176 class TestZoneMixin(object): |
176 class TestZoneMixin(object): |
177 def assertZoneEquals(self, rrs, expected): |
177 def assertZoneEquals(self, rrs, expected): |
|
178 """ |
|
179 Tests that the given list of ZoneRecords is equal to the given {(rr.name, rr.type): str(rr.data)} dict. |
|
180 |
|
181 Multiple records for the same name/type are gathered as a list. XXX: ordering |
|
182 """ |
|
183 |
178 gather = { } |
184 gather = { } |
179 |
185 |
180 for rr in rrs: |
186 for rr in rrs: |
181 key = (rr.name.lower(), rr.type.upper()) |
187 key = (rr.name.lower(), rr.type.upper()) |
182 |
188 value = '\t'.join(rr.data) |
183 self.assertNotIn(key, gather) |
189 |
184 |
190 if key not in gather: |
185 gather[key] = rr.data |
191 gather[key] = value |
|
192 elif not isinstance(gather[key], list): |
|
193 gather[key] = [gather[key], value] |
|
194 else: |
|
195 gather[key].append(value) |
186 |
196 |
187 self.assertDictEqual(gather, expected) |
197 self.assertDictEqual(gather, expected) |
188 |
198 |
189 |
199 |
190 class TestForwardZone(TestZoneMixin, unittest.TestCase): |
200 class TestForwardZone(TestZoneMixin, unittest.TestCase): |
200 ip = '192.0.2.1', |
210 ip = '192.0.2.1', |
201 ip6 = '2001:db8::192.0.2.1', |
211 ip6 = '2001:db8::192.0.2.1', |
202 ) |
212 ) |
203 |
213 |
204 self.assertZoneEquals(zone.host_forward(h, 'domain'), { |
214 self.assertZoneEquals(zone.host_forward(h, 'domain'), { |
205 ('host', 'A'): ['192.0.2.1'], |
215 ('host', 'A'): '192.0.2.1', |
206 ('host', 'AAAA'): ['2001:db8::c000:201'], |
216 ('host', 'AAAA'): '2001:db8::c000:201', |
207 }) |
217 }) |
208 |
218 |
209 def testHostAlias(self): |
219 def testHostAlias(self): |
210 h = Host.build('host', 'domain', |
220 h = Host.build('host', 'domain', |
211 ip = '192.0.2.1', |
221 ip = '192.0.2.1', |
213 ) |
223 ) |
214 |
224 |
215 self.assertEquals(h.alias, ['test', '*.test']) |
225 self.assertEquals(h.alias, ['test', '*.test']) |
216 |
226 |
217 self.assertZoneEquals(zone.host_forward(h, 'domain'), { |
227 self.assertZoneEquals(zone.host_forward(h, 'domain'), { |
218 ('host', 'A'): ['192.0.2.1'], |
228 ('host', 'A'): '192.0.2.1', |
219 ('test', 'CNAME'): ['host'], |
229 ('test', 'CNAME'): 'host', |
220 ('*.test', 'CNAME'): ['host'], |
230 ('*.test', 'CNAME'): 'host', |
221 }) |
231 }) |
222 |
232 |
223 def testHostAlias46(self): |
233 def testHostAlias46(self): |
224 h = Host.build('host', 'domain', |
234 h = Host.build('host', 'domain', |
225 ip = '192.0.2.1', |
235 ip = '192.0.2.1', |
227 alias4 = 'test4', |
237 alias4 = 'test4', |
228 alias6 = 'test6', |
238 alias6 = 'test6', |
229 ) |
239 ) |
230 |
240 |
231 self.assertZoneEquals(zone.host_forward(h, 'domain'), { |
241 self.assertZoneEquals(zone.host_forward(h, 'domain'), { |
232 ('host', 'A'): ['192.0.2.1'], |
242 ('host', 'A'): '192.0.2.1', |
233 ('host', 'AAAA'): ['2001:db8::c000:201'], |
243 ('host', 'AAAA'): '2001:db8::c000:201', |
234 ('test4', 'A'): ['192.0.2.1'], |
244 ('test4', 'A'): '192.0.2.1', |
235 ('test6', 'AAAA'): ['2001:db8::c000:201'], |
245 ('test6', 'AAAA'): '2001:db8::c000:201', |
236 }) |
246 }) |
237 |
247 |
238 def testHostAlias4Missing(self): |
248 def testHostAlias4Missing(self): |
239 h = Host.build('host', 'domain', |
249 h = Host.build('host', 'domain', |
240 ip6 = '2001:db8::192.0.2.1', |
250 ip6 = '2001:db8::192.0.2.1', |
268 h = Host.build('host', 'example.com', |
278 h = Host.build('host', 'example.com', |
269 forward = 'host.example.net', |
279 forward = 'host.example.net', |
270 ) |
280 ) |
271 |
281 |
272 self.assertZoneEquals(zone.host_forward(h, 'example.com'), { |
282 self.assertZoneEquals(zone.host_forward(h, 'example.com'), { |
273 ('host', 'CNAME'): ['host.example.net.'], |
283 ('host', 'CNAME'): 'host.example.net.', |
274 }) |
284 }) |
275 |
285 |
276 def testHostForwardAlias(self): |
286 def testHostForwardAlias(self): |
277 h = Host.build('host', 'domain', |
287 h = Host.build('host', 'domain', |
278 forward = 'host.example.net', |
288 forward = 'host.example.net', |
279 alias = 'test', |
289 alias = 'test', |
280 ) |
290 ) |
281 |
291 |
282 self.assertZoneEquals(zone.host_forward(h, 'domain'), { |
292 self.assertZoneEquals(zone.host_forward(h, 'domain'), { |
283 ('host', 'CNAME'): ['host.example.net.'], |
293 ('host', 'CNAME'): 'host.example.net.', |
284 ('test', 'CNAME'): ['host'], |
294 ('test', 'CNAME'): 'host', |
285 }) |
295 }) |
286 |
296 |
287 def testHostLocation(self): |
297 def testHostLocation(self): |
288 h = Host.build('host', 'domain', |
298 h = Host.build('host', 'domain', |
289 ip = '192.0.2.1', |
299 ip = '192.0.2.1', |
291 ) |
301 ) |
292 |
302 |
293 self.assertEquals(h.location, ('test', 'domain')) |
303 self.assertEquals(h.location, ('test', 'domain')) |
294 |
304 |
295 self.assertZoneEquals(zone.host_forward(h, 'domain'), { |
305 self.assertZoneEquals(zone.host_forward(h, 'domain'), { |
296 ('host', 'A'): ['192.0.2.1'], |
306 ('host', 'A'): '192.0.2.1', |
297 ('test', 'CNAME'): ['host'], |
307 ('test', 'CNAME'): 'host', |
298 }) |
308 }) |
299 |
309 |
300 def testHostLocationDomain(self): |
310 def testHostLocationDomain(self): |
301 h = Host.build('host', 'foo.domain', |
311 h = Host.build('host', 'foo.domain', |
302 ip = '192.0.2.1', |
312 ip = '192.0.2.1', |
304 ) |
314 ) |
305 |
315 |
306 self.assertEquals(h.location, ('test', 'bar.domain')) |
316 self.assertEquals(h.location, ('test', 'bar.domain')) |
307 |
317 |
308 self.assertZoneEquals(zone.host_forward(h, 'domain'), { |
318 self.assertZoneEquals(zone.host_forward(h, 'domain'), { |
309 ('host.foo', 'A'): ['192.0.2.1'], |
319 ('host.foo', 'A'): '192.0.2.1', |
310 ('test.bar', 'CNAME'): ['host.foo'], |
320 ('test.bar', 'CNAME'): 'host.foo', |
311 }) |
321 }) |
312 |
322 |
313 def testHostLocationDomainOutOfOrigin(self): |
323 def testHostLocationDomainOutOfOrigin(self): |
314 h = Host.build('host', 'foo.domain', |
324 h = Host.build('host', 'foo.domain', |
315 ip = '192.0.2.1', |
325 ip = '192.0.2.1', |
318 |
328 |
319 self.assertEquals(h.location, ('test', 'bar.domain')) |
329 self.assertEquals(h.location, ('test', 'bar.domain')) |
320 |
330 |
321 with self.assertRaises(zone.HostZoneError): |
331 with self.assertRaises(zone.HostZoneError): |
322 self.assertZoneEquals(zone.host_forward(h, 'foo.domain'), { |
332 self.assertZoneEquals(zone.host_forward(h, 'foo.domain'), { |
323 ('host', 'A'): ['192.0.2.1'], |
333 ('host', 'A'): '192.0.2.1', |
324 }) |
334 }) |
325 |
335 |
326 # TODO |
336 # TODO |
327 #self.assertZoneEquals(zone.host_forward(h, 'bar.domain'), { |
337 #self.assertZoneEquals(zone.host_forward(h, 'bar.domain'), { |
328 # ('test', 'CNAME'): ['host.foo'], |
338 # ('test', 'CNAME'): ['host.foo'], |
349 rd = next(rrs) |
359 rd = next(rrs) |
350 |
360 |
351 self.assertEquals(unicode(rd), '$ORIGIN\tdomain.') |
361 self.assertEquals(unicode(rd), '$ORIGIN\tdomain.') |
352 |
362 |
353 self.assertZoneEquals(rrs, { |
363 self.assertZoneEquals(rrs, { |
354 ('foo', 'A'): ['192.0.2.1'], |
364 ('foo', 'A'): '192.0.2.1', |
355 ('foo', 'AAAA'): ['2001:db8::c000:201'], |
365 ('foo', 'AAAA'): '2001:db8::c000:201', |
356 ('test', 'CNAME'): ['foo'], |
366 ('test', 'CNAME'): 'foo', |
357 ('bar', 'A'): ['192.0.2.2'], |
367 ('bar', 'A'): '192.0.2.2', |
|
368 }) |
|
369 |
|
370 def testHostsMultiAlias(self): |
|
371 hosts = [ |
|
372 Host.build('foo', 'domain', |
|
373 ip = '192.0.2.1', |
|
374 alias4 = 'test', |
|
375 ), |
|
376 Host.build('bar', 'domain', |
|
377 ip = '192.0.2.2', |
|
378 alias4 = 'test', |
|
379 ) |
|
380 ] |
|
381 |
|
382 self.assertZoneEquals(zone.apply_hosts_forward(hosts, 'domain', check_conflicts=False), { |
|
383 ('foo', 'A'): '192.0.2.1', |
|
384 ('bar', 'A'): '192.0.2.2', |
|
385 ('test', 'A'): ['192.0.2.1', '192.0.2.2'], |
358 }) |
386 }) |
359 |
387 |
360 def testHostsConflict(self): |
388 def testHostsConflict(self): |
361 hosts = [ |
389 hosts = [ |
362 Host.build('foo', 'domain', |
390 Host.build('foo', 'domain', |
410 ip = '192.0.2.1', |
438 ip = '192.0.2.1', |
411 ip6 = '2001:db8::192.0.2.1', |
439 ip6 = '2001:db8::192.0.2.1', |
412 ) |
440 ) |
413 |
441 |
414 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.2.1/24'))), { |
442 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.2.1/24'))), { |
415 ('1', 'PTR'): ['host.domain.'], |
443 ('1', 'PTR'): 'host.domain.', |
416 }) |
444 }) |
417 |
445 |
418 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('2001:db8::/64'))), { |
446 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('2001:db8::/64'))), { |
419 ('1.0.2.0.0.0.0.c.0.0.0.0.0.0.0.0', 'PTR'): ['host.domain.'], |
447 ('1.0.2.0.0.0.0.c.0.0.0.0.0.0.0.0', 'PTR'): 'host.domain.', |
420 }) |
448 }) |
421 |
449 |
422 def testHostIP4(self): |
450 def testHostIP4(self): |
423 h = Host.build('host', 'domain', |
451 h = Host.build('host', 'domain', |
424 ip = '192.0.2.1', |
452 ip = '192.0.2.1', |
425 ) |
453 ) |
426 |
454 |
427 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.2.1/24'))), { |
455 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.2.1/24'))), { |
428 ('1', 'PTR'): ['host.domain.'], |
456 ('1', 'PTR'): 'host.domain.', |
429 }) |
457 }) |
430 |
458 |
431 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.0.0/16'))), { |
459 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.0.0/16'))), { |
432 ('1.2', 'PTR'): ['host.domain.'], |
460 ('1.2', 'PTR'): 'host.domain.', |
433 }) |
461 }) |
434 |
462 |
435 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.0.0/12'))), { |
463 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.0.0/12'))), { |
436 ('1.2.0', 'PTR'): ['host.domain.'], |
464 ('1.2.0', 'PTR'): 'host.domain.', |
437 }) |
465 }) |
438 |
466 |
439 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('2001:db8::/64'))), { |
467 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('2001:db8::/64'))), { |
440 |
468 |
441 }) |
469 }) |
447 |
475 |
448 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.2.1/24'))), { |
476 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.2.1/24'))), { |
449 }) |
477 }) |
450 |
478 |
451 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('2001:db8::/64'))), { |
479 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('2001:db8::/64'))), { |
452 ('1.0.2.0.0.0.0.c.0.0.0.0.0.0.0.0', 'PTR'): ['host.domain.'], |
480 ('1.0.2.0.0.0.0.c.0.0.0.0.0.0.0.0', 'PTR'): 'host.domain.', |
453 }) |
481 }) |
454 |
482 |
455 def testHostIPOutOfPrefix(self): |
483 def testHostIPOutOfPrefix(self): |
456 h = Host.build('host', 'domain', |
484 h = Host.build('host', 'domain', |
457 ip = '192.0.2.1', |
485 ip = '192.0.2.1', |
471 ip = '192.0.2.3', |
499 ip = '192.0.2.3', |
472 ip6 = '2001:db8::192.0.2.3', |
500 ip6 = '2001:db8::192.0.2.3', |
473 ) |
501 ) |
474 |
502 |
475 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.2.1/24'))), { |
503 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.2.1/24'))), { |
476 ('3', 'PTR'): ['host.example.net.'], |
504 ('3', 'PTR'): 'host.example.net.', |
477 |
505 |
478 }) |
506 }) |
479 |
507 |
480 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('2001:db8::/64'))), { |
508 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('2001:db8::/64'))), { |
481 ('3.0.2.0.0.0.0.c.0.0.0.0.0.0.0.0', 'PTR'): ['host.example.net.'], |
509 ('3.0.2.0.0.0.0.c.0.0.0.0.0.0.0.0', 'PTR'): 'host.example.net.', |
482 }) |
510 }) |
483 |
511 |
484 def testHostDelegate(self): |
512 def testHostDelegate(self): |
485 h = Host.build('host', 'example.com', |
513 h = Host.build('host', 'example.com', |
486 ip = '192.0.2.1', |
514 ip = '192.0.2.1', |
492 self.assertZoneEquals(zone.host_forward(h, 'example.com'), { |
520 self.assertZoneEquals(zone.host_forward(h, 'example.com'), { |
493 |
521 |
494 }) |
522 }) |
495 |
523 |
496 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.2.1/24'))), { |
524 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('192.0.2.1/24'))), { |
497 ('1', 'CNAME'): ['1.0/28.2.0.192.in-addr.arpa.'], |
525 ('1', 'CNAME'): '1.0/28.2.0.192.in-addr.arpa.', |
498 }) |
526 }) |
499 |
527 |
500 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('2001:db8::/64'))), { |
528 self.assertZoneEquals((rr for ip, rr in zone.host_reverse(h, ipaddr.IPNetwork('2001:db8::/64'))), { |
501 |
529 |
502 }) |
530 }) |
510 ip = '192.0.2.2', |
538 ip = '192.0.2.2', |
511 ) |
539 ) |
512 ] |
540 ] |
513 |
541 |
514 self.assertZoneEquals(zone.apply_hosts_reverse(hosts, ipaddr.IPNetwork('192.0.2.1/24')), { |
542 self.assertZoneEquals(zone.apply_hosts_reverse(hosts, ipaddr.IPNetwork('192.0.2.1/24')), { |
515 ('1', 'PTR'): ['foo.domain.'], |
543 ('1', 'PTR'): 'foo.domain.', |
516 ('2', 'PTR'): ['bar.domain.'], |
544 ('2', 'PTR'): 'bar.domain.', |
517 }) |
545 }) |
518 |
546 |
519 # in ip order |
547 # in ip order |
520 self.assertZoneEquals(zone.apply_hosts_reverse(reversed(hosts), ipaddr.IPNetwork('192.0.2.1/24')), { |
548 self.assertZoneEquals(zone.apply_hosts_reverse(reversed(hosts), ipaddr.IPNetwork('192.0.2.1/24')), { |
521 ('1', 'PTR'): ['foo.domain.'], |
549 ('1', 'PTR'): 'foo.domain.', |
522 ('2', 'PTR'): ['bar.domain.'], |
550 ('2', 'PTR'): 'bar.domain.', |
523 }) |
551 }) |
524 |
552 |
525 def testHostsConflict(self): |
553 def testHostsConflict(self): |
526 hosts = [ |
554 hosts = [ |
527 Host.build('foo', 'domain', |
555 Host.build('foo', 'domain', |
547 |
575 |
548 self.assertZoneEquals(zone.apply_hosts_reverse(hosts, ipaddr.IPNetwork('192.0.2.1/29'), |
576 self.assertZoneEquals(zone.apply_hosts_reverse(hosts, ipaddr.IPNetwork('192.0.2.1/29'), |
549 unknown_host = 'ufc', |
577 unknown_host = 'ufc', |
550 unknown_domain = 'domain', |
578 unknown_domain = 'domain', |
551 ), { |
579 ), { |
552 ('1', 'PTR'): ['foo.domain.'], |
580 ('1', 'PTR'): 'foo.domain.', |
553 ('2', 'PTR'): ['ufc.domain.'], |
581 ('2', 'PTR'): 'ufc.domain.', |
554 ('3', 'PTR'): ['ufc.domain.'], |
582 ('3', 'PTR'): 'ufc.domain.', |
555 ('4', 'PTR'): ['ufc.domain.'], |
583 ('4', 'PTR'): 'ufc.domain.', |
556 ('5', 'PTR'): ['bar.domain.'], |
584 ('5', 'PTR'): 'bar.domain.', |
557 ('6', 'PTR'): ['ufc.domain.'], |
585 ('6', 'PTR'): 'ufc.domain.', |
558 }) |
586 }) |
559 |
587 |
560 class TestDhcp(unittest.TestCase): |
588 class TestDhcp(unittest.TestCase): |
561 def assertBlockEqual(self, block, (key, items, blocks)): |
589 def assertBlockEqual(self, block, (key, items, blocks)): |
562 self.assertEqual(block.key, key) |
590 self.assertEqual(block.key, key) |