1# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license
2
3# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc.
4#
5# Permission to use, copy, modify, and distribute this software and its
6# documentation for any purpose with or without fee is hereby granted,
7# provided that the above copyright notice and this permission notice
8# appear in all copies.
9#
10# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
18import sys
19sys.path.insert(0, '../')  # Force the local project to be *the* dns
20
21import unittest
22
23import dns.exception
24import dns.rdata
25import dns.rdataclass
26import dns.rdatatype
27import dns.rrset
28import dns.zone
29from dns._compat import long
30
31import pprint
32
33
34pp = pprint.PrettyPrinter(indent=2)
35
36example_text = """$TTL 1h
37$ORIGIN 0.0.192.IN-ADDR.ARPA.
38$GENERATE 1-2 0 CNAME SERVER$.EXAMPLE.
39"""
40
41example_text1 = """$TTL 1h
42$ORIGIN 0.0.192.IN-ADDR.ARPA.
43$GENERATE 1-10 fooo$ CNAME $.0
44"""
45
46example_text2 = """$TTL 1h
47@ 3600 IN SOA foo bar 1 2 3 4 5
48@ 3600 IN NS ns1
49@ 3600 IN NS ns2
50bar.foo 300 IN MX 0 blaz.foo
51ns1 3600 IN A 10.0.0.1
52ns2 3600 IN A 10.0.0.2
53$GENERATE 3-5 foo$ A 10.0.0.$
54"""
55
56example_text3 = """$TTL 1h
57@ 3600 IN SOA foo bar 1 2 3 4 5
58@ 3600 IN NS ns1
59@ 3600 IN NS ns2
60bar.foo 300 IN MX 0 blaz.foo
61ns1 3600 IN A 10.0.0.1
62ns2 3600 IN A 10.0.0.2
63$GENERATE 4-8/2 foo$ A 10.0.0.$
64"""
65
66example_text4 = """$TTL 1h
67@ 3600 IN SOA foo bar 1 2 3 4 5
68@ 3600 IN NS ns1
69@ 3600 IN NS ns2
70bar.foo 300 IN MX 0 blaz.foo
71ns1 3600 IN A 10.0.0.1
72ns2 3600 IN A 10.0.0.2
73$GENERATE 11-13 wp-db${-10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR.
74"""
75
76example_text5 = """$TTL 1h
77@ 3600 IN SOA foo bar 1 2 3 4 5
78@ 3600 IN NS ns1
79@ 3600 IN NS ns2
80bar.foo 300 IN MX 0 blaz.foo
81ns1 3600 IN A 10.0.0.1
82ns2 3600 IN A 10.0.0.2
83$GENERATE 11-13 wp-db${10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR.
84"""
85
86example_text6 = """$TTL 1h
87@ 3600 IN SOA foo bar 1 2 3 4 5
88@ 3600 IN NS ns1
89@ 3600 IN NS ns2
90bar.foo 300 IN MX 0 blaz.foo
91ns1 3600 IN A 10.0.0.1
92ns2 3600 IN A 10.0.0.2
93$GENERATE 11-13 wp-db${+10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR.
94"""
95
96example_text7 = """$TTL 1h
97@ 3600 IN SOA foo bar 1 2 3 4 5
98@ 3600 IN NS ns1
99@ 3600 IN NS ns2
100bar.foo 300 IN MX 0 blaz.foo
101ns1 3600 IN A 10.0.0.1
102ns2 3600 IN A 10.0.0.2
103$GENERATE 11-13     sync${-10}.db   IN  A   10.10.16.0
104"""
105
106example_text8 = """$TTL 1h
107@ 3600 IN SOA foo bar 1 2 3 4 5
108@ 3600 IN NS ns1
109@ 3600 IN NS ns2
110bar.foo 300 IN MX 0 blaz.foo
111ns1 3600 IN A 10.0.0.1
112ns2 3600 IN A 10.0.0.2
113$GENERATE 11-12 wp-db${-10,2,d} IN A 10.10.16.0
114"""
115
116example_text9 = """$TTL 1h
117@ 3600 IN SOA foo bar 1 2 3 4 5
118@ 3600 IN NS ns1
119@ 3600 IN NS ns2
120bar.foo 300 IN MX 0 blaz.foo
121ns1 3600 IN A 10.0.0.1
122ns2 3600 IN A 10.0.0.2
123$GENERATE 11-12 wp-db${-10,2,d} IN A 10.10.16.0
124$GENERATE 11-13     sync${-10}.db   IN  A   10.10.16.0
125"""
126example_text10 = """$TTL 1h
127@ 3600 IN SOA foo bar 1 2 3 4 5
128@ 3600 IN NS ns1
129@ 3600 IN NS ns2
130bar.foo 300 IN MX 0 blaz.foo
131ns1 3600 IN A 10.0.0.1
132ns2 3600 IN A 10.0.0.2
133$GENERATE 27-28 $.2 PTR zlb${-26}.oob
134"""
135
136def _rdata_sort(a):
137    return (a[0], a[2].rdclass, a[2].to_text())
138
139
140class GenerateTestCase(unittest.TestCase):
141
142    def testFromText(self): # type: () -> None
143        def bad(): # type: () -> None
144            dns.zone.from_text(example_text, 'example.', relativize=True)
145        self.failUnlessRaises(dns.zone.NoSOA, bad)
146
147    def testFromText1(self): # type: () -> None
148        def bad(): # type: () -> None
149            dns.zone.from_text(example_text1, 'example.', relativize=True)
150        self.failUnlessRaises(dns.zone.NoSOA, bad)
151
152    def testIterateAllRdatas2(self): # type: () -> None
153        z = dns.zone.from_text(example_text2, 'example.', relativize=True)
154        l = list(z.iterate_rdatas())
155        l.sort(key=_rdata_sort)
156        exl = [(dns.name.from_text('@', None),
157                3600,
158                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
159                                    'ns1')),
160               (dns.name.from_text('@', None),
161                3600,
162                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
163                                    'ns2')),
164               (dns.name.from_text('@', None),
165                3600,
166                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
167                                    'foo bar 1 2 3 4 5')),
168               (dns.name.from_text('bar.foo', None),
169                300,
170                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
171                                    '0 blaz.foo')),
172                (dns.name.from_text('ns1', None),
173                3600,
174                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
175                                    '10.0.0.1')),
176                (dns.name.from_text('ns2', None),
177                3600,
178                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
179                                    '10.0.0.2')),
180                (dns.name.from_text('foo3', None),
181                3600,
182                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
183                                    '10.0.0.3')),
184                (dns.name.from_text('foo4', None),
185                3600,
186                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
187                                    '10.0.0.4')),
188                (dns.name.from_text('foo5', None),
189                3600,
190                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
191                                    '10.0.0.5'))]
192
193        exl.sort(key=_rdata_sort)
194        self.failUnless(l == exl)
195
196    def testIterateAllRdatas3(self): # type: () -> None
197        z = dns.zone.from_text(example_text3, 'example.', relativize=True)
198        l = list(z.iterate_rdatas())
199        l.sort(key=_rdata_sort)
200        exl = [(dns.name.from_text('@', None),
201                3600,
202                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
203                                    'ns1')),
204               (dns.name.from_text('@', None),
205                3600,
206                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
207                                    'ns2')),
208               (dns.name.from_text('@', None),
209                3600,
210                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
211                                    'foo bar 1 2 3 4 5')),
212               (dns.name.from_text('bar.foo', None),
213                300,
214                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
215                                    '0 blaz.foo')),
216               (dns.name.from_text('ns1', None),
217                3600,
218                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
219                                    '10.0.0.1')),
220               (dns.name.from_text('ns2', None),
221                3600,
222                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
223                                    '10.0.0.2')),
224                (dns.name.from_text('foo4', None), 3600,
225                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
226                                    '10.0.0.4')),
227                (dns.name.from_text('foo6', None), 3600,
228                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
229                                    '10.0.0.6')),
230                (dns.name.from_text('foo8', None), 3600,
231                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
232                                    '10.0.0.8'))]
233        exl.sort(key=_rdata_sort)
234        self.failUnless(l == exl)
235    def testGenerate1(self): # type: () -> None
236        z = dns.zone.from_text(example_text4, 'example.', relativize=True)
237        l = list(z.iterate_rdatas())
238        l.sort(key=_rdata_sort)
239        exl = [(dns.name.from_text('@', None),
240                long(3600),
241                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
242                                    'ns1')),
243               (dns.name.from_text('@', None),
244                long(3600),
245                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
246                                    'ns2')),
247               (dns.name.from_text('@', None),
248                long(3600),
249                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
250                                    'foo bar 1 2 3 4 5')),
251               (dns.name.from_text('bar.foo', None),
252                long(300),
253                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
254                                    '0 blaz.foo')),
255               (dns.name.from_text('ns1', None),
256                long(3600),
257                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
258                                    '10.0.0.1')),
259               (dns.name.from_text('ns2', None),
260                long(3600),
261                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
262                                    '10.0.0.2')),
263
264                (dns.name.from_text('wp-db01.services.mozilla.com', None),
265                    long(0),
266                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
267                                    'SERVER.FOOBAR.')),
268
269                (dns.name.from_text('wp-db02.services.mozilla.com', None),
270                    long(0),
271                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
272                                    'SERVER.FOOBAR.')),
273
274                (dns.name.from_text('wp-db03.services.mozilla.com', None),
275                    long(0),
276                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
277                                    'SERVER.FOOBAR.'))]
278        exl.sort(key=_rdata_sort)
279        self.assertEqual(l, exl)
280
281    def testGenerate2(self): # type: () -> None
282        z = dns.zone.from_text(example_text5, 'example.', relativize=True)
283        l = list(z.iterate_rdatas())
284        l.sort(key=_rdata_sort)
285        exl = [(dns.name.from_text('@', None),
286                long(3600),
287                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
288                                    'ns1')),
289               (dns.name.from_text('@', None),
290                long(3600),
291                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
292                                    'ns2')),
293               (dns.name.from_text('@', None),
294                long(3600),
295                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
296                                    'foo bar 1 2 3 4 5')),
297               (dns.name.from_text('bar.foo', None),
298                long(300),
299                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
300                                    '0 blaz.foo')),
301               (dns.name.from_text('ns1', None),
302                long(3600),
303                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
304                                    '10.0.0.1')),
305               (dns.name.from_text('ns2', None),
306                long(3600),
307                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
308                                    '10.0.0.2')),
309
310                (dns.name.from_text('wp-db21.services.mozilla.com', None), long(0),
311                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
312                                    'SERVER.FOOBAR.')),
313
314                (dns.name.from_text('wp-db22.services.mozilla.com', None), long(0),
315                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
316                                    'SERVER.FOOBAR.')),
317
318                (dns.name.from_text('wp-db23.services.mozilla.com', None), long(0),
319                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
320                                    'SERVER.FOOBAR.'))]
321        exl.sort(key=_rdata_sort)
322        self.failUnless(l == exl)
323
324    def testGenerate3(self): # type: () -> None
325        z = dns.zone.from_text(example_text6, 'example.', relativize=True)
326        l = list(z.iterate_rdatas())
327        l.sort(key=_rdata_sort)
328
329        exl = [(dns.name.from_text('@', None),
330                long(3600),
331                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
332                                    'ns1')),
333               (dns.name.from_text('@', None),
334                long(3600),
335                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
336                                    'ns2')),
337               (dns.name.from_text('@', None),
338                long(3600),
339                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
340                                    'foo bar 1 2 3 4 5')),
341               (dns.name.from_text('bar.foo', None),
342                long(300),
343                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
344                                    '0 blaz.foo')),
345               (dns.name.from_text('ns1', None),
346                long(3600),
347                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
348                                    '10.0.0.1')),
349               (dns.name.from_text('ns2', None),
350                long(3600),
351                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
352                                    '10.0.0.2')),
353                (dns.name.from_text('wp-db21.services.mozilla.com', None), long(0),
354                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
355                                    'SERVER.FOOBAR.')),
356
357                (dns.name.from_text('wp-db22.services.mozilla.com', None), long(0),
358                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
359                                    'SERVER.FOOBAR.')),
360
361                (dns.name.from_text('wp-db23.services.mozilla.com', None), long(0),
362                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME,
363                                    'SERVER.FOOBAR.'))]
364        exl.sort(key=_rdata_sort)
365        self.failUnless(l == exl)
366
367    def testGenerate4(self): # type: () -> None
368        z = dns.zone.from_text(example_text7, 'example.', relativize=True)
369        l = list(z.iterate_rdatas())
370        l.sort(key=_rdata_sort)
371        exl = [(dns.name.from_text('@', None),
372                long(3600),
373                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
374                                    'ns1')),
375               (dns.name.from_text('@', None),
376                long(3600),
377                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
378                                    'ns2')),
379               (dns.name.from_text('@', None),
380                long(3600),
381                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
382                                    'foo bar 1 2 3 4 5')),
383               (dns.name.from_text('bar.foo', None),
384                long(300),
385                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
386                                    '0 blaz.foo')),
387               (dns.name.from_text('ns1', None),
388                long(3600),
389                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
390                                    '10.0.0.1')),
391               (dns.name.from_text('ns2', None),
392                long(3600),
393                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
394                                    '10.0.0.2')),
395
396                (dns.name.from_text('sync1.db', None), long(3600),
397                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
398                                    '10.10.16.0')),
399
400                (dns.name.from_text('sync2.db', None), long(3600),
401                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
402                                    '10.10.16.0')),
403
404                (dns.name.from_text('sync3.db', None), long(3600),
405                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
406                                    '10.10.16.0'))]
407        exl.sort(key=_rdata_sort)
408        self.failUnless(l == exl)
409
410    def testGenerate6(self): # type: () -> None
411        z = dns.zone.from_text(example_text9, 'example.', relativize=True)
412        l = list(z.iterate_rdatas())
413        l.sort(key=_rdata_sort)
414        exl = [(dns.name.from_text('@', None),
415                long(3600),
416                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
417                                    'ns1')),
418               (dns.name.from_text('@', None),
419                long(3600),
420                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
421                                    'ns2')),
422               (dns.name.from_text('@', None),
423                long(3600),
424                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
425                                    'foo bar 1 2 3 4 5')),
426               (dns.name.from_text('bar.foo', None),
427                long(300),
428                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
429                                    '0 blaz.foo')),
430               (dns.name.from_text('ns1', None),
431                long(3600),
432                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
433                                    '10.0.0.1')),
434               (dns.name.from_text('ns2', None),
435                long(3600),
436                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
437                                    '10.0.0.2')),
438
439                (dns.name.from_text('wp-db01', None), long(3600),
440                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
441                                    '10.10.16.0')),
442                (dns.name.from_text('wp-db02', None), long(3600),
443                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
444                                    '10.10.16.0')),
445
446                (dns.name.from_text('sync1.db', None), long(3600),
447                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
448                                    '10.10.16.0')),
449
450                (dns.name.from_text('sync2.db', None), long(3600),
451                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
452                                    '10.10.16.0')),
453
454                (dns.name.from_text('sync3.db', None), long(3600),
455                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
456                                    '10.10.16.0'))]
457        exl.sort(key=_rdata_sort)
458        self.failUnless(l == exl)
459
460    def testGenerate7(self): # type: () -> None
461        z = dns.zone.from_text(example_text10, 'example.', relativize=True)
462        l = list(z.iterate_rdatas())
463        l.sort(key=_rdata_sort)
464        exl = [(dns.name.from_text('@', None),
465                long(3600),
466                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
467                                    'ns1')),
468               (dns.name.from_text('@', None),
469                long(3600),
470                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS,
471                                    'ns2')),
472               (dns.name.from_text('@', None),
473                long(3600),
474                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,
475                                    'foo bar 1 2 3 4 5')),
476               (dns.name.from_text('bar.foo', None),
477                long(300),
478                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX,
479                                    '0 blaz.foo')),
480               (dns.name.from_text('ns1', None),
481                long(3600),
482                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
483                                    '10.0.0.1')),
484               (dns.name.from_text('ns2', None),
485                long(3600),
486                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A,
487                                    '10.0.0.2')),
488
489                (dns.name.from_text('27.2', None), long(3600),
490                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR,
491                                    'zlb1.oob')),
492
493                (dns.name.from_text('28.2', None), long(3600),
494                dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR,
495                                    'zlb2.oob'))]
496
497        exl.sort(key=_rdata_sort)
498        self.failUnless(l == exl)
499
500
501if __name__ == '__main__':
502    unittest.main()
503