# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose with or without fee is hereby granted, # provided that the above copyright notice and this permission notice # appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. import sys sys.path.insert(0, "../") # Force the local project to be *the* dns import unittest import dns.exception import dns.rdata import dns.rdataclass import dns.rdatatype import dns.rrset import dns.zone example_text = """$TTL 1h $ORIGIN 0.0.192.IN-ADDR.ARPA. $GENERATE 1-2 0 CNAME SERVER$.EXAMPLE. """ example_text1 = """$TTL 1h $ORIGIN 0.0.192.IN-ADDR.ARPA. $GENERATE 1-10 fooo$ CNAME $.0 """ example_text2 = """$TTL 1h @ 3600 IN SOA foo bar 1 2 3 4 5 @ 3600 IN NS ns1 @ 3600 IN NS ns2 bar.foo 300 IN MX 0 blaz.foo ns1 3600 IN A 10.0.0.1 ns2 3600 IN A 10.0.0.2 $GENERATE 3-5 foo$ A 10.0.0.$ """ example_text3 = """$TTL 1h @ 3600 IN SOA foo bar 1 2 3 4 5 @ 3600 IN NS ns1 @ 3600 IN NS ns2 bar.foo 300 IN MX 0 blaz.foo ns1 3600 IN A 10.0.0.1 ns2 3600 IN A 10.0.0.2 $GENERATE 4-8/2 foo$ A 10.0.0.$ """ example_text4 = """$TTL 1h @ 3600 IN SOA foo bar 1 2 3 4 5 @ 3600 IN NS ns1 @ 3600 IN NS ns2 bar.foo 300 IN MX 0 blaz.foo ns1 3600 IN A 10.0.0.1 ns2 3600 IN A 10.0.0.2 $GENERATE 11-13 wp-db${-10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR. """ example_text5 = """$TTL 1h @ 3600 IN SOA foo bar 1 2 3 4 5 @ 3600 IN NS ns1 @ 3600 IN NS ns2 bar.foo 300 IN MX 0 blaz.foo ns1 3600 IN A 10.0.0.1 ns2 3600 IN A 10.0.0.2 $GENERATE 11-13 wp-db${10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR. """ example_text6 = """$TTL 1h @ 3600 IN SOA foo bar 1 2 3 4 5 @ 3600 IN NS ns1 @ 3600 IN NS ns2 bar.foo 300 IN MX 0 blaz.foo ns1 3600 IN A 10.0.0.1 ns2 3600 IN A 10.0.0.2 $GENERATE 11-13 wp-db${+10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR. """ example_text7 = """$TTL 1h @ 3600 IN SOA foo bar 1 2 3 4 5 @ 3600 IN NS ns1 @ 3600 IN NS ns2 bar.foo 300 IN MX 0 blaz.foo ns1 3600 IN A 10.0.0.1 ns2 3600 IN A 10.0.0.2 $GENERATE 11-13 sync${-10}.db IN A 10.10.16.0 """ example_text8 = """$TTL 1h @ 3600 IN SOA foo bar 1 2 3 4 5 @ 3600 IN NS ns1 @ 3600 IN NS ns2 bar.foo 300 IN MX 0 blaz.foo ns1 3600 IN A 10.0.0.1 ns2 3600 IN A 10.0.0.2 $GENERATE 11-12 wp-db${-10,2,d} IN A 10.10.16.0 """ example_text9 = """$TTL 1h @ 3600 IN SOA foo bar 1 2 3 4 5 @ 3600 IN NS ns1 @ 3600 IN NS ns2 bar.foo 300 IN MX 0 blaz.foo ns1 3600 IN A 10.0.0.1 ns2 3600 IN A 10.0.0.2 $GENERATE 11-12 wp-db${-10,2,d} IN A 10.10.16.0 $GENERATE 11-13 sync${-10}.db IN A 10.10.16.0 """ example_text10 = """$TTL 1h @ 3600 IN SOA foo bar 1 2 3 4 5 @ 3600 IN NS ns1 @ 3600 IN NS ns2 bar.foo 300 IN MX 0 blaz.foo ns1 3600 IN A 10.0.0.1 ns2 3600 IN A 10.0.0.2 $GENERATE 27-28 $.2 PTR zlb${-26}.oob """ example_text11 = """$TTL 1h @ 3600 IN SOA foo bar 1 2 3 4 5 @ 3600 IN NS ns1 @ 3600 IN NS ns2 bar.foo 300 IN MX 0 blaz.foo ns1 3600 IN A 10.0.0.1 ns2 3600 IN A 10.0.0.2 $GENERATE 27-28 prefix-${0,3} A 10.0.0.$ """ last_ttl_input = """foo 300 mx 10 target. $GENERATE 1-10 foo$ CNAME $.0 @ 3600 IN SOA foo bar 1 2 3 4 5 @ 3600 IN NS ns1 @ 3600 IN NS ns2 """ def _rdata_sort(a): return (a[0], a[2].rdclass, a[2].to_text()) class GenerateTestCase(unittest.TestCase): def testFromText(self): # type: () -> None def bad(): # type: () -> None dns.zone.from_text(example_text, "example.", relativize=True) self.assertRaises(dns.zone.NoSOA, bad) def testFromText1(self): # type: () -> None def bad(): # type: () -> None dns.zone.from_text(example_text1, "example.", relativize=True) self.assertRaises(dns.zone.NoSOA, bad) def testIterateAllRdatas2(self): # type: () -> None z = dns.zone.from_text(example_text2, "example.", relativize=True) l = list(z.iterate_rdatas()) l.sort(key=_rdata_sort) exl = [ ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.SOA, "foo bar 1 2 3 4 5" ), ), ( dns.name.from_text("bar.foo", None), 300, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"), ), ( dns.name.from_text("ns1", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"), ), ( dns.name.from_text("ns2", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"), ), ( dns.name.from_text("foo3", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.3"), ), ( dns.name.from_text("foo4", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.4"), ), ( dns.name.from_text("foo5", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.5"), ), ] exl.sort(key=_rdata_sort) self.assertEqual(l, exl) def testIterateAllRdatas3(self): # type: () -> None z = dns.zone.from_text(example_text3, "example.", relativize=True) l = list(z.iterate_rdatas()) l.sort(key=_rdata_sort) exl = [ ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.SOA, "foo bar 1 2 3 4 5" ), ), ( dns.name.from_text("bar.foo", None), 300, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"), ), ( dns.name.from_text("ns1", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"), ), ( dns.name.from_text("ns2", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"), ), ( dns.name.from_text("foo4", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.4"), ), ( dns.name.from_text("foo6", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.6"), ), ( dns.name.from_text("foo8", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.8"), ), ] exl.sort(key=_rdata_sort) self.assertEqual(l, exl) def testGenerate1(self): # type: () -> None z = dns.zone.from_text(example_text4, "example.", relativize=True) l = list(z.iterate_rdatas()) l.sort(key=_rdata_sort) exl = [ ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.SOA, "foo bar 1 2 3 4 5" ), ), ( dns.name.from_text("bar.foo", None), 300, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"), ), ( dns.name.from_text("ns1", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"), ), ( dns.name.from_text("ns2", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"), ), ( dns.name.from_text("wp-db01.services.mozilla.com", None), 0, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR." ), ), ( dns.name.from_text("wp-db02.services.mozilla.com", None), 0, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR." ), ), ( dns.name.from_text("wp-db03.services.mozilla.com", None), 0, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR." ), ), ] exl.sort(key=_rdata_sort) self.assertEqual(l, exl) def testGenerate2(self): # type: () -> None z = dns.zone.from_text(example_text5, "example.", relativize=True) l = list(z.iterate_rdatas()) l.sort(key=_rdata_sort) exl = [ ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.SOA, "foo bar 1 2 3 4 5" ), ), ( dns.name.from_text("bar.foo", None), 300, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"), ), ( dns.name.from_text("ns1", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"), ), ( dns.name.from_text("ns2", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"), ), ( dns.name.from_text("wp-db21.services.mozilla.com", None), 0, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR." ), ), ( dns.name.from_text("wp-db22.services.mozilla.com", None), 0, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR." ), ), ( dns.name.from_text("wp-db23.services.mozilla.com", None), 0, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR." ), ), ] exl.sort(key=_rdata_sort) self.assertEqual(l, exl) def testGenerate3(self): # type: () -> None z = dns.zone.from_text(example_text6, "example.", relativize=True) l = list(z.iterate_rdatas()) l.sort(key=_rdata_sort) exl = [ ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.SOA, "foo bar 1 2 3 4 5" ), ), ( dns.name.from_text("bar.foo", None), 300, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"), ), ( dns.name.from_text("ns1", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"), ), ( dns.name.from_text("ns2", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"), ), ( dns.name.from_text("wp-db21.services.mozilla.com", None), 0, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR." ), ), ( dns.name.from_text("wp-db22.services.mozilla.com", None), 0, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR." ), ), ( dns.name.from_text("wp-db23.services.mozilla.com", None), 0, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.CNAME, "SERVER.FOOBAR." ), ), ] exl.sort(key=_rdata_sort) self.assertEqual(l, exl) def testGenerate4(self): # type: () -> None z = dns.zone.from_text(example_text7, "example.", relativize=True) l = list(z.iterate_rdatas()) l.sort(key=_rdata_sort) exl = [ ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.SOA, "foo bar 1 2 3 4 5" ), ), ( dns.name.from_text("bar.foo", None), 300, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"), ), ( dns.name.from_text("ns1", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"), ), ( dns.name.from_text("ns2", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"), ), ( dns.name.from_text("sync1.db", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"), ), ( dns.name.from_text("sync2.db", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"), ), ( dns.name.from_text("sync3.db", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"), ), ] exl.sort(key=_rdata_sort) self.assertEqual(l, exl) def testGenerate6(self): # type: () -> None z = dns.zone.from_text(example_text9, "example.", relativize=True) l = list(z.iterate_rdatas()) l.sort(key=_rdata_sort) exl = [ ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.SOA, "foo bar 1 2 3 4 5" ), ), ( dns.name.from_text("bar.foo", None), 300, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"), ), ( dns.name.from_text("ns1", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"), ), ( dns.name.from_text("ns2", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"), ), ( dns.name.from_text("wp-db01", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"), ), ( dns.name.from_text("wp-db02", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"), ), ( dns.name.from_text("sync1.db", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"), ), ( dns.name.from_text("sync2.db", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"), ), ( dns.name.from_text("sync3.db", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.10.16.0"), ), ] exl.sort(key=_rdata_sort) self.assertEqual(l, exl) def testGenerate7(self): # type: () -> None z = dns.zone.from_text(example_text10, "example.", relativize=True) l = list(z.iterate_rdatas()) l.sort(key=_rdata_sort) exl = [ ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.SOA, "foo bar 1 2 3 4 5" ), ), ( dns.name.from_text("bar.foo", None), 300, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"), ), ( dns.name.from_text("ns1", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"), ), ( dns.name.from_text("ns2", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"), ), ( dns.name.from_text("27.2", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR, "zlb1.oob"), ), ( dns.name.from_text("28.2", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR, "zlb2.oob"), ), ] exl.sort(key=_rdata_sort) self.assertEqual(l, exl) def testGenerate8(self): # type: () -> None z = dns.zone.from_text(example_text11, "example.", relativize=True) l = list(z.iterate_rdatas()) l.sort(key=_rdata_sort) exl = [ ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns1"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, "ns2"), ), ( dns.name.from_text("@", None), 3600, dns.rdata.from_text( dns.rdataclass.IN, dns.rdatatype.SOA, "foo bar 1 2 3 4 5" ), ), ( dns.name.from_text("bar.foo", None), 300, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, "0 blaz.foo"), ), ( dns.name.from_text("prefix-027", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.27"), ), ( dns.name.from_text("prefix-028", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.28"), ), ( dns.name.from_text("ns1", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.1"), ), ( dns.name.from_text("ns2", None), 3600, dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, "10.0.0.2"), ), ] exl.sort(key=_rdata_sort) self.assertEqual(l, exl) def testNoOrigin(self): def bad(): dns.zone.from_text("$GENERATE 1-10 fooo$ CNAME $.0") self.assertRaises(dns.zone.UnknownOrigin, bad) def testBadRdata(self): def bad(): dns.zone.from_text("$GENERATE 1-10 fooo$ CNAME 10 $.0", "example") self.assertRaises(dns.exception.SyntaxError, bad) def testUsesLastTTL(self): z = dns.zone.from_text(last_ttl_input, "example") rrs = z.find_rrset("foo9", "CNAME") self.assertEqual(rrs.ttl, 300) def testClassMismatch(self): def bad(): dns.zone.from_text("$GENERATE 1-10 fooo$ CH CNAME $.0", "example") self.assertRaises(dns.exception.SyntaxError, bad) def testUnknownRdatatype(self): def bad(): dns.zone.from_text("$GENERATE 1-10 fooo$ BOGUSTYPE $.0", "example") self.assertRaises(dns.exception.SyntaxError, bad) def testBadAndDangling(self): def bad1(): dns.zone.from_text("$GENERATE bogus fooo$ CNAME $.0", "example.") self.assertRaises(dns.exception.SyntaxError, bad1) def bad2(): dns.zone.from_text("$GENERATE 1-10", "example.") self.assertRaises(dns.exception.SyntaxError, bad2) def bad3(): dns.zone.from_text("$GENERATE 1-10 foo$", "example.") self.assertRaises(dns.exception.SyntaxError, bad3) if __name__ == "__main__": unittest.main()