Imported Upstream version 1.12.0
SVN-Git Migration
8 years ago
0 | 2014-09-01 Bob Halley <halley@dnspython.org> | |
1 | ||
2 | * (Version 1.12.0 released) | |
3 | ||
4 | 2014-08-31 Bob Halley <halley@dnspython.org> | |
5 | ||
6 | * The test system can now run the tests without requiring dnspython | |
7 | to be installed. | |
8 | ||
9 | 2014-07-24 Bob Halley <halley@dnspython.org> | |
10 | ||
11 | * The 64-bit version of Python on Windows has sys.maxint set to | |
12 | 2^31-1, yet passes 2^63-1 as the "unspecified bound" value in | |
13 | slices. This is a bug in Python as the documentation says the | |
14 | unspecified bound value should be sys.maxint. We now cope with | |
15 | this. Thanks to Matthäus Wander for reporting the problem. | |
16 | ||
17 | 2014-06-21 Bob Halley <halley@dnspython.org> | |
18 | ||
19 | * When reading from a masterfile, if the first content line | |
20 | started with leading whitespace, we raised an ugly exception | |
21 | instead of doing the right thing, namely using the zone origin as | |
22 | the name. [#73] Thanks to Tassatux for reporting the issue. | |
23 | ||
24 | * Added dns.zone.to_text() convenience method. Thanks to Brandon | |
25 | Whaley <redkrieg@gmail.com> for the patch. | |
26 | ||
27 | * The /etc/resolv.conf setting "options rotate" is now understood | |
28 | by the resolver. If present, the resolver will shuffle the | |
29 | nameserver list each time dns.resolver.query() is called. Thanks | |
30 | to underrun for the patch. Note that you don't want to add | |
31 | "options rotate" to your /etc/resolv.conf if your system's | |
32 | resolver library does not understand it. In this case, just set | |
33 | resolver.rotate = True by hand. | |
34 | ||
35 | 2014-06-19 Bob Halley <halley@dnspython.org> | |
36 | ||
37 | * Escaping of Unicode has been corrected. Previously we escaped | |
38 | and then converted to Unicode, but the right thing to do is | |
39 | convert to Unicode, then escape. Also, characters > 0x7f should | |
40 | NOT be escaped in Unicode mode. Thanks to Martin Basti for the | |
41 | patch. | |
42 | ||
43 | * dns.rdtypes.ANY.DNSKEY now has helpers functions to convert | |
44 | between the numeric form of the flags and a set of human-friendly | |
45 | strings. Thanks to Petr Spacek for the patch. | |
46 | ||
47 | * RRSIGs did not respect relativization settings in to_text(). | |
48 | Thanks to Brian Smith for reporting the bug and submitting a | |
49 | (slightly different) patch. | |
50 | ||
51 | 2014-06-18 Bob Halley <halley@dnspython.org> | |
52 | ||
53 | * dns/rdtypes/IN/APL.py: The APL from_wire() method did not accept an | |
54 | rdata length of 0 as valid. Thanks to salzmdan for reporting the | |
55 | problem. | |
56 | ||
57 | 2014-05-31 Bob Halley <halley@dnspython.org> | |
58 | ||
59 | * dns/ipv6.py: Add is_mapped() | |
60 | ||
61 | * dns/reversename.py: Lookup IPv6 mapped IPv4 addresses in the v4 | |
62 | reverse namespace. Thanks to Devin Bayer. Yes, I finally fixed | |
63 | this one :) | |
64 | ||
65 | 2014-04-11 Bob Halley <halley@dnspython.org> | |
66 | ||
67 | * dns/zone.py: Do not put back an unescaped token. This was | |
68 | causing escape processing for domain names to break. Thanks to | |
69 | connormclaud for reporting the problem. | |
70 | ||
71 | 2014-04-04 Bob Halley <halley@dnspython.org> | |
72 | ||
73 | * dns/message.py: Making a response didn't work correctly if the | |
74 | query was signed with TSIG and we knew the key. Thanks to Jeffrey | |
75 | Stiles for reporting the problem. | |
76 | ||
77 | 2013-12-11 Bob Halley <halley@dnspython.org> | |
78 | ||
79 | * dns/query.py: Fix problems with the IXFR state machine which caused | |
80 | long diffs to fail. Thanks to James Raftery for the fix and the | |
81 | repeated prodding to get it applied :) | |
82 | ||
0 | 83 | 2013-09-02 Bob Halley <halley@dnspython.org> |
1 | 84 | |
2 | 85 | * (Version 1.11.1 released) |
0 | 0 | Metadata-Version: 1.1 |
1 | 1 | Name: dnspython |
2 | Version: 1.11.1 | |
2 | Version: 1.12.0 | |
3 | 3 | Summary: DNS toolkit |
4 | 4 | Home-page: http://www.dnspython.org |
5 | 5 | Author: Bob Halley |
6 | 6 | Author-email: halley@dnspython.org |
7 | 7 | License: BSD-like |
8 | Download-URL: http://www.dnspython.org/kits/1.11.1/dnspython-1.11.1.tar.gz | |
8 | Download-URL: http://www.dnspython.org/kits/1.12.0/dnspython-1.12.0.tar.gz | |
9 | 9 | Description: dnspython is a DNS toolkit for Python. It supports almost all |
10 | 10 | record types. It can be used for queries, zone transfers, and dynamic |
11 | 11 | updates. It supports TSIG authenticated messages and EDNS0. |
21 | 21 | |
22 | 22 | ABOUT THIS RELEASE |
23 | 23 | |
24 | This is dnspython 1.11.1 | |
24 | This is dnspython 1.12.0 | |
25 | ||
26 | New since 1.11.1: | |
27 | ||
28 | Added dns.zone.to_text(). | |
29 | ||
30 | Added support for "options rotate" in /etc/resolv.conf. | |
31 | ||
32 | dns.rdtypes.ANY.DNSKEY now has helpers functions to convert | |
33 | between the numeric form of the flags and a set of | |
34 | human-friendly strings | |
35 | ||
36 | The reverse name of an IPv6 mapped IPv4 address is now in the | |
37 | IPv4 reverse namespace. | |
38 | ||
39 | The test system can now run the tests without requiring | |
40 | dnspython to be installed. | |
41 | ||
42 | Preliminary Elliptic Curve DNSSEC Validation (requires ecdsa module) | |
43 | ||
44 | Bugs fixed since 1.11.1: | |
45 | ||
46 | dnspython raised an exception when reading a masterfile starting | |
47 | with leading whitespace | |
48 | ||
49 | dnspython was affected by a python slicing API bug present on | |
50 | 64-bit windows. | |
51 | ||
52 | Unicode escaping was applied at the wrong time. | |
53 | ||
54 | RRSIG to_text() did not respect the relativize setting. | |
55 | ||
56 | APL RRs with zero rdlength were rejected. | |
57 | ||
58 | The tokenizer could put back an unescaped token. | |
59 | ||
60 | Making a response to a message signed with TSIG was broken. | |
61 | ||
62 | The IXFR state machine didn't handle long IXFR diffs. | |
25 | 63 | |
26 | 64 | New since 1.11.0: |
27 | 65 | |
28 | 66 | Nothing |
29 | 67 | |
30 | Bugs fixed since 1.11.1: | |
68 | Bugs fixed since 1.11.0: | |
31 | 69 | |
32 | 70 | dns.resolver.Resolver erroneously referred to 'retry_servfail' |
33 | 71 | instead of 'self.retry_servfail'. |
44 | 44 | RSASHA1NSEC3SHA1 = 7 |
45 | 45 | RSASHA256 = 8 |
46 | 46 | RSASHA512 = 10 |
47 | ECDSAP256SHA256 = 13 | |
48 | ECDSAP384SHA384 = 14 | |
47 | 49 | INDIRECT = 252 |
48 | 50 | PRIVATEDNS = 253 |
49 | 51 | PRIVATEOID = 254 |
59 | 61 | 'RSASHA256' : RSASHA256, |
60 | 62 | 'RSASHA512' : RSASHA512, |
61 | 63 | 'INDIRECT' : INDIRECT, |
64 | 'ECDSAP256SHA256' : ECDSAP256SHA256, | |
65 | 'ECDSAP384SHA384' : ECDSAP384SHA384, | |
62 | 66 | 'PRIVATEDNS' : PRIVATEDNS, |
63 | 67 | 'PRIVATEOID' : PRIVATEOID, |
64 | 68 | } |
152 | 156 | def _is_dsa(algorithm): |
153 | 157 | return algorithm in (DSA, DSANSEC3SHA1) |
154 | 158 | |
159 | def _is_ecdsa(algorithm): | |
160 | return _have_ecdsa and (algorithm in (ECDSAP256SHA256, ECDSAP384SHA384)) | |
161 | ||
155 | 162 | def _is_md5(algorithm): |
156 | 163 | return algorithm == RSAMD5 |
157 | 164 | |
160 | 167 | DSANSEC3SHA1, RSASHA1NSEC3SHA1) |
161 | 168 | |
162 | 169 | def _is_sha256(algorithm): |
163 | return algorithm == RSASHA256 | |
170 | return algorithm in (RSASHA256, ECDSAP256SHA256) | |
171 | ||
172 | def _is_sha384(algorithm): | |
173 | return algorithm == ECDSAP384SHA384 | |
164 | 174 | |
165 | 175 | def _is_sha512(algorithm): |
166 | 176 | return algorithm == RSASHA512 |
172 | 182 | return dns.hash.get('SHA1')() |
173 | 183 | if _is_sha256(algorithm): |
174 | 184 | return dns.hash.get('SHA256')() |
185 | if _is_sha384(algorithm): | |
186 | return dns.hash.get('SHA384')() | |
175 | 187 | if _is_sha512(algorithm): |
176 | 188 | return dns.hash.get('SHA512')() |
177 | 189 | raise ValidationFailure, 'unknown hash for algorithm %u' % algorithm |
273 | 285 | (dsa_r, dsa_s) = struct.unpack('!20s20s', rrsig.signature[1:]) |
274 | 286 | sig = (Crypto.Util.number.bytes_to_long(dsa_r), |
275 | 287 | Crypto.Util.number.bytes_to_long(dsa_s)) |
288 | elif _is_ecdsa(rrsig.algorithm): | |
289 | if rrsig.algorithm == ECDSAP256SHA256: | |
290 | curve = ecdsa.curves.NIST256p | |
291 | key_len = 32 | |
292 | digest_len = 32 | |
293 | elif rrsig.algorithm == ECDSAP384SHA384: | |
294 | curve = ecdsa.curves.NIST384p | |
295 | key_len = 48 | |
296 | digest_len = 48 | |
297 | else: | |
298 | # shouldn't happen | |
299 | raise ValidationFailure, 'unknown ECDSA curve' | |
300 | keyptr = candidate_key.key | |
301 | x = Crypto.Util.number.bytes_to_long(keyptr[0:key_len]) | |
302 | y = Crypto.Util.number.bytes_to_long(keyptr[key_len:key_len * 2]) | |
303 | assert ecdsa.ecdsa.point_is_valid(curve.generator, x, y) | |
304 | point = ecdsa.ellipticcurve.Point(curve.curve, x, y, curve.order) | |
305 | verifying_key = ecdsa.keys.VerifyingKey.from_public_point(point, | |
306 | curve) | |
307 | pubkey = ECKeyWrapper(verifying_key, key_len) | |
308 | r = rrsig.signature[:key_len] | |
309 | s = rrsig.signature[key_len:] | |
310 | sig = ecdsa.ecdsa.Signature(Crypto.Util.number.bytes_to_long(r), | |
311 | Crypto.Util.number.bytes_to_long(s)) | |
276 | 312 | else: |
277 | 313 | raise ValidationFailure, 'unknown algorithm %u' % rrsig.algorithm |
278 | 314 | |
301 | 337 | digest = _make_algorithm_id(rrsig.algorithm) + digest |
302 | 338 | padlen = keylen // 8 - len(digest) - 3 |
303 | 339 | digest = chr(0) + chr(1) + chr(0xFF) * padlen + chr(0) + digest |
304 | elif _is_dsa(rrsig.algorithm): | |
340 | elif _is_dsa(rrsig.algorithm) or _is_ecdsa(rrsig.algorithm): | |
305 | 341 | pass |
306 | 342 | else: |
307 | 343 | # Raise here for code clarity; this won't actually ever happen |
368 | 404 | import Crypto.Util.number |
369 | 405 | validate = _validate |
370 | 406 | validate_rrsig = _validate_rrsig |
407 | _have_pycrypto = True | |
371 | 408 | except ImportError: |
372 | 409 | validate = _need_pycrypto |
373 | 410 | validate_rrsig = _need_pycrypto |
411 | _have_pycrypto = False | |
412 | ||
413 | try: | |
414 | import ecdsa | |
415 | import ecdsa.ecdsa | |
416 | import ecdsa.ellipticcurve | |
417 | import ecdsa.keys | |
418 | _have_ecdsa = True | |
419 | ||
420 | class ECKeyWrapper(object): | |
421 | def __init__(self, key, key_len): | |
422 | self.key = key | |
423 | self.key_len = key_len | |
424 | def verify(self, digest, sig): | |
425 | diglong = Crypto.Util.number.bytes_to_long(digest) | |
426 | return self.key.pubkey.verifies(diglong, sig) | |
427 | ||
428 | except ImportError: | |
429 | _have_ecdsa = False |
160 | 160 | return text.decode('hex_codec') |
161 | 161 | except TypeError: |
162 | 162 | raise dns.exception.SyntaxError |
163 | ||
164 | _mapped_prefix = '\x00' * 10 + '\xff\xff' | |
165 | ||
166 | def is_mapped(address): | |
167 | return address.startswith(_mapped_prefix) |
664 | 664 | secret = self.message.keyring.get(absolute_name) |
665 | 665 | if secret is None: |
666 | 666 | raise UnknownTSIGKey("key '%s' unknown" % name) |
667 | self.message.keyname = absolute_name | |
668 | (self.message.keyalgorithm, self.message.mac) = \ | |
669 | dns.tsig.get_algorithm_and_mac(self.wire, self.current, | |
670 | rdlen) | |
667 | 671 | self.message.tsig_ctx = \ |
668 | 672 | dns.tsig.validate(self.wire, |
669 | 673 | absolute_name, |
1070 | 1074 | m.want_dnssec(want_dnssec) |
1071 | 1075 | return m |
1072 | 1076 | |
1073 | def make_response(query, recursion_available=False, our_payload=8192): | |
1077 | def make_response(query, recursion_available=False, our_payload=8192, | |
1078 | fudge=300): | |
1074 | 1079 | """Make a message which is a response for the specified query. |
1075 | 1080 | The message returned is really a response skeleton; it has all |
1076 | 1081 | of the infrastructure required of a response, but none of the |
1087 | 1092 | @param our_payload: payload size to advertise in EDNS responses; default |
1088 | 1093 | is 8192. |
1089 | 1094 | @type our_payload: int |
1095 | @param fudge: TSIG time fudge; default is 300 seconds. | |
1096 | @type fudge: int | |
1090 | 1097 | @rtype: dns.message.Message object""" |
1091 | 1098 | |
1092 | 1099 | if query.flags & dns.flags.QR: |
1099 | 1106 | response.question = list(query.question) |
1100 | 1107 | if query.edns >= 0: |
1101 | 1108 | response.use_edns(0, 0, our_payload, query.payload) |
1102 | if not query.keyname is None: | |
1103 | response.keyname = query.keyname | |
1104 | response.keyring = query.keyring | |
1109 | if query.had_tsig: | |
1110 | response.use_tsig(query.keyring, query.keyname, fudge, None, 0, '', | |
1111 | query.keyalgorithm) | |
1105 | 1112 | response.request_mac = query.mac |
1106 | 1113 | return response |
23 | 23 | import cStringIO |
24 | 24 | import struct |
25 | 25 | import sys |
26 | import copy | |
26 | 27 | |
27 | 28 | if sys.hexversion >= 0x02030000: |
28 | 29 | import encodings.idna |
86 | 87 | '$' : True |
87 | 88 | } |
88 | 89 | |
89 | def _escapify(label): | |
90 | def _escapify(label, unicode_mode=False): | |
90 | 91 | """Escape the characters in label which need it. |
92 | @param unicode_mode: escapify only special and whitespace (<= 0x20) | |
93 | characters | |
91 | 94 | @returns: the escaped string |
92 | 95 | @rtype: string""" |
93 | 96 | text = '' |
97 | 100 | elif ord(c) > 0x20 and ord(c) < 0x7F: |
98 | 101 | text += c |
99 | 102 | else: |
100 | text += '\\%03d' % ord(c) | |
103 | if unicode_mode and ord(c) >= 0x7F: | |
104 | text += c | |
105 | else: | |
106 | text += '\\%03d' % ord(c) | |
101 | 107 | return text |
102 | 108 | |
103 | 109 | def _validate_labels(labels): |
147 | 153 | |
148 | 154 | def __setattr__(self, name, value): |
149 | 155 | raise TypeError("object doesn't support attribute assignment") |
156 | ||
157 | def __copy__(self): | |
158 | return Name(self.labels) | |
159 | ||
160 | def __deepcopy__(self, memo): | |
161 | return Name(copy.deepcopy(self.labels, memo)) | |
150 | 162 | |
151 | 163 | def is_absolute(self): |
152 | 164 | """Is the most significant label of this name the root label? |
344 | 356 | l = self.labels[:-1] |
345 | 357 | else: |
346 | 358 | l = self.labels |
347 | s = u'.'.join([encodings.idna.ToUnicode(_escapify(x)) for x in l]) | |
359 | s = u'.'.join([_escapify(encodings.idna.ToUnicode(x), True) for x in l]) | |
348 | 360 | return s |
349 | 361 | |
350 | 362 | def to_digestable(self, origin=None): |
410 | 410 | tcpmsg = struct.pack("!H", l) + wire |
411 | 411 | _net_write(s, tcpmsg, expiration) |
412 | 412 | done = False |
413 | delete_mode = True | |
414 | expecting_SOA = False | |
413 | 415 | soa_rrset = None |
414 | 416 | soa_count = 0 |
415 | 417 | if relativize: |
438 | 440 | tsig_ctx = r.tsig_ctx |
439 | 441 | first = False |
440 | 442 | answer_index = 0 |
441 | delete_mode = False | |
442 | expecting_SOA = False | |
443 | 443 | if soa_rrset is None: |
444 | 444 | if not r.answer or r.answer[0].name != oname: |
445 | raise dns.exception.FormError | |
445 | raise dns.exception.FormError("No answer or RRset not for qname") | |
446 | 446 | rrset = r.answer[0] |
447 | 447 | if rrset.rdtype != dns.rdatatype.SOA: |
448 | 448 | raise dns.exception.FormError("first RRset is not an SOA") |
449 | 449 | answer_index = 1 |
450 | 450 | soa_rrset = rrset.copy() |
451 | 451 | if rdtype == dns.rdatatype.IXFR: |
452 | if soa_rrset[0].serial == serial: | |
452 | if soa_rrset[0].serial <= serial: | |
453 | 453 | # |
454 | 454 | # We're already up-to-date. |
455 | 455 | # |
470 | 470 | expecting_SOA = False |
471 | 471 | elif rdtype == dns.rdatatype.IXFR: |
472 | 472 | delete_mode = not delete_mode |
473 | if rrset == soa_rrset and not delete_mode: | |
473 | # | |
474 | # If this SOA RRset is equal to the first we saw then we're | |
475 | # finished. If this is an IXFR we also check that we're seeing | |
476 | # the record in the expected part of the response. | |
477 | # | |
478 | if rrset == soa_rrset and \ | |
479 | (rdtype == dns.rdatatype.AXFR or \ | |
480 | (rdtype == dns.rdatatype.IXFR and delete_mode)): | |
474 | 481 | done = True |
475 | 482 | elif expecting_SOA: |
476 | 483 | # |
19 | 19 | import dns.dnssec |
20 | 20 | import dns.rdata |
21 | 21 | |
22 | ||
22 | 23 | # flag constants |
23 | 24 | SEP = 0x0001 |
24 | 25 | REVOKE = 0x0080 |
25 | 26 | ZONE = 0x0100 |
27 | ||
28 | _flag_by_text = { | |
29 | 'SEP': SEP, | |
30 | 'REVOKE': REVOKE, | |
31 | 'ZONE': ZONE | |
32 | } | |
33 | ||
34 | # We construct the inverse mapping programmatically to ensure that we | |
35 | # cannot make any mistakes (e.g. omissions, cut-and-paste errors) that | |
36 | # would cause the mapping not to be true inverse. | |
37 | _flag_by_value = dict([(y, x) for x, y in _flag_by_text.iteritems()]) | |
38 | ||
39 | ||
40 | def flags_to_text_set(flags): | |
41 | """Convert a DNSKEY flags value to set texts | |
42 | @rtype: set([string])""" | |
43 | ||
44 | flags_set = set() | |
45 | mask = 0x1 | |
46 | while mask <= 0x8000: | |
47 | if flags & mask: | |
48 | text = _flag_by_value.get(mask) | |
49 | if not text: | |
50 | text = hex(mask) | |
51 | flags_set.add(text) | |
52 | mask <<= 1 | |
53 | return flags_set | |
54 | ||
55 | ||
56 | def flags_from_text_set(texts_set): | |
57 | """Convert set of DNSKEY flag mnemonic texts to DNSKEY flag value | |
58 | @rtype: int""" | |
59 | ||
60 | flags = 0 | |
61 | for text in texts_set: | |
62 | try: | |
63 | flags += _flag_by_text[text] | |
64 | except KeyError: | |
65 | raise NotImplementedError( | |
66 | "DNSKEY flag '%s' is not supported" % text) | |
67 | return flags | |
68 | ||
26 | 69 | |
27 | 70 | class DNSKEY(dns.rdata.Rdata): |
28 | 71 | """DNSKEY record |
91 | 134 | if v == 0: |
92 | 135 | v = cmp(self.key, other.key) |
93 | 136 | return v |
137 | ||
138 | def flags_to_text_set(self): | |
139 | """Convert a DNSKEY flags value to set texts | |
140 | @rtype: set([string])""" | |
141 | return flags_to_text_set(self.flags) |
21 | 21 | _pows = (1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L, |
22 | 22 | 100000000L, 1000000000L, 10000000000L) |
23 | 23 | |
24 | # default values are in centimeters | |
25 | _default_size = 100.0 | |
26 | _default_hprec = 1000000.0 | |
27 | _default_vprec = 1000.0 | |
28 | ||
24 | 29 | def _exponent_of(what, desc): |
30 | if what == 0: | |
31 | return 0 | |
25 | 32 | exp = None |
26 | 33 | for i in xrange(len(_pows)): |
27 | 34 | if what // _pows[i] == 0L: |
97 | 104 | 'horizontal_precision', 'vertical_precision'] |
98 | 105 | |
99 | 106 | def __init__(self, rdclass, rdtype, latitude, longitude, altitude, |
100 | size=1.0, hprec=10000.0, vprec=10.0): | |
107 | size=_default_size, hprec=_default_hprec, vprec=_default_vprec): | |
101 | 108 | """Initialize a LOC record instance. |
102 | 109 | |
103 | 110 | The parameters I{latitude} and I{longitude} may be either a 4-tuple |
104 | 111 | of integers specifying (degrees, minutes, seconds, milliseconds), |
105 | 112 | or they may be floating point values specifying the number of |
106 | degrees. The other parameters are floats.""" | |
113 | degrees. The other parameters are floats. Size, horizontal precision, | |
114 | and vertical precision are specified in centimeters.""" | |
107 | 115 | |
108 | 116 | super(LOC, self).__init__(rdclass, rdtype) |
109 | 117 | if isinstance(latitude, int) or isinstance(latitude, long): |
140 | 148 | self.longitude[3], long_hemisphere, self.altitude / 100.0 |
141 | 149 | ) |
142 | 150 | |
143 | if self.size != 1.0 or self.horizontal_precision != 10000.0 or \ | |
144 | self.vertical_precision != 10.0: | |
151 | # do not print default values | |
152 | if self.size != _default_size or \ | |
153 | self.horizontal_precision != _default_hprec or \ | |
154 | self.vertical_precision != _default_vprec: | |
145 | 155 | text += " %0.2fm %0.2fm %0.2fm" % ( |
146 | 156 | self.size / 100.0, self.horizontal_precision / 100.0, |
147 | 157 | self.vertical_precision / 100.0 |
151 | 161 | def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True): |
152 | 162 | latitude = [0, 0, 0, 0] |
153 | 163 | longitude = [0, 0, 0, 0] |
154 | size = 1.0 | |
155 | hprec = 10000.0 | |
156 | vprec = 10.0 | |
164 | size = _default_size | |
165 | hprec = _default_hprec | |
166 | vprec = _default_vprec | |
157 | 167 | |
158 | 168 | latitude[0] = tok.get_int() |
159 | 169 | t = tok.get_string() |
239 | 249 | value = token.value |
240 | 250 | if value[-1] == 'm': |
241 | 251 | value = value[0 : -1] |
242 | vprec = float(value) * 100.0 # m -> cm | |
243 | tok.get_eol() | |
252 | vprec = float(value) * 100.0 # m -> cm | |
253 | tok.get_eol() | |
244 | 254 | |
245 | 255 | return cls(rdclass, rdtype, latitude, longitude, altitude, |
246 | 256 | size, hprec, vprec) |
55 | 55 | salt = '' |
56 | 56 | else: |
57 | 57 | salt = salt.decode('hex-codec') |
58 | tok.get_eol() | |
58 | 59 | return cls(rdclass, rdtype, algorithm, flags, iterations, salt) |
59 | 60 | |
60 | 61 | from_text = classmethod(from_text) |
92 | 92 | posixtime_to_sigtime(self.expiration), |
93 | 93 | posixtime_to_sigtime(self.inception), |
94 | 94 | self.key_tag, |
95 | self.signer, | |
95 | self.signer.choose_relativity(origin, relativize), | |
96 | 96 | dns.rdata._base64ify(self.signature) |
97 | 97 | ) |
98 | 98 |
117 | 117 | def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None): |
118 | 118 | items = [] |
119 | 119 | while 1: |
120 | if rdlen == 0: | |
121 | break | |
120 | 122 | if rdlen < 4: |
121 | 123 | raise dns.exception.FormError |
122 | 124 | header = struct.unpack('!HBB', wire[current : current + 4]) |
150 | 152 | rdlen -= afdlen |
151 | 153 | item = APLItem(header[0], negation, address, header[1]) |
152 | 154 | items.append(item) |
153 | if rdlen == 0: | |
154 | break | |
155 | 155 | return cls(rdclass, rdtype, items) |
156 | 156 | |
157 | 157 | from_wire = classmethod(from_wire) |
20 | 20 | import socket |
21 | 21 | import sys |
22 | 22 | import time |
23 | import random | |
23 | 24 | |
24 | 25 | try: |
25 | 26 | import threading as _threading |
507 | 508 | self.cache = None |
508 | 509 | self.flags = None |
509 | 510 | self.retry_servfail = False |
511 | self.rotate = False | |
510 | 512 | |
511 | 513 | def read_resolv_conf(self, f): |
512 | 514 | """Process f as a file in the /etc/resolv.conf format. If f is |
537 | 539 | elif tokens[0] == 'search': |
538 | 540 | for suffix in tokens[1:]: |
539 | 541 | self.search.append(dns.name.from_text(suffix)) |
542 | elif tokens[0] == 'options': | |
543 | if 'rotate' in tokens[1:]: | |
544 | self.rotate = True | |
540 | 545 | finally: |
541 | 546 | if want_close: |
542 | 547 | f.close() |
810 | 815 | # make a copy of the servers list so we can alter it later. |
811 | 816 | # |
812 | 817 | nameservers = self.nameservers[:] |
818 | if self.rotate: | |
819 | random.shuffle(nameservers) | |
813 | 820 | backoff = 0.10 |
814 | 821 | while response is None: |
815 | 822 | if len(nameservers) == 0: |
36 | 36 | @rtype: dns.name.Name object |
37 | 37 | """ |
38 | 38 | try: |
39 | parts = list(dns.ipv6.inet_aton(text).encode('hex_codec')) | |
40 | origin = ipv6_reverse_domain | |
39 | v6 = dns.ipv6.inet_aton(text) | |
40 | if dns.ipv6.is_mapped(v6): | |
41 | parts = ['%d' % ord(byte) for byte in v6[12:]] | |
42 | origin = ipv4_reverse_domain | |
43 | else: | |
44 | parts = list(v6.encode('hex_codec')) | |
45 | origin = ipv6_reverse_domain | |
41 | 46 | except: |
42 | 47 | parts = ['%d' % ord(byte) for byte in dns.ipv4.inet_aton(text)] |
43 | 48 | origin = ipv4_reverse_domain |
220 | 220 | except KeyError: |
221 | 221 | raise NotImplementedError("TSIG algorithm " + str(algorithm) + |
222 | 222 | " is not supported") |
223 | ||
224 | def get_algorithm_and_mac(wire, tsig_rdata, tsig_rdlen): | |
225 | """Return the tsig algorithm for the specified tsig_rdata | |
226 | @raises FormError: The TSIG is badly formed. | |
227 | """ | |
228 | current = tsig_rdata | |
229 | (aname, used) = dns.name.from_wire(wire, current) | |
230 | current = current + used | |
231 | (upper_time, lower_time, fudge, mac_size) = \ | |
232 | struct.unpack("!HIHH", wire[current:current + 10]) | |
233 | current += 10 | |
234 | mac = wire[current:current + mac_size] | |
235 | current += mac_size | |
236 | if current > tsig_rdata + tsig_rdlen: | |
237 | raise dns.exception.FormError | |
238 | return (aname, mac) |
15 | 15 | """dnspython release version information.""" |
16 | 16 | |
17 | 17 | MAJOR = 1 |
18 | MINOR = 11 | |
19 | MICRO = 1 | |
18 | MINOR = 12 | |
19 | MICRO = 0 | |
20 | 20 | RELEASELEVEL = 0x0f |
21 | 21 | SERIAL = 0 |
22 | 22 |
18 | 18 | |
19 | 19 | import dns.exception |
20 | 20 | |
21 | # Figure out what constant python passes for an unspecified slice bound. | |
22 | # It's supposed to be sys.maxint, yet on 64-bit windows sys.maxint is 2^31 - 1 | |
23 | # but Python uses 2^63 - 1 as the constant. Rather than making pointless | |
24 | # extra comparisons, duplicating code, or weakening WireData, we just figure | |
25 | # out what constant Python will use. | |
26 | ||
27 | class _SliceUnspecifiedBound(str): | |
28 | def __getslice__(self, i, j): | |
29 | return j | |
30 | ||
31 | _unspecified_bound = _SliceUnspecifiedBound('')[1:] | |
32 | ||
21 | 33 | class WireData(str): |
22 | 34 | # WireData is a string with stricter slicing |
23 | 35 | def __getitem__(self, key): |
27 | 39 | raise dns.exception.FormError |
28 | 40 | def __getslice__(self, i, j): |
29 | 41 | try: |
30 | if j == sys.maxint: | |
42 | if j == _unspecified_bound: | |
31 | 43 | # handle the case where the right bound is unspecified |
32 | 44 | j = len(self) |
33 | 45 | if i < 0 or j < 0: |
30 | 30 | import dns.ttl |
31 | 31 | import dns.grange |
32 | 32 | |
33 | try: | |
34 | from cStringIO import StringIO | |
35 | except ImportError: | |
36 | from io import StringIO | |
33 | 37 | |
34 | 38 | class BadZone(dns.exception.DNSException): |
35 | 39 | """The zone is malformed.""" |
504 | 508 | finally: |
505 | 509 | if want_close: |
506 | 510 | f.close() |
511 | ||
512 | def to_text(self, sorted=True, relativize=True, nl=None): | |
513 | """Return a zone's text as though it were written to a file. | |
514 | ||
515 | @param sorted: if True, the file will be written with the | |
516 | names sorted in DNSSEC order from least to greatest. Otherwise | |
517 | the names will be written in whatever order they happen to have | |
518 | in the zone's dictionary. | |
519 | @param relativize: if True, domain names in the output will be | |
520 | relativized to the zone's origin (if possible). | |
521 | @type relativize: bool | |
522 | @param nl: The end of line string. If not specified, the | |
523 | output will use the platform's native end-of-line marker (i.e. | |
524 | LF on POSIX, CRLF on Windows, CR on Macintosh). | |
525 | @type nl: string or None | |
526 | """ | |
527 | temp_buffer = StringIO() | |
528 | self.to_file(temp_buffer, sorted, relativize, nl) | |
529 | return_value = temp_buffer.getvalue() | |
530 | temp_buffer.close() | |
531 | return return_value | |
507 | 532 | |
508 | 533 | def check_origin(self): |
509 | 534 | """Do some simple checking of the zone's origin. |
557 | 582 | self.current_origin = origin |
558 | 583 | self.relativize = relativize |
559 | 584 | self.ttl = 0 |
560 | self.last_name = None | |
585 | self.last_name = self.current_origin | |
561 | 586 | self.zone = zone_factory(origin, rdclass, relativize=relativize) |
562 | 587 | self.saved_state = [] |
563 | 588 | self.current_file = None |
812 | 837 | |
813 | 838 | try: |
814 | 839 | while 1: |
815 | token = self.tok.get(True, True).unescape() | |
840 | token = self.tok.get(True, True) | |
816 | 841 | if token.is_eof(): |
817 | 842 | if not self.current_file is None: |
818 | 843 | self.current_file.close() |
17 | 17 | import sys |
18 | 18 | from distutils.core import setup |
19 | 19 | |
20 | version = '1.11.1' | |
20 | version = '1.12.0' | |
21 | 21 | |
22 | 22 | kwargs = { |
23 | 23 | 'name' : 'dnspython', |
19 | 19 | check: test |
20 | 20 | |
21 | 21 | test: |
22 | @for i in *.py; do \ | |
23 | echo "Running $$i:"; \ | |
24 | ${PYTHON} $$i || exit 1; \ | |
25 | done | |
22 | ${PYTHON} ./utest.py |
0 | # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.rdata | |
18 | import dns.rdataclass | |
19 | import dns.rdatatype | |
20 | import dns.ttl | |
21 | ||
22 | class BugsTestCase(unittest.TestCase): | |
23 | ||
24 | def test_float_LOC(self): | |
25 | rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.LOC, | |
26 | "30 30 0.000 N 100 30 0.000 W 10.00m 20m 2000m 20m") | |
27 | self.failUnless(rdata.float_latitude == 30.5) | |
28 | self.failUnless(rdata.float_longitude == -100.5) | |
29 | ||
30 | def test_SOA_BIND8_TTL(self): | |
31 | rdata1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
32 | "a b 100 1s 1m 1h 1d") | |
33 | rdata2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
34 | "a b 100 1 60 3600 86400") | |
35 | self.failUnless(rdata1 == rdata2) | |
36 | ||
37 | def test_TTL_bounds_check(self): | |
38 | def bad(): | |
39 | ttl = dns.ttl.from_text("2147483648") | |
40 | self.failUnlessRaises(dns.ttl.BadTTL, bad) | |
41 | ||
42 | def test_empty_NSEC3_window(self): | |
43 | rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NSEC3, | |
44 | "1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715") | |
45 | self.failUnless(rdata.windows == []) | |
46 | ||
47 | if __name__ == '__main__': | |
48 | unittest.main() |
0 | # Copyright (C) 2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.dnssec | |
18 | import dns.name | |
19 | import dns.rdata | |
20 | import dns.rdataclass | |
21 | import dns.rdatatype | |
22 | import dns.rrset | |
23 | ||
24 | abs_dnspython_org = dns.name.from_text('dnspython.org') | |
25 | ||
26 | abs_keys = { abs_dnspython_org : | |
27 | dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'DNSKEY', | |
28 | '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=', | |
29 | '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF') | |
30 | } | |
31 | ||
32 | abs_keys_duplicate_keytag = { abs_dnspython_org : | |
33 | dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'DNSKEY', | |
34 | '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=', | |
35 | '256 3 5 AwEAAdSSg++++THIS/IS/NOT/THE/CORRECT/KEY++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ AaOSydAF', | |
36 | '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF') | |
37 | } | |
38 | ||
39 | rel_keys = { dns.name.empty : | |
40 | dns.rrset.from_text('@', 3600, 'IN', 'DNSKEY', | |
41 | '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=', | |
42 | '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF') | |
43 | } | |
44 | ||
45 | when = 1290250287 | |
46 | ||
47 | abs_soa = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'SOA', | |
48 | 'howl.dnspython.org. hostmaster.dnspython.org. 2010020047 3600 1800 604800 3600') | |
49 | ||
50 | abs_other_soa = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'SOA', | |
51 | 'foo.dnspython.org. hostmaster.dnspython.org. 2010020047 3600 1800 604800 3600') | |
52 | ||
53 | abs_soa_rrsig = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'RRSIG', | |
54 | 'SOA 5 2 3600 20101127004331 20101119213831 61695 dnspython.org. sDUlltRlFTQw5ITFxOXW3TgmrHeMeNpdqcZ4EXxM9FHhIlte6V9YCnDw t6dvM9jAXdIEi03l9H/RAd9xNNW6gvGMHsBGzpvvqFQxIBR2PoiZA1mX /SWHZFdbt4xjYTtXqpyYvrMK0Dt7bUYPadyhPFCJ1B+I8Zi7B5WJEOd0 8vs=') | |
55 | ||
56 | rel_soa = dns.rrset.from_text('@', 3600, 'IN', 'SOA', | |
57 | 'howl hostmaster 2010020047 3600 1800 604800 3600') | |
58 | ||
59 | rel_other_soa = dns.rrset.from_text('@', 3600, 'IN', 'SOA', | |
60 | 'foo hostmaster 2010020047 3600 1800 604800 3600') | |
61 | ||
62 | rel_soa_rrsig = dns.rrset.from_text('@', 3600, 'IN', 'RRSIG', | |
63 | 'SOA 5 2 3600 20101127004331 20101119213831 61695 @ sDUlltRlFTQw5ITFxOXW3TgmrHeMeNpdqcZ4EXxM9FHhIlte6V9YCnDw t6dvM9jAXdIEi03l9H/RAd9xNNW6gvGMHsBGzpvvqFQxIBR2PoiZA1mX /SWHZFdbt4xjYTtXqpyYvrMK0Dt7bUYPadyhPFCJ1B+I8Zi7B5WJEOd0 8vs=') | |
64 | ||
65 | sep_key = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DNSKEY, | |
66 | '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=') | |
67 | ||
68 | good_ds = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, | |
69 | '57349 5 2 53A79A3E7488AB44FFC56B2D1109F0699D1796DD977E72108B841F96 E47D7013') | |
70 | ||
71 | when2 = 1290425644 | |
72 | ||
73 | abs_example = dns.name.from_text('example') | |
74 | ||
75 | abs_dsa_keys = { abs_example : | |
76 | dns.rrset.from_text('example.', 86400, 'IN', 'DNSKEY', | |
77 | '257 3 3 CI3nCqyJsiCJHTjrNsJOT4RaszetzcJPYuoH3F9ZTVt3KJXncCVR3bwn 1w0iavKljb9hDlAYSfHbFCp4ic/rvg4p1L8vh5s8ToMjqDNl40A0hUGQ Ybx5hsECyK+qHoajilUX1phYSAD8d9WAGO3fDWzUPBuzR7o85NiZCDxz yXuNVfni0uhj9n1KYhEO5yAbbruDGN89wIZcxMKuQsdUY2GYD93ssnBv a55W6XRABYWayKZ90WkRVODLVYLSn53Pj/wwxGH+XdhIAZJXimrZL4yl My7rtBsLMqq8Ihs4Tows7LqYwY7cp6y/50tw6pj8tFqMYcPUjKZV36l1 M/2t5BVg3i7IK61Aidt6aoC3TDJtzAxg3ZxfjZWJfhHjMJqzQIfbW5b9 q1mjFsW5EUv39RaNnX+3JWPRLyDqD4pIwDyqfutMsdk/Py3paHn82FGp CaOg+nicqZ9TiMZURN/XXy5JoXUNQ3RNvbHCUiPUe18KUkY6mTfnyHld 1l9YCWmzXQVClkx/hOYxjJ4j8Ife58+Obu5X', | |
78 | '256 3 3 CJE1yb9YRQiw5d2xZrMUMR+cGCTt1bp1KDCefmYKmS+Z1+q9f42ETVhx JRiQwXclYwmxborzIkSZegTNYIV6mrYwbNB27Q44c3UGcspb3PiOw5TC jNPRYEcdwGvDZ2wWy+vkSV/S9tHXY8O6ODiE6abZJDDg/RnITyi+eoDL R3KZ5n/V1f1T1b90rrV6EewhBGQJpQGDogaXb2oHww9Tm6NfXyo7SoMM pbwbzOckXv+GxRPJIQNSF4D4A9E8XCksuzVVdE/0lr37+uoiAiPia38U 5W2QWe/FJAEPLjIp2eTzf0TrADc1pKP1wrA2ASpdzpm/aX3IB5RPp8Ew S9U72eBFZJAUwg635HxJVxH1maG6atzorR566E+e0OZSaxXS9o1o6QqN 3oPlYLGPORDiExilKfez3C/x/yioOupW9K5eKF0gmtaqrHX0oq9s67f/ RIM2xVaKHgG9Vf2cgJIZkhv7sntujr+E4htnRmy9P9BxyFxsItYxPI6Z bzygHAZpGhlI/7ltEGlIwKxyTK3ZKBm67q7B') | |
79 | } | |
80 | ||
81 | abs_dsa_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', | |
82 | 'ns1.example. hostmaster.example. 2 10800 3600 604800 86400') | |
83 | ||
84 | abs_other_dsa_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', | |
85 | 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401') | |
86 | ||
87 | abs_dsa_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', | |
88 | 'SOA 3 1 86400 20101129143231 20101122112731 42088 example. CGul9SuBofsktunV8cJs4eRs6u+3NCS3yaPKvBbD+pB2C76OUXDZq9U=') | |
89 | ||
90 | example_sep_key = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DNSKEY, | |
91 | '257 3 3 CI3nCqyJsiCJHTjrNsJOT4RaszetzcJPYuoH3F9ZTVt3KJXncCVR3bwn 1w0iavKljb9hDlAYSfHbFCp4ic/rvg4p1L8vh5s8ToMjqDNl40A0hUGQ Ybx5hsECyK+qHoajilUX1phYSAD8d9WAGO3fDWzUPBuzR7o85NiZCDxz yXuNVfni0uhj9n1KYhEO5yAbbruDGN89wIZcxMKuQsdUY2GYD93ssnBv a55W6XRABYWayKZ90WkRVODLVYLSn53Pj/wwxGH+XdhIAZJXimrZL4yl My7rtBsLMqq8Ihs4Tows7LqYwY7cp6y/50tw6pj8tFqMYcPUjKZV36l1 M/2t5BVg3i7IK61Aidt6aoC3TDJtzAxg3ZxfjZWJfhHjMJqzQIfbW5b9 q1mjFsW5EUv39RaNnX+3JWPRLyDqD4pIwDyqfutMsdk/Py3paHn82FGp CaOg+nicqZ9TiMZURN/XXy5JoXUNQ3RNvbHCUiPUe18KUkY6mTfnyHld 1l9YCWmzXQVClkx/hOYxjJ4j8Ife58+Obu5X') | |
92 | ||
93 | example_ds_sha1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, | |
94 | '18673 3 1 71b71d4f3e11bbd71b4eff12cde69f7f9215bbe7') | |
95 | ||
96 | example_ds_sha256 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, | |
97 | '18673 3 2 eb8344cbbf07c9d3d3d6c81d10c76653e28d8611a65e639ef8f716e4e4e5d913') | |
98 | ||
99 | class DNSSECValidatorTestCase(unittest.TestCase): | |
100 | ||
101 | def testAbsoluteRSAGood(self): | |
102 | dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys, None, when) | |
103 | ||
104 | def testDuplicateKeytag(self): | |
105 | dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys_duplicate_keytag, None, when) | |
106 | ||
107 | def testAbsoluteRSABad(self): | |
108 | def bad(): | |
109 | dns.dnssec.validate(abs_other_soa, abs_soa_rrsig, abs_keys, None, | |
110 | when) | |
111 | self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) | |
112 | ||
113 | def testRelativeRSAGood(self): | |
114 | dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys, | |
115 | abs_dnspython_org, when) | |
116 | ||
117 | def testRelativeRSABad(self): | |
118 | def bad(): | |
119 | dns.dnssec.validate(rel_other_soa, rel_soa_rrsig, rel_keys, | |
120 | abs_dnspython_org, when) | |
121 | self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) | |
122 | ||
123 | def testMakeSHA256DS(self): | |
124 | ds = dns.dnssec.make_ds(abs_dnspython_org, sep_key, 'SHA256') | |
125 | self.failUnless(ds == good_ds) | |
126 | ||
127 | def testAbsoluteDSAGood(self): | |
128 | dns.dnssec.validate(abs_dsa_soa, abs_dsa_soa_rrsig, abs_dsa_keys, None, | |
129 | when2) | |
130 | ||
131 | def testAbsoluteDSABad(self): | |
132 | def bad(): | |
133 | dns.dnssec.validate(abs_other_dsa_soa, abs_dsa_soa_rrsig, | |
134 | abs_dsa_keys, None, when2) | |
135 | self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) | |
136 | ||
137 | def testMakeExampleSHA1DS(self): | |
138 | ds = dns.dnssec.make_ds(abs_example, example_sep_key, 'SHA1') | |
139 | self.failUnless(ds == example_ds_sha1) | |
140 | ||
141 | def testMakeExampleSHA256DS(self): | |
142 | ds = dns.dnssec.make_ds(abs_example, example_sep_key, 'SHA256') | |
143 | self.failUnless(ds == example_ds_sha256) | |
144 | ||
145 | if __name__ == '__main__': | |
146 | import_ok = False | |
147 | try: | |
148 | import Crypto.Util.number | |
149 | import_ok = True | |
150 | except: | |
151 | pass | |
152 | if import_ok: | |
153 | unittest.main() | |
154 | else: | |
155 | print 'skipping DNSSEC tests because pycrypto is not installed' |
0 | @ 300 IN SOA ns1 hostmaster 1 2000 2000 1814400 3600 | |
1 | @ 300 IN NS ns1 | |
2 | @ 300 IN NS ns2 | |
3 | * 300 IN MX 10 mail | |
4 | a 300 IN TXT "foo foo foo" | |
5 | a 300 IN PTR foo.net. | |
6 | a01 3600 IN A 0.0.0.0 | |
7 | a02 3600 IN A 255.255.255.255 | |
8 | aaaa01 3600 IN AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | |
9 | aaaa02 3600 IN AAAA ::1 | |
10 | afsdb01 3600 IN AFSDB 0 hostname | |
11 | afsdb02 3600 IN AFSDB 65535 . | |
12 | apl01 3600 IN APL 1:192.168.32.0/21 !1:192.168.38.0/28 | |
13 | apl02 3600 IN APL 1:224.0.0.0/4 2:FF00:0:0:0:0:0:0:0/8 | |
14 | b 300 IN CNAME foo.net. | |
15 | c 300 IN A 73.80.65.49 | |
16 | cert01 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz 45IkskceFGgiWCn/GxHhai6VAuHAoNUz 4YoU1tVfSCSqQYn6//11U6Nld80jEeC8 aTrO+KKmCaY= | |
17 | cname01 3600 IN CNAME cname-target. | |
18 | cname02 3600 IN CNAME cname-target | |
19 | cname03 3600 IN CNAME . | |
20 | d 300 IN A 73.80.65.49 | |
21 | dhcid01 3600 IN DHCID AAIBY2/AuCccgoJbsaxcQc9TUapptP69 lOjxfNuVAA2kjEA= | |
22 | dhcid02 3600 IN DHCID AAEBOSD+XR3Os/0LozeXVqcNc7FwCfQd WL3b/NaiUDlW2No= | |
23 | dhcid03 3600 IN DHCID AAABxLmlskllE0MVjd57zHcWmEH3pCQ6 VytcKD//7es/deY= | |
24 | dlv01 3600 IN DLV 12345 3 1 123456789abcdef67890123456789abcdef67890 | |
25 | dname01 3600 IN DNAME dname-target. | |
26 | dname02 3600 IN DNAME dname-target | |
27 | dname03 3600 IN DNAME . | |
28 | dnskey01 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8= | |
29 | dnskey02 3600 IN DNSKEY 257 3 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRu niJDBzC7w0aRyzWZriO6i2odGWWQVucZ qKVsENW91IOW4vqudngPZsY3GvQ/xVA8 /7pyFj6b7Esga60zyGW6LFe9r8n6paHr lG5ojqf0BaqHT+8= | |
30 | ds01 3600 IN DS 12345 3 1 123456789abcdef67890123456789abcdef67890 | |
31 | e 300 IN MX 10 mail | |
32 | e 300 IN TXT "one" | |
33 | e 300 IN TXT "three" | |
34 | e 300 IN TXT "two" | |
35 | e 300 IN A 73.80.65.49 | |
36 | e 300 IN A 73.80.65.50 | |
37 | e 300 IN A 73.80.65.52 | |
38 | e 300 IN A 73.80.65.51 | |
39 | f 300 IN A 73.80.65.52 | |
40 | gpos01 3600 IN GPOS -22.6882 116.8652 250.0 | |
41 | hinfo01 3600 IN HINFO "Generic PC clone" "NetBSD-1.4" | |
42 | hinfo02 3600 IN HINFO "PC" "NetBSD" | |
43 | hip01 3600 IN HIP 2 200100107b1a74df365639cc39f1d578 AwEAAbdxyhNuSutc5EMzxTs9LBPCIkOFH8cIvM4p9+LrV4e19WzK00+CI6zBCQTdtWsuxKbWIy87UOoJTwkUs7lBu+Upr1gsNrut79ryra+bSRGQb1slImA8YVJyuIDsj7kwzG7jnERNqnWxZ48AWkskmdHaVDP4BcelrTI3rMXdXF5D rvs1.example.com. rvs2 | |
44 | ipseckey01 3600 IN IPSECKEY 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== | |
45 | ipseckey02 3600 IN IPSECKEY 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== | |
46 | ipseckey03 3600 IN IPSECKEY 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== | |
47 | ipseckey04 3600 IN IPSECKEY 10 2 2 2001:0DB8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== | |
48 | ipseckey05 3600 IN IPSECKEY 10 3 2 mygateway2 AQNRU3mG7TVTO2BkR47usntb102uFJtu gbo6BSGvgqt4AQ== | |
49 | isdn01 3600 IN ISDN "isdn-address" | |
50 | isdn02 3600 IN ISDN "isdn-address" "subaddress" | |
51 | isdn03 3600 IN ISDN "isdn-address" | |
52 | isdn04 3600 IN ISDN "isdn-address" "subaddress" | |
53 | kx01 3600 IN KX 10 kdc | |
54 | kx02 3600 IN KX 10 . | |
55 | loc01 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m | |
56 | loc02 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m | |
57 | loc03 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 90000000.00m 2000.00m 20.00m | |
58 | loc04 3600 IN LOC 60 9 1.500 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m | |
59 | loc05 3600 IN LOC 60 9 1.510 N 24 39 0.000 E 10.00m 20.00m 2000.00m 20.00m | |
60 | mx01 3600 IN MX 10 mail | |
61 | mx02 3600 IN MX 10 . | |
62 | naptr01 3600 IN NAPTR 0 0 "" "" "" . | |
63 | naptr02 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo. | |
64 | ns1 300 IN A 10.53.0.1 | |
65 | ns2 300 IN A 10.53.0.2 | |
66 | nsap-ptr01 3600 IN NSAP-PTR foo. | |
67 | nsap-ptr01 3600 IN NSAP-PTR . | |
68 | nsap01 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 | |
69 | nsap02 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100 | |
70 | nsec01 3600 IN NSEC a.secure. A MX RRSIG NSEC TYPE1234 | |
71 | nsec02 3600 IN NSEC . NSAP-PTR NSEC | |
72 | nsec03 3600 IN NSEC . NSEC TYPE65535 | |
73 | nsec301 3600 IN NSEC3 1 1 12 aabbccdd 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM | |
74 | nsec302 3600 IN NSEC3 1 1 12 - 2t7b4g4vsa5smi47k61mv5bv1a22bojr NS SOA MX RRSIG DNSKEY NSEC3PARAM | |
75 | nsec3param01 3600 IN NSEC3PARAM 1 1 12 aabbccdd | |
76 | nsec3param02 3600 IN NSEC3PARAM 1 1 12 - | |
77 | ptr01 3600 IN PTR @ | |
78 | px01 3600 IN PX 65535 foo. bar. | |
79 | px02 3600 IN PX 65535 . . | |
80 | rp01 3600 IN RP mbox-dname txt-dname | |
81 | rp02 3600 IN RP . . | |
82 | rrsig01 3600 IN RRSIG NSEC 1 3 3600 20200101000000 20030101000000 2143 foo MxFcby9k/yvedMfQgKzhH5er0Mu/vILz 45IkskceFGgiWCn/GxHhai6VAuHAoNUz 4YoU1tVfSCSqQYn6//11U6Nld80jEeC8 aTrO+KKmCaY= | |
83 | rt01 3600 IN RT 0 intermediate-host | |
84 | rt02 3600 IN RT 65535 . | |
85 | s 300 IN NS ns.s | |
86 | ns.s 300 IN A 73.80.65.49 | |
87 | spf 3600 IN SPF "v=spf1 mx -all" | |
88 | srv01 3600 IN SRV 0 0 0 . | |
89 | srv02 3600 IN SRV 65535 65535 65535 old-slow-box.example.com. | |
90 | sshfp1 3600 IN SSHFP 1 1 aa549bfe898489c02d1715d97d79c57ba2fa76ab | |
91 | t 301 IN A 73.80.65.49 | |
92 | tlsa1 3600 IN TLSA 3 1 1 a9cdf989b504fe5dca90c0d2167b6550570734f7c763e09fdf88904e06157065 | |
93 | tlsa2 3600 IN TLSA 1 0 1 efddf0d915c7bdc5782c0881e1b2a95ad099fbdd06d7b1f77982d9364338d955 | |
94 | tlsa3 3600 IN TLSA 1 0 2 81ee7f6c0ecc6b09b7785a9418f54432de630dd54dc6ee9e3c49de547708d236d4c413c3e97e44f969e635958aa410495844127c04883503e5b024cf7a8f6a94 | |
95 | txt01 3600 IN TXT "foo" | |
96 | txt02 3600 IN TXT "foo" "bar" | |
97 | txt03 3600 IN TXT "foo" | |
98 | txt04 3600 IN TXT "foo" "bar" | |
99 | txt05 3600 IN TXT "foo bar" | |
100 | txt06 3600 IN TXT "foo bar" | |
101 | txt07 3600 IN TXT "foo bar" | |
102 | txt08 3600 IN TXT "foo\010bar" | |
103 | txt09 3600 IN TXT "foo\010bar" | |
104 | txt10 3600 IN TXT "foo bar" | |
105 | txt11 3600 IN TXT "\"foo\"" | |
106 | txt12 3600 IN TXT "\"foo\"" | |
107 | txt13 3600 IN TXT "foo" | |
108 | u 300 IN TXT "txt-not-in-nxt" | |
109 | a.u 300 IN A 73.80.65.49 | |
110 | b.u 300 IN A 73.80.65.49 | |
111 | unknown2 3600 IN TYPE999 \# 8 0a0000010a000001 | |
112 | unknown3 3600 IN A 127.0.0.2 | |
113 | wks01 3600 IN WKS 10.0.0.1 6 0 1 2 21 23 | |
114 | wks02 3600 IN WKS 10.0.0.1 17 0 1 2 53 | |
115 | wks03 3600 IN WKS 10.0.0.2 6 65535 | |
116 | x2501 3600 IN X25 "123456789" |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.flags | |
18 | import dns.rcode | |
19 | import dns.opcode | |
20 | ||
21 | class FlagsTestCase(unittest.TestCase): | |
22 | ||
23 | def test_rcode1(self): | |
24 | self.failUnless(dns.rcode.from_text('FORMERR') == dns.rcode.FORMERR) | |
25 | ||
26 | def test_rcode2(self): | |
27 | self.failUnless(dns.rcode.to_text(dns.rcode.FORMERR) == "FORMERR") | |
28 | ||
29 | def test_rcode3(self): | |
30 | self.failUnless(dns.rcode.to_flags(dns.rcode.FORMERR) == (1, 0)) | |
31 | ||
32 | def test_rcode4(self): | |
33 | self.failUnless(dns.rcode.to_flags(dns.rcode.BADVERS) == \ | |
34 | (0, 0x01000000)) | |
35 | ||
36 | def test_rcode6(self): | |
37 | self.failUnless(dns.rcode.from_flags(0, 0x01000000) == \ | |
38 | dns.rcode.BADVERS) | |
39 | ||
40 | def test_rcode6(self): | |
41 | self.failUnless(dns.rcode.from_flags(5, 0) == dns.rcode.REFUSED) | |
42 | ||
43 | def test_rcode7(self): | |
44 | def bad(): | |
45 | dns.rcode.to_flags(4096) | |
46 | self.failUnlessRaises(ValueError, bad) | |
47 | ||
48 | def test_flags1(self): | |
49 | self.failUnless(dns.flags.from_text("RA RD AA QR") == \ | |
50 | dns.flags.QR|dns.flags.AA|dns.flags.RD|dns.flags.RA) | |
51 | ||
52 | def test_flags2(self): | |
53 | flags = dns.flags.QR|dns.flags.AA|dns.flags.RD|dns.flags.RA | |
54 | self.failUnless(dns.flags.to_text(flags) == "QR AA RD RA") | |
55 | ||
56 | ||
57 | if __name__ == '__main__': | |
58 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import sys | |
16 | sys.path.insert(0, '../') # Force the local project to be *the* dns | |
17 | ||
18 | import cStringIO | |
19 | import filecmp | |
20 | import os | |
21 | import unittest | |
22 | ||
23 | import dns.exception | |
24 | import dns.rdata | |
25 | import dns.rdataclass | |
26 | import dns.rdatatype | |
27 | import dns.rrset | |
28 | import dns.zone | |
29 | ||
30 | import pprint | |
31 | ||
32 | pp = pprint.PrettyPrinter(indent=2) | |
33 | ||
34 | import pdb | |
35 | example_text = """$TTL 1h | |
36 | $ORIGIN 0.0.192.IN-ADDR.ARPA. | |
37 | $GENERATE 1-2 0 CNAME SERVER$.EXAMPLE. | |
38 | """ | |
39 | ||
40 | example_text1 = """$TTL 1h | |
41 | $ORIGIN 0.0.192.IN-ADDR.ARPA. | |
42 | $GENERATE 1-10 fooo$ CNAME $.0 | |
43 | """ | |
44 | ||
45 | example_text2 = """$TTL 1h | |
46 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
47 | @ 3600 IN NS ns1 | |
48 | @ 3600 IN NS ns2 | |
49 | bar.foo 300 IN MX 0 blaz.foo | |
50 | ns1 3600 IN A 10.0.0.1 | |
51 | ns2 3600 IN A 10.0.0.2 | |
52 | $GENERATE 3-5 foo$ A 10.0.0.$ | |
53 | """ | |
54 | ||
55 | example_text3 = """$TTL 1h | |
56 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
57 | @ 3600 IN NS ns1 | |
58 | @ 3600 IN NS ns2 | |
59 | bar.foo 300 IN MX 0 blaz.foo | |
60 | ns1 3600 IN A 10.0.0.1 | |
61 | ns2 3600 IN A 10.0.0.2 | |
62 | $GENERATE 4-8/2 foo$ A 10.0.0.$ | |
63 | """ | |
64 | ||
65 | example_text4 = """$TTL 1h | |
66 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
67 | @ 3600 IN NS ns1 | |
68 | @ 3600 IN NS ns2 | |
69 | bar.foo 300 IN MX 0 blaz.foo | |
70 | ns1 3600 IN A 10.0.0.1 | |
71 | ns2 3600 IN A 10.0.0.2 | |
72 | $GENERATE 11-13 wp-db${-10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR. | |
73 | """ | |
74 | ||
75 | example_text5 = """$TTL 1h | |
76 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
77 | @ 3600 IN NS ns1 | |
78 | @ 3600 IN NS ns2 | |
79 | bar.foo 300 IN MX 0 blaz.foo | |
80 | ns1 3600 IN A 10.0.0.1 | |
81 | ns2 3600 IN A 10.0.0.2 | |
82 | $GENERATE 11-13 wp-db${10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR. | |
83 | """ | |
84 | ||
85 | example_text6 = """$TTL 1h | |
86 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
87 | @ 3600 IN NS ns1 | |
88 | @ 3600 IN NS ns2 | |
89 | bar.foo 300 IN MX 0 blaz.foo | |
90 | ns1 3600 IN A 10.0.0.1 | |
91 | ns2 3600 IN A 10.0.0.2 | |
92 | $GENERATE 11-13 wp-db${+10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR. | |
93 | """ | |
94 | ||
95 | example_text7 = """$TTL 1h | |
96 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
97 | @ 3600 IN NS ns1 | |
98 | @ 3600 IN NS ns2 | |
99 | bar.foo 300 IN MX 0 blaz.foo | |
100 | ns1 3600 IN A 10.0.0.1 | |
101 | ns2 3600 IN A 10.0.0.2 | |
102 | $GENERATE 11-13 sync${-10}.db IN A 10.10.16.0 | |
103 | """ | |
104 | ||
105 | example_text8 = """$TTL 1h | |
106 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
107 | @ 3600 IN NS ns1 | |
108 | @ 3600 IN NS ns2 | |
109 | bar.foo 300 IN MX 0 blaz.foo | |
110 | ns1 3600 IN A 10.0.0.1 | |
111 | ns2 3600 IN A 10.0.0.2 | |
112 | $GENERATE 11-12 wp-db${-10,2,d} IN A 10.10.16.0 | |
113 | """ | |
114 | ||
115 | example_text9 = """$TTL 1h | |
116 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
117 | @ 3600 IN NS ns1 | |
118 | @ 3600 IN NS ns2 | |
119 | bar.foo 300 IN MX 0 blaz.foo | |
120 | ns1 3600 IN A 10.0.0.1 | |
121 | ns2 3600 IN A 10.0.0.2 | |
122 | $GENERATE 11-12 wp-db${-10,2,d} IN A 10.10.16.0 | |
123 | $GENERATE 11-13 sync${-10}.db IN A 10.10.16.0 | |
124 | """ | |
125 | example_text10 = """$TTL 1h | |
126 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
127 | @ 3600 IN NS ns1 | |
128 | @ 3600 IN NS ns2 | |
129 | bar.foo 300 IN MX 0 blaz.foo | |
130 | ns1 3600 IN A 10.0.0.1 | |
131 | ns2 3600 IN A 10.0.0.2 | |
132 | $GENERATE 27-28 $.2 PTR zlb${-26}.oob | |
133 | """ | |
134 | ||
135 | ||
136 | class GenerateTestCase(unittest.TestCase): | |
137 | ||
138 | def testFromText(self): | |
139 | def bad(): | |
140 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
141 | self.failUnlessRaises(dns.zone.NoSOA, bad) | |
142 | ||
143 | def testFromText1(self): | |
144 | def bad(): | |
145 | z = dns.zone.from_text(example_text1, 'example.', relativize=True) | |
146 | self.failUnlessRaises(dns.zone.NoSOA, bad) | |
147 | ||
148 | def testIterateAllRdatas2(self): | |
149 | z = dns.zone.from_text(example_text2, 'example.', relativize=True) | |
150 | l = list(z.iterate_rdatas()) | |
151 | l.sort() | |
152 | exl = [(dns.name.from_text('@', None), | |
153 | 3600, | |
154 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
155 | 'ns1')), | |
156 | (dns.name.from_text('@', None), | |
157 | 3600, | |
158 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
159 | 'ns2')), | |
160 | (dns.name.from_text('@', None), | |
161 | 3600, | |
162 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
163 | 'foo bar 1 2 3 4 5')), | |
164 | (dns.name.from_text('bar.foo', None), | |
165 | 300, | |
166 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
167 | '0 blaz.foo')), | |
168 | (dns.name.from_text('ns1', None), | |
169 | 3600, | |
170 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
171 | '10.0.0.1')), | |
172 | (dns.name.from_text('ns2', None), | |
173 | 3600, | |
174 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
175 | '10.0.0.2')), | |
176 | (dns.name.from_text('foo3', None), | |
177 | 3600, | |
178 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
179 | '10.0.0.3')), | |
180 | (dns.name.from_text('foo4', None), | |
181 | 3600, | |
182 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
183 | '10.0.0.4')), | |
184 | (dns.name.from_text('foo5', None), | |
185 | 3600, | |
186 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
187 | '10.0.0.5'))] | |
188 | ||
189 | exl.sort() | |
190 | self.failUnless(l == exl) | |
191 | ||
192 | def testIterateAllRdatas3(self): | |
193 | z = dns.zone.from_text(example_text3, 'example.', relativize=True) | |
194 | l = list(z.iterate_rdatas()) | |
195 | l.sort() | |
196 | exl = [(dns.name.from_text('@', None), | |
197 | 3600, | |
198 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
199 | 'ns1')), | |
200 | (dns.name.from_text('@', None), | |
201 | 3600, | |
202 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
203 | 'ns2')), | |
204 | (dns.name.from_text('@', None), | |
205 | 3600, | |
206 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
207 | 'foo bar 1 2 3 4 5')), | |
208 | (dns.name.from_text('bar.foo', None), | |
209 | 300, | |
210 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
211 | '0 blaz.foo')), | |
212 | (dns.name.from_text('ns1', None), | |
213 | 3600, | |
214 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
215 | '10.0.0.1')), | |
216 | (dns.name.from_text('ns2', None), | |
217 | 3600, | |
218 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
219 | '10.0.0.2')), | |
220 | (dns.name.from_text('foo4', None), 3600, | |
221 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
222 | '10.0.0.4')), | |
223 | (dns.name.from_text('foo6', None), 3600, | |
224 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
225 | '10.0.0.6')), | |
226 | (dns.name.from_text('foo8', None), 3600, | |
227 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
228 | '10.0.0.8'))] | |
229 | exl.sort() | |
230 | self.failUnless(l == exl) | |
231 | def testGenerate1(self): | |
232 | z = dns.zone.from_text(example_text4, 'example.', relativize=True) | |
233 | l = list(z.iterate_rdatas()) | |
234 | l.sort() | |
235 | exl = [(dns.name.from_text('@', None), | |
236 | 3600L, | |
237 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
238 | 'ns1')), | |
239 | (dns.name.from_text('@', None), | |
240 | 3600L, | |
241 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
242 | 'ns2')), | |
243 | (dns.name.from_text('@', None), | |
244 | 3600L, | |
245 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
246 | 'foo bar 1 2 3 4 5')), | |
247 | (dns.name.from_text('bar.foo', None), | |
248 | 300L, | |
249 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
250 | '0 blaz.foo')), | |
251 | (dns.name.from_text('ns1', None), | |
252 | 3600L, | |
253 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
254 | '10.0.0.1')), | |
255 | (dns.name.from_text('ns2', None), | |
256 | 3600L, | |
257 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
258 | '10.0.0.2')), | |
259 | ||
260 | (dns.name.from_text('wp-db01.services.mozilla.com', None), | |
261 | 0L, | |
262 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
263 | 'SERVER.FOOBAR.')), | |
264 | ||
265 | (dns.name.from_text('wp-db02.services.mozilla.com', None), | |
266 | 0L, | |
267 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
268 | 'SERVER.FOOBAR.')), | |
269 | ||
270 | (dns.name.from_text('wp-db03.services.mozilla.com', None), | |
271 | 0L, | |
272 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
273 | 'SERVER.FOOBAR.'))] | |
274 | exl.sort() | |
275 | self.failUnless(l == exl) | |
276 | ||
277 | def testGenerate2(self): | |
278 | z = dns.zone.from_text(example_text5, 'example.', relativize=True) | |
279 | l = list(z.iterate_rdatas()) | |
280 | l.sort() | |
281 | exl = [(dns.name.from_text('@', None), | |
282 | 3600L, | |
283 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
284 | 'ns1')), | |
285 | (dns.name.from_text('@', None), | |
286 | 3600L, | |
287 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
288 | 'ns2')), | |
289 | (dns.name.from_text('@', None), | |
290 | 3600L, | |
291 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
292 | 'foo bar 1 2 3 4 5')), | |
293 | (dns.name.from_text('bar.foo', None), | |
294 | 300L, | |
295 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
296 | '0 blaz.foo')), | |
297 | (dns.name.from_text('ns1', None), | |
298 | 3600L, | |
299 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
300 | '10.0.0.1')), | |
301 | (dns.name.from_text('ns2', None), | |
302 | 3600L, | |
303 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
304 | '10.0.0.2')), | |
305 | ||
306 | (dns.name.from_text('wp-db21.services.mozilla.com', None), 0L, | |
307 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
308 | 'SERVER.FOOBAR.')), | |
309 | ||
310 | (dns.name.from_text('wp-db22.services.mozilla.com', None), 0L, | |
311 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
312 | 'SERVER.FOOBAR.')), | |
313 | ||
314 | (dns.name.from_text('wp-db23.services.mozilla.com', None), 0L, | |
315 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
316 | 'SERVER.FOOBAR.'))] | |
317 | exl.sort() | |
318 | self.failUnless(l == exl) | |
319 | ||
320 | def testGenerate3(self): | |
321 | z = dns.zone.from_text(example_text6, 'example.', relativize=True) | |
322 | l = list(z.iterate_rdatas()) | |
323 | l.sort() | |
324 | ||
325 | exl = [(dns.name.from_text('@', None), | |
326 | 3600L, | |
327 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
328 | 'ns1')), | |
329 | (dns.name.from_text('@', None), | |
330 | 3600L, | |
331 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
332 | 'ns2')), | |
333 | (dns.name.from_text('@', None), | |
334 | 3600L, | |
335 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
336 | 'foo bar 1 2 3 4 5')), | |
337 | (dns.name.from_text('bar.foo', None), | |
338 | 300L, | |
339 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
340 | '0 blaz.foo')), | |
341 | (dns.name.from_text('ns1', None), | |
342 | 3600L, | |
343 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
344 | '10.0.0.1')), | |
345 | (dns.name.from_text('ns2', None), | |
346 | 3600L, | |
347 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
348 | '10.0.0.2')), | |
349 | (dns.name.from_text('wp-db21.services.mozilla.com', None), 0L, | |
350 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
351 | 'SERVER.FOOBAR.')), | |
352 | ||
353 | (dns.name.from_text('wp-db22.services.mozilla.com', None), 0L, | |
354 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
355 | 'SERVER.FOOBAR.')), | |
356 | ||
357 | (dns.name.from_text('wp-db23.services.mozilla.com', None), 0L, | |
358 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
359 | 'SERVER.FOOBAR.'))] | |
360 | exl.sort() | |
361 | self.failUnless(l == exl) | |
362 | ||
363 | def testGenerate4(self): | |
364 | z = dns.zone.from_text(example_text7, 'example.', relativize=True) | |
365 | l = list(z.iterate_rdatas()) | |
366 | l.sort() | |
367 | exl = [(dns.name.from_text('@', None), | |
368 | 3600L, | |
369 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
370 | 'ns1')), | |
371 | (dns.name.from_text('@', None), | |
372 | 3600L, | |
373 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
374 | 'ns2')), | |
375 | (dns.name.from_text('@', None), | |
376 | 3600L, | |
377 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
378 | 'foo bar 1 2 3 4 5')), | |
379 | (dns.name.from_text('bar.foo', None), | |
380 | 300L, | |
381 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
382 | '0 blaz.foo')), | |
383 | (dns.name.from_text('ns1', None), | |
384 | 3600L, | |
385 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
386 | '10.0.0.1')), | |
387 | (dns.name.from_text('ns2', None), | |
388 | 3600L, | |
389 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
390 | '10.0.0.2')), | |
391 | ||
392 | (dns.name.from_text('sync1.db', None), 3600L, | |
393 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
394 | '10.10.16.0')), | |
395 | ||
396 | (dns.name.from_text('sync2.db', None), 3600L, | |
397 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
398 | '10.10.16.0')), | |
399 | ||
400 | (dns.name.from_text('sync3.db', None), 3600L, | |
401 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
402 | '10.10.16.0'))] | |
403 | exl.sort() | |
404 | self.failUnless(l == exl) | |
405 | ||
406 | def testGenerate6(self): | |
407 | z = dns.zone.from_text(example_text9, 'example.', relativize=True) | |
408 | l = list(z.iterate_rdatas()) | |
409 | l.sort() | |
410 | exl = [(dns.name.from_text('@', None), | |
411 | 3600L, | |
412 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
413 | 'ns1')), | |
414 | (dns.name.from_text('@', None), | |
415 | 3600L, | |
416 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
417 | 'ns2')), | |
418 | (dns.name.from_text('@', None), | |
419 | 3600L, | |
420 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
421 | 'foo bar 1 2 3 4 5')), | |
422 | (dns.name.from_text('bar.foo', None), | |
423 | 300L, | |
424 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
425 | '0 blaz.foo')), | |
426 | (dns.name.from_text('ns1', None), | |
427 | 3600L, | |
428 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
429 | '10.0.0.1')), | |
430 | (dns.name.from_text('ns2', None), | |
431 | 3600L, | |
432 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
433 | '10.0.0.2')), | |
434 | ||
435 | (dns.name.from_text('wp-db01', None), 3600L, | |
436 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
437 | '10.10.16.0')), | |
438 | (dns.name.from_text('wp-db02', None), 3600L, | |
439 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
440 | '10.10.16.0')), | |
441 | ||
442 | (dns.name.from_text('sync1.db', None), 3600L, | |
443 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
444 | '10.10.16.0')), | |
445 | ||
446 | (dns.name.from_text('sync2.db', None), 3600L, | |
447 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
448 | '10.10.16.0')), | |
449 | ||
450 | (dns.name.from_text('sync3.db', None), 3600L, | |
451 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
452 | '10.10.16.0'))] | |
453 | exl.sort() | |
454 | self.failUnless(l == exl) | |
455 | ||
456 | def testGenerate7(self): | |
457 | z = dns.zone.from_text(example_text10, 'example.', relativize=True) | |
458 | l = list(z.iterate_rdatas()) | |
459 | l.sort() | |
460 | exl = [(dns.name.from_text('@', None), | |
461 | 3600L, | |
462 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
463 | 'ns1')), | |
464 | (dns.name.from_text('@', None), | |
465 | 3600L, | |
466 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
467 | 'ns2')), | |
468 | (dns.name.from_text('@', None), | |
469 | 3600L, | |
470 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
471 | 'foo bar 1 2 3 4 5')), | |
472 | (dns.name.from_text('bar.foo', None), | |
473 | 300L, | |
474 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
475 | '0 blaz.foo')), | |
476 | (dns.name.from_text('ns1', None), | |
477 | 3600L, | |
478 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
479 | '10.0.0.1')), | |
480 | (dns.name.from_text('ns2', None), | |
481 | 3600L, | |
482 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
483 | '10.0.0.2')), | |
484 | ||
485 | (dns.name.from_text('27.2', None), 3600L, | |
486 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR, | |
487 | 'zlb1.oob')), | |
488 | ||
489 | (dns.name.from_text('28.2', None), 3600L, | |
490 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR, | |
491 | 'zlb2.oob'))] | |
492 | ||
493 | exl.sort() | |
494 | self.failUnless(l == exl) | |
495 | ||
496 | ||
497 | if __name__ == '__main__': | |
498 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import sys | |
16 | sys.path.insert(0, '../') | |
17 | ||
18 | import cStringIO | |
19 | import filecmp | |
20 | import os | |
21 | import unittest | |
22 | ||
23 | import dns | |
24 | import dns.exception | |
25 | import dns.grange | |
26 | ||
27 | import pdb | |
28 | ||
29 | ||
30 | ||
31 | class GRangeTestCase(unittest.TestCase): | |
32 | ||
33 | def testFromText1(self): | |
34 | start, stop, step = dns.grange.from_text('1-1') | |
35 | self.assertEqual(start, 1) | |
36 | self.assertEqual(stop, 1) | |
37 | self.assertEqual(step, 1) | |
38 | ||
39 | def testFromText2(self): | |
40 | start, stop, step = dns.grange.from_text('1-4') | |
41 | self.assertEqual(start, 1) | |
42 | self.assertEqual(stop, 4) | |
43 | self.assertEqual(step, 1) | |
44 | ||
45 | def testFromText3(self): | |
46 | start, stop, step = dns.grange.from_text('4-255') | |
47 | self.assertEqual(start, 4) | |
48 | self.assertEqual(stop, 255) | |
49 | self.assertEqual(step, 1) | |
50 | ||
51 | def testFromText4(self): | |
52 | start, stop, step = dns.grange.from_text('1-1/1') | |
53 | self.assertEqual(start, 1) | |
54 | self.assertEqual(stop, 1) | |
55 | self.assertEqual(step, 1) | |
56 | ||
57 | def testFromText5(self): | |
58 | start, stop, step = dns.grange.from_text('1-4/2') | |
59 | self.assertEqual(start, 1) | |
60 | self.assertEqual(stop, 4) | |
61 | self.assertEqual(step, 2) | |
62 | ||
63 | def testFromText6(self): | |
64 | start, stop, step = dns.grange.from_text('4-255/77') | |
65 | self.assertEqual(start, 4) | |
66 | self.assertEqual(stop, 255) | |
67 | self.assertEqual(step, 77) | |
68 | ||
69 | def testFailFromText1(self): | |
70 | def bad(): | |
71 | start = 2 | |
72 | stop = 1 | |
73 | step = 1 | |
74 | dns.grange.from_text('%d-%d/%d' % (start, stop, step)) | |
75 | self.assertRaises(AssertionError, bad) | |
76 | ||
77 | def testFailFromText2(self): | |
78 | def bad(): | |
79 | start = '-1' | |
80 | stop = 3 | |
81 | step = 1 | |
82 | dns.grange.from_text('%s-%d/%d' % (start, stop, step)) | |
83 | self.assertRaises(dns.exception.SyntaxError, bad) | |
84 | ||
85 | def testFailFromText2(self): | |
86 | def bad(): | |
87 | start = 1 | |
88 | stop = 4 | |
89 | step = '-2' | |
90 | dns.grange.from_text('%d-%d/%s' % (start, stop, step)) | |
91 | self.assertRaises(dns.exception.SyntaxError, bad) | |
92 | ||
93 | if __name__ == '__main__': | |
94 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import cStringIO | |
16 | import os | |
17 | import unittest | |
18 | ||
19 | import dns.exception | |
20 | import dns.message | |
21 | ||
22 | query_text = """id 1234 | |
23 | opcode QUERY | |
24 | rcode NOERROR | |
25 | flags RD | |
26 | edns 0 | |
27 | eflags DO | |
28 | payload 4096 | |
29 | ;QUESTION | |
30 | wwww.dnspython.org. IN A | |
31 | ;ANSWER | |
32 | ;AUTHORITY | |
33 | ;ADDITIONAL""" | |
34 | ||
35 | goodhex = '04d201000001000000000001047777777709646e73707974686f6e' \ | |
36 | '036f726700000100010000291000000080000000' | |
37 | ||
38 | goodwire = goodhex.decode('hex_codec') | |
39 | ||
40 | answer_text = """id 1234 | |
41 | opcode QUERY | |
42 | rcode NOERROR | |
43 | flags QR AA RD | |
44 | ;QUESTION | |
45 | dnspython.org. IN SOA | |
46 | ;ANSWER | |
47 | dnspython.org. 3600 IN SOA woof.dnspython.org. hostmaster.dnspython.org. 2003052700 3600 1800 604800 3600 | |
48 | ;AUTHORITY | |
49 | dnspython.org. 3600 IN NS ns1.staff.nominum.org. | |
50 | dnspython.org. 3600 IN NS ns2.staff.nominum.org. | |
51 | dnspython.org. 3600 IN NS woof.play-bow.org. | |
52 | ;ADDITIONAL | |
53 | woof.play-bow.org. 3600 IN A 204.152.186.150 | |
54 | """ | |
55 | ||
56 | goodhex2 = '04d2 8500 0001 0001 0003 0001' \ | |
57 | '09646e73707974686f6e036f726700 0006 0001' \ | |
58 | 'c00c 0006 0001 00000e10 0028 ' \ | |
59 | '04776f6f66c00c 0a686f73746d6173746572c00c' \ | |
60 | '7764289c 00000e10 00000708 00093a80 00000e10' \ | |
61 | 'c00c 0002 0001 00000e10 0014' \ | |
62 | '036e7331057374616666076e6f6d696e756dc016' \ | |
63 | 'c00c 0002 0001 00000e10 0006 036e7332c063' \ | |
64 | 'c00c 0002 0001 00000e10 0010 04776f6f6608706c61792d626f77c016' \ | |
65 | 'c091 0001 0001 00000e10 0004 cc98ba96' | |
66 | ||
67 | ||
68 | goodwire2 = goodhex2.replace(' ', '').decode('hex_codec') | |
69 | ||
70 | query_text_2 = """id 1234 | |
71 | opcode QUERY | |
72 | rcode 4095 | |
73 | flags RD | |
74 | edns 0 | |
75 | eflags DO | |
76 | payload 4096 | |
77 | ;QUESTION | |
78 | wwww.dnspython.org. IN A | |
79 | ;ANSWER | |
80 | ;AUTHORITY | |
81 | ;ADDITIONAL""" | |
82 | ||
83 | goodhex3 = '04d2010f0001000000000001047777777709646e73707974686f6e' \ | |
84 | '036f726700000100010000291000ff0080000000' | |
85 | ||
86 | goodwire3 = goodhex3.decode('hex_codec') | |
87 | ||
88 | class MessageTestCase(unittest.TestCase): | |
89 | ||
90 | def test_comparison_eq1(self): | |
91 | q1 = dns.message.from_text(query_text) | |
92 | q2 = dns.message.from_text(query_text) | |
93 | self.failUnless(q1 == q2) | |
94 | ||
95 | def test_comparison_ne1(self): | |
96 | q1 = dns.message.from_text(query_text) | |
97 | q2 = dns.message.from_text(query_text) | |
98 | q2.id = 10 | |
99 | self.failUnless(q1 != q2) | |
100 | ||
101 | def test_comparison_ne2(self): | |
102 | q1 = dns.message.from_text(query_text) | |
103 | q2 = dns.message.from_text(query_text) | |
104 | q2.question = [] | |
105 | self.failUnless(q1 != q2) | |
106 | ||
107 | def test_comparison_ne3(self): | |
108 | q1 = dns.message.from_text(query_text) | |
109 | self.failUnless(q1 != 1) | |
110 | ||
111 | def test_EDNS_to_wire1(self): | |
112 | q = dns.message.from_text(query_text) | |
113 | w = q.to_wire() | |
114 | self.failUnless(w == goodwire) | |
115 | ||
116 | def test_EDNS_from_wire1(self): | |
117 | m = dns.message.from_wire(goodwire) | |
118 | self.failUnless(str(m) == query_text) | |
119 | ||
120 | def test_EDNS_to_wire2(self): | |
121 | q = dns.message.from_text(query_text_2) | |
122 | w = q.to_wire() | |
123 | self.failUnless(w == goodwire3) | |
124 | ||
125 | def test_EDNS_from_wire2(self): | |
126 | m = dns.message.from_wire(goodwire3) | |
127 | self.failUnless(str(m) == query_text_2) | |
128 | ||
129 | def test_TooBig(self): | |
130 | def bad(): | |
131 | q = dns.message.from_text(query_text) | |
132 | for i in xrange(0, 25): | |
133 | rrset = dns.rrset.from_text('foo%d.' % i, 3600, | |
134 | dns.rdataclass.IN, | |
135 | dns.rdatatype.A, | |
136 | '10.0.0.%d' % i) | |
137 | q.additional.append(rrset) | |
138 | w = q.to_wire(max_size=512) | |
139 | self.failUnlessRaises(dns.exception.TooBig, bad) | |
140 | ||
141 | def test_answer1(self): | |
142 | a = dns.message.from_text(answer_text) | |
143 | wire = a.to_wire(want_shuffle=False) | |
144 | self.failUnless(wire == goodwire2) | |
145 | ||
146 | def test_TrailingJunk(self): | |
147 | def bad(): | |
148 | badwire = goodwire + '\x00' | |
149 | m = dns.message.from_wire(badwire) | |
150 | self.failUnlessRaises(dns.message.TrailingJunk, bad) | |
151 | ||
152 | def test_ShortHeader(self): | |
153 | def bad(): | |
154 | badwire = '\x00' * 11 | |
155 | m = dns.message.from_wire(badwire) | |
156 | self.failUnlessRaises(dns.message.ShortHeader, bad) | |
157 | ||
158 | def test_RespondingToResponse(self): | |
159 | def bad(): | |
160 | q = dns.message.make_query('foo', 'A') | |
161 | r1 = dns.message.make_response(q) | |
162 | r2 = dns.message.make_response(r1) | |
163 | self.failUnlessRaises(dns.exception.FormError, bad) | |
164 | ||
165 | def test_ExtendedRcodeSetting(self): | |
166 | m = dns.message.make_query('foo', 'A') | |
167 | m.set_rcode(4095) | |
168 | self.failUnless(m.rcode() == 4095) | |
169 | m.set_rcode(2) | |
170 | self.failUnless(m.rcode() == 2) | |
171 | ||
172 | def test_EDNSVersionCoherence(self): | |
173 | m = dns.message.make_query('foo', 'A') | |
174 | m.use_edns(1) | |
175 | self.failUnless((m.ednsflags >> 16) & 0xFF == 1) | |
176 | ||
177 | if __name__ == '__main__': | |
178 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import cStringIO | |
18 | import socket | |
19 | ||
20 | import dns.name | |
21 | import dns.reversename | |
22 | import dns.e164 | |
23 | ||
24 | class NameTestCase(unittest.TestCase): | |
25 | def setUp(self): | |
26 | self.origin = dns.name.from_text('example.') | |
27 | ||
28 | def testFromTextRel1(self): | |
29 | n = dns.name.from_text('foo.bar') | |
30 | self.failUnless(n.labels == ('foo', 'bar', '')) | |
31 | ||
32 | def testFromTextRel2(self): | |
33 | n = dns.name.from_text('foo.bar', origin=self.origin) | |
34 | self.failUnless(n.labels == ('foo', 'bar', 'example', '')) | |
35 | ||
36 | def testFromTextRel3(self): | |
37 | n = dns.name.from_text('foo.bar', origin=None) | |
38 | self.failUnless(n.labels == ('foo', 'bar')) | |
39 | ||
40 | def testFromTextRel4(self): | |
41 | n = dns.name.from_text('@', origin=None) | |
42 | self.failUnless(n == dns.name.empty) | |
43 | ||
44 | def testFromTextRel5(self): | |
45 | n = dns.name.from_text('@', origin=self.origin) | |
46 | self.failUnless(n == self.origin) | |
47 | ||
48 | def testFromTextAbs1(self): | |
49 | n = dns.name.from_text('foo.bar.') | |
50 | self.failUnless(n.labels == ('foo', 'bar', '')) | |
51 | ||
52 | def testTortureFromText(self): | |
53 | good = [ | |
54 | r'.', | |
55 | r'a', | |
56 | r'a.', | |
57 | r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', | |
58 | r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', | |
59 | r'\000.\008.\010.\032.\046.\092.\099.\255', | |
60 | r'\\', | |
61 | r'\..\.', | |
62 | r'\\.\\', | |
63 | r'!"#%&/()=+-', | |
64 | r'\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255', | |
65 | ] | |
66 | bad = [ | |
67 | r'..', | |
68 | r'.a', | |
69 | r'\\..', | |
70 | '\\', # yes, we don't want the 'r' prefix! | |
71 | r'\0', | |
72 | r'\00', | |
73 | r'\00Z', | |
74 | r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', | |
75 | r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', | |
76 | r'\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255', | |
77 | ] | |
78 | for t in good: | |
79 | try: | |
80 | n = dns.name.from_text(t) | |
81 | except: | |
82 | self.fail("good test '%s' raised an exception" % t) | |
83 | for t in bad: | |
84 | caught = False | |
85 | try: | |
86 | n = dns.name.from_text(t) | |
87 | except: | |
88 | caught = True | |
89 | if not caught: | |
90 | self.fail("bad test '%s' did not raise an exception" % t) | |
91 | ||
92 | def testImmutable1(self): | |
93 | def bad(): | |
94 | self.origin.labels = () | |
95 | self.failUnlessRaises(TypeError, bad) | |
96 | ||
97 | def testImmutable2(self): | |
98 | def bad(): | |
99 | self.origin.labels[0] = 'foo' | |
100 | self.failUnlessRaises(TypeError, bad) | |
101 | ||
102 | def testAbs1(self): | |
103 | self.failUnless(dns.name.root.is_absolute()) | |
104 | ||
105 | def testAbs2(self): | |
106 | self.failUnless(not dns.name.empty.is_absolute()) | |
107 | ||
108 | def testAbs3(self): | |
109 | self.failUnless(self.origin.is_absolute()) | |
110 | ||
111 | def testAbs3(self): | |
112 | n = dns.name.from_text('foo', origin=None) | |
113 | self.failUnless(not n.is_absolute()) | |
114 | ||
115 | def testWild1(self): | |
116 | n = dns.name.from_text('*.foo', origin=None) | |
117 | self.failUnless(n.is_wild()) | |
118 | ||
119 | def testWild2(self): | |
120 | n = dns.name.from_text('*a.foo', origin=None) | |
121 | self.failUnless(not n.is_wild()) | |
122 | ||
123 | def testWild3(self): | |
124 | n = dns.name.from_text('a.*.foo', origin=None) | |
125 | self.failUnless(not n.is_wild()) | |
126 | ||
127 | def testWild4(self): | |
128 | self.failUnless(not dns.name.root.is_wild()) | |
129 | ||
130 | def testWild5(self): | |
131 | self.failUnless(not dns.name.empty.is_wild()) | |
132 | ||
133 | def testHash1(self): | |
134 | n1 = dns.name.from_text('fOo.COM') | |
135 | n2 = dns.name.from_text('foo.com') | |
136 | self.failUnless(hash(n1) == hash(n2)) | |
137 | ||
138 | def testCompare1(self): | |
139 | n1 = dns.name.from_text('a') | |
140 | n2 = dns.name.from_text('b') | |
141 | self.failUnless(n1 < n2) | |
142 | self.failUnless(n2 > n1) | |
143 | ||
144 | def testCompare2(self): | |
145 | n1 = dns.name.from_text('') | |
146 | n2 = dns.name.from_text('b') | |
147 | self.failUnless(n1 < n2) | |
148 | self.failUnless(n2 > n1) | |
149 | ||
150 | def testCompare3(self): | |
151 | self.failUnless(dns.name.empty < dns.name.root) | |
152 | self.failUnless(dns.name.root > dns.name.empty) | |
153 | ||
154 | def testCompare4(self): | |
155 | self.failUnless(dns.name.root != 1) | |
156 | ||
157 | def testCompare5(self): | |
158 | self.failUnless(dns.name.root < 1 or dns.name.root > 1) | |
159 | ||
160 | def testSubdomain1(self): | |
161 | self.failUnless(not dns.name.empty.is_subdomain(dns.name.root)) | |
162 | ||
163 | def testSubdomain2(self): | |
164 | self.failUnless(not dns.name.root.is_subdomain(dns.name.empty)) | |
165 | ||
166 | def testSubdomain3(self): | |
167 | n = dns.name.from_text('foo', origin=self.origin) | |
168 | self.failUnless(n.is_subdomain(self.origin)) | |
169 | ||
170 | def testSubdomain4(self): | |
171 | n = dns.name.from_text('foo', origin=self.origin) | |
172 | self.failUnless(n.is_subdomain(dns.name.root)) | |
173 | ||
174 | def testSubdomain5(self): | |
175 | n = dns.name.from_text('foo', origin=self.origin) | |
176 | self.failUnless(n.is_subdomain(n)) | |
177 | ||
178 | def testSuperdomain1(self): | |
179 | self.failUnless(not dns.name.empty.is_superdomain(dns.name.root)) | |
180 | ||
181 | def testSuperdomain2(self): | |
182 | self.failUnless(not dns.name.root.is_superdomain(dns.name.empty)) | |
183 | ||
184 | def testSuperdomain3(self): | |
185 | n = dns.name.from_text('foo', origin=self.origin) | |
186 | self.failUnless(self.origin.is_superdomain(n)) | |
187 | ||
188 | def testSuperdomain4(self): | |
189 | n = dns.name.from_text('foo', origin=self.origin) | |
190 | self.failUnless(dns.name.root.is_superdomain(n)) | |
191 | ||
192 | def testSuperdomain5(self): | |
193 | n = dns.name.from_text('foo', origin=self.origin) | |
194 | self.failUnless(n.is_superdomain(n)) | |
195 | ||
196 | def testCanonicalize1(self): | |
197 | n = dns.name.from_text('FOO.bar', origin=self.origin) | |
198 | c = n.canonicalize() | |
199 | self.failUnless(c.labels == ('foo', 'bar', 'example', '')) | |
200 | ||
201 | def testToText1(self): | |
202 | n = dns.name.from_text('FOO.bar', origin=self.origin) | |
203 | t = n.to_text() | |
204 | self.failUnless(t == 'FOO.bar.example.') | |
205 | ||
206 | def testToText2(self): | |
207 | n = dns.name.from_text('FOO.bar', origin=self.origin) | |
208 | t = n.to_text(True) | |
209 | self.failUnless(t == 'FOO.bar.example') | |
210 | ||
211 | def testToText3(self): | |
212 | n = dns.name.from_text('FOO.bar', origin=None) | |
213 | t = n.to_text() | |
214 | self.failUnless(t == 'FOO.bar') | |
215 | ||
216 | def testToText4(self): | |
217 | t = dns.name.empty.to_text() | |
218 | self.failUnless(t == '@') | |
219 | ||
220 | def testToText5(self): | |
221 | t = dns.name.root.to_text() | |
222 | self.failUnless(t == '.') | |
223 | ||
224 | def testToText6(self): | |
225 | n = dns.name.from_text('FOO bar', origin=None) | |
226 | t = n.to_text() | |
227 | self.failUnless(t == r'FOO\032bar') | |
228 | ||
229 | def testToText7(self): | |
230 | n = dns.name.from_text(r'FOO\.bar', origin=None) | |
231 | t = n.to_text() | |
232 | self.failUnless(t == r'FOO\.bar') | |
233 | ||
234 | def testToText8(self): | |
235 | n = dns.name.from_text(r'\070OO\.bar', origin=None) | |
236 | t = n.to_text() | |
237 | self.failUnless(t == r'FOO\.bar') | |
238 | ||
239 | def testSlice1(self): | |
240 | n = dns.name.from_text(r'a.b.c.', origin=None) | |
241 | s = n[:] | |
242 | self.failUnless(s == ('a', 'b', 'c', '')) | |
243 | ||
244 | def testSlice2(self): | |
245 | n = dns.name.from_text(r'a.b.c.', origin=None) | |
246 | s = n[:2] | |
247 | self.failUnless(s == ('a', 'b')) | |
248 | ||
249 | def testSlice3(self): | |
250 | n = dns.name.from_text(r'a.b.c.', origin=None) | |
251 | s = n[2:] | |
252 | self.failUnless(s == ('c', '')) | |
253 | ||
254 | def testEmptyLabel1(self): | |
255 | def bad(): | |
256 | n = dns.name.Name(['a', '', 'b']) | |
257 | self.failUnlessRaises(dns.name.EmptyLabel, bad) | |
258 | ||
259 | def testEmptyLabel2(self): | |
260 | def bad(): | |
261 | n = dns.name.Name(['', 'b']) | |
262 | self.failUnlessRaises(dns.name.EmptyLabel, bad) | |
263 | ||
264 | def testEmptyLabel3(self): | |
265 | n = dns.name.Name(['b', '']) | |
266 | self.failUnless(n) | |
267 | ||
268 | def testLongLabel(self): | |
269 | n = dns.name.Name(['a' * 63]) | |
270 | self.failUnless(n) | |
271 | ||
272 | def testLabelTooLong(self): | |
273 | def bad(): | |
274 | n = dns.name.Name(['a' * 64, 'b']) | |
275 | self.failUnlessRaises(dns.name.LabelTooLong, bad) | |
276 | ||
277 | def testLongName(self): | |
278 | n = dns.name.Name(['a' * 63, 'a' * 63, 'a' * 63, 'a' * 62]) | |
279 | self.failUnless(n) | |
280 | ||
281 | def testNameTooLong(self): | |
282 | def bad(): | |
283 | n = dns.name.Name(['a' * 63, 'a' * 63, 'a' * 63, 'a' * 63]) | |
284 | self.failUnlessRaises(dns.name.NameTooLong, bad) | |
285 | ||
286 | def testConcat1(self): | |
287 | n1 = dns.name.Name(['a', 'b']) | |
288 | n2 = dns.name.Name(['c', 'd']) | |
289 | e = dns.name.Name(['a', 'b', 'c', 'd']) | |
290 | r = n1 + n2 | |
291 | self.failUnless(r == e) | |
292 | ||
293 | def testConcat2(self): | |
294 | n1 = dns.name.Name(['a', 'b']) | |
295 | n2 = dns.name.Name([]) | |
296 | e = dns.name.Name(['a', 'b']) | |
297 | r = n1 + n2 | |
298 | self.failUnless(r == e) | |
299 | ||
300 | def testConcat2(self): | |
301 | n1 = dns.name.Name([]) | |
302 | n2 = dns.name.Name(['a', 'b']) | |
303 | e = dns.name.Name(['a', 'b']) | |
304 | r = n1 + n2 | |
305 | self.failUnless(r == e) | |
306 | ||
307 | def testConcat3(self): | |
308 | n1 = dns.name.Name(['a', 'b', '']) | |
309 | n2 = dns.name.Name([]) | |
310 | e = dns.name.Name(['a', 'b', '']) | |
311 | r = n1 + n2 | |
312 | self.failUnless(r == e) | |
313 | ||
314 | def testConcat4(self): | |
315 | n1 = dns.name.Name(['a', 'b']) | |
316 | n2 = dns.name.Name(['c', '']) | |
317 | e = dns.name.Name(['a', 'b', 'c', '']) | |
318 | r = n1 + n2 | |
319 | self.failUnless(r == e) | |
320 | ||
321 | def testConcat5(self): | |
322 | def bad(): | |
323 | n1 = dns.name.Name(['a', 'b', '']) | |
324 | n2 = dns.name.Name(['c']) | |
325 | r = n1 + n2 | |
326 | self.failUnlessRaises(dns.name.AbsoluteConcatenation, bad) | |
327 | ||
328 | def testBadEscape(self): | |
329 | def bad(): | |
330 | n = dns.name.from_text(r'a.b\0q1.c.') | |
331 | print n | |
332 | self.failUnlessRaises(dns.name.BadEscape, bad) | |
333 | ||
334 | def testDigestable1(self): | |
335 | n = dns.name.from_text('FOO.bar') | |
336 | d = n.to_digestable() | |
337 | self.failUnless(d == '\x03foo\x03bar\x00') | |
338 | ||
339 | def testDigestable2(self): | |
340 | n1 = dns.name.from_text('FOO.bar') | |
341 | n2 = dns.name.from_text('foo.BAR.') | |
342 | d1 = n1.to_digestable() | |
343 | d2 = n2.to_digestable() | |
344 | self.failUnless(d1 == d2) | |
345 | ||
346 | def testDigestable3(self): | |
347 | d = dns.name.root.to_digestable() | |
348 | self.failUnless(d == '\x00') | |
349 | ||
350 | def testDigestable4(self): | |
351 | n = dns.name.from_text('FOO.bar', None) | |
352 | d = n.to_digestable(dns.name.root) | |
353 | self.failUnless(d == '\x03foo\x03bar\x00') | |
354 | ||
355 | def testBadDigestable(self): | |
356 | def bad(): | |
357 | n = dns.name.from_text('FOO.bar', None) | |
358 | d = n.to_digestable() | |
359 | self.failUnlessRaises(dns.name.NeedAbsoluteNameOrOrigin, bad) | |
360 | ||
361 | def testToWire1(self): | |
362 | n = dns.name.from_text('FOO.bar') | |
363 | f = cStringIO.StringIO() | |
364 | compress = {} | |
365 | n.to_wire(f, compress) | |
366 | self.failUnless(f.getvalue() == '\x03FOO\x03bar\x00') | |
367 | ||
368 | def testToWire2(self): | |
369 | n = dns.name.from_text('FOO.bar') | |
370 | f = cStringIO.StringIO() | |
371 | compress = {} | |
372 | n.to_wire(f, compress) | |
373 | n.to_wire(f, compress) | |
374 | self.failUnless(f.getvalue() == '\x03FOO\x03bar\x00\xc0\x00') | |
375 | ||
376 | def testToWire3(self): | |
377 | n1 = dns.name.from_text('FOO.bar') | |
378 | n2 = dns.name.from_text('foo.bar') | |
379 | f = cStringIO.StringIO() | |
380 | compress = {} | |
381 | n1.to_wire(f, compress) | |
382 | n2.to_wire(f, compress) | |
383 | self.failUnless(f.getvalue() == '\x03FOO\x03bar\x00\xc0\x00') | |
384 | ||
385 | def testToWire4(self): | |
386 | n1 = dns.name.from_text('FOO.bar') | |
387 | n2 = dns.name.from_text('a.foo.bar') | |
388 | f = cStringIO.StringIO() | |
389 | compress = {} | |
390 | n1.to_wire(f, compress) | |
391 | n2.to_wire(f, compress) | |
392 | self.failUnless(f.getvalue() == '\x03FOO\x03bar\x00\x01\x61\xc0\x00') | |
393 | ||
394 | def testToWire5(self): | |
395 | n1 = dns.name.from_text('FOO.bar') | |
396 | n2 = dns.name.from_text('a.foo.bar') | |
397 | f = cStringIO.StringIO() | |
398 | compress = {} | |
399 | n1.to_wire(f, compress) | |
400 | n2.to_wire(f, None) | |
401 | self.failUnless(f.getvalue() == \ | |
402 | '\x03FOO\x03bar\x00\x01\x61\x03foo\x03bar\x00') | |
403 | ||
404 | def testToWire6(self): | |
405 | n = dns.name.from_text('FOO.bar') | |
406 | v = n.to_wire() | |
407 | self.failUnless(v == '\x03FOO\x03bar\x00') | |
408 | ||
409 | def testBadToWire(self): | |
410 | def bad(): | |
411 | n = dns.name.from_text('FOO.bar', None) | |
412 | f = cStringIO.StringIO() | |
413 | compress = {} | |
414 | n.to_wire(f, compress) | |
415 | self.failUnlessRaises(dns.name.NeedAbsoluteNameOrOrigin, bad) | |
416 | ||
417 | def testSplit1(self): | |
418 | n = dns.name.from_text('foo.bar.') | |
419 | (prefix, suffix) = n.split(2) | |
420 | ep = dns.name.from_text('foo', None) | |
421 | es = dns.name.from_text('bar.', None) | |
422 | self.failUnless(prefix == ep and suffix == es) | |
423 | ||
424 | def testSplit2(self): | |
425 | n = dns.name.from_text('foo.bar.') | |
426 | (prefix, suffix) = n.split(1) | |
427 | ep = dns.name.from_text('foo.bar', None) | |
428 | es = dns.name.from_text('.', None) | |
429 | self.failUnless(prefix == ep and suffix == es) | |
430 | ||
431 | def testSplit3(self): | |
432 | n = dns.name.from_text('foo.bar.') | |
433 | (prefix, suffix) = n.split(0) | |
434 | ep = dns.name.from_text('foo.bar.', None) | |
435 | es = dns.name.from_text('', None) | |
436 | self.failUnless(prefix == ep and suffix == es) | |
437 | ||
438 | def testSplit4(self): | |
439 | n = dns.name.from_text('foo.bar.') | |
440 | (prefix, suffix) = n.split(3) | |
441 | ep = dns.name.from_text('', None) | |
442 | es = dns.name.from_text('foo.bar.', None) | |
443 | self.failUnless(prefix == ep and suffix == es) | |
444 | ||
445 | def testBadSplit1(self): | |
446 | def bad(): | |
447 | n = dns.name.from_text('foo.bar.') | |
448 | (prefix, suffix) = n.split(-1) | |
449 | self.failUnlessRaises(ValueError, bad) | |
450 | ||
451 | def testBadSplit2(self): | |
452 | def bad(): | |
453 | n = dns.name.from_text('foo.bar.') | |
454 | (prefix, suffix) = n.split(4) | |
455 | self.failUnlessRaises(ValueError, bad) | |
456 | ||
457 | def testRelativize1(self): | |
458 | n = dns.name.from_text('a.foo.bar.', None) | |
459 | o = dns.name.from_text('bar.', None) | |
460 | e = dns.name.from_text('a.foo', None) | |
461 | self.failUnless(n.relativize(o) == e) | |
462 | ||
463 | def testRelativize2(self): | |
464 | n = dns.name.from_text('a.foo.bar.', None) | |
465 | o = n | |
466 | e = dns.name.empty | |
467 | self.failUnless(n.relativize(o) == e) | |
468 | ||
469 | def testRelativize3(self): | |
470 | n = dns.name.from_text('a.foo.bar.', None) | |
471 | o = dns.name.from_text('blaz.', None) | |
472 | e = n | |
473 | self.failUnless(n.relativize(o) == e) | |
474 | ||
475 | def testRelativize4(self): | |
476 | n = dns.name.from_text('a.foo', None) | |
477 | o = dns.name.root | |
478 | e = n | |
479 | self.failUnless(n.relativize(o) == e) | |
480 | ||
481 | def testDerelativize1(self): | |
482 | n = dns.name.from_text('a.foo', None) | |
483 | o = dns.name.from_text('bar.', None) | |
484 | e = dns.name.from_text('a.foo.bar.', None) | |
485 | self.failUnless(n.derelativize(o) == e) | |
486 | ||
487 | def testDerelativize2(self): | |
488 | n = dns.name.empty | |
489 | o = dns.name.from_text('a.foo.bar.', None) | |
490 | e = o | |
491 | self.failUnless(n.derelativize(o) == e) | |
492 | ||
493 | def testDerelativize3(self): | |
494 | n = dns.name.from_text('a.foo.bar.', None) | |
495 | o = dns.name.from_text('blaz.', None) | |
496 | e = n | |
497 | self.failUnless(n.derelativize(o) == e) | |
498 | ||
499 | def testChooseRelativity1(self): | |
500 | n = dns.name.from_text('a.foo.bar.', None) | |
501 | o = dns.name.from_text('bar.', None) | |
502 | e = dns.name.from_text('a.foo', None) | |
503 | self.failUnless(n.choose_relativity(o, True) == e) | |
504 | ||
505 | def testChooseRelativity2(self): | |
506 | n = dns.name.from_text('a.foo.bar.', None) | |
507 | o = dns.name.from_text('bar.', None) | |
508 | e = n | |
509 | self.failUnless(n.choose_relativity(o, False) == e) | |
510 | ||
511 | def testChooseRelativity3(self): | |
512 | n = dns.name.from_text('a.foo', None) | |
513 | o = dns.name.from_text('bar.', None) | |
514 | e = dns.name.from_text('a.foo.bar.', None) | |
515 | self.failUnless(n.choose_relativity(o, False) == e) | |
516 | ||
517 | def testChooseRelativity4(self): | |
518 | n = dns.name.from_text('a.foo', None) | |
519 | o = None | |
520 | e = n | |
521 | self.failUnless(n.choose_relativity(o, True) == e) | |
522 | ||
523 | def testChooseRelativity5(self): | |
524 | n = dns.name.from_text('a.foo', None) | |
525 | o = None | |
526 | e = n | |
527 | self.failUnless(n.choose_relativity(o, False) == e) | |
528 | ||
529 | def testChooseRelativity6(self): | |
530 | n = dns.name.from_text('a.foo.', None) | |
531 | o = None | |
532 | e = n | |
533 | self.failUnless(n.choose_relativity(o, True) == e) | |
534 | ||
535 | def testChooseRelativity7(self): | |
536 | n = dns.name.from_text('a.foo.', None) | |
537 | o = None | |
538 | e = n | |
539 | self.failUnless(n.choose_relativity(o, False) == e) | |
540 | ||
541 | def testFromWire1(self): | |
542 | w = '\x03foo\x00\xc0\x00' | |
543 | (n1, cused1) = dns.name.from_wire(w, 0) | |
544 | (n2, cused2) = dns.name.from_wire(w, cused1) | |
545 | en1 = dns.name.from_text('foo.') | |
546 | en2 = en1 | |
547 | ecused1 = 5 | |
548 | ecused2 = 2 | |
549 | self.failUnless(n1 == en1 and cused1 == ecused1 and \ | |
550 | n2 == en2 and cused2 == ecused2) | |
551 | ||
552 | def testFromWire1(self): | |
553 | w = '\x03foo\x00\x01a\xc0\x00\x01b\xc0\x05' | |
554 | current = 0 | |
555 | (n1, cused1) = dns.name.from_wire(w, current) | |
556 | current += cused1 | |
557 | (n2, cused2) = dns.name.from_wire(w, current) | |
558 | current += cused2 | |
559 | (n3, cused3) = dns.name.from_wire(w, current) | |
560 | en1 = dns.name.from_text('foo.') | |
561 | en2 = dns.name.from_text('a.foo.') | |
562 | en3 = dns.name.from_text('b.a.foo.') | |
563 | ecused1 = 5 | |
564 | ecused2 = 4 | |
565 | ecused3 = 4 | |
566 | self.failUnless(n1 == en1 and cused1 == ecused1 and \ | |
567 | n2 == en2 and cused2 == ecused2 and \ | |
568 | n3 == en3 and cused3 == ecused3) | |
569 | ||
570 | def testBadFromWire1(self): | |
571 | def bad(): | |
572 | w = '\x03foo\xc0\x04' | |
573 | (n, cused) = dns.name.from_wire(w, 0) | |
574 | self.failUnlessRaises(dns.name.BadPointer, bad) | |
575 | ||
576 | def testBadFromWire2(self): | |
577 | def bad(): | |
578 | w = '\x03foo\xc0\x05' | |
579 | (n, cused) = dns.name.from_wire(w, 0) | |
580 | self.failUnlessRaises(dns.name.BadPointer, bad) | |
581 | ||
582 | def testBadFromWire3(self): | |
583 | def bad(): | |
584 | w = '\xbffoo' | |
585 | (n, cused) = dns.name.from_wire(w, 0) | |
586 | self.failUnlessRaises(dns.name.BadLabelType, bad) | |
587 | ||
588 | def testBadFromWire4(self): | |
589 | def bad(): | |
590 | w = '\x41foo' | |
591 | (n, cused) = dns.name.from_wire(w, 0) | |
592 | self.failUnlessRaises(dns.name.BadLabelType, bad) | |
593 | ||
594 | def testParent1(self): | |
595 | n = dns.name.from_text('foo.bar.') | |
596 | self.failUnless(n.parent() == dns.name.from_text('bar.')) | |
597 | self.failUnless(n.parent().parent() == dns.name.root) | |
598 | ||
599 | def testParent2(self): | |
600 | n = dns.name.from_text('foo.bar', None) | |
601 | self.failUnless(n.parent() == dns.name.from_text('bar', None)) | |
602 | self.failUnless(n.parent().parent() == dns.name.empty) | |
603 | ||
604 | def testParent3(self): | |
605 | def bad(): | |
606 | n = dns.name.root | |
607 | n.parent() | |
608 | self.failUnlessRaises(dns.name.NoParent, bad) | |
609 | ||
610 | def testParent4(self): | |
611 | def bad(): | |
612 | n = dns.name.empty | |
613 | n.parent() | |
614 | self.failUnlessRaises(dns.name.NoParent, bad) | |
615 | ||
616 | def testFromUnicode1(self): | |
617 | n = dns.name.from_text(u'foo.bar') | |
618 | self.failUnless(n.labels == ('foo', 'bar', '')) | |
619 | ||
620 | def testFromUnicode2(self): | |
621 | n = dns.name.from_text(u'foo\u1234bar.bar') | |
622 | self.failUnless(n.labels == ('xn--foobar-r5z', 'bar', '')) | |
623 | ||
624 | def testFromUnicodeAlternateDot1(self): | |
625 | n = dns.name.from_text(u'foo\u3002bar') | |
626 | self.failUnless(n.labels == ('foo', 'bar', '')) | |
627 | ||
628 | def testFromUnicodeAlternateDot2(self): | |
629 | n = dns.name.from_text(u'foo\uff0ebar') | |
630 | self.failUnless(n.labels == ('foo', 'bar', '')) | |
631 | ||
632 | def testFromUnicodeAlternateDot3(self): | |
633 | n = dns.name.from_text(u'foo\uff61bar') | |
634 | self.failUnless(n.labels == ('foo', 'bar', '')) | |
635 | ||
636 | def testToUnicode1(self): | |
637 | n = dns.name.from_text(u'foo.bar') | |
638 | s = n.to_unicode() | |
639 | self.failUnless(s == u'foo.bar.') | |
640 | ||
641 | def testToUnicode2(self): | |
642 | n = dns.name.from_text(u'foo\u1234bar.bar') | |
643 | s = n.to_unicode() | |
644 | self.failUnless(s == u'foo\u1234bar.bar.') | |
645 | ||
646 | def testToUnicode3(self): | |
647 | n = dns.name.from_text('foo.bar') | |
648 | s = n.to_unicode() | |
649 | self.failUnless(s == u'foo.bar.') | |
650 | ||
651 | def testReverseIPv4(self): | |
652 | e = dns.name.from_text('1.0.0.127.in-addr.arpa.') | |
653 | n = dns.reversename.from_address('127.0.0.1') | |
654 | self.failUnless(e == n) | |
655 | ||
656 | def testReverseIPv6(self): | |
657 | e = dns.name.from_text('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.') | |
658 | n = dns.reversename.from_address('::1') | |
659 | self.failUnless(e == n) | |
660 | ||
661 | def testBadReverseIPv4(self): | |
662 | def bad(): | |
663 | n = dns.reversename.from_address('127.0.foo.1') | |
664 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
665 | ||
666 | def testBadReverseIPv6(self): | |
667 | def bad(): | |
668 | n = dns.reversename.from_address('::1::1') | |
669 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
670 | ||
671 | def testForwardIPv4(self): | |
672 | n = dns.name.from_text('1.0.0.127.in-addr.arpa.') | |
673 | e = '127.0.0.1' | |
674 | text = dns.reversename.to_address(n) | |
675 | self.failUnless(text == e) | |
676 | ||
677 | def testForwardIPv6(self): | |
678 | n = dns.name.from_text('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.') | |
679 | e = '::1' | |
680 | text = dns.reversename.to_address(n) | |
681 | self.failUnless(text == e) | |
682 | ||
683 | def testE164ToEnum(self): | |
684 | text = '+1 650 555 1212' | |
685 | e = dns.name.from_text('2.1.2.1.5.5.5.0.5.6.1.e164.arpa.') | |
686 | n = dns.e164.from_e164(text) | |
687 | self.failUnless(n == e) | |
688 | ||
689 | def testEnumToE164(self): | |
690 | n = dns.name.from_text('2.1.2.1.5.5.5.0.5.6.1.e164.arpa.') | |
691 | e = '+16505551212' | |
692 | text = dns.e164.to_e164(n) | |
693 | self.failUnless(text == e) | |
694 | ||
695 | if __name__ == '__main__': | |
696 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.name | |
18 | import dns.namedict | |
19 | ||
20 | class NameTestCase(unittest.TestCase): | |
21 | ||
22 | def setUp(self): | |
23 | self.ndict = dns.namedict.NameDict() | |
24 | n1 = dns.name.from_text('foo.bar.') | |
25 | n2 = dns.name.from_text('bar.') | |
26 | self.ndict[n1] = 1 | |
27 | self.ndict[n2] = 2 | |
28 | self.rndict = dns.namedict.NameDict() | |
29 | n1 = dns.name.from_text('foo.bar', None) | |
30 | n2 = dns.name.from_text('bar', None) | |
31 | self.rndict[n1] = 1 | |
32 | self.rndict[n2] = 2 | |
33 | ||
34 | def testDepth(self): | |
35 | self.failUnless(self.ndict.max_depth == 3) | |
36 | ||
37 | def testLookup1(self): | |
38 | k = dns.name.from_text('foo.bar.') | |
39 | self.failUnless(self.ndict[k] == 1) | |
40 | ||
41 | def testLookup2(self): | |
42 | k = dns.name.from_text('foo.bar.') | |
43 | self.failUnless(self.ndict.get_deepest_match(k)[1] == 1) | |
44 | ||
45 | def testLookup3(self): | |
46 | k = dns.name.from_text('a.b.c.foo.bar.') | |
47 | self.failUnless(self.ndict.get_deepest_match(k)[1] == 1) | |
48 | ||
49 | def testLookup4(self): | |
50 | k = dns.name.from_text('a.b.c.bar.') | |
51 | self.failUnless(self.ndict.get_deepest_match(k)[1] == 2) | |
52 | ||
53 | def testLookup5(self): | |
54 | def bad(): | |
55 | n = dns.name.from_text('a.b.c.') | |
56 | (k, v) = self.ndict.get_deepest_match(n) | |
57 | self.failUnlessRaises(KeyError, bad) | |
58 | ||
59 | def testLookup6(self): | |
60 | def bad(): | |
61 | (k, v) = self.ndict.get_deepest_match(dns.name.empty) | |
62 | self.failUnlessRaises(KeyError, bad) | |
63 | ||
64 | def testLookup7(self): | |
65 | self.ndict[dns.name.empty] = 100 | |
66 | n = dns.name.from_text('a.b.c.') | |
67 | (k, v) = self.ndict.get_deepest_match(n) | |
68 | self.failUnless(v == 100) | |
69 | ||
70 | def testLookup8(self): | |
71 | def bad(): | |
72 | self.ndict['foo'] = 100 | |
73 | self.failUnlessRaises(ValueError, bad) | |
74 | ||
75 | def testRelDepth(self): | |
76 | self.failUnless(self.rndict.max_depth == 2) | |
77 | ||
78 | def testRelLookup1(self): | |
79 | k = dns.name.from_text('foo.bar', None) | |
80 | self.failUnless(self.rndict[k] == 1) | |
81 | ||
82 | def testRelLookup2(self): | |
83 | k = dns.name.from_text('foo.bar', None) | |
84 | self.failUnless(self.rndict.get_deepest_match(k)[1] == 1) | |
85 | ||
86 | def testRelLookup3(self): | |
87 | k = dns.name.from_text('a.b.c.foo.bar', None) | |
88 | self.failUnless(self.rndict.get_deepest_match(k)[1] == 1) | |
89 | ||
90 | def testRelLookup4(self): | |
91 | k = dns.name.from_text('a.b.c.bar', None) | |
92 | self.failUnless(self.rndict.get_deepest_match(k)[1] == 2) | |
93 | ||
94 | def testRelLookup7(self): | |
95 | self.rndict[dns.name.empty] = 100 | |
96 | n = dns.name.from_text('a.b.c', None) | |
97 | (k, v) = self.rndict.get_deepest_match(n) | |
98 | self.failUnless(v == 100) | |
99 | ||
100 | if __name__ == '__main__': | |
101 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.exception | |
18 | import dns.ipv4 | |
19 | import dns.ipv6 | |
20 | ||
21 | # for convenience | |
22 | aton4 = dns.ipv4.inet_aton | |
23 | ntoa4 = dns.ipv4.inet_ntoa | |
24 | aton6 = dns.ipv6.inet_aton | |
25 | ntoa6 = dns.ipv6.inet_ntoa | |
26 | ||
27 | v4_bad_addrs = ['256.1.1.1', '1.1.1', '1.1.1.1.1', '01.1.1.1', | |
28 | '+1.1.1.1', '1.1.1.1+', '1..2.3.4', '.1.2.3.4', | |
29 | '1.2.3.4.'] | |
30 | ||
31 | class NtoAAtoNTestCase(unittest.TestCase): | |
32 | ||
33 | def test_aton1(self): | |
34 | a = aton6('::') | |
35 | self.failUnless(a == '\x00' * 16) | |
36 | ||
37 | def test_aton2(self): | |
38 | a = aton6('::1') | |
39 | self.failUnless(a == '\x00' * 15 + '\x01') | |
40 | ||
41 | def test_aton3(self): | |
42 | a = aton6('::10.0.0.1') | |
43 | self.failUnless(a == '\x00' * 12 + '\x0a\x00\x00\x01') | |
44 | ||
45 | def test_aton4(self): | |
46 | a = aton6('abcd::dcba') | |
47 | self.failUnless(a == '\xab\xcd' + '\x00' * 12 + '\xdc\xba') | |
48 | ||
49 | def test_aton5(self): | |
50 | a = aton6('1:2:3:4:5:6:7:8') | |
51 | self.failUnless(a == \ | |
52 | '00010002000300040005000600070008'.decode('hex_codec')) | |
53 | ||
54 | def test_bad_aton1(self): | |
55 | def bad(): | |
56 | a = aton6('abcd:dcba') | |
57 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
58 | ||
59 | def test_bad_aton2(self): | |
60 | def bad(): | |
61 | a = aton6('abcd::dcba::1') | |
62 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
63 | ||
64 | def test_bad_aton3(self): | |
65 | def bad(): | |
66 | a = aton6('1:2:3:4:5:6:7:8:9') | |
67 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
68 | ||
69 | def test_aton1(self): | |
70 | a = aton6('::') | |
71 | self.failUnless(a == '\x00' * 16) | |
72 | ||
73 | def test_aton2(self): | |
74 | a = aton6('::1') | |
75 | self.failUnless(a == '\x00' * 15 + '\x01') | |
76 | ||
77 | def test_aton3(self): | |
78 | a = aton6('::10.0.0.1') | |
79 | self.failUnless(a == '\x00' * 12 + '\x0a\x00\x00\x01') | |
80 | ||
81 | def test_aton4(self): | |
82 | a = aton6('abcd::dcba') | |
83 | self.failUnless(a == '\xab\xcd' + '\x00' * 12 + '\xdc\xba') | |
84 | ||
85 | def test_ntoa1(self): | |
86 | b = '00010002000300040005000600070008'.decode('hex_codec') | |
87 | t = ntoa6(b) | |
88 | self.failUnless(t == '1:2:3:4:5:6:7:8') | |
89 | ||
90 | def test_ntoa2(self): | |
91 | b = '\x00' * 16 | |
92 | t = ntoa6(b) | |
93 | self.failUnless(t == '::') | |
94 | ||
95 | def test_ntoa3(self): | |
96 | b = '\x00' * 15 + '\x01' | |
97 | t = ntoa6(b) | |
98 | self.failUnless(t == '::1') | |
99 | ||
100 | def test_ntoa4(self): | |
101 | b = '\x80' + '\x00' * 15 | |
102 | t = ntoa6(b) | |
103 | self.failUnless(t == '8000::') | |
104 | ||
105 | def test_ntoa5(self): | |
106 | b = '\x01\xcd' + '\x00' * 12 + '\x03\xef' | |
107 | t = ntoa6(b) | |
108 | self.failUnless(t == '1cd::3ef') | |
109 | ||
110 | def test_ntoa6(self): | |
111 | b = 'ffff00000000ffff000000000000ffff'.decode('hex_codec') | |
112 | t = ntoa6(b) | |
113 | self.failUnless(t == 'ffff:0:0:ffff::ffff') | |
114 | ||
115 | def test_ntoa7(self): | |
116 | b = '00000000ffff000000000000ffffffff'.decode('hex_codec') | |
117 | t = ntoa6(b) | |
118 | self.failUnless(t == '0:0:ffff::ffff:ffff') | |
119 | ||
120 | def test_ntoa8(self): | |
121 | b = 'ffff0000ffff00000000ffff00000000'.decode('hex_codec') | |
122 | t = ntoa6(b) | |
123 | self.failUnless(t == 'ffff:0:ffff::ffff:0:0') | |
124 | ||
125 | def test_ntoa9(self): | |
126 | b = '0000000000000000000000000a000001'.decode('hex_codec') | |
127 | t = ntoa6(b) | |
128 | self.failUnless(t == '::10.0.0.1') | |
129 | ||
130 | def test_ntoa10(self): | |
131 | b = '0000000000000000000000010a000001'.decode('hex_codec') | |
132 | t = ntoa6(b) | |
133 | self.failUnless(t == '::1:a00:1') | |
134 | ||
135 | def test_ntoa11(self): | |
136 | b = '00000000000000000000ffff0a000001'.decode('hex_codec') | |
137 | t = ntoa6(b) | |
138 | self.failUnless(t == '::ffff:10.0.0.1') | |
139 | ||
140 | def test_ntoa12(self): | |
141 | b = '000000000000000000000000ffffffff'.decode('hex_codec') | |
142 | t = ntoa6(b) | |
143 | self.failUnless(t == '::255.255.255.255') | |
144 | ||
145 | def test_ntoa13(self): | |
146 | b = '00000000000000000000ffffffffffff'.decode('hex_codec') | |
147 | t = ntoa6(b) | |
148 | self.failUnless(t == '::ffff:255.255.255.255') | |
149 | ||
150 | def test_ntoa14(self): | |
151 | b = '0000000000000000000000000001ffff'.decode('hex_codec') | |
152 | t = ntoa6(b) | |
153 | self.failUnless(t == '::0.1.255.255') | |
154 | ||
155 | def test_bad_ntoa1(self): | |
156 | def bad(): | |
157 | a = ntoa6('') | |
158 | self.failUnlessRaises(ValueError, bad) | |
159 | ||
160 | def test_bad_ntoa2(self): | |
161 | def bad(): | |
162 | a = ntoa6('\x00' * 17) | |
163 | self.failUnlessRaises(ValueError, bad) | |
164 | ||
165 | def test_good_v4_aton(self): | |
166 | pairs = [('1.2.3.4', '\x01\x02\x03\x04'), | |
167 | ('255.255.255.255', '\xff\xff\xff\xff'), | |
168 | ('0.0.0.0', '\x00\x00\x00\x00')] | |
169 | for (t, b) in pairs: | |
170 | b1 = aton4(t) | |
171 | t1 = ntoa4(b1) | |
172 | self.failUnless(b1 == b) | |
173 | self.failUnless(t1 == t) | |
174 | ||
175 | def test_bad_v4_aton(self): | |
176 | def make_bad(a): | |
177 | def bad(): | |
178 | return aton4(a) | |
179 | return bad | |
180 | for addr in v4_bad_addrs: | |
181 | self.failUnlessRaises(dns.exception.SyntaxError, make_bad(addr)) | |
182 | ||
183 | def test_bad_v6_aton(self): | |
184 | addrs = ['+::0', '0::0::', '::0::', '1:2:3:4:5:6:7:8:9', | |
185 | ':::::::'] | |
186 | embedded = ['::' + x for x in v4_bad_addrs] | |
187 | addrs.extend(embedded) | |
188 | def make_bad(a): | |
189 | def bad(): | |
190 | x = aton6(a) | |
191 | return bad | |
192 | for addr in addrs: | |
193 | self.failUnlessRaises(dns.exception.SyntaxError, make_bad(addr)) | |
194 | ||
195 | def test_rfc5952_section_4_2_2(self): | |
196 | addr = '2001:db8:0:1:1:1:1:1' | |
197 | b1 = aton6(addr) | |
198 | t1 = ntoa6(b1) | |
199 | self.failUnless(t1 == addr) | |
200 | ||
201 | if __name__ == '__main__': | |
202 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.rdataclass | |
18 | import dns.rdatatype | |
19 | ||
20 | class RdTypeAndClassTestCase(unittest.TestCase): | |
21 | ||
22 | # Classes | |
23 | ||
24 | def test_class_meta1(self): | |
25 | self.failUnless(dns.rdataclass.is_metaclass(dns.rdataclass.ANY)) | |
26 | ||
27 | def test_class_meta2(self): | |
28 | self.failUnless(not dns.rdataclass.is_metaclass(dns.rdataclass.IN)) | |
29 | ||
30 | def test_class_bytext1(self): | |
31 | self.failUnless(dns.rdataclass.from_text('IN') == dns.rdataclass.IN) | |
32 | ||
33 | def test_class_bytext2(self): | |
34 | self.failUnless(dns.rdataclass.from_text('CLASS1') == | |
35 | dns.rdataclass.IN) | |
36 | ||
37 | def test_class_bytext_bounds1(self): | |
38 | self.failUnless(dns.rdataclass.from_text('CLASS0') == 0) | |
39 | self.failUnless(dns.rdataclass.from_text('CLASS65535') == 65535) | |
40 | ||
41 | def test_class_bytext_bounds2(self): | |
42 | def bad(): | |
43 | junk = dns.rdataclass.from_text('CLASS65536') | |
44 | self.failUnlessRaises(ValueError, bad) | |
45 | ||
46 | def test_class_bytext_unknown(self): | |
47 | def bad(): | |
48 | junk = dns.rdataclass.from_text('XXX') | |
49 | self.failUnlessRaises(dns.rdataclass.UnknownRdataclass, bad) | |
50 | ||
51 | def test_class_totext1(self): | |
52 | self.failUnless(dns.rdataclass.to_text(dns.rdataclass.IN) == 'IN') | |
53 | ||
54 | def test_class_totext1(self): | |
55 | self.failUnless(dns.rdataclass.to_text(999) == 'CLASS999') | |
56 | ||
57 | def test_class_totext_bounds1(self): | |
58 | def bad(): | |
59 | junk = dns.rdataclass.to_text(-1) | |
60 | self.failUnlessRaises(ValueError, bad) | |
61 | ||
62 | def test_class_totext_bounds2(self): | |
63 | def bad(): | |
64 | junk = dns.rdataclass.to_text(65536) | |
65 | self.failUnlessRaises(ValueError, bad) | |
66 | ||
67 | # Types | |
68 | ||
69 | def test_type_meta1(self): | |
70 | self.failUnless(dns.rdatatype.is_metatype(dns.rdatatype.ANY)) | |
71 | ||
72 | def test_type_meta2(self): | |
73 | self.failUnless(dns.rdatatype.is_metatype(dns.rdatatype.OPT)) | |
74 | ||
75 | def test_type_meta3(self): | |
76 | self.failUnless(not dns.rdatatype.is_metatype(dns.rdatatype.A)) | |
77 | ||
78 | def test_type_singleton1(self): | |
79 | self.failUnless(dns.rdatatype.is_singleton(dns.rdatatype.SOA)) | |
80 | ||
81 | def test_type_singleton2(self): | |
82 | self.failUnless(not dns.rdatatype.is_singleton(dns.rdatatype.A)) | |
83 | ||
84 | def test_type_bytext1(self): | |
85 | self.failUnless(dns.rdatatype.from_text('A') == dns.rdatatype.A) | |
86 | ||
87 | def test_type_bytext2(self): | |
88 | self.failUnless(dns.rdatatype.from_text('TYPE1') == | |
89 | dns.rdatatype.A) | |
90 | ||
91 | def test_type_bytext_bounds1(self): | |
92 | self.failUnless(dns.rdatatype.from_text('TYPE0') == 0) | |
93 | self.failUnless(dns.rdatatype.from_text('TYPE65535') == 65535) | |
94 | ||
95 | def test_type_bytext_bounds2(self): | |
96 | def bad(): | |
97 | junk = dns.rdatatype.from_text('TYPE65536') | |
98 | self.failUnlessRaises(ValueError, bad) | |
99 | ||
100 | def test_type_bytext_unknown(self): | |
101 | def bad(): | |
102 | junk = dns.rdatatype.from_text('XXX') | |
103 | self.failUnlessRaises(dns.rdatatype.UnknownRdatatype, bad) | |
104 | ||
105 | def test_type_totext1(self): | |
106 | self.failUnless(dns.rdatatype.to_text(dns.rdatatype.A) == 'A') | |
107 | ||
108 | def test_type_totext1(self): | |
109 | self.failUnless(dns.rdatatype.to_text(999) == 'TYPE999') | |
110 | ||
111 | def test_type_totext_bounds1(self): | |
112 | def bad(): | |
113 | junk = dns.rdatatype.to_text(-1) | |
114 | self.failUnlessRaises(ValueError, bad) | |
115 | ||
116 | def test_type_totext_bounds2(self): | |
117 | def bad(): | |
118 | junk = dns.rdatatype.to_text(65536) | |
119 | self.failUnlessRaises(ValueError, bad) | |
120 | ||
121 | if __name__ == '__main__': | |
122 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import cStringIO | |
16 | import select | |
17 | import sys | |
18 | import time | |
19 | import unittest | |
20 | ||
21 | import dns.name | |
22 | import dns.message | |
23 | import dns.name | |
24 | import dns.rdataclass | |
25 | import dns.rdatatype | |
26 | import dns.resolver | |
27 | ||
28 | resolv_conf = """ | |
29 | /t/t | |
30 | # comment 1 | |
31 | ; comment 2 | |
32 | domain foo | |
33 | nameserver 10.0.0.1 | |
34 | nameserver 10.0.0.2 | |
35 | """ | |
36 | ||
37 | message_text = """id 1234 | |
38 | opcode QUERY | |
39 | rcode NOERROR | |
40 | flags QR AA RD | |
41 | ;QUESTION | |
42 | example. IN A | |
43 | ;ANSWER | |
44 | example. 1 IN A 10.0.0.1 | |
45 | ;AUTHORITY | |
46 | ;ADDITIONAL | |
47 | """ | |
48 | ||
49 | class FakeAnswer(object): | |
50 | def __init__(self, expiration): | |
51 | self.expiration = expiration | |
52 | ||
53 | class BaseResolverTests(object): | |
54 | ||
55 | if sys.platform != 'win32': | |
56 | def testRead(self): | |
57 | f = cStringIO.StringIO(resolv_conf) | |
58 | r = dns.resolver.Resolver(f) | |
59 | self.failUnless(r.nameservers == ['10.0.0.1', '10.0.0.2'] and | |
60 | r.domain == dns.name.from_text('foo')) | |
61 | ||
62 | def testCacheExpiration(self): | |
63 | message = dns.message.from_text(message_text) | |
64 | name = dns.name.from_text('example.') | |
65 | answer = dns.resolver.Answer(name, dns.rdatatype.A, dns.rdataclass.IN, | |
66 | message) | |
67 | cache = dns.resolver.Cache() | |
68 | cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) | |
69 | time.sleep(2) | |
70 | self.failUnless(cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)) | |
71 | is None) | |
72 | ||
73 | def testCacheCleaning(self): | |
74 | message = dns.message.from_text(message_text) | |
75 | name = dns.name.from_text('example.') | |
76 | answer = dns.resolver.Answer(name, dns.rdatatype.A, dns.rdataclass.IN, | |
77 | message) | |
78 | cache = dns.resolver.Cache(cleaning_interval=1.0) | |
79 | cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) | |
80 | time.sleep(2) | |
81 | self.failUnless(cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)) | |
82 | is None) | |
83 | ||
84 | def testZoneForName1(self): | |
85 | name = dns.name.from_text('www.dnspython.org.') | |
86 | ezname = dns.name.from_text('dnspython.org.') | |
87 | zname = dns.resolver.zone_for_name(name) | |
88 | self.failUnless(zname == ezname) | |
89 | ||
90 | def testZoneForName2(self): | |
91 | name = dns.name.from_text('a.b.www.dnspython.org.') | |
92 | ezname = dns.name.from_text('dnspython.org.') | |
93 | zname = dns.resolver.zone_for_name(name) | |
94 | self.failUnless(zname == ezname) | |
95 | ||
96 | def testZoneForName3(self): | |
97 | name = dns.name.from_text('dnspython.org.') | |
98 | ezname = dns.name.from_text('dnspython.org.') | |
99 | zname = dns.resolver.zone_for_name(name) | |
100 | self.failUnless(zname == ezname) | |
101 | ||
102 | def testZoneForName4(self): | |
103 | def bad(): | |
104 | name = dns.name.from_text('dnspython.org', None) | |
105 | zname = dns.resolver.zone_for_name(name) | |
106 | self.failUnlessRaises(dns.resolver.NotAbsolute, bad) | |
107 | ||
108 | def testLRUReplace(self): | |
109 | cache = dns.resolver.LRUCache(4) | |
110 | for i in xrange(0, 5): | |
111 | name = dns.name.from_text('example%d.' % i) | |
112 | answer = FakeAnswer(time.time() + 1) | |
113 | cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) | |
114 | for i in xrange(0, 5): | |
115 | name = dns.name.from_text('example%d.' % i) | |
116 | if i == 0: | |
117 | self.failUnless(cache.get((name, dns.rdatatype.A, | |
118 | dns.rdataclass.IN)) | |
119 | is None) | |
120 | else: | |
121 | self.failUnless(not cache.get((name, dns.rdatatype.A, | |
122 | dns.rdataclass.IN)) | |
123 | is None) | |
124 | ||
125 | def testLRUDoesLRU(self): | |
126 | cache = dns.resolver.LRUCache(4) | |
127 | for i in xrange(0, 4): | |
128 | name = dns.name.from_text('example%d.' % i) | |
129 | answer = FakeAnswer(time.time() + 1) | |
130 | cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) | |
131 | name = dns.name.from_text('example0.') | |
132 | cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)) | |
133 | # The LRU is now example1. | |
134 | name = dns.name.from_text('example4.') | |
135 | answer = FakeAnswer(time.time() + 1) | |
136 | cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) | |
137 | for i in xrange(0, 5): | |
138 | name = dns.name.from_text('example%d.' % i) | |
139 | if i == 1: | |
140 | self.failUnless(cache.get((name, dns.rdatatype.A, | |
141 | dns.rdataclass.IN)) | |
142 | is None) | |
143 | else: | |
144 | self.failUnless(not cache.get((name, dns.rdatatype.A, | |
145 | dns.rdataclass.IN)) | |
146 | is None) | |
147 | ||
148 | def testLRUExpiration(self): | |
149 | cache = dns.resolver.LRUCache(4) | |
150 | for i in xrange(0, 4): | |
151 | name = dns.name.from_text('example%d.' % i) | |
152 | answer = FakeAnswer(time.time() + 1) | |
153 | cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) | |
154 | time.sleep(2) | |
155 | for i in xrange(0, 4): | |
156 | name = dns.name.from_text('example%d.' % i) | |
157 | self.failUnless(cache.get((name, dns.rdatatype.A, | |
158 | dns.rdataclass.IN)) | |
159 | is None) | |
160 | ||
161 | class PollingMonkeyPatchMixin(object): | |
162 | def setUp(self): | |
163 | self.__native_polling_backend = dns.query._polling_backend | |
164 | dns.query._set_polling_backend(self.polling_backend()) | |
165 | ||
166 | unittest.TestCase.setUp(self) | |
167 | ||
168 | def tearDown(self): | |
169 | dns.query._set_polling_backend(self.__native_polling_backend) | |
170 | ||
171 | unittest.TestCase.tearDown(self) | |
172 | ||
173 | class SelectResolverTestCase(PollingMonkeyPatchMixin, BaseResolverTests, unittest.TestCase): | |
174 | def polling_backend(self): | |
175 | return dns.query._select_for | |
176 | ||
177 | if hasattr(select, 'poll'): | |
178 | class PollResolverTestCase(PollingMonkeyPatchMixin, BaseResolverTests, unittest.TestCase): | |
179 | def polling_backend(self): | |
180 | return dns.query._poll_for | |
181 | ||
182 | if __name__ == '__main__': | |
183 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.rrset | |
18 | ||
19 | class RRsetTestCase(unittest.TestCase): | |
20 | ||
21 | def testEqual1(self): | |
22 | r1 = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1', '10.0.0.2') | |
23 | r2 = dns.rrset.from_text('FOO', 300, 'in', 'a', '10.0.0.2', '10.0.0.1') | |
24 | self.failUnless(r1 == r2) | |
25 | ||
26 | def testEqual2(self): | |
27 | r1 = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1', '10.0.0.2') | |
28 | r2 = dns.rrset.from_text('FOO', 600, 'in', 'a', '10.0.0.2', '10.0.0.1') | |
29 | self.failUnless(r1 == r2) | |
30 | ||
31 | def testNotEqual1(self): | |
32 | r1 = dns.rrset.from_text('fooa', 30, 'in', 'a', '10.0.0.1', '10.0.0.2') | |
33 | r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1') | |
34 | self.failUnless(r1 != r2) | |
35 | ||
36 | def testNotEqual2(self): | |
37 | r1 = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1', '10.0.0.3') | |
38 | r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1') | |
39 | self.failUnless(r1 != r2) | |
40 | ||
41 | def testNotEqual3(self): | |
42 | r1 = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1', '10.0.0.2', | |
43 | '10.0.0.3') | |
44 | r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1') | |
45 | self.failUnless(r1 != r2) | |
46 | ||
47 | def testNotEqual4(self): | |
48 | r1 = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1') | |
49 | r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1') | |
50 | self.failUnless(r1 != r2) | |
51 | ||
52 | if __name__ == '__main__': | |
53 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.set | |
18 | ||
19 | # for convenience | |
20 | S = dns.set.Set | |
21 | ||
22 | class SimpleSetTestCase(unittest.TestCase): | |
23 | ||
24 | def testLen1(self): | |
25 | s1 = S() | |
26 | self.failUnless(len(s1) == 0) | |
27 | ||
28 | def testLen2(self): | |
29 | s1 = S([1, 2, 3]) | |
30 | self.failUnless(len(s1) == 3) | |
31 | ||
32 | def testLen3(self): | |
33 | s1 = S([1, 2, 3, 3, 3]) | |
34 | self.failUnless(len(s1) == 3) | |
35 | ||
36 | def testUnion1(self): | |
37 | s1 = S([1, 2, 3]) | |
38 | s2 = S([1, 2, 3]) | |
39 | e = S([1, 2, 3]) | |
40 | self.failUnless(s1 | s2 == e) | |
41 | ||
42 | def testUnion2(self): | |
43 | s1 = S([1, 2, 3]) | |
44 | s2 = S([]) | |
45 | e = S([1, 2, 3]) | |
46 | self.failUnless(s1 | s2 == e) | |
47 | ||
48 | def testUnion3(self): | |
49 | s1 = S([1, 2, 3]) | |
50 | s2 = S([3, 4]) | |
51 | e = S([1, 2, 3, 4]) | |
52 | self.failUnless(s1 | s2 == e) | |
53 | ||
54 | def testIntersection1(self): | |
55 | s1 = S([1, 2, 3]) | |
56 | s2 = S([1, 2, 3]) | |
57 | e = S([1, 2, 3]) | |
58 | self.failUnless(s1 & s2 == e) | |
59 | ||
60 | def testIntersection2(self): | |
61 | s1 = S([0, 1, 2, 3]) | |
62 | s2 = S([1, 2, 3, 4]) | |
63 | e = S([1, 2, 3]) | |
64 | self.failUnless(s1 & s2 == e) | |
65 | ||
66 | def testIntersection3(self): | |
67 | s1 = S([1, 2, 3]) | |
68 | s2 = S([]) | |
69 | e = S([]) | |
70 | self.failUnless(s1 & s2 == e) | |
71 | ||
72 | def testIntersection4(self): | |
73 | s1 = S([1, 2, 3]) | |
74 | s2 = S([5, 4]) | |
75 | e = S([]) | |
76 | self.failUnless(s1 & s2 == e) | |
77 | ||
78 | def testDifference1(self): | |
79 | s1 = S([1, 2, 3]) | |
80 | s2 = S([5, 4]) | |
81 | e = S([1, 2, 3]) | |
82 | self.failUnless(s1 - s2 == e) | |
83 | ||
84 | def testDifference2(self): | |
85 | s1 = S([1, 2, 3]) | |
86 | s2 = S([]) | |
87 | e = S([1, 2, 3]) | |
88 | self.failUnless(s1 - s2 == e) | |
89 | ||
90 | def testDifference3(self): | |
91 | s1 = S([1, 2, 3]) | |
92 | s2 = S([3, 2]) | |
93 | e = S([1]) | |
94 | self.failUnless(s1 - s2 == e) | |
95 | ||
96 | def testDifference4(self): | |
97 | s1 = S([1, 2, 3]) | |
98 | s2 = S([3, 2, 1]) | |
99 | e = S([]) | |
100 | self.failUnless(s1 - s2 == e) | |
101 | ||
102 | def testSubset1(self): | |
103 | s1 = S([1, 2, 3]) | |
104 | s2 = S([3, 2, 1]) | |
105 | self.failUnless(s1.issubset(s2)) | |
106 | ||
107 | def testSubset2(self): | |
108 | s1 = S([1, 2, 3]) | |
109 | self.failUnless(s1.issubset(s1)) | |
110 | ||
111 | def testSubset3(self): | |
112 | s1 = S([]) | |
113 | s2 = S([1, 2, 3]) | |
114 | self.failUnless(s1.issubset(s2)) | |
115 | ||
116 | def testSubset4(self): | |
117 | s1 = S([1]) | |
118 | s2 = S([1, 2, 3]) | |
119 | self.failUnless(s1.issubset(s2)) | |
120 | ||
121 | def testSubset5(self): | |
122 | s1 = S([]) | |
123 | s2 = S([]) | |
124 | self.failUnless(s1.issubset(s2)) | |
125 | ||
126 | def testSubset6(self): | |
127 | s1 = S([1, 4]) | |
128 | s2 = S([1, 2, 3]) | |
129 | self.failUnless(not s1.issubset(s2)) | |
130 | ||
131 | def testSuperset1(self): | |
132 | s1 = S([1, 2, 3]) | |
133 | s2 = S([3, 2, 1]) | |
134 | self.failUnless(s1.issuperset(s2)) | |
135 | ||
136 | def testSuperset2(self): | |
137 | s1 = S([1, 2, 3]) | |
138 | self.failUnless(s1.issuperset(s1)) | |
139 | ||
140 | def testSuperset3(self): | |
141 | s1 = S([1, 2, 3]) | |
142 | s2 = S([]) | |
143 | self.failUnless(s1.issuperset(s2)) | |
144 | ||
145 | def testSuperset4(self): | |
146 | s1 = S([1, 2, 3]) | |
147 | s2 = S([1]) | |
148 | self.failUnless(s1.issuperset(s2)) | |
149 | ||
150 | def testSuperset5(self): | |
151 | s1 = S([]) | |
152 | s2 = S([]) | |
153 | self.failUnless(s1.issuperset(s2)) | |
154 | ||
155 | def testSuperset6(self): | |
156 | s1 = S([1, 2, 3]) | |
157 | s2 = S([1, 4]) | |
158 | self.failUnless(not s1.issuperset(s2)) | |
159 | ||
160 | def testUpdate1(self): | |
161 | s1 = S([1, 2, 3]) | |
162 | u = (4, 5, 6) | |
163 | e = S([1, 2, 3, 4, 5, 6]) | |
164 | s1.update(u) | |
165 | self.failUnless(s1 == e) | |
166 | ||
167 | def testUpdate2(self): | |
168 | s1 = S([1, 2, 3]) | |
169 | u = [] | |
170 | e = S([1, 2, 3]) | |
171 | s1.update(u) | |
172 | self.failUnless(s1 == e) | |
173 | ||
174 | def testGetitem(self): | |
175 | s1 = S([1, 2, 3]) | |
176 | i0 = s1[0] | |
177 | i1 = s1[1] | |
178 | i2 = s1[2] | |
179 | s2 = S([i0, i1, i2]) | |
180 | self.failUnless(s1 == s2) | |
181 | ||
182 | def testGetslice(self): | |
183 | s1 = S([1, 2, 3]) | |
184 | slice = s1[0:2] | |
185 | self.failUnless(len(slice) == 2) | |
186 | item = s1[2] | |
187 | slice.append(item) | |
188 | s2 = S(slice) | |
189 | self.failUnless(s1 == s2) | |
190 | ||
191 | def testDelitem(self): | |
192 | s1 = S([1, 2, 3]) | |
193 | del s1[0] | |
194 | i1 = s1[0] | |
195 | i2 = s1[1] | |
196 | self.failUnless(i1 != i2) | |
197 | self.failUnless(i1 == 1 or i1 == 2 or i1 == 3) | |
198 | self.failUnless(i2 == 1 or i2 == 2 or i2 == 3) | |
199 | ||
200 | def testDelslice(self): | |
201 | s1 = S([1, 2, 3]) | |
202 | del s1[0:2] | |
203 | i1 = s1[0] | |
204 | self.failUnless(i1 == 1 or i1 == 2 or i1 == 3) | |
205 | ||
206 | if __name__ == '__main__': | |
207 | unittest.main() |
0 | # Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.rdata | |
18 | import dns.rdataclass | |
19 | import dns.rdatatype | |
20 | import dns.ttl | |
21 | ||
22 | class BugsTestCase(unittest.TestCase): | |
23 | ||
24 | def test_float_LOC(self): | |
25 | rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.LOC, | |
26 | "30 30 0.000 N 100 30 0.000 W 10.00m 20m 2000m 20m") | |
27 | self.failUnless(rdata.float_latitude == 30.5) | |
28 | self.failUnless(rdata.float_longitude == -100.5) | |
29 | ||
30 | def test_SOA_BIND8_TTL(self): | |
31 | rdata1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
32 | "a b 100 1s 1m 1h 1d") | |
33 | rdata2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
34 | "a b 100 1 60 3600 86400") | |
35 | self.failUnless(rdata1 == rdata2) | |
36 | ||
37 | def test_TTL_bounds_check(self): | |
38 | def bad(): | |
39 | ttl = dns.ttl.from_text("2147483648") | |
40 | self.failUnlessRaises(dns.ttl.BadTTL, bad) | |
41 | ||
42 | def test_empty_NSEC3_window(self): | |
43 | rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NSEC3, | |
44 | "1 0 100 ABCD SCBCQHKU35969L2A68P3AD59LHF30715") | |
45 | self.failUnless(rdata.windows == []) | |
46 | ||
47 | def test_zero_size_APL(self): | |
48 | rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.APL, | |
49 | "") | |
50 | rdata2 = dns.rdata.from_wire(dns.rdataclass.IN, dns.rdatatype.APL, | |
51 | "", 0, 0) | |
52 | self.failUnless(rdata == rdata2) | |
53 | ||
54 | if __name__ == '__main__': | |
55 | unittest.main() |
0 | # Copyright (C) 2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.dnssec | |
18 | import dns.name | |
19 | import dns.rdata | |
20 | import dns.rdataclass | |
21 | import dns.rdatatype | |
22 | import dns.rrset | |
23 | ||
24 | abs_dnspython_org = dns.name.from_text('dnspython.org') | |
25 | ||
26 | abs_keys = { abs_dnspython_org : | |
27 | dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'DNSKEY', | |
28 | '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=', | |
29 | '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF') | |
30 | } | |
31 | ||
32 | abs_keys_duplicate_keytag = { abs_dnspython_org : | |
33 | dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'DNSKEY', | |
34 | '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=', | |
35 | '256 3 5 AwEAAdSSg++++THIS/IS/NOT/THE/CORRECT/KEY++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ AaOSydAF', | |
36 | '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF') | |
37 | } | |
38 | ||
39 | rel_keys = { dns.name.empty : | |
40 | dns.rrset.from_text('@', 3600, 'IN', 'DNSKEY', | |
41 | '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=', | |
42 | '256 3 5 AwEAAdSSghOGjU33IQZgwZM2Hh771VGXX05olJK49FxpSyuEAjDBXY58 LGU9R2Zgeecnk/b9EAhFu/vCV9oECtiTCvwuVAkt9YEweqYDluQInmgP NGMJCKdSLlnX93DkjDw8rMYv5dqXCuSGPlKChfTJOLQxIAxGloS7lL+c 0CTZydAF') | |
43 | } | |
44 | ||
45 | when = 1290250287 | |
46 | ||
47 | abs_soa = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'SOA', | |
48 | 'howl.dnspython.org. hostmaster.dnspython.org. 2010020047 3600 1800 604800 3600') | |
49 | ||
50 | abs_other_soa = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'SOA', | |
51 | 'foo.dnspython.org. hostmaster.dnspython.org. 2010020047 3600 1800 604800 3600') | |
52 | ||
53 | abs_soa_rrsig = dns.rrset.from_text('dnspython.org.', 3600, 'IN', 'RRSIG', | |
54 | 'SOA 5 2 3600 20101127004331 20101119213831 61695 dnspython.org. sDUlltRlFTQw5ITFxOXW3TgmrHeMeNpdqcZ4EXxM9FHhIlte6V9YCnDw t6dvM9jAXdIEi03l9H/RAd9xNNW6gvGMHsBGzpvvqFQxIBR2PoiZA1mX /SWHZFdbt4xjYTtXqpyYvrMK0Dt7bUYPadyhPFCJ1B+I8Zi7B5WJEOd0 8vs=') | |
55 | ||
56 | rel_soa = dns.rrset.from_text('@', 3600, 'IN', 'SOA', | |
57 | 'howl hostmaster 2010020047 3600 1800 604800 3600') | |
58 | ||
59 | rel_other_soa = dns.rrset.from_text('@', 3600, 'IN', 'SOA', | |
60 | 'foo hostmaster 2010020047 3600 1800 604800 3600') | |
61 | ||
62 | rel_soa_rrsig = dns.rrset.from_text('@', 3600, 'IN', 'RRSIG', | |
63 | 'SOA 5 2 3600 20101127004331 20101119213831 61695 @ sDUlltRlFTQw5ITFxOXW3TgmrHeMeNpdqcZ4EXxM9FHhIlte6V9YCnDw t6dvM9jAXdIEi03l9H/RAd9xNNW6gvGMHsBGzpvvqFQxIBR2PoiZA1mX /SWHZFdbt4xjYTtXqpyYvrMK0Dt7bUYPadyhPFCJ1B+I8Zi7B5WJEOd0 8vs=') | |
64 | ||
65 | sep_key = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DNSKEY, | |
66 | '257 3 5 AwEAAenVTr9L1OMlL1/N2ta0Qj9LLLnnmFWIr1dJoAsWM9BQfsbV7kFZ XbAkER/FY9Ji2o7cELxBwAsVBuWn6IUUAJXLH74YbC1anY0lifjgt29z SwDzuB7zmC7yVYZzUunBulVW4zT0tg1aePbpVL2EtTL8VzREqbJbE25R KuQYHZtFwG8S4iBxJUmT2Bbd0921LLxSQgVoFXlQx/gFV2+UERXcJ5ce iX6A6wc02M/pdg/YbJd2rBa0MYL3/Fz/Xltre0tqsImZGxzi6YtYDs45 NC8gH+44egz82e2DATCVM1ICPmRDjXYTLldQiWA2ZXIWnK0iitl5ue24 7EsWJefrIhE=') | |
67 | ||
68 | good_ds = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, | |
69 | '57349 5 2 53A79A3E7488AB44FFC56B2D1109F0699D1796DD977E72108B841F96 E47D7013') | |
70 | ||
71 | when2 = 1290425644 | |
72 | ||
73 | abs_example = dns.name.from_text('example') | |
74 | ||
75 | abs_dsa_keys = { abs_example : | |
76 | dns.rrset.from_text('example.', 86400, 'IN', 'DNSKEY', | |
77 | '257 3 3 CI3nCqyJsiCJHTjrNsJOT4RaszetzcJPYuoH3F9ZTVt3KJXncCVR3bwn 1w0iavKljb9hDlAYSfHbFCp4ic/rvg4p1L8vh5s8ToMjqDNl40A0hUGQ Ybx5hsECyK+qHoajilUX1phYSAD8d9WAGO3fDWzUPBuzR7o85NiZCDxz yXuNVfni0uhj9n1KYhEO5yAbbruDGN89wIZcxMKuQsdUY2GYD93ssnBv a55W6XRABYWayKZ90WkRVODLVYLSn53Pj/wwxGH+XdhIAZJXimrZL4yl My7rtBsLMqq8Ihs4Tows7LqYwY7cp6y/50tw6pj8tFqMYcPUjKZV36l1 M/2t5BVg3i7IK61Aidt6aoC3TDJtzAxg3ZxfjZWJfhHjMJqzQIfbW5b9 q1mjFsW5EUv39RaNnX+3JWPRLyDqD4pIwDyqfutMsdk/Py3paHn82FGp CaOg+nicqZ9TiMZURN/XXy5JoXUNQ3RNvbHCUiPUe18KUkY6mTfnyHld 1l9YCWmzXQVClkx/hOYxjJ4j8Ife58+Obu5X', | |
78 | '256 3 3 CJE1yb9YRQiw5d2xZrMUMR+cGCTt1bp1KDCefmYKmS+Z1+q9f42ETVhx JRiQwXclYwmxborzIkSZegTNYIV6mrYwbNB27Q44c3UGcspb3PiOw5TC jNPRYEcdwGvDZ2wWy+vkSV/S9tHXY8O6ODiE6abZJDDg/RnITyi+eoDL R3KZ5n/V1f1T1b90rrV6EewhBGQJpQGDogaXb2oHww9Tm6NfXyo7SoMM pbwbzOckXv+GxRPJIQNSF4D4A9E8XCksuzVVdE/0lr37+uoiAiPia38U 5W2QWe/FJAEPLjIp2eTzf0TrADc1pKP1wrA2ASpdzpm/aX3IB5RPp8Ew S9U72eBFZJAUwg635HxJVxH1maG6atzorR566E+e0OZSaxXS9o1o6QqN 3oPlYLGPORDiExilKfez3C/x/yioOupW9K5eKF0gmtaqrHX0oq9s67f/ RIM2xVaKHgG9Vf2cgJIZkhv7sntujr+E4htnRmy9P9BxyFxsItYxPI6Z bzygHAZpGhlI/7ltEGlIwKxyTK3ZKBm67q7B') | |
79 | } | |
80 | ||
81 | abs_dsa_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', | |
82 | 'ns1.example. hostmaster.example. 2 10800 3600 604800 86400') | |
83 | ||
84 | abs_other_dsa_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', | |
85 | 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401') | |
86 | ||
87 | abs_dsa_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', | |
88 | 'SOA 3 1 86400 20101129143231 20101122112731 42088 example. CGul9SuBofsktunV8cJs4eRs6u+3NCS3yaPKvBbD+pB2C76OUXDZq9U=') | |
89 | ||
90 | example_sep_key = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DNSKEY, | |
91 | '257 3 3 CI3nCqyJsiCJHTjrNsJOT4RaszetzcJPYuoH3F9ZTVt3KJXncCVR3bwn 1w0iavKljb9hDlAYSfHbFCp4ic/rvg4p1L8vh5s8ToMjqDNl40A0hUGQ Ybx5hsECyK+qHoajilUX1phYSAD8d9WAGO3fDWzUPBuzR7o85NiZCDxz yXuNVfni0uhj9n1KYhEO5yAbbruDGN89wIZcxMKuQsdUY2GYD93ssnBv a55W6XRABYWayKZ90WkRVODLVYLSn53Pj/wwxGH+XdhIAZJXimrZL4yl My7rtBsLMqq8Ihs4Tows7LqYwY7cp6y/50tw6pj8tFqMYcPUjKZV36l1 M/2t5BVg3i7IK61Aidt6aoC3TDJtzAxg3ZxfjZWJfhHjMJqzQIfbW5b9 q1mjFsW5EUv39RaNnX+3JWPRLyDqD4pIwDyqfutMsdk/Py3paHn82FGp CaOg+nicqZ9TiMZURN/XXy5JoXUNQ3RNvbHCUiPUe18KUkY6mTfnyHld 1l9YCWmzXQVClkx/hOYxjJ4j8Ife58+Obu5X') | |
92 | ||
93 | example_ds_sha1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, | |
94 | '18673 3 1 71b71d4f3e11bbd71b4eff12cde69f7f9215bbe7') | |
95 | ||
96 | example_ds_sha256 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.DS, | |
97 | '18673 3 2 eb8344cbbf07c9d3d3d6c81d10c76653e28d8611a65e639ef8f716e4e4e5d913') | |
98 | ||
99 | when3 = 1379801800 | |
100 | ||
101 | abs_ecdsa256_keys = { abs_example : | |
102 | dns.rrset.from_text('example.', 86400, 'IN', 'DNSKEY', | |
103 | "256 3 13 +3ss1sCpdARVA61DJigEsL/8quo2a8MszKtn2gkkfxgzFs8S2UHtpb4N fY+XFmNW+JK6MsCkI3jHYN8eEQUgMw==", | |
104 | "257 3 13 eJCEVH7AS3wnoaQpaNlAXH0W8wxymtT9P6P3qjN2ZCV641ED8pF7wZ5V yWfOpgTs6oaZevbJgehl/GaRPUgVyQ==") | |
105 | } | |
106 | ||
107 | abs_ecdsa256_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', | |
108 | 'ns1.example. hostmaster.example. 4 10800 3600 604800 86400') | |
109 | ||
110 | abs_other_ecdsa256_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', | |
111 | 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401') | |
112 | ||
113 | abs_ecdsa256_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', | |
114 | "SOA 13 1 86400 20130921221753 20130921221638 7460 example. Sm09SOGz1ULB5D/duwdE2Zpn8bWbVBM77H6N1wPkc42LevvVO+kZEjpq 2nq4GOMJcih52667GIAbMrwmU5P2MQ==") | |
115 | ||
116 | when4 = 1379804850 | |
117 | ||
118 | abs_ecdsa384_keys = { abs_example : | |
119 | dns.rrset.from_text('example.', 86400, 'IN', 'DNSKEY', | |
120 | "256 3 14 1bG8qWviKNXQX3BIuG6/T5jrP1FISiLW/8qGF6BsM9DQtWYhhZUA3Owr OAEiyHAhQwjkN2kTvWiAYoPN80Ii+5ff9/atzY4F9W50P4l75Dj9PYrL HN/hLUgWMNVc9pvA", | |
121 | "257 3 14 mSub2n0KRt6u2FaD5XJ3oQu0R4XvB/9vUJcyW6+oo0y+KzfQeTdkf1ro ZMVKoyWXW9zUKBYGJpMUIdbAxzrYi7f5HyZ3yDpBFz1hw9+o3CX+gtgb +RyhHfJDwwFXBid9") | |
122 | } | |
123 | ||
124 | abs_ecdsa384_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', | |
125 | 'ns1.example. hostmaster.example. 2 10800 3600 604800 86400') | |
126 | ||
127 | abs_other_ecdsa384_soa = dns.rrset.from_text('example.', 86400, 'IN', 'SOA', | |
128 | 'ns1.example. hostmaster.example. 2 10800 3600 604800 86401') | |
129 | ||
130 | abs_ecdsa384_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', | |
131 | "SOA 14 1 86400 20130929021229 20130921230729 63571 example. CrnCu34EeeRz0fEhL9PLlwjpBKGYW8QjBjFQTwd+ViVLRAS8tNkcDwQE NhSV89NEjj7ze1a/JcCfcJ+/mZgnvH4NHLNg3Tf6KuLZsgs2I4kKQXEk 37oIHravPEOlGYNI") | |
132 | ||
133 | class DNSSECValidatorTestCase(unittest.TestCase): | |
134 | ||
135 | @unittest.skipIf(not dns.dnssec._have_pycrypto, | |
136 | "PyCrypto cannot be imported") | |
137 | def testAbsoluteRSAGood(self): | |
138 | dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys, None, when) | |
139 | ||
140 | @unittest.skipIf(not dns.dnssec._have_pycrypto, | |
141 | "PyCrypto cannot be imported") | |
142 | def testDuplicateKeytag(self): | |
143 | dns.dnssec.validate(abs_soa, abs_soa_rrsig, abs_keys_duplicate_keytag, None, when) | |
144 | ||
145 | @unittest.skipIf(not dns.dnssec._have_pycrypto, | |
146 | "PyCrypto cannot be imported") | |
147 | def testAbsoluteRSABad(self): | |
148 | def bad(): | |
149 | dns.dnssec.validate(abs_other_soa, abs_soa_rrsig, abs_keys, None, | |
150 | when) | |
151 | self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) | |
152 | ||
153 | @unittest.skipIf(not dns.dnssec._have_pycrypto, | |
154 | "PyCrypto cannot be imported") | |
155 | def testRelativeRSAGood(self): | |
156 | dns.dnssec.validate(rel_soa, rel_soa_rrsig, rel_keys, | |
157 | abs_dnspython_org, when) | |
158 | ||
159 | @unittest.skipIf(not dns.dnssec._have_pycrypto, | |
160 | "PyCrypto cannot be imported") | |
161 | def testRelativeRSABad(self): | |
162 | def bad(): | |
163 | dns.dnssec.validate(rel_other_soa, rel_soa_rrsig, rel_keys, | |
164 | abs_dnspython_org, when) | |
165 | self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) | |
166 | ||
167 | def testMakeSHA256DS(self): | |
168 | ds = dns.dnssec.make_ds(abs_dnspython_org, sep_key, 'SHA256') | |
169 | self.failUnless(ds == good_ds) | |
170 | ||
171 | @unittest.skipIf(not dns.dnssec._have_pycrypto, | |
172 | "PyCrypto cannot be imported") | |
173 | def testAbsoluteDSAGood(self): | |
174 | dns.dnssec.validate(abs_dsa_soa, abs_dsa_soa_rrsig, abs_dsa_keys, None, | |
175 | when2) | |
176 | ||
177 | @unittest.skipIf(not dns.dnssec._have_pycrypto, | |
178 | "PyCrypto cannot be imported") | |
179 | def testAbsoluteDSABad(self): | |
180 | def bad(): | |
181 | dns.dnssec.validate(abs_other_dsa_soa, abs_dsa_soa_rrsig, | |
182 | abs_dsa_keys, None, when2) | |
183 | self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) | |
184 | ||
185 | def testMakeExampleSHA1DS(self): | |
186 | ds = dns.dnssec.make_ds(abs_example, example_sep_key, 'SHA1') | |
187 | self.failUnless(ds == example_ds_sha1) | |
188 | ||
189 | def testMakeExampleSHA256DS(self): | |
190 | ds = dns.dnssec.make_ds(abs_example, example_sep_key, 'SHA256') | |
191 | self.failUnless(ds == example_ds_sha256) | |
192 | ||
193 | @unittest.skipIf(not dns.dnssec._have_ecdsa, | |
194 | "python ECDSA cannot be imported") | |
195 | def testAbsoluteECDSA256Good(self): | |
196 | dns.dnssec.validate(abs_ecdsa256_soa, abs_ecdsa256_soa_rrsig, | |
197 | abs_ecdsa256_keys, None, when3) | |
198 | ||
199 | @unittest.skipIf(not dns.dnssec._have_ecdsa, | |
200 | "python ECDSA cannot be imported") | |
201 | def testAbsoluteECDSA256Bad(self): | |
202 | def bad(): | |
203 | dns.dnssec.validate(abs_other_ecdsa256_soa, abs_ecdsa256_soa_rrsig, | |
204 | abs_ecdsa256_keys, None, when3) | |
205 | self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) | |
206 | ||
207 | @unittest.skipIf(not dns.dnssec._have_ecdsa, | |
208 | "python ECDSA can not be imported") | |
209 | def testAbsoluteECDSA384Good(self): | |
210 | dns.dnssec.validate(abs_ecdsa384_soa, abs_ecdsa384_soa_rrsig, | |
211 | abs_ecdsa384_keys, None, when4) | |
212 | ||
213 | @unittest.skipIf(not dns.dnssec._have_ecdsa, | |
214 | "python ECDSA can not be imported") | |
215 | def testAbsoluteECDSA384Bad(self): | |
216 | def bad(): | |
217 | dns.dnssec.validate(abs_other_ecdsa384_soa, abs_ecdsa384_soa_rrsig, | |
218 | abs_ecdsa384_keys, None, when4) | |
219 | self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) | |
220 | ||
221 | ||
222 | if __name__ == '__main__': | |
223 | import_ok = False | |
224 | try: | |
225 | import Crypto.Util.number | |
226 | import_ok = True | |
227 | except: | |
228 | pass | |
229 | if import_ok: | |
230 | unittest.main() | |
231 | else: | |
232 | print 'skipping DNSSEC tests because pycrypto is not installed' |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.flags | |
18 | import dns.rcode | |
19 | import dns.opcode | |
20 | ||
21 | class FlagsTestCase(unittest.TestCase): | |
22 | ||
23 | def test_rcode1(self): | |
24 | self.failUnless(dns.rcode.from_text('FORMERR') == dns.rcode.FORMERR) | |
25 | ||
26 | def test_rcode2(self): | |
27 | self.failUnless(dns.rcode.to_text(dns.rcode.FORMERR) == "FORMERR") | |
28 | ||
29 | def test_rcode3(self): | |
30 | self.failUnless(dns.rcode.to_flags(dns.rcode.FORMERR) == (1, 0)) | |
31 | ||
32 | def test_rcode4(self): | |
33 | self.failUnless(dns.rcode.to_flags(dns.rcode.BADVERS) == \ | |
34 | (0, 0x01000000)) | |
35 | ||
36 | def test_rcode6(self): | |
37 | self.failUnless(dns.rcode.from_flags(0, 0x01000000) == \ | |
38 | dns.rcode.BADVERS) | |
39 | ||
40 | def test_rcode6(self): | |
41 | self.failUnless(dns.rcode.from_flags(5, 0) == dns.rcode.REFUSED) | |
42 | ||
43 | def test_rcode7(self): | |
44 | def bad(): | |
45 | dns.rcode.to_flags(4096) | |
46 | self.failUnlessRaises(ValueError, bad) | |
47 | ||
48 | def test_flags1(self): | |
49 | self.failUnless(dns.flags.from_text("RA RD AA QR") == \ | |
50 | dns.flags.QR|dns.flags.AA|dns.flags.RD|dns.flags.RA) | |
51 | ||
52 | def test_flags2(self): | |
53 | flags = dns.flags.QR|dns.flags.AA|dns.flags.RD|dns.flags.RA | |
54 | self.failUnless(dns.flags.to_text(flags) == "QR AA RD RA") | |
55 | ||
56 | ||
57 | if __name__ == '__main__': | |
58 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import sys | |
16 | sys.path.insert(0, '../') # Force the local project to be *the* dns | |
17 | ||
18 | import cStringIO | |
19 | import filecmp | |
20 | import os | |
21 | import unittest | |
22 | ||
23 | import dns.exception | |
24 | import dns.rdata | |
25 | import dns.rdataclass | |
26 | import dns.rdatatype | |
27 | import dns.rrset | |
28 | import dns.zone | |
29 | ||
30 | import pprint | |
31 | ||
32 | pp = pprint.PrettyPrinter(indent=2) | |
33 | ||
34 | import pdb | |
35 | example_text = """$TTL 1h | |
36 | $ORIGIN 0.0.192.IN-ADDR.ARPA. | |
37 | $GENERATE 1-2 0 CNAME SERVER$.EXAMPLE. | |
38 | """ | |
39 | ||
40 | example_text1 = """$TTL 1h | |
41 | $ORIGIN 0.0.192.IN-ADDR.ARPA. | |
42 | $GENERATE 1-10 fooo$ CNAME $.0 | |
43 | """ | |
44 | ||
45 | example_text2 = """$TTL 1h | |
46 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
47 | @ 3600 IN NS ns1 | |
48 | @ 3600 IN NS ns2 | |
49 | bar.foo 300 IN MX 0 blaz.foo | |
50 | ns1 3600 IN A 10.0.0.1 | |
51 | ns2 3600 IN A 10.0.0.2 | |
52 | $GENERATE 3-5 foo$ A 10.0.0.$ | |
53 | """ | |
54 | ||
55 | example_text3 = """$TTL 1h | |
56 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
57 | @ 3600 IN NS ns1 | |
58 | @ 3600 IN NS ns2 | |
59 | bar.foo 300 IN MX 0 blaz.foo | |
60 | ns1 3600 IN A 10.0.0.1 | |
61 | ns2 3600 IN A 10.0.0.2 | |
62 | $GENERATE 4-8/2 foo$ A 10.0.0.$ | |
63 | """ | |
64 | ||
65 | example_text4 = """$TTL 1h | |
66 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
67 | @ 3600 IN NS ns1 | |
68 | @ 3600 IN NS ns2 | |
69 | bar.foo 300 IN MX 0 blaz.foo | |
70 | ns1 3600 IN A 10.0.0.1 | |
71 | ns2 3600 IN A 10.0.0.2 | |
72 | $GENERATE 11-13 wp-db${-10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR. | |
73 | """ | |
74 | ||
75 | example_text5 = """$TTL 1h | |
76 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
77 | @ 3600 IN NS ns1 | |
78 | @ 3600 IN NS ns2 | |
79 | bar.foo 300 IN MX 0 blaz.foo | |
80 | ns1 3600 IN A 10.0.0.1 | |
81 | ns2 3600 IN A 10.0.0.2 | |
82 | $GENERATE 11-13 wp-db${10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR. | |
83 | """ | |
84 | ||
85 | example_text6 = """$TTL 1h | |
86 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
87 | @ 3600 IN NS ns1 | |
88 | @ 3600 IN NS ns2 | |
89 | bar.foo 300 IN MX 0 blaz.foo | |
90 | ns1 3600 IN A 10.0.0.1 | |
91 | ns2 3600 IN A 10.0.0.2 | |
92 | $GENERATE 11-13 wp-db${+10,2,d}.services.mozilla.com 0 CNAME SERVER.FOOBAR. | |
93 | """ | |
94 | ||
95 | example_text7 = """$TTL 1h | |
96 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
97 | @ 3600 IN NS ns1 | |
98 | @ 3600 IN NS ns2 | |
99 | bar.foo 300 IN MX 0 blaz.foo | |
100 | ns1 3600 IN A 10.0.0.1 | |
101 | ns2 3600 IN A 10.0.0.2 | |
102 | $GENERATE 11-13 sync${-10}.db IN A 10.10.16.0 | |
103 | """ | |
104 | ||
105 | example_text8 = """$TTL 1h | |
106 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
107 | @ 3600 IN NS ns1 | |
108 | @ 3600 IN NS ns2 | |
109 | bar.foo 300 IN MX 0 blaz.foo | |
110 | ns1 3600 IN A 10.0.0.1 | |
111 | ns2 3600 IN A 10.0.0.2 | |
112 | $GENERATE 11-12 wp-db${-10,2,d} IN A 10.10.16.0 | |
113 | """ | |
114 | ||
115 | example_text9 = """$TTL 1h | |
116 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
117 | @ 3600 IN NS ns1 | |
118 | @ 3600 IN NS ns2 | |
119 | bar.foo 300 IN MX 0 blaz.foo | |
120 | ns1 3600 IN A 10.0.0.1 | |
121 | ns2 3600 IN A 10.0.0.2 | |
122 | $GENERATE 11-12 wp-db${-10,2,d} IN A 10.10.16.0 | |
123 | $GENERATE 11-13 sync${-10}.db IN A 10.10.16.0 | |
124 | """ | |
125 | example_text10 = """$TTL 1h | |
126 | @ 3600 IN SOA foo bar 1 2 3 4 5 | |
127 | @ 3600 IN NS ns1 | |
128 | @ 3600 IN NS ns2 | |
129 | bar.foo 300 IN MX 0 blaz.foo | |
130 | ns1 3600 IN A 10.0.0.1 | |
131 | ns2 3600 IN A 10.0.0.2 | |
132 | $GENERATE 27-28 $.2 PTR zlb${-26}.oob | |
133 | """ | |
134 | ||
135 | ||
136 | class GenerateTestCase(unittest.TestCase): | |
137 | ||
138 | def testFromText(self): | |
139 | def bad(): | |
140 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
141 | self.failUnlessRaises(dns.zone.NoSOA, bad) | |
142 | ||
143 | def testFromText1(self): | |
144 | def bad(): | |
145 | z = dns.zone.from_text(example_text1, 'example.', relativize=True) | |
146 | self.failUnlessRaises(dns.zone.NoSOA, bad) | |
147 | ||
148 | def testIterateAllRdatas2(self): | |
149 | z = dns.zone.from_text(example_text2, 'example.', relativize=True) | |
150 | l = list(z.iterate_rdatas()) | |
151 | l.sort() | |
152 | exl = [(dns.name.from_text('@', None), | |
153 | 3600, | |
154 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
155 | 'ns1')), | |
156 | (dns.name.from_text('@', None), | |
157 | 3600, | |
158 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
159 | 'ns2')), | |
160 | (dns.name.from_text('@', None), | |
161 | 3600, | |
162 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
163 | 'foo bar 1 2 3 4 5')), | |
164 | (dns.name.from_text('bar.foo', None), | |
165 | 300, | |
166 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
167 | '0 blaz.foo')), | |
168 | (dns.name.from_text('ns1', None), | |
169 | 3600, | |
170 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
171 | '10.0.0.1')), | |
172 | (dns.name.from_text('ns2', None), | |
173 | 3600, | |
174 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
175 | '10.0.0.2')), | |
176 | (dns.name.from_text('foo3', None), | |
177 | 3600, | |
178 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
179 | '10.0.0.3')), | |
180 | (dns.name.from_text('foo4', None), | |
181 | 3600, | |
182 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
183 | '10.0.0.4')), | |
184 | (dns.name.from_text('foo5', None), | |
185 | 3600, | |
186 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
187 | '10.0.0.5'))] | |
188 | ||
189 | exl.sort() | |
190 | self.failUnless(l == exl) | |
191 | ||
192 | def testIterateAllRdatas3(self): | |
193 | z = dns.zone.from_text(example_text3, 'example.', relativize=True) | |
194 | l = list(z.iterate_rdatas()) | |
195 | l.sort() | |
196 | exl = [(dns.name.from_text('@', None), | |
197 | 3600, | |
198 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
199 | 'ns1')), | |
200 | (dns.name.from_text('@', None), | |
201 | 3600, | |
202 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
203 | 'ns2')), | |
204 | (dns.name.from_text('@', None), | |
205 | 3600, | |
206 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
207 | 'foo bar 1 2 3 4 5')), | |
208 | (dns.name.from_text('bar.foo', None), | |
209 | 300, | |
210 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
211 | '0 blaz.foo')), | |
212 | (dns.name.from_text('ns1', None), | |
213 | 3600, | |
214 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
215 | '10.0.0.1')), | |
216 | (dns.name.from_text('ns2', None), | |
217 | 3600, | |
218 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
219 | '10.0.0.2')), | |
220 | (dns.name.from_text('foo4', None), 3600, | |
221 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
222 | '10.0.0.4')), | |
223 | (dns.name.from_text('foo6', None), 3600, | |
224 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
225 | '10.0.0.6')), | |
226 | (dns.name.from_text('foo8', None), 3600, | |
227 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
228 | '10.0.0.8'))] | |
229 | exl.sort() | |
230 | self.failUnless(l == exl) | |
231 | def testGenerate1(self): | |
232 | z = dns.zone.from_text(example_text4, 'example.', relativize=True) | |
233 | l = list(z.iterate_rdatas()) | |
234 | l.sort() | |
235 | exl = [(dns.name.from_text('@', None), | |
236 | 3600L, | |
237 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
238 | 'ns1')), | |
239 | (dns.name.from_text('@', None), | |
240 | 3600L, | |
241 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
242 | 'ns2')), | |
243 | (dns.name.from_text('@', None), | |
244 | 3600L, | |
245 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
246 | 'foo bar 1 2 3 4 5')), | |
247 | (dns.name.from_text('bar.foo', None), | |
248 | 300L, | |
249 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
250 | '0 blaz.foo')), | |
251 | (dns.name.from_text('ns1', None), | |
252 | 3600L, | |
253 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
254 | '10.0.0.1')), | |
255 | (dns.name.from_text('ns2', None), | |
256 | 3600L, | |
257 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
258 | '10.0.0.2')), | |
259 | ||
260 | (dns.name.from_text('wp-db01.services.mozilla.com', None), | |
261 | 0L, | |
262 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
263 | 'SERVER.FOOBAR.')), | |
264 | ||
265 | (dns.name.from_text('wp-db02.services.mozilla.com', None), | |
266 | 0L, | |
267 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
268 | 'SERVER.FOOBAR.')), | |
269 | ||
270 | (dns.name.from_text('wp-db03.services.mozilla.com', None), | |
271 | 0L, | |
272 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
273 | 'SERVER.FOOBAR.'))] | |
274 | exl.sort() | |
275 | self.failUnless(l == exl) | |
276 | ||
277 | def testGenerate2(self): | |
278 | z = dns.zone.from_text(example_text5, 'example.', relativize=True) | |
279 | l = list(z.iterate_rdatas()) | |
280 | l.sort() | |
281 | exl = [(dns.name.from_text('@', None), | |
282 | 3600L, | |
283 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
284 | 'ns1')), | |
285 | (dns.name.from_text('@', None), | |
286 | 3600L, | |
287 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
288 | 'ns2')), | |
289 | (dns.name.from_text('@', None), | |
290 | 3600L, | |
291 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
292 | 'foo bar 1 2 3 4 5')), | |
293 | (dns.name.from_text('bar.foo', None), | |
294 | 300L, | |
295 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
296 | '0 blaz.foo')), | |
297 | (dns.name.from_text('ns1', None), | |
298 | 3600L, | |
299 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
300 | '10.0.0.1')), | |
301 | (dns.name.from_text('ns2', None), | |
302 | 3600L, | |
303 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
304 | '10.0.0.2')), | |
305 | ||
306 | (dns.name.from_text('wp-db21.services.mozilla.com', None), 0L, | |
307 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
308 | 'SERVER.FOOBAR.')), | |
309 | ||
310 | (dns.name.from_text('wp-db22.services.mozilla.com', None), 0L, | |
311 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
312 | 'SERVER.FOOBAR.')), | |
313 | ||
314 | (dns.name.from_text('wp-db23.services.mozilla.com', None), 0L, | |
315 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
316 | 'SERVER.FOOBAR.'))] | |
317 | exl.sort() | |
318 | self.failUnless(l == exl) | |
319 | ||
320 | def testGenerate3(self): | |
321 | z = dns.zone.from_text(example_text6, 'example.', relativize=True) | |
322 | l = list(z.iterate_rdatas()) | |
323 | l.sort() | |
324 | ||
325 | exl = [(dns.name.from_text('@', None), | |
326 | 3600L, | |
327 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
328 | 'ns1')), | |
329 | (dns.name.from_text('@', None), | |
330 | 3600L, | |
331 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
332 | 'ns2')), | |
333 | (dns.name.from_text('@', None), | |
334 | 3600L, | |
335 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
336 | 'foo bar 1 2 3 4 5')), | |
337 | (dns.name.from_text('bar.foo', None), | |
338 | 300L, | |
339 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
340 | '0 blaz.foo')), | |
341 | (dns.name.from_text('ns1', None), | |
342 | 3600L, | |
343 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
344 | '10.0.0.1')), | |
345 | (dns.name.from_text('ns2', None), | |
346 | 3600L, | |
347 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
348 | '10.0.0.2')), | |
349 | (dns.name.from_text('wp-db21.services.mozilla.com', None), 0L, | |
350 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
351 | 'SERVER.FOOBAR.')), | |
352 | ||
353 | (dns.name.from_text('wp-db22.services.mozilla.com', None), 0L, | |
354 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
355 | 'SERVER.FOOBAR.')), | |
356 | ||
357 | (dns.name.from_text('wp-db23.services.mozilla.com', None), 0L, | |
358 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CNAME, | |
359 | 'SERVER.FOOBAR.'))] | |
360 | exl.sort() | |
361 | self.failUnless(l == exl) | |
362 | ||
363 | def testGenerate4(self): | |
364 | z = dns.zone.from_text(example_text7, 'example.', relativize=True) | |
365 | l = list(z.iterate_rdatas()) | |
366 | l.sort() | |
367 | exl = [(dns.name.from_text('@', None), | |
368 | 3600L, | |
369 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
370 | 'ns1')), | |
371 | (dns.name.from_text('@', None), | |
372 | 3600L, | |
373 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
374 | 'ns2')), | |
375 | (dns.name.from_text('@', None), | |
376 | 3600L, | |
377 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
378 | 'foo bar 1 2 3 4 5')), | |
379 | (dns.name.from_text('bar.foo', None), | |
380 | 300L, | |
381 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
382 | '0 blaz.foo')), | |
383 | (dns.name.from_text('ns1', None), | |
384 | 3600L, | |
385 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
386 | '10.0.0.1')), | |
387 | (dns.name.from_text('ns2', None), | |
388 | 3600L, | |
389 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
390 | '10.0.0.2')), | |
391 | ||
392 | (dns.name.from_text('sync1.db', None), 3600L, | |
393 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
394 | '10.10.16.0')), | |
395 | ||
396 | (dns.name.from_text('sync2.db', None), 3600L, | |
397 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
398 | '10.10.16.0')), | |
399 | ||
400 | (dns.name.from_text('sync3.db', None), 3600L, | |
401 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
402 | '10.10.16.0'))] | |
403 | exl.sort() | |
404 | self.failUnless(l == exl) | |
405 | ||
406 | def testGenerate6(self): | |
407 | z = dns.zone.from_text(example_text9, 'example.', relativize=True) | |
408 | l = list(z.iterate_rdatas()) | |
409 | l.sort() | |
410 | exl = [(dns.name.from_text('@', None), | |
411 | 3600L, | |
412 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
413 | 'ns1')), | |
414 | (dns.name.from_text('@', None), | |
415 | 3600L, | |
416 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
417 | 'ns2')), | |
418 | (dns.name.from_text('@', None), | |
419 | 3600L, | |
420 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
421 | 'foo bar 1 2 3 4 5')), | |
422 | (dns.name.from_text('bar.foo', None), | |
423 | 300L, | |
424 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
425 | '0 blaz.foo')), | |
426 | (dns.name.from_text('ns1', None), | |
427 | 3600L, | |
428 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
429 | '10.0.0.1')), | |
430 | (dns.name.from_text('ns2', None), | |
431 | 3600L, | |
432 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
433 | '10.0.0.2')), | |
434 | ||
435 | (dns.name.from_text('wp-db01', None), 3600L, | |
436 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
437 | '10.10.16.0')), | |
438 | (dns.name.from_text('wp-db02', None), 3600L, | |
439 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
440 | '10.10.16.0')), | |
441 | ||
442 | (dns.name.from_text('sync1.db', None), 3600L, | |
443 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
444 | '10.10.16.0')), | |
445 | ||
446 | (dns.name.from_text('sync2.db', None), 3600L, | |
447 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
448 | '10.10.16.0')), | |
449 | ||
450 | (dns.name.from_text('sync3.db', None), 3600L, | |
451 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
452 | '10.10.16.0'))] | |
453 | exl.sort() | |
454 | self.failUnless(l == exl) | |
455 | ||
456 | def testGenerate7(self): | |
457 | z = dns.zone.from_text(example_text10, 'example.', relativize=True) | |
458 | l = list(z.iterate_rdatas()) | |
459 | l.sort() | |
460 | exl = [(dns.name.from_text('@', None), | |
461 | 3600L, | |
462 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
463 | 'ns1')), | |
464 | (dns.name.from_text('@', None), | |
465 | 3600L, | |
466 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
467 | 'ns2')), | |
468 | (dns.name.from_text('@', None), | |
469 | 3600L, | |
470 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
471 | 'foo bar 1 2 3 4 5')), | |
472 | (dns.name.from_text('bar.foo', None), | |
473 | 300L, | |
474 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
475 | '0 blaz.foo')), | |
476 | (dns.name.from_text('ns1', None), | |
477 | 3600L, | |
478 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
479 | '10.0.0.1')), | |
480 | (dns.name.from_text('ns2', None), | |
481 | 3600L, | |
482 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
483 | '10.0.0.2')), | |
484 | ||
485 | (dns.name.from_text('27.2', None), 3600L, | |
486 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR, | |
487 | 'zlb1.oob')), | |
488 | ||
489 | (dns.name.from_text('28.2', None), 3600L, | |
490 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.PTR, | |
491 | 'zlb2.oob'))] | |
492 | ||
493 | exl.sort() | |
494 | self.failUnless(l == exl) | |
495 | ||
496 | ||
497 | if __name__ == '__main__': | |
498 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import sys | |
16 | sys.path.insert(0, '../') | |
17 | ||
18 | import cStringIO | |
19 | import filecmp | |
20 | import os | |
21 | import unittest | |
22 | ||
23 | import dns | |
24 | import dns.exception | |
25 | import dns.grange | |
26 | ||
27 | import pdb | |
28 | ||
29 | ||
30 | ||
31 | class GRangeTestCase(unittest.TestCase): | |
32 | ||
33 | def testFromText1(self): | |
34 | start, stop, step = dns.grange.from_text('1-1') | |
35 | self.assertEqual(start, 1) | |
36 | self.assertEqual(stop, 1) | |
37 | self.assertEqual(step, 1) | |
38 | ||
39 | def testFromText2(self): | |
40 | start, stop, step = dns.grange.from_text('1-4') | |
41 | self.assertEqual(start, 1) | |
42 | self.assertEqual(stop, 4) | |
43 | self.assertEqual(step, 1) | |
44 | ||
45 | def testFromText3(self): | |
46 | start, stop, step = dns.grange.from_text('4-255') | |
47 | self.assertEqual(start, 4) | |
48 | self.assertEqual(stop, 255) | |
49 | self.assertEqual(step, 1) | |
50 | ||
51 | def testFromText4(self): | |
52 | start, stop, step = dns.grange.from_text('1-1/1') | |
53 | self.assertEqual(start, 1) | |
54 | self.assertEqual(stop, 1) | |
55 | self.assertEqual(step, 1) | |
56 | ||
57 | def testFromText5(self): | |
58 | start, stop, step = dns.grange.from_text('1-4/2') | |
59 | self.assertEqual(start, 1) | |
60 | self.assertEqual(stop, 4) | |
61 | self.assertEqual(step, 2) | |
62 | ||
63 | def testFromText6(self): | |
64 | start, stop, step = dns.grange.from_text('4-255/77') | |
65 | self.assertEqual(start, 4) | |
66 | self.assertEqual(stop, 255) | |
67 | self.assertEqual(step, 77) | |
68 | ||
69 | def testFailFromText1(self): | |
70 | def bad(): | |
71 | start = 2 | |
72 | stop = 1 | |
73 | step = 1 | |
74 | dns.grange.from_text('%d-%d/%d' % (start, stop, step)) | |
75 | self.assertRaises(AssertionError, bad) | |
76 | ||
77 | def testFailFromText2(self): | |
78 | def bad(): | |
79 | start = '-1' | |
80 | stop = 3 | |
81 | step = 1 | |
82 | dns.grange.from_text('%s-%d/%d' % (start, stop, step)) | |
83 | self.assertRaises(dns.exception.SyntaxError, bad) | |
84 | ||
85 | def testFailFromText2(self): | |
86 | def bad(): | |
87 | start = 1 | |
88 | stop = 4 | |
89 | step = '-2' | |
90 | dns.grange.from_text('%d-%d/%s' % (start, stop, step)) | |
91 | self.assertRaises(dns.exception.SyntaxError, bad) | |
92 | ||
93 | if __name__ == '__main__': | |
94 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import cStringIO | |
16 | import os | |
17 | import unittest | |
18 | ||
19 | import dns.exception | |
20 | import dns.message | |
21 | ||
22 | query_text = """id 1234 | |
23 | opcode QUERY | |
24 | rcode NOERROR | |
25 | flags RD | |
26 | edns 0 | |
27 | eflags DO | |
28 | payload 4096 | |
29 | ;QUESTION | |
30 | wwww.dnspython.org. IN A | |
31 | ;ANSWER | |
32 | ;AUTHORITY | |
33 | ;ADDITIONAL""" | |
34 | ||
35 | goodhex = '04d201000001000000000001047777777709646e73707974686f6e' \ | |
36 | '036f726700000100010000291000000080000000' | |
37 | ||
38 | goodwire = goodhex.decode('hex_codec') | |
39 | ||
40 | answer_text = """id 1234 | |
41 | opcode QUERY | |
42 | rcode NOERROR | |
43 | flags QR AA RD | |
44 | ;QUESTION | |
45 | dnspython.org. IN SOA | |
46 | ;ANSWER | |
47 | dnspython.org. 3600 IN SOA woof.dnspython.org. hostmaster.dnspython.org. 2003052700 3600 1800 604800 3600 | |
48 | ;AUTHORITY | |
49 | dnspython.org. 3600 IN NS ns1.staff.nominum.org. | |
50 | dnspython.org. 3600 IN NS ns2.staff.nominum.org. | |
51 | dnspython.org. 3600 IN NS woof.play-bow.org. | |
52 | ;ADDITIONAL | |
53 | woof.play-bow.org. 3600 IN A 204.152.186.150 | |
54 | """ | |
55 | ||
56 | goodhex2 = '04d2 8500 0001 0001 0003 0001' \ | |
57 | '09646e73707974686f6e036f726700 0006 0001' \ | |
58 | 'c00c 0006 0001 00000e10 0028 ' \ | |
59 | '04776f6f66c00c 0a686f73746d6173746572c00c' \ | |
60 | '7764289c 00000e10 00000708 00093a80 00000e10' \ | |
61 | 'c00c 0002 0001 00000e10 0014' \ | |
62 | '036e7331057374616666076e6f6d696e756dc016' \ | |
63 | 'c00c 0002 0001 00000e10 0006 036e7332c063' \ | |
64 | 'c00c 0002 0001 00000e10 0010 04776f6f6608706c61792d626f77c016' \ | |
65 | 'c091 0001 0001 00000e10 0004 cc98ba96' | |
66 | ||
67 | ||
68 | goodwire2 = goodhex2.replace(' ', '').decode('hex_codec') | |
69 | ||
70 | query_text_2 = """id 1234 | |
71 | opcode QUERY | |
72 | rcode 4095 | |
73 | flags RD | |
74 | edns 0 | |
75 | eflags DO | |
76 | payload 4096 | |
77 | ;QUESTION | |
78 | wwww.dnspython.org. IN A | |
79 | ;ANSWER | |
80 | ;AUTHORITY | |
81 | ;ADDITIONAL""" | |
82 | ||
83 | goodhex3 = '04d2010f0001000000000001047777777709646e73707974686f6e' \ | |
84 | '036f726700000100010000291000ff0080000000' | |
85 | ||
86 | goodwire3 = goodhex3.decode('hex_codec') | |
87 | ||
88 | class MessageTestCase(unittest.TestCase): | |
89 | ||
90 | def test_comparison_eq1(self): | |
91 | q1 = dns.message.from_text(query_text) | |
92 | q2 = dns.message.from_text(query_text) | |
93 | self.failUnless(q1 == q2) | |
94 | ||
95 | def test_comparison_ne1(self): | |
96 | q1 = dns.message.from_text(query_text) | |
97 | q2 = dns.message.from_text(query_text) | |
98 | q2.id = 10 | |
99 | self.failUnless(q1 != q2) | |
100 | ||
101 | def test_comparison_ne2(self): | |
102 | q1 = dns.message.from_text(query_text) | |
103 | q2 = dns.message.from_text(query_text) | |
104 | q2.question = [] | |
105 | self.failUnless(q1 != q2) | |
106 | ||
107 | def test_comparison_ne3(self): | |
108 | q1 = dns.message.from_text(query_text) | |
109 | self.failUnless(q1 != 1) | |
110 | ||
111 | def test_EDNS_to_wire1(self): | |
112 | q = dns.message.from_text(query_text) | |
113 | w = q.to_wire() | |
114 | self.failUnless(w == goodwire) | |
115 | ||
116 | def test_EDNS_from_wire1(self): | |
117 | m = dns.message.from_wire(goodwire) | |
118 | self.failUnless(str(m) == query_text) | |
119 | ||
120 | def test_EDNS_to_wire2(self): | |
121 | q = dns.message.from_text(query_text_2) | |
122 | w = q.to_wire() | |
123 | self.failUnless(w == goodwire3) | |
124 | ||
125 | def test_EDNS_from_wire2(self): | |
126 | m = dns.message.from_wire(goodwire3) | |
127 | self.failUnless(str(m) == query_text_2) | |
128 | ||
129 | def test_TooBig(self): | |
130 | def bad(): | |
131 | q = dns.message.from_text(query_text) | |
132 | for i in xrange(0, 25): | |
133 | rrset = dns.rrset.from_text('foo%d.' % i, 3600, | |
134 | dns.rdataclass.IN, | |
135 | dns.rdatatype.A, | |
136 | '10.0.0.%d' % i) | |
137 | q.additional.append(rrset) | |
138 | w = q.to_wire(max_size=512) | |
139 | self.failUnlessRaises(dns.exception.TooBig, bad) | |
140 | ||
141 | def test_answer1(self): | |
142 | a = dns.message.from_text(answer_text) | |
143 | wire = a.to_wire(want_shuffle=False) | |
144 | self.failUnless(wire == goodwire2) | |
145 | ||
146 | def test_TrailingJunk(self): | |
147 | def bad(): | |
148 | badwire = goodwire + '\x00' | |
149 | m = dns.message.from_wire(badwire) | |
150 | self.failUnlessRaises(dns.message.TrailingJunk, bad) | |
151 | ||
152 | def test_ShortHeader(self): | |
153 | def bad(): | |
154 | badwire = '\x00' * 11 | |
155 | m = dns.message.from_wire(badwire) | |
156 | self.failUnlessRaises(dns.message.ShortHeader, bad) | |
157 | ||
158 | def test_RespondingToResponse(self): | |
159 | def bad(): | |
160 | q = dns.message.make_query('foo', 'A') | |
161 | r1 = dns.message.make_response(q) | |
162 | r2 = dns.message.make_response(r1) | |
163 | self.failUnlessRaises(dns.exception.FormError, bad) | |
164 | ||
165 | def test_ExtendedRcodeSetting(self): | |
166 | m = dns.message.make_query('foo', 'A') | |
167 | m.set_rcode(4095) | |
168 | self.failUnless(m.rcode() == 4095) | |
169 | m.set_rcode(2) | |
170 | self.failUnless(m.rcode() == 2) | |
171 | ||
172 | def test_EDNSVersionCoherence(self): | |
173 | m = dns.message.make_query('foo', 'A') | |
174 | m.use_edns(1) | |
175 | self.failUnless((m.ednsflags >> 16) & 0xFF == 1) | |
176 | ||
177 | if __name__ == '__main__': | |
178 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import cStringIO | |
18 | import socket | |
19 | ||
20 | import dns.name | |
21 | import dns.reversename | |
22 | import dns.e164 | |
23 | ||
24 | class NameTestCase(unittest.TestCase): | |
25 | def setUp(self): | |
26 | self.origin = dns.name.from_text('example.') | |
27 | ||
28 | def testFromTextRel1(self): | |
29 | n = dns.name.from_text('foo.bar') | |
30 | self.failUnless(n.labels == ('foo', 'bar', '')) | |
31 | ||
32 | def testFromTextRel2(self): | |
33 | n = dns.name.from_text('foo.bar', origin=self.origin) | |
34 | self.failUnless(n.labels == ('foo', 'bar', 'example', '')) | |
35 | ||
36 | def testFromTextRel3(self): | |
37 | n = dns.name.from_text('foo.bar', origin=None) | |
38 | self.failUnless(n.labels == ('foo', 'bar')) | |
39 | ||
40 | def testFromTextRel4(self): | |
41 | n = dns.name.from_text('@', origin=None) | |
42 | self.failUnless(n == dns.name.empty) | |
43 | ||
44 | def testFromTextRel5(self): | |
45 | n = dns.name.from_text('@', origin=self.origin) | |
46 | self.failUnless(n == self.origin) | |
47 | ||
48 | def testFromTextAbs1(self): | |
49 | n = dns.name.from_text('foo.bar.') | |
50 | self.failUnless(n.labels == ('foo', 'bar', '')) | |
51 | ||
52 | def testTortureFromText(self): | |
53 | good = [ | |
54 | r'.', | |
55 | r'a', | |
56 | r'a.', | |
57 | r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', | |
58 | r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', | |
59 | r'\000.\008.\010.\032.\046.\092.\099.\255', | |
60 | r'\\', | |
61 | r'\..\.', | |
62 | r'\\.\\', | |
63 | r'!"#%&/()=+-', | |
64 | r'\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255', | |
65 | ] | |
66 | bad = [ | |
67 | r'..', | |
68 | r'.a', | |
69 | r'\\..', | |
70 | '\\', # yes, we don't want the 'r' prefix! | |
71 | r'\0', | |
72 | r'\00', | |
73 | r'\00Z', | |
74 | r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', | |
75 | r'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', | |
76 | r'\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255.\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255', | |
77 | ] | |
78 | for t in good: | |
79 | try: | |
80 | n = dns.name.from_text(t) | |
81 | except: | |
82 | self.fail("good test '%s' raised an exception" % t) | |
83 | for t in bad: | |
84 | caught = False | |
85 | try: | |
86 | n = dns.name.from_text(t) | |
87 | except: | |
88 | caught = True | |
89 | if not caught: | |
90 | self.fail("bad test '%s' did not raise an exception" % t) | |
91 | ||
92 | def testImmutable1(self): | |
93 | def bad(): | |
94 | self.origin.labels = () | |
95 | self.failUnlessRaises(TypeError, bad) | |
96 | ||
97 | def testImmutable2(self): | |
98 | def bad(): | |
99 | self.origin.labels[0] = 'foo' | |
100 | self.failUnlessRaises(TypeError, bad) | |
101 | ||
102 | def testAbs1(self): | |
103 | self.failUnless(dns.name.root.is_absolute()) | |
104 | ||
105 | def testAbs2(self): | |
106 | self.failUnless(not dns.name.empty.is_absolute()) | |
107 | ||
108 | def testAbs3(self): | |
109 | self.failUnless(self.origin.is_absolute()) | |
110 | ||
111 | def testAbs3(self): | |
112 | n = dns.name.from_text('foo', origin=None) | |
113 | self.failUnless(not n.is_absolute()) | |
114 | ||
115 | def testWild1(self): | |
116 | n = dns.name.from_text('*.foo', origin=None) | |
117 | self.failUnless(n.is_wild()) | |
118 | ||
119 | def testWild2(self): | |
120 | n = dns.name.from_text('*a.foo', origin=None) | |
121 | self.failUnless(not n.is_wild()) | |
122 | ||
123 | def testWild3(self): | |
124 | n = dns.name.from_text('a.*.foo', origin=None) | |
125 | self.failUnless(not n.is_wild()) | |
126 | ||
127 | def testWild4(self): | |
128 | self.failUnless(not dns.name.root.is_wild()) | |
129 | ||
130 | def testWild5(self): | |
131 | self.failUnless(not dns.name.empty.is_wild()) | |
132 | ||
133 | def testHash1(self): | |
134 | n1 = dns.name.from_text('fOo.COM') | |
135 | n2 = dns.name.from_text('foo.com') | |
136 | self.failUnless(hash(n1) == hash(n2)) | |
137 | ||
138 | def testCompare1(self): | |
139 | n1 = dns.name.from_text('a') | |
140 | n2 = dns.name.from_text('b') | |
141 | self.failUnless(n1 < n2) | |
142 | self.failUnless(n2 > n1) | |
143 | ||
144 | def testCompare2(self): | |
145 | n1 = dns.name.from_text('') | |
146 | n2 = dns.name.from_text('b') | |
147 | self.failUnless(n1 < n2) | |
148 | self.failUnless(n2 > n1) | |
149 | ||
150 | def testCompare3(self): | |
151 | self.failUnless(dns.name.empty < dns.name.root) | |
152 | self.failUnless(dns.name.root > dns.name.empty) | |
153 | ||
154 | def testCompare4(self): | |
155 | self.failUnless(dns.name.root != 1) | |
156 | ||
157 | def testCompare5(self): | |
158 | self.failUnless(dns.name.root < 1 or dns.name.root > 1) | |
159 | ||
160 | def testSubdomain1(self): | |
161 | self.failUnless(not dns.name.empty.is_subdomain(dns.name.root)) | |
162 | ||
163 | def testSubdomain2(self): | |
164 | self.failUnless(not dns.name.root.is_subdomain(dns.name.empty)) | |
165 | ||
166 | def testSubdomain3(self): | |
167 | n = dns.name.from_text('foo', origin=self.origin) | |
168 | self.failUnless(n.is_subdomain(self.origin)) | |
169 | ||
170 | def testSubdomain4(self): | |
171 | n = dns.name.from_text('foo', origin=self.origin) | |
172 | self.failUnless(n.is_subdomain(dns.name.root)) | |
173 | ||
174 | def testSubdomain5(self): | |
175 | n = dns.name.from_text('foo', origin=self.origin) | |
176 | self.failUnless(n.is_subdomain(n)) | |
177 | ||
178 | def testSuperdomain1(self): | |
179 | self.failUnless(not dns.name.empty.is_superdomain(dns.name.root)) | |
180 | ||
181 | def testSuperdomain2(self): | |
182 | self.failUnless(not dns.name.root.is_superdomain(dns.name.empty)) | |
183 | ||
184 | def testSuperdomain3(self): | |
185 | n = dns.name.from_text('foo', origin=self.origin) | |
186 | self.failUnless(self.origin.is_superdomain(n)) | |
187 | ||
188 | def testSuperdomain4(self): | |
189 | n = dns.name.from_text('foo', origin=self.origin) | |
190 | self.failUnless(dns.name.root.is_superdomain(n)) | |
191 | ||
192 | def testSuperdomain5(self): | |
193 | n = dns.name.from_text('foo', origin=self.origin) | |
194 | self.failUnless(n.is_superdomain(n)) | |
195 | ||
196 | def testCanonicalize1(self): | |
197 | n = dns.name.from_text('FOO.bar', origin=self.origin) | |
198 | c = n.canonicalize() | |
199 | self.failUnless(c.labels == ('foo', 'bar', 'example', '')) | |
200 | ||
201 | def testToText1(self): | |
202 | n = dns.name.from_text('FOO.bar', origin=self.origin) | |
203 | t = n.to_text() | |
204 | self.failUnless(t == 'FOO.bar.example.') | |
205 | ||
206 | def testToText2(self): | |
207 | n = dns.name.from_text('FOO.bar', origin=self.origin) | |
208 | t = n.to_text(True) | |
209 | self.failUnless(t == 'FOO.bar.example') | |
210 | ||
211 | def testToText3(self): | |
212 | n = dns.name.from_text('FOO.bar', origin=None) | |
213 | t = n.to_text() | |
214 | self.failUnless(t == 'FOO.bar') | |
215 | ||
216 | def testToText4(self): | |
217 | t = dns.name.empty.to_text() | |
218 | self.failUnless(t == '@') | |
219 | ||
220 | def testToText5(self): | |
221 | t = dns.name.root.to_text() | |
222 | self.failUnless(t == '.') | |
223 | ||
224 | def testToText6(self): | |
225 | n = dns.name.from_text('FOO bar', origin=None) | |
226 | t = n.to_text() | |
227 | self.failUnless(t == r'FOO\032bar') | |
228 | ||
229 | def testToText7(self): | |
230 | n = dns.name.from_text(r'FOO\.bar', origin=None) | |
231 | t = n.to_text() | |
232 | self.failUnless(t == r'FOO\.bar') | |
233 | ||
234 | def testToText8(self): | |
235 | n = dns.name.from_text(r'\070OO\.bar', origin=None) | |
236 | t = n.to_text() | |
237 | self.failUnless(t == r'FOO\.bar') | |
238 | ||
239 | def testSlice1(self): | |
240 | n = dns.name.from_text(r'a.b.c.', origin=None) | |
241 | s = n[:] | |
242 | self.failUnless(s == ('a', 'b', 'c', '')) | |
243 | ||
244 | def testSlice2(self): | |
245 | n = dns.name.from_text(r'a.b.c.', origin=None) | |
246 | s = n[:2] | |
247 | self.failUnless(s == ('a', 'b')) | |
248 | ||
249 | def testSlice3(self): | |
250 | n = dns.name.from_text(r'a.b.c.', origin=None) | |
251 | s = n[2:] | |
252 | self.failUnless(s == ('c', '')) | |
253 | ||
254 | def testEmptyLabel1(self): | |
255 | def bad(): | |
256 | n = dns.name.Name(['a', '', 'b']) | |
257 | self.failUnlessRaises(dns.name.EmptyLabel, bad) | |
258 | ||
259 | def testEmptyLabel2(self): | |
260 | def bad(): | |
261 | n = dns.name.Name(['', 'b']) | |
262 | self.failUnlessRaises(dns.name.EmptyLabel, bad) | |
263 | ||
264 | def testEmptyLabel3(self): | |
265 | n = dns.name.Name(['b', '']) | |
266 | self.failUnless(n) | |
267 | ||
268 | def testLongLabel(self): | |
269 | n = dns.name.Name(['a' * 63]) | |
270 | self.failUnless(n) | |
271 | ||
272 | def testLabelTooLong(self): | |
273 | def bad(): | |
274 | n = dns.name.Name(['a' * 64, 'b']) | |
275 | self.failUnlessRaises(dns.name.LabelTooLong, bad) | |
276 | ||
277 | def testLongName(self): | |
278 | n = dns.name.Name(['a' * 63, 'a' * 63, 'a' * 63, 'a' * 62]) | |
279 | self.failUnless(n) | |
280 | ||
281 | def testNameTooLong(self): | |
282 | def bad(): | |
283 | n = dns.name.Name(['a' * 63, 'a' * 63, 'a' * 63, 'a' * 63]) | |
284 | self.failUnlessRaises(dns.name.NameTooLong, bad) | |
285 | ||
286 | def testConcat1(self): | |
287 | n1 = dns.name.Name(['a', 'b']) | |
288 | n2 = dns.name.Name(['c', 'd']) | |
289 | e = dns.name.Name(['a', 'b', 'c', 'd']) | |
290 | r = n1 + n2 | |
291 | self.failUnless(r == e) | |
292 | ||
293 | def testConcat2(self): | |
294 | n1 = dns.name.Name(['a', 'b']) | |
295 | n2 = dns.name.Name([]) | |
296 | e = dns.name.Name(['a', 'b']) | |
297 | r = n1 + n2 | |
298 | self.failUnless(r == e) | |
299 | ||
300 | def testConcat2(self): | |
301 | n1 = dns.name.Name([]) | |
302 | n2 = dns.name.Name(['a', 'b']) | |
303 | e = dns.name.Name(['a', 'b']) | |
304 | r = n1 + n2 | |
305 | self.failUnless(r == e) | |
306 | ||
307 | def testConcat3(self): | |
308 | n1 = dns.name.Name(['a', 'b', '']) | |
309 | n2 = dns.name.Name([]) | |
310 | e = dns.name.Name(['a', 'b', '']) | |
311 | r = n1 + n2 | |
312 | self.failUnless(r == e) | |
313 | ||
314 | def testConcat4(self): | |
315 | n1 = dns.name.Name(['a', 'b']) | |
316 | n2 = dns.name.Name(['c', '']) | |
317 | e = dns.name.Name(['a', 'b', 'c', '']) | |
318 | r = n1 + n2 | |
319 | self.failUnless(r == e) | |
320 | ||
321 | def testConcat5(self): | |
322 | def bad(): | |
323 | n1 = dns.name.Name(['a', 'b', '']) | |
324 | n2 = dns.name.Name(['c']) | |
325 | r = n1 + n2 | |
326 | self.failUnlessRaises(dns.name.AbsoluteConcatenation, bad) | |
327 | ||
328 | def testBadEscape(self): | |
329 | def bad(): | |
330 | n = dns.name.from_text(r'a.b\0q1.c.') | |
331 | print n | |
332 | self.failUnlessRaises(dns.name.BadEscape, bad) | |
333 | ||
334 | def testDigestable1(self): | |
335 | n = dns.name.from_text('FOO.bar') | |
336 | d = n.to_digestable() | |
337 | self.failUnless(d == '\x03foo\x03bar\x00') | |
338 | ||
339 | def testDigestable2(self): | |
340 | n1 = dns.name.from_text('FOO.bar') | |
341 | n2 = dns.name.from_text('foo.BAR.') | |
342 | d1 = n1.to_digestable() | |
343 | d2 = n2.to_digestable() | |
344 | self.failUnless(d1 == d2) | |
345 | ||
346 | def testDigestable3(self): | |
347 | d = dns.name.root.to_digestable() | |
348 | self.failUnless(d == '\x00') | |
349 | ||
350 | def testDigestable4(self): | |
351 | n = dns.name.from_text('FOO.bar', None) | |
352 | d = n.to_digestable(dns.name.root) | |
353 | self.failUnless(d == '\x03foo\x03bar\x00') | |
354 | ||
355 | def testBadDigestable(self): | |
356 | def bad(): | |
357 | n = dns.name.from_text('FOO.bar', None) | |
358 | d = n.to_digestable() | |
359 | self.failUnlessRaises(dns.name.NeedAbsoluteNameOrOrigin, bad) | |
360 | ||
361 | def testToWire1(self): | |
362 | n = dns.name.from_text('FOO.bar') | |
363 | f = cStringIO.StringIO() | |
364 | compress = {} | |
365 | n.to_wire(f, compress) | |
366 | self.failUnless(f.getvalue() == '\x03FOO\x03bar\x00') | |
367 | ||
368 | def testToWire2(self): | |
369 | n = dns.name.from_text('FOO.bar') | |
370 | f = cStringIO.StringIO() | |
371 | compress = {} | |
372 | n.to_wire(f, compress) | |
373 | n.to_wire(f, compress) | |
374 | self.failUnless(f.getvalue() == '\x03FOO\x03bar\x00\xc0\x00') | |
375 | ||
376 | def testToWire3(self): | |
377 | n1 = dns.name.from_text('FOO.bar') | |
378 | n2 = dns.name.from_text('foo.bar') | |
379 | f = cStringIO.StringIO() | |
380 | compress = {} | |
381 | n1.to_wire(f, compress) | |
382 | n2.to_wire(f, compress) | |
383 | self.failUnless(f.getvalue() == '\x03FOO\x03bar\x00\xc0\x00') | |
384 | ||
385 | def testToWire4(self): | |
386 | n1 = dns.name.from_text('FOO.bar') | |
387 | n2 = dns.name.from_text('a.foo.bar') | |
388 | f = cStringIO.StringIO() | |
389 | compress = {} | |
390 | n1.to_wire(f, compress) | |
391 | n2.to_wire(f, compress) | |
392 | self.failUnless(f.getvalue() == '\x03FOO\x03bar\x00\x01\x61\xc0\x00') | |
393 | ||
394 | def testToWire5(self): | |
395 | n1 = dns.name.from_text('FOO.bar') | |
396 | n2 = dns.name.from_text('a.foo.bar') | |
397 | f = cStringIO.StringIO() | |
398 | compress = {} | |
399 | n1.to_wire(f, compress) | |
400 | n2.to_wire(f, None) | |
401 | self.failUnless(f.getvalue() == \ | |
402 | '\x03FOO\x03bar\x00\x01\x61\x03foo\x03bar\x00') | |
403 | ||
404 | def testToWire6(self): | |
405 | n = dns.name.from_text('FOO.bar') | |
406 | v = n.to_wire() | |
407 | self.failUnless(v == '\x03FOO\x03bar\x00') | |
408 | ||
409 | def testBadToWire(self): | |
410 | def bad(): | |
411 | n = dns.name.from_text('FOO.bar', None) | |
412 | f = cStringIO.StringIO() | |
413 | compress = {} | |
414 | n.to_wire(f, compress) | |
415 | self.failUnlessRaises(dns.name.NeedAbsoluteNameOrOrigin, bad) | |
416 | ||
417 | def testSplit1(self): | |
418 | n = dns.name.from_text('foo.bar.') | |
419 | (prefix, suffix) = n.split(2) | |
420 | ep = dns.name.from_text('foo', None) | |
421 | es = dns.name.from_text('bar.', None) | |
422 | self.failUnless(prefix == ep and suffix == es) | |
423 | ||
424 | def testSplit2(self): | |
425 | n = dns.name.from_text('foo.bar.') | |
426 | (prefix, suffix) = n.split(1) | |
427 | ep = dns.name.from_text('foo.bar', None) | |
428 | es = dns.name.from_text('.', None) | |
429 | self.failUnless(prefix == ep and suffix == es) | |
430 | ||
431 | def testSplit3(self): | |
432 | n = dns.name.from_text('foo.bar.') | |
433 | (prefix, suffix) = n.split(0) | |
434 | ep = dns.name.from_text('foo.bar.', None) | |
435 | es = dns.name.from_text('', None) | |
436 | self.failUnless(prefix == ep and suffix == es) | |
437 | ||
438 | def testSplit4(self): | |
439 | n = dns.name.from_text('foo.bar.') | |
440 | (prefix, suffix) = n.split(3) | |
441 | ep = dns.name.from_text('', None) | |
442 | es = dns.name.from_text('foo.bar.', None) | |
443 | self.failUnless(prefix == ep and suffix == es) | |
444 | ||
445 | def testBadSplit1(self): | |
446 | def bad(): | |
447 | n = dns.name.from_text('foo.bar.') | |
448 | (prefix, suffix) = n.split(-1) | |
449 | self.failUnlessRaises(ValueError, bad) | |
450 | ||
451 | def testBadSplit2(self): | |
452 | def bad(): | |
453 | n = dns.name.from_text('foo.bar.') | |
454 | (prefix, suffix) = n.split(4) | |
455 | self.failUnlessRaises(ValueError, bad) | |
456 | ||
457 | def testRelativize1(self): | |
458 | n = dns.name.from_text('a.foo.bar.', None) | |
459 | o = dns.name.from_text('bar.', None) | |
460 | e = dns.name.from_text('a.foo', None) | |
461 | self.failUnless(n.relativize(o) == e) | |
462 | ||
463 | def testRelativize2(self): | |
464 | n = dns.name.from_text('a.foo.bar.', None) | |
465 | o = n | |
466 | e = dns.name.empty | |
467 | self.failUnless(n.relativize(o) == e) | |
468 | ||
469 | def testRelativize3(self): | |
470 | n = dns.name.from_text('a.foo.bar.', None) | |
471 | o = dns.name.from_text('blaz.', None) | |
472 | e = n | |
473 | self.failUnless(n.relativize(o) == e) | |
474 | ||
475 | def testRelativize4(self): | |
476 | n = dns.name.from_text('a.foo', None) | |
477 | o = dns.name.root | |
478 | e = n | |
479 | self.failUnless(n.relativize(o) == e) | |
480 | ||
481 | def testDerelativize1(self): | |
482 | n = dns.name.from_text('a.foo', None) | |
483 | o = dns.name.from_text('bar.', None) | |
484 | e = dns.name.from_text('a.foo.bar.', None) | |
485 | self.failUnless(n.derelativize(o) == e) | |
486 | ||
487 | def testDerelativize2(self): | |
488 | n = dns.name.empty | |
489 | o = dns.name.from_text('a.foo.bar.', None) | |
490 | e = o | |
491 | self.failUnless(n.derelativize(o) == e) | |
492 | ||
493 | def testDerelativize3(self): | |
494 | n = dns.name.from_text('a.foo.bar.', None) | |
495 | o = dns.name.from_text('blaz.', None) | |
496 | e = n | |
497 | self.failUnless(n.derelativize(o) == e) | |
498 | ||
499 | def testChooseRelativity1(self): | |
500 | n = dns.name.from_text('a.foo.bar.', None) | |
501 | o = dns.name.from_text('bar.', None) | |
502 | e = dns.name.from_text('a.foo', None) | |
503 | self.failUnless(n.choose_relativity(o, True) == e) | |
504 | ||
505 | def testChooseRelativity2(self): | |
506 | n = dns.name.from_text('a.foo.bar.', None) | |
507 | o = dns.name.from_text('bar.', None) | |
508 | e = n | |
509 | self.failUnless(n.choose_relativity(o, False) == e) | |
510 | ||
511 | def testChooseRelativity3(self): | |
512 | n = dns.name.from_text('a.foo', None) | |
513 | o = dns.name.from_text('bar.', None) | |
514 | e = dns.name.from_text('a.foo.bar.', None) | |
515 | self.failUnless(n.choose_relativity(o, False) == e) | |
516 | ||
517 | def testChooseRelativity4(self): | |
518 | n = dns.name.from_text('a.foo', None) | |
519 | o = None | |
520 | e = n | |
521 | self.failUnless(n.choose_relativity(o, True) == e) | |
522 | ||
523 | def testChooseRelativity5(self): | |
524 | n = dns.name.from_text('a.foo', None) | |
525 | o = None | |
526 | e = n | |
527 | self.failUnless(n.choose_relativity(o, False) == e) | |
528 | ||
529 | def testChooseRelativity6(self): | |
530 | n = dns.name.from_text('a.foo.', None) | |
531 | o = None | |
532 | e = n | |
533 | self.failUnless(n.choose_relativity(o, True) == e) | |
534 | ||
535 | def testChooseRelativity7(self): | |
536 | n = dns.name.from_text('a.foo.', None) | |
537 | o = None | |
538 | e = n | |
539 | self.failUnless(n.choose_relativity(o, False) == e) | |
540 | ||
541 | def testFromWire1(self): | |
542 | w = '\x03foo\x00\xc0\x00' | |
543 | (n1, cused1) = dns.name.from_wire(w, 0) | |
544 | (n2, cused2) = dns.name.from_wire(w, cused1) | |
545 | en1 = dns.name.from_text('foo.') | |
546 | en2 = en1 | |
547 | ecused1 = 5 | |
548 | ecused2 = 2 | |
549 | self.failUnless(n1 == en1 and cused1 == ecused1 and \ | |
550 | n2 == en2 and cused2 == ecused2) | |
551 | ||
552 | def testFromWire1(self): | |
553 | w = '\x03foo\x00\x01a\xc0\x00\x01b\xc0\x05' | |
554 | current = 0 | |
555 | (n1, cused1) = dns.name.from_wire(w, current) | |
556 | current += cused1 | |
557 | (n2, cused2) = dns.name.from_wire(w, current) | |
558 | current += cused2 | |
559 | (n3, cused3) = dns.name.from_wire(w, current) | |
560 | en1 = dns.name.from_text('foo.') | |
561 | en2 = dns.name.from_text('a.foo.') | |
562 | en3 = dns.name.from_text('b.a.foo.') | |
563 | ecused1 = 5 | |
564 | ecused2 = 4 | |
565 | ecused3 = 4 | |
566 | self.failUnless(n1 == en1 and cused1 == ecused1 and \ | |
567 | n2 == en2 and cused2 == ecused2 and \ | |
568 | n3 == en3 and cused3 == ecused3) | |
569 | ||
570 | def testBadFromWire1(self): | |
571 | def bad(): | |
572 | w = '\x03foo\xc0\x04' | |
573 | (n, cused) = dns.name.from_wire(w, 0) | |
574 | self.failUnlessRaises(dns.name.BadPointer, bad) | |
575 | ||
576 | def testBadFromWire2(self): | |
577 | def bad(): | |
578 | w = '\x03foo\xc0\x05' | |
579 | (n, cused) = dns.name.from_wire(w, 0) | |
580 | self.failUnlessRaises(dns.name.BadPointer, bad) | |
581 | ||
582 | def testBadFromWire3(self): | |
583 | def bad(): | |
584 | w = '\xbffoo' | |
585 | (n, cused) = dns.name.from_wire(w, 0) | |
586 | self.failUnlessRaises(dns.name.BadLabelType, bad) | |
587 | ||
588 | def testBadFromWire4(self): | |
589 | def bad(): | |
590 | w = '\x41foo' | |
591 | (n, cused) = dns.name.from_wire(w, 0) | |
592 | self.failUnlessRaises(dns.name.BadLabelType, bad) | |
593 | ||
594 | def testParent1(self): | |
595 | n = dns.name.from_text('foo.bar.') | |
596 | self.failUnless(n.parent() == dns.name.from_text('bar.')) | |
597 | self.failUnless(n.parent().parent() == dns.name.root) | |
598 | ||
599 | def testParent2(self): | |
600 | n = dns.name.from_text('foo.bar', None) | |
601 | self.failUnless(n.parent() == dns.name.from_text('bar', None)) | |
602 | self.failUnless(n.parent().parent() == dns.name.empty) | |
603 | ||
604 | def testParent3(self): | |
605 | def bad(): | |
606 | n = dns.name.root | |
607 | n.parent() | |
608 | self.failUnlessRaises(dns.name.NoParent, bad) | |
609 | ||
610 | def testParent4(self): | |
611 | def bad(): | |
612 | n = dns.name.empty | |
613 | n.parent() | |
614 | self.failUnlessRaises(dns.name.NoParent, bad) | |
615 | ||
616 | def testFromUnicode1(self): | |
617 | n = dns.name.from_text(u'foo.bar') | |
618 | self.failUnless(n.labels == ('foo', 'bar', '')) | |
619 | ||
620 | def testFromUnicode2(self): | |
621 | n = dns.name.from_text(u'foo\u1234bar.bar') | |
622 | self.failUnless(n.labels == ('xn--foobar-r5z', 'bar', '')) | |
623 | ||
624 | def testFromUnicodeAlternateDot1(self): | |
625 | n = dns.name.from_text(u'foo\u3002bar') | |
626 | self.failUnless(n.labels == ('foo', 'bar', '')) | |
627 | ||
628 | def testFromUnicodeAlternateDot2(self): | |
629 | n = dns.name.from_text(u'foo\uff0ebar') | |
630 | self.failUnless(n.labels == ('foo', 'bar', '')) | |
631 | ||
632 | def testFromUnicodeAlternateDot3(self): | |
633 | n = dns.name.from_text(u'foo\uff61bar') | |
634 | self.failUnless(n.labels == ('foo', 'bar', '')) | |
635 | ||
636 | def testToUnicode1(self): | |
637 | n = dns.name.from_text(u'foo.bar') | |
638 | s = n.to_unicode() | |
639 | self.failUnless(s == u'foo.bar.') | |
640 | ||
641 | def testToUnicode2(self): | |
642 | n = dns.name.from_text(u'foo\u1234bar.bar') | |
643 | s = n.to_unicode() | |
644 | self.failUnless(s == u'foo\u1234bar.bar.') | |
645 | ||
646 | def testToUnicode3(self): | |
647 | n = dns.name.from_text('foo.bar') | |
648 | s = n.to_unicode() | |
649 | self.failUnless(s == u'foo.bar.') | |
650 | ||
651 | def testReverseIPv4(self): | |
652 | e = dns.name.from_text('1.0.0.127.in-addr.arpa.') | |
653 | n = dns.reversename.from_address('127.0.0.1') | |
654 | self.failUnless(e == n) | |
655 | ||
656 | def testReverseIPv6(self): | |
657 | e = dns.name.from_text('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.') | |
658 | n = dns.reversename.from_address('::1') | |
659 | self.failUnless(e == n) | |
660 | ||
661 | def testReverseIPv6MappedIpv4(self): | |
662 | e = dns.name.from_text('1.0.0.127.in-addr.arpa.') | |
663 | n = dns.reversename.from_address('::ffff:127.0.0.1') | |
664 | self.failUnless(e == n) | |
665 | ||
666 | def testBadReverseIPv4(self): | |
667 | def bad(): | |
668 | n = dns.reversename.from_address('127.0.foo.1') | |
669 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
670 | ||
671 | def testBadReverseIPv6(self): | |
672 | def bad(): | |
673 | n = dns.reversename.from_address('::1::1') | |
674 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
675 | ||
676 | def testForwardIPv4(self): | |
677 | n = dns.name.from_text('1.0.0.127.in-addr.arpa.') | |
678 | e = '127.0.0.1' | |
679 | text = dns.reversename.to_address(n) | |
680 | self.failUnless(text == e) | |
681 | ||
682 | def testForwardIPv6(self): | |
683 | n = dns.name.from_text('1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.') | |
684 | e = '::1' | |
685 | text = dns.reversename.to_address(n) | |
686 | self.failUnless(text == e) | |
687 | ||
688 | def testE164ToEnum(self): | |
689 | text = '+1 650 555 1212' | |
690 | e = dns.name.from_text('2.1.2.1.5.5.5.0.5.6.1.e164.arpa.') | |
691 | n = dns.e164.from_e164(text) | |
692 | self.failUnless(n == e) | |
693 | ||
694 | def testEnumToE164(self): | |
695 | n = dns.name.from_text('2.1.2.1.5.5.5.0.5.6.1.e164.arpa.') | |
696 | e = '+16505551212' | |
697 | text = dns.e164.to_e164(n) | |
698 | self.failUnless(text == e) | |
699 | ||
700 | if __name__ == '__main__': | |
701 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.name | |
18 | import dns.namedict | |
19 | ||
20 | class NameTestCase(unittest.TestCase): | |
21 | ||
22 | def setUp(self): | |
23 | self.ndict = dns.namedict.NameDict() | |
24 | n1 = dns.name.from_text('foo.bar.') | |
25 | n2 = dns.name.from_text('bar.') | |
26 | self.ndict[n1] = 1 | |
27 | self.ndict[n2] = 2 | |
28 | self.rndict = dns.namedict.NameDict() | |
29 | n1 = dns.name.from_text('foo.bar', None) | |
30 | n2 = dns.name.from_text('bar', None) | |
31 | self.rndict[n1] = 1 | |
32 | self.rndict[n2] = 2 | |
33 | ||
34 | def testDepth(self): | |
35 | self.failUnless(self.ndict.max_depth == 3) | |
36 | ||
37 | def testLookup1(self): | |
38 | k = dns.name.from_text('foo.bar.') | |
39 | self.failUnless(self.ndict[k] == 1) | |
40 | ||
41 | def testLookup2(self): | |
42 | k = dns.name.from_text('foo.bar.') | |
43 | self.failUnless(self.ndict.get_deepest_match(k)[1] == 1) | |
44 | ||
45 | def testLookup3(self): | |
46 | k = dns.name.from_text('a.b.c.foo.bar.') | |
47 | self.failUnless(self.ndict.get_deepest_match(k)[1] == 1) | |
48 | ||
49 | def testLookup4(self): | |
50 | k = dns.name.from_text('a.b.c.bar.') | |
51 | self.failUnless(self.ndict.get_deepest_match(k)[1] == 2) | |
52 | ||
53 | def testLookup5(self): | |
54 | def bad(): | |
55 | n = dns.name.from_text('a.b.c.') | |
56 | (k, v) = self.ndict.get_deepest_match(n) | |
57 | self.failUnlessRaises(KeyError, bad) | |
58 | ||
59 | def testLookup6(self): | |
60 | def bad(): | |
61 | (k, v) = self.ndict.get_deepest_match(dns.name.empty) | |
62 | self.failUnlessRaises(KeyError, bad) | |
63 | ||
64 | def testLookup7(self): | |
65 | self.ndict[dns.name.empty] = 100 | |
66 | n = dns.name.from_text('a.b.c.') | |
67 | (k, v) = self.ndict.get_deepest_match(n) | |
68 | self.failUnless(v == 100) | |
69 | ||
70 | def testLookup8(self): | |
71 | def bad(): | |
72 | self.ndict['foo'] = 100 | |
73 | self.failUnlessRaises(ValueError, bad) | |
74 | ||
75 | def testRelDepth(self): | |
76 | self.failUnless(self.rndict.max_depth == 2) | |
77 | ||
78 | def testRelLookup1(self): | |
79 | k = dns.name.from_text('foo.bar', None) | |
80 | self.failUnless(self.rndict[k] == 1) | |
81 | ||
82 | def testRelLookup2(self): | |
83 | k = dns.name.from_text('foo.bar', None) | |
84 | self.failUnless(self.rndict.get_deepest_match(k)[1] == 1) | |
85 | ||
86 | def testRelLookup3(self): | |
87 | k = dns.name.from_text('a.b.c.foo.bar', None) | |
88 | self.failUnless(self.rndict.get_deepest_match(k)[1] == 1) | |
89 | ||
90 | def testRelLookup4(self): | |
91 | k = dns.name.from_text('a.b.c.bar', None) | |
92 | self.failUnless(self.rndict.get_deepest_match(k)[1] == 2) | |
93 | ||
94 | def testRelLookup7(self): | |
95 | self.rndict[dns.name.empty] = 100 | |
96 | n = dns.name.from_text('a.b.c', None) | |
97 | (k, v) = self.rndict.get_deepest_match(n) | |
98 | self.failUnless(v == 100) | |
99 | ||
100 | if __name__ == '__main__': | |
101 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.exception | |
18 | import dns.ipv4 | |
19 | import dns.ipv6 | |
20 | ||
21 | # for convenience | |
22 | aton4 = dns.ipv4.inet_aton | |
23 | ntoa4 = dns.ipv4.inet_ntoa | |
24 | aton6 = dns.ipv6.inet_aton | |
25 | ntoa6 = dns.ipv6.inet_ntoa | |
26 | ||
27 | v4_bad_addrs = ['256.1.1.1', '1.1.1', '1.1.1.1.1', '01.1.1.1', | |
28 | '+1.1.1.1', '1.1.1.1+', '1..2.3.4', '.1.2.3.4', | |
29 | '1.2.3.4.'] | |
30 | ||
31 | class NtoAAtoNTestCase(unittest.TestCase): | |
32 | ||
33 | def test_aton1(self): | |
34 | a = aton6('::') | |
35 | self.failUnless(a == '\x00' * 16) | |
36 | ||
37 | def test_aton2(self): | |
38 | a = aton6('::1') | |
39 | self.failUnless(a == '\x00' * 15 + '\x01') | |
40 | ||
41 | def test_aton3(self): | |
42 | a = aton6('::10.0.0.1') | |
43 | self.failUnless(a == '\x00' * 12 + '\x0a\x00\x00\x01') | |
44 | ||
45 | def test_aton4(self): | |
46 | a = aton6('abcd::dcba') | |
47 | self.failUnless(a == '\xab\xcd' + '\x00' * 12 + '\xdc\xba') | |
48 | ||
49 | def test_aton5(self): | |
50 | a = aton6('1:2:3:4:5:6:7:8') | |
51 | self.failUnless(a == \ | |
52 | '00010002000300040005000600070008'.decode('hex_codec')) | |
53 | ||
54 | def test_bad_aton1(self): | |
55 | def bad(): | |
56 | a = aton6('abcd:dcba') | |
57 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
58 | ||
59 | def test_bad_aton2(self): | |
60 | def bad(): | |
61 | a = aton6('abcd::dcba::1') | |
62 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
63 | ||
64 | def test_bad_aton3(self): | |
65 | def bad(): | |
66 | a = aton6('1:2:3:4:5:6:7:8:9') | |
67 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
68 | ||
69 | def test_aton1(self): | |
70 | a = aton6('::') | |
71 | self.failUnless(a == '\x00' * 16) | |
72 | ||
73 | def test_aton2(self): | |
74 | a = aton6('::1') | |
75 | self.failUnless(a == '\x00' * 15 + '\x01') | |
76 | ||
77 | def test_aton3(self): | |
78 | a = aton6('::10.0.0.1') | |
79 | self.failUnless(a == '\x00' * 12 + '\x0a\x00\x00\x01') | |
80 | ||
81 | def test_aton4(self): | |
82 | a = aton6('abcd::dcba') | |
83 | self.failUnless(a == '\xab\xcd' + '\x00' * 12 + '\xdc\xba') | |
84 | ||
85 | def test_ntoa1(self): | |
86 | b = '00010002000300040005000600070008'.decode('hex_codec') | |
87 | t = ntoa6(b) | |
88 | self.failUnless(t == '1:2:3:4:5:6:7:8') | |
89 | ||
90 | def test_ntoa2(self): | |
91 | b = '\x00' * 16 | |
92 | t = ntoa6(b) | |
93 | self.failUnless(t == '::') | |
94 | ||
95 | def test_ntoa3(self): | |
96 | b = '\x00' * 15 + '\x01' | |
97 | t = ntoa6(b) | |
98 | self.failUnless(t == '::1') | |
99 | ||
100 | def test_ntoa4(self): | |
101 | b = '\x80' + '\x00' * 15 | |
102 | t = ntoa6(b) | |
103 | self.failUnless(t == '8000::') | |
104 | ||
105 | def test_ntoa5(self): | |
106 | b = '\x01\xcd' + '\x00' * 12 + '\x03\xef' | |
107 | t = ntoa6(b) | |
108 | self.failUnless(t == '1cd::3ef') | |
109 | ||
110 | def test_ntoa6(self): | |
111 | b = 'ffff00000000ffff000000000000ffff'.decode('hex_codec') | |
112 | t = ntoa6(b) | |
113 | self.failUnless(t == 'ffff:0:0:ffff::ffff') | |
114 | ||
115 | def test_ntoa7(self): | |
116 | b = '00000000ffff000000000000ffffffff'.decode('hex_codec') | |
117 | t = ntoa6(b) | |
118 | self.failUnless(t == '0:0:ffff::ffff:ffff') | |
119 | ||
120 | def test_ntoa8(self): | |
121 | b = 'ffff0000ffff00000000ffff00000000'.decode('hex_codec') | |
122 | t = ntoa6(b) | |
123 | self.failUnless(t == 'ffff:0:ffff::ffff:0:0') | |
124 | ||
125 | def test_ntoa9(self): | |
126 | b = '0000000000000000000000000a000001'.decode('hex_codec') | |
127 | t = ntoa6(b) | |
128 | self.failUnless(t == '::10.0.0.1') | |
129 | ||
130 | def test_ntoa10(self): | |
131 | b = '0000000000000000000000010a000001'.decode('hex_codec') | |
132 | t = ntoa6(b) | |
133 | self.failUnless(t == '::1:a00:1') | |
134 | ||
135 | def test_ntoa11(self): | |
136 | b = '00000000000000000000ffff0a000001'.decode('hex_codec') | |
137 | t = ntoa6(b) | |
138 | self.failUnless(t == '::ffff:10.0.0.1') | |
139 | ||
140 | def test_ntoa12(self): | |
141 | b = '000000000000000000000000ffffffff'.decode('hex_codec') | |
142 | t = ntoa6(b) | |
143 | self.failUnless(t == '::255.255.255.255') | |
144 | ||
145 | def test_ntoa13(self): | |
146 | b = '00000000000000000000ffffffffffff'.decode('hex_codec') | |
147 | t = ntoa6(b) | |
148 | self.failUnless(t == '::ffff:255.255.255.255') | |
149 | ||
150 | def test_ntoa14(self): | |
151 | b = '0000000000000000000000000001ffff'.decode('hex_codec') | |
152 | t = ntoa6(b) | |
153 | self.failUnless(t == '::0.1.255.255') | |
154 | ||
155 | def test_bad_ntoa1(self): | |
156 | def bad(): | |
157 | a = ntoa6('') | |
158 | self.failUnlessRaises(ValueError, bad) | |
159 | ||
160 | def test_bad_ntoa2(self): | |
161 | def bad(): | |
162 | a = ntoa6('\x00' * 17) | |
163 | self.failUnlessRaises(ValueError, bad) | |
164 | ||
165 | def test_good_v4_aton(self): | |
166 | pairs = [('1.2.3.4', '\x01\x02\x03\x04'), | |
167 | ('255.255.255.255', '\xff\xff\xff\xff'), | |
168 | ('0.0.0.0', '\x00\x00\x00\x00')] | |
169 | for (t, b) in pairs: | |
170 | b1 = aton4(t) | |
171 | t1 = ntoa4(b1) | |
172 | self.failUnless(b1 == b) | |
173 | self.failUnless(t1 == t) | |
174 | ||
175 | def test_bad_v4_aton(self): | |
176 | def make_bad(a): | |
177 | def bad(): | |
178 | return aton4(a) | |
179 | return bad | |
180 | for addr in v4_bad_addrs: | |
181 | self.failUnlessRaises(dns.exception.SyntaxError, make_bad(addr)) | |
182 | ||
183 | def test_bad_v6_aton(self): | |
184 | addrs = ['+::0', '0::0::', '::0::', '1:2:3:4:5:6:7:8:9', | |
185 | ':::::::'] | |
186 | embedded = ['::' + x for x in v4_bad_addrs] | |
187 | addrs.extend(embedded) | |
188 | def make_bad(a): | |
189 | def bad(): | |
190 | x = aton6(a) | |
191 | return bad | |
192 | for addr in addrs: | |
193 | self.failUnlessRaises(dns.exception.SyntaxError, make_bad(addr)) | |
194 | ||
195 | def test_rfc5952_section_4_2_2(self): | |
196 | addr = '2001:db8:0:1:1:1:1:1' | |
197 | b1 = aton6(addr) | |
198 | t1 = ntoa6(b1) | |
199 | self.failUnless(t1 == addr) | |
200 | ||
201 | def test_is_mapped(self): | |
202 | t1 = '2001:db8:0:1:1:1:1:1' | |
203 | t2 = '::ffff:127.0.0.1' | |
204 | t3 = '1::ffff:127.0.0.1' | |
205 | self.failIf(dns.ipv6.is_mapped(aton6(t1))) | |
206 | self.failUnless(dns.ipv6.is_mapped(aton6(t2))) | |
207 | self.failIf(dns.ipv6.is_mapped(aton6(t3))) | |
208 | ||
209 | if __name__ == '__main__': | |
210 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.rdataclass | |
18 | import dns.rdatatype | |
19 | ||
20 | class RdTypeAndClassTestCase(unittest.TestCase): | |
21 | ||
22 | # Classes | |
23 | ||
24 | def test_class_meta1(self): | |
25 | self.failUnless(dns.rdataclass.is_metaclass(dns.rdataclass.ANY)) | |
26 | ||
27 | def test_class_meta2(self): | |
28 | self.failUnless(not dns.rdataclass.is_metaclass(dns.rdataclass.IN)) | |
29 | ||
30 | def test_class_bytext1(self): | |
31 | self.failUnless(dns.rdataclass.from_text('IN') == dns.rdataclass.IN) | |
32 | ||
33 | def test_class_bytext2(self): | |
34 | self.failUnless(dns.rdataclass.from_text('CLASS1') == | |
35 | dns.rdataclass.IN) | |
36 | ||
37 | def test_class_bytext_bounds1(self): | |
38 | self.failUnless(dns.rdataclass.from_text('CLASS0') == 0) | |
39 | self.failUnless(dns.rdataclass.from_text('CLASS65535') == 65535) | |
40 | ||
41 | def test_class_bytext_bounds2(self): | |
42 | def bad(): | |
43 | junk = dns.rdataclass.from_text('CLASS65536') | |
44 | self.failUnlessRaises(ValueError, bad) | |
45 | ||
46 | def test_class_bytext_unknown(self): | |
47 | def bad(): | |
48 | junk = dns.rdataclass.from_text('XXX') | |
49 | self.failUnlessRaises(dns.rdataclass.UnknownRdataclass, bad) | |
50 | ||
51 | def test_class_totext1(self): | |
52 | self.failUnless(dns.rdataclass.to_text(dns.rdataclass.IN) == 'IN') | |
53 | ||
54 | def test_class_totext1(self): | |
55 | self.failUnless(dns.rdataclass.to_text(999) == 'CLASS999') | |
56 | ||
57 | def test_class_totext_bounds1(self): | |
58 | def bad(): | |
59 | junk = dns.rdataclass.to_text(-1) | |
60 | self.failUnlessRaises(ValueError, bad) | |
61 | ||
62 | def test_class_totext_bounds2(self): | |
63 | def bad(): | |
64 | junk = dns.rdataclass.to_text(65536) | |
65 | self.failUnlessRaises(ValueError, bad) | |
66 | ||
67 | # Types | |
68 | ||
69 | def test_type_meta1(self): | |
70 | self.failUnless(dns.rdatatype.is_metatype(dns.rdatatype.ANY)) | |
71 | ||
72 | def test_type_meta2(self): | |
73 | self.failUnless(dns.rdatatype.is_metatype(dns.rdatatype.OPT)) | |
74 | ||
75 | def test_type_meta3(self): | |
76 | self.failUnless(not dns.rdatatype.is_metatype(dns.rdatatype.A)) | |
77 | ||
78 | def test_type_singleton1(self): | |
79 | self.failUnless(dns.rdatatype.is_singleton(dns.rdatatype.SOA)) | |
80 | ||
81 | def test_type_singleton2(self): | |
82 | self.failUnless(not dns.rdatatype.is_singleton(dns.rdatatype.A)) | |
83 | ||
84 | def test_type_bytext1(self): | |
85 | self.failUnless(dns.rdatatype.from_text('A') == dns.rdatatype.A) | |
86 | ||
87 | def test_type_bytext2(self): | |
88 | self.failUnless(dns.rdatatype.from_text('TYPE1') == | |
89 | dns.rdatatype.A) | |
90 | ||
91 | def test_type_bytext_bounds1(self): | |
92 | self.failUnless(dns.rdatatype.from_text('TYPE0') == 0) | |
93 | self.failUnless(dns.rdatatype.from_text('TYPE65535') == 65535) | |
94 | ||
95 | def test_type_bytext_bounds2(self): | |
96 | def bad(): | |
97 | junk = dns.rdatatype.from_text('TYPE65536') | |
98 | self.failUnlessRaises(ValueError, bad) | |
99 | ||
100 | def test_type_bytext_unknown(self): | |
101 | def bad(): | |
102 | junk = dns.rdatatype.from_text('XXX') | |
103 | self.failUnlessRaises(dns.rdatatype.UnknownRdatatype, bad) | |
104 | ||
105 | def test_type_totext1(self): | |
106 | self.failUnless(dns.rdatatype.to_text(dns.rdatatype.A) == 'A') | |
107 | ||
108 | def test_type_totext1(self): | |
109 | self.failUnless(dns.rdatatype.to_text(999) == 'TYPE999') | |
110 | ||
111 | def test_type_totext_bounds1(self): | |
112 | def bad(): | |
113 | junk = dns.rdatatype.to_text(-1) | |
114 | self.failUnlessRaises(ValueError, bad) | |
115 | ||
116 | def test_type_totext_bounds2(self): | |
117 | def bad(): | |
118 | junk = dns.rdatatype.to_text(65536) | |
119 | self.failUnlessRaises(ValueError, bad) | |
120 | ||
121 | if __name__ == '__main__': | |
122 | unittest.main() |
0 | # Copyright (C) 2014 Red Hat, Inc. | |
1 | # Author: Petr Spacek <pspacek@redhat.com> | |
2 | # | |
3 | # Permission to use, copy, modify, and distribute this software and its | |
4 | # documentation for any purpose with or without fee is hereby granted, | |
5 | # provided that the above copyright notice and this permission notice | |
6 | # appear in all copies. | |
7 | # | |
8 | # THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES | |
9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | ||
16 | import unittest | |
17 | ||
18 | import dns.rrset | |
19 | import dns.rdtypes.ANY.DNSKEY | |
20 | ||
21 | ||
22 | class RdtypeAnyDnskeyTestCase(unittest.TestCase): | |
23 | ||
24 | def testFlagsEmpty(self): | |
25 | '''Test DNSKEY flag to/from text conversion for zero flag/empty set.''' | |
26 | good_s = set() | |
27 | good_f = 0 | |
28 | from_flags = dns.rdtypes.ANY.DNSKEY.flags_to_text_set(good_f) | |
29 | self.failUnless(from_flags == good_s, | |
30 | '"%s" != "%s"' % (from_flags, good_s)) | |
31 | from_set = dns.rdtypes.ANY.DNSKEY.flags_from_text_set(good_s) | |
32 | self.failUnless(from_set == good_f, | |
33 | '"0x%x" != "0x%x"' % (from_set, good_f)) | |
34 | ||
35 | def testFlagsAll(self): | |
36 | '''Test that all defined flags are recognized.''' | |
37 | good_s = set(['SEP', 'REVOKE', 'ZONE']) | |
38 | good_f = 0x181 | |
39 | from_flags = dns.rdtypes.ANY.DNSKEY.flags_to_text_set(good_f) | |
40 | self.failUnless(from_flags == good_s, | |
41 | '"%s" != "%s"' % (from_flags, good_s)) | |
42 | from_text = dns.rdtypes.ANY.DNSKEY.flags_from_text_set(good_s) | |
43 | self.failUnless(from_text == good_f, | |
44 | '"0x%x" != "0x%x"' % (from_text, good_f)) | |
45 | ||
46 | def testFlagsUnknownToText(self): | |
47 | '''Test that undefined flags are returned in hexadecimal notation.''' | |
48 | unk_s = set(['0x8000']) | |
49 | flags_s = dns.rdtypes.ANY.DNSKEY.flags_to_text_set(0x8000) | |
50 | self.failUnless(flags_s == unk_s, '"%s" != "%s"' % (flags_s, unk_s)) | |
51 | ||
52 | def testFlagsUnknownToFlags(self): | |
53 | '''Test that conversion from undefined mnemonic raises error.''' | |
54 | self.failUnlessRaises(NotImplementedError, | |
55 | dns.rdtypes.ANY.DNSKEY.flags_from_text_set, | |
56 | (['0x8000'])) | |
57 | ||
58 | def testFlagsRRToText(self): | |
59 | '''Test that RR method returns correct flags.''' | |
60 | rr = dns.rrset.from_text('foo', 300, 'IN', 'DNSKEY', '257 3 8 KEY=')[0] | |
61 | rr_s = set(['ZONE', 'SEP']) | |
62 | flags_s = rr.flags_to_text_set() | |
63 | self.failUnless(flags_s == rr_s, '"%s" != "%s"' % (flags_s, rr_s)) | |
64 | ||
65 | ||
66 | if __name__ == '__main__': | |
67 | unittest.main() |
0 | # Copyright (C) 2014 Red Hat, Inc. | |
1 | # Author: Petr Spacek <pspacek@redhat.com> | |
2 | # | |
3 | # Permission to use, copy, modify, and distribute this software and its | |
4 | # documentation for any purpose with or without fee is hereby granted, | |
5 | # provided that the above copyright notice and this permission notice | |
6 | # appear in all copies. | |
7 | # | |
8 | # THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES | |
9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
14 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 | ||
16 | import unittest | |
17 | ||
18 | import dns.rrset | |
19 | import dns.rdtypes.ANY.LOC | |
20 | ||
21 | class RdtypeAnyLocTestCase(unittest.TestCase): | |
22 | ||
23 | def testEqual1(self): | |
24 | '''Test default values for size, horizontal and vertical precision.''' | |
25 | r1 = dns.rrset.from_text('foo', 300, 'IN', 'LOC', | |
26 | '49 11 42.400 N 16 36 29.600 E 227.64m') | |
27 | r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc', | |
28 | '49 11 42.400 N 16 36 29.600 E 227.64m ' | |
29 | '1.00m 10000.00m 10.00m') | |
30 | self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2)) | |
31 | ||
32 | def testEqual2(self): | |
33 | '''Test default values for size, horizontal and vertical precision.''' | |
34 | r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400), | |
35 | (16, 36, 29, 600), 22764.0) # centimeters | |
36 | r2 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400), | |
37 | (16, 36, 29, 600), 22764.0, # centimeters | |
38 | 100.0, 1000000.00, 1000.0) # centimeters | |
39 | self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2)) | |
40 | ||
41 | def testEqual3(self): | |
42 | '''Test size, horizontal and vertical precision parsers: 100 cm == 1 m. | |
43 | ||
44 | Parsers in from_text() and __init__() have to produce equal results.''' | |
45 | r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400), | |
46 | (16, 36, 29, 600), 22764.0, | |
47 | 200.0, 1000.00, 200.0) # centimeters | |
48 | r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc', | |
49 | '49 11 42.400 N 16 36 29.600 E 227.64m ' | |
50 | '2.00m 10.00m 2.00m')[0] | |
51 | self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2)) | |
52 | ||
53 | def testEqual4(self): | |
54 | '''Test size, horizontal and vertical precision parsers without unit. | |
55 | ||
56 | Parsers in from_text() and __init__() have produce equal result | |
57 | for values with and without trailing "m".''' | |
58 | r1 = dns.rdtypes.ANY.LOC.LOC(1, 29, (49, 11, 42, 400), | |
59 | (16, 36, 29, 600), 22764.0, | |
60 | 200.0, 1000.00, 200.0) # centimeters | |
61 | r2 = dns.rrset.from_text('FOO', 600, 'in', 'loc', | |
62 | '49 11 42.400 N 16 36 29.600 E 227.64 ' | |
63 | '2 10 2')[0] # meters without explicit unit | |
64 | self.failUnless(r1 == r2, '"%s" != "%s"' % (r1, r2)) | |
65 | ||
66 | if __name__ == '__main__': | |
67 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import cStringIO | |
16 | import select | |
17 | import sys | |
18 | import time | |
19 | import unittest | |
20 | ||
21 | import dns.name | |
22 | import dns.message | |
23 | import dns.name | |
24 | import dns.rdataclass | |
25 | import dns.rdatatype | |
26 | import dns.resolver | |
27 | ||
28 | resolv_conf = """ | |
29 | /t/t | |
30 | # comment 1 | |
31 | ; comment 2 | |
32 | domain foo | |
33 | nameserver 10.0.0.1 | |
34 | nameserver 10.0.0.2 | |
35 | """ | |
36 | ||
37 | message_text = """id 1234 | |
38 | opcode QUERY | |
39 | rcode NOERROR | |
40 | flags QR AA RD | |
41 | ;QUESTION | |
42 | example. IN A | |
43 | ;ANSWER | |
44 | example. 1 IN A 10.0.0.1 | |
45 | ;AUTHORITY | |
46 | ;ADDITIONAL | |
47 | """ | |
48 | ||
49 | class FakeAnswer(object): | |
50 | def __init__(self, expiration): | |
51 | self.expiration = expiration | |
52 | ||
53 | class BaseResolverTests(object): | |
54 | ||
55 | if sys.platform != 'win32': | |
56 | def testRead(self): | |
57 | f = cStringIO.StringIO(resolv_conf) | |
58 | r = dns.resolver.Resolver(f) | |
59 | self.failUnless(r.nameservers == ['10.0.0.1', '10.0.0.2'] and | |
60 | r.domain == dns.name.from_text('foo')) | |
61 | ||
62 | def testCacheExpiration(self): | |
63 | message = dns.message.from_text(message_text) | |
64 | name = dns.name.from_text('example.') | |
65 | answer = dns.resolver.Answer(name, dns.rdatatype.A, dns.rdataclass.IN, | |
66 | message) | |
67 | cache = dns.resolver.Cache() | |
68 | cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) | |
69 | time.sleep(2) | |
70 | self.failUnless(cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)) | |
71 | is None) | |
72 | ||
73 | def testCacheCleaning(self): | |
74 | message = dns.message.from_text(message_text) | |
75 | name = dns.name.from_text('example.') | |
76 | answer = dns.resolver.Answer(name, dns.rdatatype.A, dns.rdataclass.IN, | |
77 | message) | |
78 | cache = dns.resolver.Cache(cleaning_interval=1.0) | |
79 | cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) | |
80 | time.sleep(2) | |
81 | self.failUnless(cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)) | |
82 | is None) | |
83 | ||
84 | def testZoneForName1(self): | |
85 | name = dns.name.from_text('www.dnspython.org.') | |
86 | ezname = dns.name.from_text('dnspython.org.') | |
87 | zname = dns.resolver.zone_for_name(name) | |
88 | self.failUnless(zname == ezname) | |
89 | ||
90 | def testZoneForName2(self): | |
91 | name = dns.name.from_text('a.b.www.dnspython.org.') | |
92 | ezname = dns.name.from_text('dnspython.org.') | |
93 | zname = dns.resolver.zone_for_name(name) | |
94 | self.failUnless(zname == ezname) | |
95 | ||
96 | def testZoneForName3(self): | |
97 | name = dns.name.from_text('dnspython.org.') | |
98 | ezname = dns.name.from_text('dnspython.org.') | |
99 | zname = dns.resolver.zone_for_name(name) | |
100 | self.failUnless(zname == ezname) | |
101 | ||
102 | def testZoneForName4(self): | |
103 | def bad(): | |
104 | name = dns.name.from_text('dnspython.org', None) | |
105 | zname = dns.resolver.zone_for_name(name) | |
106 | self.failUnlessRaises(dns.resolver.NotAbsolute, bad) | |
107 | ||
108 | def testLRUReplace(self): | |
109 | cache = dns.resolver.LRUCache(4) | |
110 | for i in xrange(0, 5): | |
111 | name = dns.name.from_text('example%d.' % i) | |
112 | answer = FakeAnswer(time.time() + 1) | |
113 | cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) | |
114 | for i in xrange(0, 5): | |
115 | name = dns.name.from_text('example%d.' % i) | |
116 | if i == 0: | |
117 | self.failUnless(cache.get((name, dns.rdatatype.A, | |
118 | dns.rdataclass.IN)) | |
119 | is None) | |
120 | else: | |
121 | self.failUnless(not cache.get((name, dns.rdatatype.A, | |
122 | dns.rdataclass.IN)) | |
123 | is None) | |
124 | ||
125 | def testLRUDoesLRU(self): | |
126 | cache = dns.resolver.LRUCache(4) | |
127 | for i in xrange(0, 4): | |
128 | name = dns.name.from_text('example%d.' % i) | |
129 | answer = FakeAnswer(time.time() + 1) | |
130 | cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) | |
131 | name = dns.name.from_text('example0.') | |
132 | cache.get((name, dns.rdatatype.A, dns.rdataclass.IN)) | |
133 | # The LRU is now example1. | |
134 | name = dns.name.from_text('example4.') | |
135 | answer = FakeAnswer(time.time() + 1) | |
136 | cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) | |
137 | for i in xrange(0, 5): | |
138 | name = dns.name.from_text('example%d.' % i) | |
139 | if i == 1: | |
140 | self.failUnless(cache.get((name, dns.rdatatype.A, | |
141 | dns.rdataclass.IN)) | |
142 | is None) | |
143 | else: | |
144 | self.failUnless(not cache.get((name, dns.rdatatype.A, | |
145 | dns.rdataclass.IN)) | |
146 | is None) | |
147 | ||
148 | def testLRUExpiration(self): | |
149 | cache = dns.resolver.LRUCache(4) | |
150 | for i in xrange(0, 4): | |
151 | name = dns.name.from_text('example%d.' % i) | |
152 | answer = FakeAnswer(time.time() + 1) | |
153 | cache.put((name, dns.rdatatype.A, dns.rdataclass.IN), answer) | |
154 | time.sleep(2) | |
155 | for i in xrange(0, 4): | |
156 | name = dns.name.from_text('example%d.' % i) | |
157 | self.failUnless(cache.get((name, dns.rdatatype.A, | |
158 | dns.rdataclass.IN)) | |
159 | is None) | |
160 | ||
161 | class PollingMonkeyPatchMixin(object): | |
162 | def setUp(self): | |
163 | self.__native_polling_backend = dns.query._polling_backend | |
164 | dns.query._set_polling_backend(self.polling_backend()) | |
165 | ||
166 | unittest.TestCase.setUp(self) | |
167 | ||
168 | def tearDown(self): | |
169 | dns.query._set_polling_backend(self.__native_polling_backend) | |
170 | ||
171 | unittest.TestCase.tearDown(self) | |
172 | ||
173 | class SelectResolverTestCase(PollingMonkeyPatchMixin, BaseResolverTests, unittest.TestCase): | |
174 | def polling_backend(self): | |
175 | return dns.query._select_for | |
176 | ||
177 | if hasattr(select, 'poll'): | |
178 | class PollResolverTestCase(PollingMonkeyPatchMixin, BaseResolverTests, unittest.TestCase): | |
179 | def polling_backend(self): | |
180 | return dns.query._poll_for | |
181 | ||
182 | if __name__ == '__main__': | |
183 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.rrset | |
18 | ||
19 | class RRsetTestCase(unittest.TestCase): | |
20 | ||
21 | def testEqual1(self): | |
22 | r1 = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1', '10.0.0.2') | |
23 | r2 = dns.rrset.from_text('FOO', 300, 'in', 'a', '10.0.0.2', '10.0.0.1') | |
24 | self.failUnless(r1 == r2) | |
25 | ||
26 | def testEqual2(self): | |
27 | r1 = dns.rrset.from_text('foo', 300, 'in', 'a', '10.0.0.1', '10.0.0.2') | |
28 | r2 = dns.rrset.from_text('FOO', 600, 'in', 'a', '10.0.0.2', '10.0.0.1') | |
29 | self.failUnless(r1 == r2) | |
30 | ||
31 | def testNotEqual1(self): | |
32 | r1 = dns.rrset.from_text('fooa', 30, 'in', 'a', '10.0.0.1', '10.0.0.2') | |
33 | r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1') | |
34 | self.failUnless(r1 != r2) | |
35 | ||
36 | def testNotEqual2(self): | |
37 | r1 = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1', '10.0.0.3') | |
38 | r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1') | |
39 | self.failUnless(r1 != r2) | |
40 | ||
41 | def testNotEqual3(self): | |
42 | r1 = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1', '10.0.0.2', | |
43 | '10.0.0.3') | |
44 | r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1') | |
45 | self.failUnless(r1 != r2) | |
46 | ||
47 | def testNotEqual4(self): | |
48 | r1 = dns.rrset.from_text('foo', 30, 'in', 'a', '10.0.0.1') | |
49 | r2 = dns.rrset.from_text('FOO', 30, 'in', 'a', '10.0.0.2', '10.0.0.1') | |
50 | self.failUnless(r1 != r2) | |
51 | ||
52 | if __name__ == '__main__': | |
53 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.set | |
18 | ||
19 | # for convenience | |
20 | S = dns.set.Set | |
21 | ||
22 | class SimpleSetTestCase(unittest.TestCase): | |
23 | ||
24 | def testLen1(self): | |
25 | s1 = S() | |
26 | self.failUnless(len(s1) == 0) | |
27 | ||
28 | def testLen2(self): | |
29 | s1 = S([1, 2, 3]) | |
30 | self.failUnless(len(s1) == 3) | |
31 | ||
32 | def testLen3(self): | |
33 | s1 = S([1, 2, 3, 3, 3]) | |
34 | self.failUnless(len(s1) == 3) | |
35 | ||
36 | def testUnion1(self): | |
37 | s1 = S([1, 2, 3]) | |
38 | s2 = S([1, 2, 3]) | |
39 | e = S([1, 2, 3]) | |
40 | self.failUnless(s1 | s2 == e) | |
41 | ||
42 | def testUnion2(self): | |
43 | s1 = S([1, 2, 3]) | |
44 | s2 = S([]) | |
45 | e = S([1, 2, 3]) | |
46 | self.failUnless(s1 | s2 == e) | |
47 | ||
48 | def testUnion3(self): | |
49 | s1 = S([1, 2, 3]) | |
50 | s2 = S([3, 4]) | |
51 | e = S([1, 2, 3, 4]) | |
52 | self.failUnless(s1 | s2 == e) | |
53 | ||
54 | def testIntersection1(self): | |
55 | s1 = S([1, 2, 3]) | |
56 | s2 = S([1, 2, 3]) | |
57 | e = S([1, 2, 3]) | |
58 | self.failUnless(s1 & s2 == e) | |
59 | ||
60 | def testIntersection2(self): | |
61 | s1 = S([0, 1, 2, 3]) | |
62 | s2 = S([1, 2, 3, 4]) | |
63 | e = S([1, 2, 3]) | |
64 | self.failUnless(s1 & s2 == e) | |
65 | ||
66 | def testIntersection3(self): | |
67 | s1 = S([1, 2, 3]) | |
68 | s2 = S([]) | |
69 | e = S([]) | |
70 | self.failUnless(s1 & s2 == e) | |
71 | ||
72 | def testIntersection4(self): | |
73 | s1 = S([1, 2, 3]) | |
74 | s2 = S([5, 4]) | |
75 | e = S([]) | |
76 | self.failUnless(s1 & s2 == e) | |
77 | ||
78 | def testDifference1(self): | |
79 | s1 = S([1, 2, 3]) | |
80 | s2 = S([5, 4]) | |
81 | e = S([1, 2, 3]) | |
82 | self.failUnless(s1 - s2 == e) | |
83 | ||
84 | def testDifference2(self): | |
85 | s1 = S([1, 2, 3]) | |
86 | s2 = S([]) | |
87 | e = S([1, 2, 3]) | |
88 | self.failUnless(s1 - s2 == e) | |
89 | ||
90 | def testDifference3(self): | |
91 | s1 = S([1, 2, 3]) | |
92 | s2 = S([3, 2]) | |
93 | e = S([1]) | |
94 | self.failUnless(s1 - s2 == e) | |
95 | ||
96 | def testDifference4(self): | |
97 | s1 = S([1, 2, 3]) | |
98 | s2 = S([3, 2, 1]) | |
99 | e = S([]) | |
100 | self.failUnless(s1 - s2 == e) | |
101 | ||
102 | def testSubset1(self): | |
103 | s1 = S([1, 2, 3]) | |
104 | s2 = S([3, 2, 1]) | |
105 | self.failUnless(s1.issubset(s2)) | |
106 | ||
107 | def testSubset2(self): | |
108 | s1 = S([1, 2, 3]) | |
109 | self.failUnless(s1.issubset(s1)) | |
110 | ||
111 | def testSubset3(self): | |
112 | s1 = S([]) | |
113 | s2 = S([1, 2, 3]) | |
114 | self.failUnless(s1.issubset(s2)) | |
115 | ||
116 | def testSubset4(self): | |
117 | s1 = S([1]) | |
118 | s2 = S([1, 2, 3]) | |
119 | self.failUnless(s1.issubset(s2)) | |
120 | ||
121 | def testSubset5(self): | |
122 | s1 = S([]) | |
123 | s2 = S([]) | |
124 | self.failUnless(s1.issubset(s2)) | |
125 | ||
126 | def testSubset6(self): | |
127 | s1 = S([1, 4]) | |
128 | s2 = S([1, 2, 3]) | |
129 | self.failUnless(not s1.issubset(s2)) | |
130 | ||
131 | def testSuperset1(self): | |
132 | s1 = S([1, 2, 3]) | |
133 | s2 = S([3, 2, 1]) | |
134 | self.failUnless(s1.issuperset(s2)) | |
135 | ||
136 | def testSuperset2(self): | |
137 | s1 = S([1, 2, 3]) | |
138 | self.failUnless(s1.issuperset(s1)) | |
139 | ||
140 | def testSuperset3(self): | |
141 | s1 = S([1, 2, 3]) | |
142 | s2 = S([]) | |
143 | self.failUnless(s1.issuperset(s2)) | |
144 | ||
145 | def testSuperset4(self): | |
146 | s1 = S([1, 2, 3]) | |
147 | s2 = S([1]) | |
148 | self.failUnless(s1.issuperset(s2)) | |
149 | ||
150 | def testSuperset5(self): | |
151 | s1 = S([]) | |
152 | s2 = S([]) | |
153 | self.failUnless(s1.issuperset(s2)) | |
154 | ||
155 | def testSuperset6(self): | |
156 | s1 = S([1, 2, 3]) | |
157 | s2 = S([1, 4]) | |
158 | self.failUnless(not s1.issuperset(s2)) | |
159 | ||
160 | def testUpdate1(self): | |
161 | s1 = S([1, 2, 3]) | |
162 | u = (4, 5, 6) | |
163 | e = S([1, 2, 3, 4, 5, 6]) | |
164 | s1.update(u) | |
165 | self.failUnless(s1 == e) | |
166 | ||
167 | def testUpdate2(self): | |
168 | s1 = S([1, 2, 3]) | |
169 | u = [] | |
170 | e = S([1, 2, 3]) | |
171 | s1.update(u) | |
172 | self.failUnless(s1 == e) | |
173 | ||
174 | def testGetitem(self): | |
175 | s1 = S([1, 2, 3]) | |
176 | i0 = s1[0] | |
177 | i1 = s1[1] | |
178 | i2 = s1[2] | |
179 | s2 = S([i0, i1, i2]) | |
180 | self.failUnless(s1 == s2) | |
181 | ||
182 | def testGetslice(self): | |
183 | s1 = S([1, 2, 3]) | |
184 | slice = s1[0:2] | |
185 | self.failUnless(len(slice) == 2) | |
186 | item = s1[2] | |
187 | slice.append(item) | |
188 | s2 = S(slice) | |
189 | self.failUnless(s1 == s2) | |
190 | ||
191 | def testDelitem(self): | |
192 | s1 = S([1, 2, 3]) | |
193 | del s1[0] | |
194 | i1 = s1[0] | |
195 | i2 = s1[1] | |
196 | self.failUnless(i1 != i2) | |
197 | self.failUnless(i1 == 1 or i1 == 2 or i1 == 3) | |
198 | self.failUnless(i2 == 1 or i2 == 2 or i2 == 3) | |
199 | ||
200 | def testDelslice(self): | |
201 | s1 = S([1, 2, 3]) | |
202 | del s1[0:2] | |
203 | i1 = s1[0] | |
204 | self.failUnless(i1 == 1 or i1 == 2 or i1 == 3) | |
205 | ||
206 | if __name__ == '__main__': | |
207 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.exception | |
18 | import dns.tokenizer | |
19 | ||
20 | Token = dns.tokenizer.Token | |
21 | ||
22 | class TokenizerTestCase(unittest.TestCase): | |
23 | ||
24 | def testQuotedString1(self): | |
25 | tok = dns.tokenizer.Tokenizer(r'"foo"') | |
26 | token = tok.get() | |
27 | self.failUnless(token == Token(dns.tokenizer.QUOTED_STRING, 'foo')) | |
28 | ||
29 | def testQuotedString2(self): | |
30 | tok = dns.tokenizer.Tokenizer(r'""') | |
31 | token = tok.get() | |
32 | self.failUnless(token == Token(dns.tokenizer.QUOTED_STRING, '')) | |
33 | ||
34 | def testQuotedString3(self): | |
35 | tok = dns.tokenizer.Tokenizer(r'"\"foo\""') | |
36 | token = tok.get() | |
37 | self.failUnless(token == Token(dns.tokenizer.QUOTED_STRING, '"foo"')) | |
38 | ||
39 | def testQuotedString4(self): | |
40 | tok = dns.tokenizer.Tokenizer(r'"foo\010bar"') | |
41 | token = tok.get() | |
42 | self.failUnless(token == Token(dns.tokenizer.QUOTED_STRING, 'foo\x0abar')) | |
43 | ||
44 | def testQuotedString5(self): | |
45 | def bad(): | |
46 | tok = dns.tokenizer.Tokenizer(r'"foo') | |
47 | token = tok.get() | |
48 | self.failUnlessRaises(dns.exception.UnexpectedEnd, bad) | |
49 | ||
50 | def testQuotedString6(self): | |
51 | def bad(): | |
52 | tok = dns.tokenizer.Tokenizer(r'"foo\01') | |
53 | token = tok.get() | |
54 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
55 | ||
56 | def testQuotedString7(self): | |
57 | def bad(): | |
58 | tok = dns.tokenizer.Tokenizer('"foo\nbar"') | |
59 | token = tok.get() | |
60 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
61 | ||
62 | def testEmpty1(self): | |
63 | tok = dns.tokenizer.Tokenizer('') | |
64 | token = tok.get() | |
65 | self.failUnless(token.is_eof()) | |
66 | ||
67 | def testEmpty2(self): | |
68 | tok = dns.tokenizer.Tokenizer('') | |
69 | token1 = tok.get() | |
70 | token2 = tok.get() | |
71 | self.failUnless(token1.is_eof() and token2.is_eof()) | |
72 | ||
73 | def testEOL(self): | |
74 | tok = dns.tokenizer.Tokenizer('\n') | |
75 | token1 = tok.get() | |
76 | token2 = tok.get() | |
77 | self.failUnless(token1.is_eol() and token2.is_eof()) | |
78 | ||
79 | def testWS1(self): | |
80 | tok = dns.tokenizer.Tokenizer(' \n') | |
81 | token1 = tok.get() | |
82 | self.failUnless(token1.is_eol()) | |
83 | ||
84 | def testWS2(self): | |
85 | tok = dns.tokenizer.Tokenizer(' \n') | |
86 | token1 = tok.get(want_leading=True) | |
87 | self.failUnless(token1.is_whitespace()) | |
88 | ||
89 | def testComment1(self): | |
90 | tok = dns.tokenizer.Tokenizer(' ;foo\n') | |
91 | token1 = tok.get() | |
92 | self.failUnless(token1.is_eol()) | |
93 | ||
94 | def testComment2(self): | |
95 | tok = dns.tokenizer.Tokenizer(' ;foo\n') | |
96 | token1 = tok.get(want_comment = True) | |
97 | token2 = tok.get() | |
98 | self.failUnless(token1 == Token(dns.tokenizer.COMMENT, 'foo') and | |
99 | token2.is_eol()) | |
100 | ||
101 | def testComment3(self): | |
102 | tok = dns.tokenizer.Tokenizer(' ;foo bar\n') | |
103 | token1 = tok.get(want_comment = True) | |
104 | token2 = tok.get() | |
105 | self.failUnless(token1 == Token(dns.tokenizer.COMMENT, 'foo bar') and | |
106 | token2.is_eol()) | |
107 | ||
108 | def testMultiline1(self): | |
109 | tok = dns.tokenizer.Tokenizer('( foo\n\n bar\n)') | |
110 | tokens = list(iter(tok)) | |
111 | self.failUnless(tokens == [Token(dns.tokenizer.IDENTIFIER, 'foo'), | |
112 | Token(dns.tokenizer.IDENTIFIER, 'bar')]) | |
113 | ||
114 | def testMultiline2(self): | |
115 | tok = dns.tokenizer.Tokenizer('( foo\n\n bar\n)\n') | |
116 | tokens = list(iter(tok)) | |
117 | self.failUnless(tokens == [Token(dns.tokenizer.IDENTIFIER, 'foo'), | |
118 | Token(dns.tokenizer.IDENTIFIER, 'bar'), | |
119 | Token(dns.tokenizer.EOL, '\n')]) | |
120 | def testMultiline3(self): | |
121 | def bad(): | |
122 | tok = dns.tokenizer.Tokenizer('foo)') | |
123 | tokens = list(iter(tok)) | |
124 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
125 | ||
126 | def testMultiline4(self): | |
127 | def bad(): | |
128 | tok = dns.tokenizer.Tokenizer('((foo)') | |
129 | tokens = list(iter(tok)) | |
130 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
131 | ||
132 | def testUnget1(self): | |
133 | tok = dns.tokenizer.Tokenizer('foo') | |
134 | t1 = tok.get() | |
135 | tok.unget(t1) | |
136 | t2 = tok.get() | |
137 | self.failUnless(t1 == t2 and t1.ttype == dns.tokenizer.IDENTIFIER and \ | |
138 | t1.value == 'foo') | |
139 | ||
140 | def testUnget2(self): | |
141 | def bad(): | |
142 | tok = dns.tokenizer.Tokenizer('foo') | |
143 | t1 = tok.get() | |
144 | tok.unget(t1) | |
145 | tok.unget(t1) | |
146 | self.failUnlessRaises(dns.tokenizer.UngetBufferFull, bad) | |
147 | ||
148 | def testGetEOL1(self): | |
149 | tok = dns.tokenizer.Tokenizer('\n') | |
150 | t = tok.get_eol() | |
151 | self.failUnless(t == '\n') | |
152 | ||
153 | def testGetEOL2(self): | |
154 | tok = dns.tokenizer.Tokenizer('') | |
155 | t = tok.get_eol() | |
156 | self.failUnless(t == '') | |
157 | ||
158 | def testEscapedDelimiter1(self): | |
159 | tok = dns.tokenizer.Tokenizer(r'ch\ ld') | |
160 | t = tok.get() | |
161 | self.failUnless(t.ttype == dns.tokenizer.IDENTIFIER and t.value == r'ch\ ld') | |
162 | ||
163 | def testEscapedDelimiter2(self): | |
164 | tok = dns.tokenizer.Tokenizer(r'ch\032ld') | |
165 | t = tok.get() | |
166 | self.failUnless(t.ttype == dns.tokenizer.IDENTIFIER and t.value == r'ch\032ld') | |
167 | ||
168 | def testEscapedDelimiter3(self): | |
169 | tok = dns.tokenizer.Tokenizer(r'ch\ild') | |
170 | t = tok.get() | |
171 | self.failUnless(t.ttype == dns.tokenizer.IDENTIFIER and t.value == r'ch\ild') | |
172 | ||
173 | def testEscapedDelimiter1u(self): | |
174 | tok = dns.tokenizer.Tokenizer(r'ch\ ld') | |
175 | t = tok.get().unescape() | |
176 | self.failUnless(t.ttype == dns.tokenizer.IDENTIFIER and t.value == r'ch ld') | |
177 | ||
178 | def testEscapedDelimiter2u(self): | |
179 | tok = dns.tokenizer.Tokenizer(r'ch\032ld') | |
180 | t = tok.get().unescape() | |
181 | self.failUnless(t.ttype == dns.tokenizer.IDENTIFIER and t.value == 'ch ld') | |
182 | ||
183 | def testEscapedDelimiter3u(self): | |
184 | tok = dns.tokenizer.Tokenizer(r'ch\ild') | |
185 | t = tok.get().unescape() | |
186 | self.failUnless(t.ttype == dns.tokenizer.IDENTIFIER and t.value == r'child') | |
187 | ||
188 | if __name__ == '__main__': | |
189 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.update | |
18 | import dns.rdata | |
19 | import dns.rdataset | |
20 | ||
21 | goodhex = '0001 2800 0001 0005 0007 0000' \ | |
22 | '076578616d706c6500 0006 0001' \ | |
23 | '03666f6fc00c 00ff 00ff 00000000 0000' \ | |
24 | 'c019 0001 00ff 00000000 0000' \ | |
25 | '03626172c00c 0001 0001 00000000 0004 0a000005' \ | |
26 | '05626c617a32c00c 00ff 00fe 00000000 0000' \ | |
27 | 'c049 0001 00fe 00000000 0000' \ | |
28 | 'c019 0001 00ff 00000000 0000' \ | |
29 | 'c019 0001 0001 0000012c 0004 0a000001' \ | |
30 | 'c019 0001 0001 0000012c 0004 0a000002' \ | |
31 | 'c035 0001 0001 0000012c 0004 0a000003' \ | |
32 | 'c035 0001 00fe 00000000 0004 0a000004' \ | |
33 | '04626c617ac00c 0001 00ff 00000000 0000' \ | |
34 | 'c049 00ff 00ff 00000000 0000' | |
35 | ||
36 | goodwire = goodhex.replace(' ', '').decode('hex_codec') | |
37 | ||
38 | update_text="""id 1 | |
39 | opcode UPDATE | |
40 | rcode NOERROR | |
41 | ;ZONE | |
42 | example. IN SOA | |
43 | ;PREREQ | |
44 | foo ANY ANY | |
45 | foo ANY A | |
46 | bar 0 IN A 10.0.0.5 | |
47 | blaz2 NONE ANY | |
48 | blaz2 NONE A | |
49 | ;UPDATE | |
50 | foo ANY A | |
51 | foo 300 IN A 10.0.0.1 | |
52 | foo 300 IN A 10.0.0.2 | |
53 | bar 300 IN A 10.0.0.3 | |
54 | bar 0 NONE A 10.0.0.4 | |
55 | blaz ANY A | |
56 | blaz2 ANY ANY | |
57 | """ | |
58 | ||
59 | class UpdateTestCase(unittest.TestCase): | |
60 | ||
61 | def test_to_wire1(self): | |
62 | update = dns.update.Update('example') | |
63 | update.id = 1 | |
64 | update.present('foo') | |
65 | update.present('foo', 'a') | |
66 | update.present('bar', 'a', '10.0.0.5') | |
67 | update.absent('blaz2') | |
68 | update.absent('blaz2', 'a') | |
69 | update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2') | |
70 | update.add('bar', 300, 'a', '10.0.0.3') | |
71 | update.delete('bar', 'a', '10.0.0.4') | |
72 | update.delete('blaz','a') | |
73 | update.delete('blaz2') | |
74 | self.failUnless(update.to_wire() == goodwire) | |
75 | ||
76 | def test_to_wire2(self): | |
77 | update = dns.update.Update('example') | |
78 | update.id = 1 | |
79 | update.present('foo') | |
80 | update.present('foo', 'a') | |
81 | update.present('bar', 'a', '10.0.0.5') | |
82 | update.absent('blaz2') | |
83 | update.absent('blaz2', 'a') | |
84 | update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2') | |
85 | update.add('bar', 300, dns.rdata.from_text(1, 1, '10.0.0.3')) | |
86 | update.delete('bar', 'a', '10.0.0.4') | |
87 | update.delete('blaz','a') | |
88 | update.delete('blaz2') | |
89 | self.failUnless(update.to_wire() == goodwire) | |
90 | ||
91 | def test_to_wire3(self): | |
92 | update = dns.update.Update('example') | |
93 | update.id = 1 | |
94 | update.present('foo') | |
95 | update.present('foo', 'a') | |
96 | update.present('bar', 'a', '10.0.0.5') | |
97 | update.absent('blaz2') | |
98 | update.absent('blaz2', 'a') | |
99 | update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2') | |
100 | update.add('bar', dns.rdataset.from_text(1, 1, 300, '10.0.0.3')) | |
101 | update.delete('bar', 'a', '10.0.0.4') | |
102 | update.delete('blaz','a') | |
103 | update.delete('blaz2') | |
104 | self.failUnless(update.to_wire() == goodwire) | |
105 | ||
106 | def test_from_text1(self): | |
107 | update = dns.message.from_text(update_text) | |
108 | w = update.to_wire(origin=dns.name.from_text('example'), | |
109 | want_shuffle=False) | |
110 | self.failUnless(w == goodwire) | |
111 | ||
112 | if __name__ == '__main__': | |
113 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import cStringIO | |
16 | import filecmp | |
17 | import os | |
18 | import unittest | |
19 | ||
20 | import dns.exception | |
21 | import dns.rdata | |
22 | import dns.rdataclass | |
23 | import dns.rdatatype | |
24 | import dns.rrset | |
25 | import dns.zone | |
26 | ||
27 | example_text = """$TTL 3600 | |
28 | $ORIGIN example. | |
29 | @ soa foo bar 1 2 3 4 5 | |
30 | @ ns ns1 | |
31 | @ ns ns2 | |
32 | ns1 a 10.0.0.1 | |
33 | ns2 a 10.0.0.2 | |
34 | $TTL 300 | |
35 | $ORIGIN foo.example. | |
36 | bar mx 0 blaz | |
37 | """ | |
38 | ||
39 | example_text_output = """@ 3600 IN SOA foo bar 1 2 3 4 5 | |
40 | @ 3600 IN NS ns1 | |
41 | @ 3600 IN NS ns2 | |
42 | bar.foo 300 IN MX 0 blaz.foo | |
43 | ns1 3600 IN A 10.0.0.1 | |
44 | ns2 3600 IN A 10.0.0.2 | |
45 | """ | |
46 | ||
47 | something_quite_similar = """@ 3600 IN SOA foo bar 1 2 3 4 5 | |
48 | @ 3600 IN NS ns1 | |
49 | @ 3600 IN NS ns2 | |
50 | bar.foo 300 IN MX 0 blaz.foo | |
51 | ns1 3600 IN A 10.0.0.1 | |
52 | ns2 3600 IN A 10.0.0.3 | |
53 | """ | |
54 | ||
55 | something_different = """@ 3600 IN SOA fooa bar 1 2 3 4 5 | |
56 | @ 3600 IN NS ns11 | |
57 | @ 3600 IN NS ns21 | |
58 | bar.fooa 300 IN MX 0 blaz.fooa | |
59 | ns11 3600 IN A 10.0.0.11 | |
60 | ns21 3600 IN A 10.0.0.21 | |
61 | """ | |
62 | ||
63 | ttl_example_text = """$TTL 1h | |
64 | $ORIGIN example. | |
65 | @ soa foo bar 1 2 3 4 5 | |
66 | @ ns ns1 | |
67 | @ ns ns2 | |
68 | ns1 1d1s a 10.0.0.1 | |
69 | ns2 1w1D1h1m1S a 10.0.0.2 | |
70 | """ | |
71 | ||
72 | no_soa_text = """$TTL 1h | |
73 | $ORIGIN example. | |
74 | @ ns ns1 | |
75 | @ ns ns2 | |
76 | ns1 1d1s a 10.0.0.1 | |
77 | ns2 1w1D1h1m1S a 10.0.0.2 | |
78 | """ | |
79 | ||
80 | no_ns_text = """$TTL 1h | |
81 | $ORIGIN example. | |
82 | @ soa foo bar 1 2 3 4 5 | |
83 | """ | |
84 | ||
85 | include_text = """$INCLUDE "example" | |
86 | """ | |
87 | ||
88 | bad_directive_text = """$FOO bar | |
89 | $ORIGIN example. | |
90 | @ soa foo bar 1 2 3 4 5 | |
91 | @ ns ns1 | |
92 | @ ns ns2 | |
93 | ns1 1d1s a 10.0.0.1 | |
94 | ns2 1w1D1h1m1S a 10.0.0.2 | |
95 | """ | |
96 | ||
97 | _keep_output = False | |
98 | ||
99 | class ZoneTestCase(unittest.TestCase): | |
100 | ||
101 | def testFromFile1(self): | |
102 | z = dns.zone.from_file('example', 'example') | |
103 | ok = False | |
104 | try: | |
105 | z.to_file('example1.out', nl='\x0a') | |
106 | ok = filecmp.cmp('example1.out', 'example1.good') | |
107 | finally: | |
108 | if not _keep_output: | |
109 | os.unlink('example1.out') | |
110 | self.failUnless(ok) | |
111 | ||
112 | def testFromFile2(self): | |
113 | z = dns.zone.from_file('example', 'example', relativize=False) | |
114 | ok = False | |
115 | try: | |
116 | z.to_file('example2.out', relativize=False, nl='\x0a') | |
117 | ok = filecmp.cmp('example2.out', 'example2.good') | |
118 | finally: | |
119 | if not _keep_output: | |
120 | os.unlink('example2.out') | |
121 | self.failUnless(ok) | |
122 | ||
123 | def testToText(self): | |
124 | z = dns.zone.from_file('example', 'example') | |
125 | ok = False | |
126 | try: | |
127 | text_zone = z.to_text(nl='\x0a') | |
128 | f = open('example3.out', 'wb') | |
129 | f.write(text_zone) | |
130 | f.close() | |
131 | ok = filecmp.cmp('example3.out', 'example3.good') | |
132 | finally: | |
133 | if not _keep_output: | |
134 | os.unlink('example3.out') | |
135 | self.failUnless(ok) | |
136 | ||
137 | def testFromText(self): | |
138 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
139 | f = cStringIO.StringIO() | |
140 | names = z.nodes.keys() | |
141 | names.sort() | |
142 | for n in names: | |
143 | print >> f, z[n].to_text(n) | |
144 | self.failUnless(f.getvalue() == example_text_output) | |
145 | ||
146 | def testTorture1(self): | |
147 | # | |
148 | # Read a zone containing all our supported RR types, and | |
149 | # for each RR in the zone, convert the rdata into wire format | |
150 | # and then back out, and see if we get equal rdatas. | |
151 | # | |
152 | f = cStringIO.StringIO() | |
153 | o = dns.name.from_text('example.') | |
154 | z = dns.zone.from_file('example', o) | |
155 | for (name, node) in z.iteritems(): | |
156 | for rds in node: | |
157 | for rd in rds: | |
158 | f.seek(0) | |
159 | f.truncate() | |
160 | rd.to_wire(f, origin=o) | |
161 | wire = f.getvalue() | |
162 | rd2 = dns.rdata.from_wire(rds.rdclass, rds.rdtype, | |
163 | wire, 0, len(wire), | |
164 | origin = o) | |
165 | self.failUnless(rd == rd2) | |
166 | ||
167 | def testEqual(self): | |
168 | z1 = dns.zone.from_text(example_text, 'example.', relativize=True) | |
169 | z2 = dns.zone.from_text(example_text_output, 'example.', | |
170 | relativize=True) | |
171 | self.failUnless(z1 == z2) | |
172 | ||
173 | def testNotEqual1(self): | |
174 | z1 = dns.zone.from_text(example_text, 'example.', relativize=True) | |
175 | z2 = dns.zone.from_text(something_quite_similar, 'example.', | |
176 | relativize=True) | |
177 | self.failUnless(z1 != z2) | |
178 | ||
179 | def testNotEqual2(self): | |
180 | z1 = dns.zone.from_text(example_text, 'example.', relativize=True) | |
181 | z2 = dns.zone.from_text(something_different, 'example.', | |
182 | relativize=True) | |
183 | self.failUnless(z1 != z2) | |
184 | ||
185 | def testNotEqual3(self): | |
186 | z1 = dns.zone.from_text(example_text, 'example.', relativize=True) | |
187 | z2 = dns.zone.from_text(something_different, 'example2.', | |
188 | relativize=True) | |
189 | self.failUnless(z1 != z2) | |
190 | ||
191 | def testFindRdataset1(self): | |
192 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
193 | rds = z.find_rdataset('@', 'soa') | |
194 | exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5') | |
195 | self.failUnless(rds == exrds) | |
196 | ||
197 | def testFindRdataset2(self): | |
198 | def bad(): | |
199 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
200 | rds = z.find_rdataset('@', 'loc') | |
201 | self.failUnlessRaises(KeyError, bad) | |
202 | ||
203 | def testFindRRset1(self): | |
204 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
205 | rrs = z.find_rrset('@', 'soa') | |
206 | exrrs = dns.rrset.from_text('@', 300, 'IN', 'SOA', 'foo bar 1 2 3 4 5') | |
207 | self.failUnless(rrs == exrrs) | |
208 | ||
209 | def testFindRRset2(self): | |
210 | def bad(): | |
211 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
212 | rrs = z.find_rrset('@', 'loc') | |
213 | self.failUnlessRaises(KeyError, bad) | |
214 | ||
215 | def testGetRdataset1(self): | |
216 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
217 | rds = z.get_rdataset('@', 'soa') | |
218 | exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5') | |
219 | self.failUnless(rds == exrds) | |
220 | ||
221 | def testGetRdataset2(self): | |
222 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
223 | rds = z.get_rdataset('@', 'loc') | |
224 | self.failUnless(rds == None) | |
225 | ||
226 | def testGetRRset1(self): | |
227 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
228 | rrs = z.get_rrset('@', 'soa') | |
229 | exrrs = dns.rrset.from_text('@', 300, 'IN', 'SOA', 'foo bar 1 2 3 4 5') | |
230 | self.failUnless(rrs == exrrs) | |
231 | ||
232 | def testGetRRset2(self): | |
233 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
234 | rrs = z.get_rrset('@', 'loc') | |
235 | self.failUnless(rrs == None) | |
236 | ||
237 | def testReplaceRdataset1(self): | |
238 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
239 | rdataset = dns.rdataset.from_text('in', 'ns', 300, 'ns3', 'ns4') | |
240 | z.replace_rdataset('@', rdataset) | |
241 | rds = z.get_rdataset('@', 'ns') | |
242 | self.failUnless(rds is rdataset) | |
243 | ||
244 | def testReplaceRdataset2(self): | |
245 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
246 | rdataset = dns.rdataset.from_text('in', 'txt', 300, '"foo"') | |
247 | z.replace_rdataset('@', rdataset) | |
248 | rds = z.get_rdataset('@', 'txt') | |
249 | self.failUnless(rds is rdataset) | |
250 | ||
251 | def testDeleteRdataset1(self): | |
252 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
253 | z.delete_rdataset('@', 'ns') | |
254 | rds = z.get_rdataset('@', 'ns') | |
255 | self.failUnless(rds is None) | |
256 | ||
257 | def testDeleteRdataset2(self): | |
258 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
259 | z.delete_rdataset('ns1', 'a') | |
260 | node = z.get_node('ns1') | |
261 | self.failUnless(node is None) | |
262 | ||
263 | def testNodeFindRdataset1(self): | |
264 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
265 | node = z['@'] | |
266 | rds = node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) | |
267 | exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5') | |
268 | self.failUnless(rds == exrds) | |
269 | ||
270 | def testNodeFindRdataset2(self): | |
271 | def bad(): | |
272 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
273 | node = z['@'] | |
274 | rds = node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC) | |
275 | self.failUnlessRaises(KeyError, bad) | |
276 | ||
277 | def testNodeGetRdataset1(self): | |
278 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
279 | node = z['@'] | |
280 | rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) | |
281 | exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5') | |
282 | self.failUnless(rds == exrds) | |
283 | ||
284 | def testNodeGetRdataset2(self): | |
285 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
286 | node = z['@'] | |
287 | rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC) | |
288 | self.failUnless(rds == None) | |
289 | ||
290 | def testNodeDeleteRdataset1(self): | |
291 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
292 | node = z['@'] | |
293 | rds = node.delete_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) | |
294 | rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) | |
295 | self.failUnless(rds == None) | |
296 | ||
297 | def testNodeDeleteRdataset2(self): | |
298 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
299 | node = z['@'] | |
300 | rds = node.delete_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC) | |
301 | rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC) | |
302 | self.failUnless(rds == None) | |
303 | ||
304 | def testIterateRdatasets(self): | |
305 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
306 | ns = [n for n, r in z.iterate_rdatasets('A')] | |
307 | ns.sort() | |
308 | self.failUnless(ns == [dns.name.from_text('ns1', None), | |
309 | dns.name.from_text('ns2', None)]) | |
310 | ||
311 | def testIterateAllRdatasets(self): | |
312 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
313 | ns = [n for n, r in z.iterate_rdatasets()] | |
314 | ns.sort() | |
315 | self.failUnless(ns == [dns.name.from_text('@', None), | |
316 | dns.name.from_text('@', None), | |
317 | dns.name.from_text('bar.foo', None), | |
318 | dns.name.from_text('ns1', None), | |
319 | dns.name.from_text('ns2', None)]) | |
320 | ||
321 | def testIterateRdatas(self): | |
322 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
323 | l = list(z.iterate_rdatas('A')) | |
324 | l.sort() | |
325 | exl = [(dns.name.from_text('ns1', None), | |
326 | 3600, | |
327 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
328 | '10.0.0.1')), | |
329 | (dns.name.from_text('ns2', None), | |
330 | 3600, | |
331 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
332 | '10.0.0.2'))] | |
333 | self.failUnless(l == exl) | |
334 | ||
335 | def testIterateAllRdatas(self): | |
336 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
337 | l = list(z.iterate_rdatas()) | |
338 | l.sort() | |
339 | exl = [(dns.name.from_text('@', None), | |
340 | 3600, | |
341 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
342 | 'ns1')), | |
343 | (dns.name.from_text('@', None), | |
344 | 3600, | |
345 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
346 | 'ns2')), | |
347 | (dns.name.from_text('@', None), | |
348 | 3600, | |
349 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
350 | 'foo bar 1 2 3 4 5')), | |
351 | (dns.name.from_text('bar.foo', None), | |
352 | 300, | |
353 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
354 | '0 blaz.foo')), | |
355 | (dns.name.from_text('ns1', None), | |
356 | 3600, | |
357 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
358 | '10.0.0.1')), | |
359 | (dns.name.from_text('ns2', None), | |
360 | 3600, | |
361 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
362 | '10.0.0.2'))] | |
363 | self.failUnless(l == exl) | |
364 | ||
365 | def testTTLs(self): | |
366 | z = dns.zone.from_text(ttl_example_text, 'example.', relativize=True) | |
367 | n = z['@'] | |
368 | rds = n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) | |
369 | self.failUnless(rds.ttl == 3600) | |
370 | n = z['ns1'] | |
371 | rds = n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A) | |
372 | self.failUnless(rds.ttl == 86401) | |
373 | n = z['ns2'] | |
374 | rds = n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A) | |
375 | self.failUnless(rds.ttl == 694861) | |
376 | ||
377 | def testNoSOA(self): | |
378 | def bad(): | |
379 | z = dns.zone.from_text(no_soa_text, 'example.', | |
380 | relativize=True) | |
381 | self.failUnlessRaises(dns.zone.NoSOA, bad) | |
382 | ||
383 | def testNoNS(self): | |
384 | def bad(): | |
385 | z = dns.zone.from_text(no_ns_text, 'example.', | |
386 | relativize=True) | |
387 | self.failUnlessRaises(dns.zone.NoNS, bad) | |
388 | ||
389 | def testInclude(self): | |
390 | z1 = dns.zone.from_text(include_text, 'example.', relativize=True, | |
391 | allow_include=True) | |
392 | z2 = dns.zone.from_file('example', 'example.', relativize=True) | |
393 | self.failUnless(z1 == z2) | |
394 | ||
395 | def testBadDirective(self): | |
396 | def bad(): | |
397 | z = dns.zone.from_text(bad_directive_text, 'example.', | |
398 | relativize=True) | |
399 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
400 | ||
401 | def testFirstRRStartsWithWhitespace(self): | |
402 | # no name is specified, so default to the intial origin | |
403 | # no ttl is specified, so default to the initial TTL of 0 | |
404 | z = dns.zone.from_text(' IN A 10.0.0.1', origin='example.', | |
405 | check_origin=False) | |
406 | n = z['@'] | |
407 | rds = n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A) | |
408 | self.failUnless(rds.ttl == 0) | |
409 | ||
410 | if __name__ == '__main__': | |
411 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.exception | |
18 | import dns.tokenizer | |
19 | ||
20 | Token = dns.tokenizer.Token | |
21 | ||
22 | class TokenizerTestCase(unittest.TestCase): | |
23 | ||
24 | def testQuotedString1(self): | |
25 | tok = dns.tokenizer.Tokenizer(r'"foo"') | |
26 | token = tok.get() | |
27 | self.failUnless(token == Token(dns.tokenizer.QUOTED_STRING, 'foo')) | |
28 | ||
29 | def testQuotedString2(self): | |
30 | tok = dns.tokenizer.Tokenizer(r'""') | |
31 | token = tok.get() | |
32 | self.failUnless(token == Token(dns.tokenizer.QUOTED_STRING, '')) | |
33 | ||
34 | def testQuotedString3(self): | |
35 | tok = dns.tokenizer.Tokenizer(r'"\"foo\""') | |
36 | token = tok.get() | |
37 | self.failUnless(token == Token(dns.tokenizer.QUOTED_STRING, '"foo"')) | |
38 | ||
39 | def testQuotedString4(self): | |
40 | tok = dns.tokenizer.Tokenizer(r'"foo\010bar"') | |
41 | token = tok.get() | |
42 | self.failUnless(token == Token(dns.tokenizer.QUOTED_STRING, 'foo\x0abar')) | |
43 | ||
44 | def testQuotedString5(self): | |
45 | def bad(): | |
46 | tok = dns.tokenizer.Tokenizer(r'"foo') | |
47 | token = tok.get() | |
48 | self.failUnlessRaises(dns.exception.UnexpectedEnd, bad) | |
49 | ||
50 | def testQuotedString6(self): | |
51 | def bad(): | |
52 | tok = dns.tokenizer.Tokenizer(r'"foo\01') | |
53 | token = tok.get() | |
54 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
55 | ||
56 | def testQuotedString7(self): | |
57 | def bad(): | |
58 | tok = dns.tokenizer.Tokenizer('"foo\nbar"') | |
59 | token = tok.get() | |
60 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
61 | ||
62 | def testEmpty1(self): | |
63 | tok = dns.tokenizer.Tokenizer('') | |
64 | token = tok.get() | |
65 | self.failUnless(token.is_eof()) | |
66 | ||
67 | def testEmpty2(self): | |
68 | tok = dns.tokenizer.Tokenizer('') | |
69 | token1 = tok.get() | |
70 | token2 = tok.get() | |
71 | self.failUnless(token1.is_eof() and token2.is_eof()) | |
72 | ||
73 | def testEOL(self): | |
74 | tok = dns.tokenizer.Tokenizer('\n') | |
75 | token1 = tok.get() | |
76 | token2 = tok.get() | |
77 | self.failUnless(token1.is_eol() and token2.is_eof()) | |
78 | ||
79 | def testWS1(self): | |
80 | tok = dns.tokenizer.Tokenizer(' \n') | |
81 | token1 = tok.get() | |
82 | self.failUnless(token1.is_eol()) | |
83 | ||
84 | def testWS2(self): | |
85 | tok = dns.tokenizer.Tokenizer(' \n') | |
86 | token1 = tok.get(want_leading=True) | |
87 | self.failUnless(token1.is_whitespace()) | |
88 | ||
89 | def testComment1(self): | |
90 | tok = dns.tokenizer.Tokenizer(' ;foo\n') | |
91 | token1 = tok.get() | |
92 | self.failUnless(token1.is_eol()) | |
93 | ||
94 | def testComment2(self): | |
95 | tok = dns.tokenizer.Tokenizer(' ;foo\n') | |
96 | token1 = tok.get(want_comment = True) | |
97 | token2 = tok.get() | |
98 | self.failUnless(token1 == Token(dns.tokenizer.COMMENT, 'foo') and | |
99 | token2.is_eol()) | |
100 | ||
101 | def testComment3(self): | |
102 | tok = dns.tokenizer.Tokenizer(' ;foo bar\n') | |
103 | token1 = tok.get(want_comment = True) | |
104 | token2 = tok.get() | |
105 | self.failUnless(token1 == Token(dns.tokenizer.COMMENT, 'foo bar') and | |
106 | token2.is_eol()) | |
107 | ||
108 | def testMultiline1(self): | |
109 | tok = dns.tokenizer.Tokenizer('( foo\n\n bar\n)') | |
110 | tokens = list(iter(tok)) | |
111 | self.failUnless(tokens == [Token(dns.tokenizer.IDENTIFIER, 'foo'), | |
112 | Token(dns.tokenizer.IDENTIFIER, 'bar')]) | |
113 | ||
114 | def testMultiline2(self): | |
115 | tok = dns.tokenizer.Tokenizer('( foo\n\n bar\n)\n') | |
116 | tokens = list(iter(tok)) | |
117 | self.failUnless(tokens == [Token(dns.tokenizer.IDENTIFIER, 'foo'), | |
118 | Token(dns.tokenizer.IDENTIFIER, 'bar'), | |
119 | Token(dns.tokenizer.EOL, '\n')]) | |
120 | def testMultiline3(self): | |
121 | def bad(): | |
122 | tok = dns.tokenizer.Tokenizer('foo)') | |
123 | tokens = list(iter(tok)) | |
124 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
125 | ||
126 | def testMultiline4(self): | |
127 | def bad(): | |
128 | tok = dns.tokenizer.Tokenizer('((foo)') | |
129 | tokens = list(iter(tok)) | |
130 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
131 | ||
132 | def testUnget1(self): | |
133 | tok = dns.tokenizer.Tokenizer('foo') | |
134 | t1 = tok.get() | |
135 | tok.unget(t1) | |
136 | t2 = tok.get() | |
137 | self.failUnless(t1 == t2 and t1.ttype == dns.tokenizer.IDENTIFIER and \ | |
138 | t1.value == 'foo') | |
139 | ||
140 | def testUnget2(self): | |
141 | def bad(): | |
142 | tok = dns.tokenizer.Tokenizer('foo') | |
143 | t1 = tok.get() | |
144 | tok.unget(t1) | |
145 | tok.unget(t1) | |
146 | self.failUnlessRaises(dns.tokenizer.UngetBufferFull, bad) | |
147 | ||
148 | def testGetEOL1(self): | |
149 | tok = dns.tokenizer.Tokenizer('\n') | |
150 | t = tok.get_eol() | |
151 | self.failUnless(t == '\n') | |
152 | ||
153 | def testGetEOL2(self): | |
154 | tok = dns.tokenizer.Tokenizer('') | |
155 | t = tok.get_eol() | |
156 | self.failUnless(t == '') | |
157 | ||
158 | def testEscapedDelimiter1(self): | |
159 | tok = dns.tokenizer.Tokenizer(r'ch\ ld') | |
160 | t = tok.get() | |
161 | self.failUnless(t.ttype == dns.tokenizer.IDENTIFIER and t.value == r'ch\ ld') | |
162 | ||
163 | def testEscapedDelimiter2(self): | |
164 | tok = dns.tokenizer.Tokenizer(r'ch\032ld') | |
165 | t = tok.get() | |
166 | self.failUnless(t.ttype == dns.tokenizer.IDENTIFIER and t.value == r'ch\032ld') | |
167 | ||
168 | def testEscapedDelimiter3(self): | |
169 | tok = dns.tokenizer.Tokenizer(r'ch\ild') | |
170 | t = tok.get() | |
171 | self.failUnless(t.ttype == dns.tokenizer.IDENTIFIER and t.value == r'ch\ild') | |
172 | ||
173 | def testEscapedDelimiter1u(self): | |
174 | tok = dns.tokenizer.Tokenizer(r'ch\ ld') | |
175 | t = tok.get().unescape() | |
176 | self.failUnless(t.ttype == dns.tokenizer.IDENTIFIER and t.value == r'ch ld') | |
177 | ||
178 | def testEscapedDelimiter2u(self): | |
179 | tok = dns.tokenizer.Tokenizer(r'ch\032ld') | |
180 | t = tok.get().unescape() | |
181 | self.failUnless(t.ttype == dns.tokenizer.IDENTIFIER and t.value == 'ch ld') | |
182 | ||
183 | def testEscapedDelimiter3u(self): | |
184 | tok = dns.tokenizer.Tokenizer(r'ch\ild') | |
185 | t = tok.get().unescape() | |
186 | self.failUnless(t.ttype == dns.tokenizer.IDENTIFIER and t.value == r'child') | |
187 | ||
188 | if __name__ == '__main__': | |
189 | unittest.main() |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import unittest | |
16 | ||
17 | import dns.update | |
18 | import dns.rdata | |
19 | import dns.rdataset | |
20 | ||
21 | goodhex = '0001 2800 0001 0005 0007 0000' \ | |
22 | '076578616d706c6500 0006 0001' \ | |
23 | '03666f6fc00c 00ff 00ff 00000000 0000' \ | |
24 | 'c019 0001 00ff 00000000 0000' \ | |
25 | '03626172c00c 0001 0001 00000000 0004 0a000005' \ | |
26 | '05626c617a32c00c 00ff 00fe 00000000 0000' \ | |
27 | 'c049 0001 00fe 00000000 0000' \ | |
28 | 'c019 0001 00ff 00000000 0000' \ | |
29 | 'c019 0001 0001 0000012c 0004 0a000001' \ | |
30 | 'c019 0001 0001 0000012c 0004 0a000002' \ | |
31 | 'c035 0001 0001 0000012c 0004 0a000003' \ | |
32 | 'c035 0001 00fe 00000000 0004 0a000004' \ | |
33 | '04626c617ac00c 0001 00ff 00000000 0000' \ | |
34 | 'c049 00ff 00ff 00000000 0000' | |
35 | ||
36 | goodwire = goodhex.replace(' ', '').decode('hex_codec') | |
37 | ||
38 | update_text="""id 1 | |
39 | opcode UPDATE | |
40 | rcode NOERROR | |
41 | ;ZONE | |
42 | example. IN SOA | |
43 | ;PREREQ | |
44 | foo ANY ANY | |
45 | foo ANY A | |
46 | bar 0 IN A 10.0.0.5 | |
47 | blaz2 NONE ANY | |
48 | blaz2 NONE A | |
49 | ;UPDATE | |
50 | foo ANY A | |
51 | foo 300 IN A 10.0.0.1 | |
52 | foo 300 IN A 10.0.0.2 | |
53 | bar 300 IN A 10.0.0.3 | |
54 | bar 0 NONE A 10.0.0.4 | |
55 | blaz ANY A | |
56 | blaz2 ANY ANY | |
57 | """ | |
58 | ||
59 | class UpdateTestCase(unittest.TestCase): | |
60 | ||
61 | def test_to_wire1(self): | |
62 | update = dns.update.Update('example') | |
63 | update.id = 1 | |
64 | update.present('foo') | |
65 | update.present('foo', 'a') | |
66 | update.present('bar', 'a', '10.0.0.5') | |
67 | update.absent('blaz2') | |
68 | update.absent('blaz2', 'a') | |
69 | update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2') | |
70 | update.add('bar', 300, 'a', '10.0.0.3') | |
71 | update.delete('bar', 'a', '10.0.0.4') | |
72 | update.delete('blaz','a') | |
73 | update.delete('blaz2') | |
74 | self.failUnless(update.to_wire() == goodwire) | |
75 | ||
76 | def test_to_wire2(self): | |
77 | update = dns.update.Update('example') | |
78 | update.id = 1 | |
79 | update.present('foo') | |
80 | update.present('foo', 'a') | |
81 | update.present('bar', 'a', '10.0.0.5') | |
82 | update.absent('blaz2') | |
83 | update.absent('blaz2', 'a') | |
84 | update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2') | |
85 | update.add('bar', 300, dns.rdata.from_text(1, 1, '10.0.0.3')) | |
86 | update.delete('bar', 'a', '10.0.0.4') | |
87 | update.delete('blaz','a') | |
88 | update.delete('blaz2') | |
89 | self.failUnless(update.to_wire() == goodwire) | |
90 | ||
91 | def test_to_wire3(self): | |
92 | update = dns.update.Update('example') | |
93 | update.id = 1 | |
94 | update.present('foo') | |
95 | update.present('foo', 'a') | |
96 | update.present('bar', 'a', '10.0.0.5') | |
97 | update.absent('blaz2') | |
98 | update.absent('blaz2', 'a') | |
99 | update.replace('foo', 300, 'a', '10.0.0.1', '10.0.0.2') | |
100 | update.add('bar', dns.rdataset.from_text(1, 1, 300, '10.0.0.3')) | |
101 | update.delete('bar', 'a', '10.0.0.4') | |
102 | update.delete('blaz','a') | |
103 | update.delete('blaz2') | |
104 | self.failUnless(update.to_wire() == goodwire) | |
105 | ||
106 | def test_from_text1(self): | |
107 | update = dns.message.from_text(update_text) | |
108 | w = update.to_wire(origin=dns.name.from_text('example'), | |
109 | want_shuffle=False) | |
110 | self.failUnless(w == goodwire) | |
111 | ||
112 | if __name__ == '__main__': | |
113 | unittest.main() |
0 | import os.path | |
1 | import sys | |
2 | import unittest | |
3 | ||
4 | if __name__ == '__main__': | |
5 | sys.path.insert(0, os.path.realpath('..')) | |
6 | suites = unittest.defaultTestLoader.discover('.') | |
7 | unittest.TextTestRunner(verbosity=2).run(suites) |
0 | # Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. | |
1 | # | |
2 | # Permission to use, copy, modify, and distribute this software and its | |
3 | # documentation for any purpose with or without fee is hereby granted, | |
4 | # provided that the above copyright notice and this permission notice | |
5 | # appear in all copies. | |
6 | # | |
7 | # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES | |
8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR | |
10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | |
13 | # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
14 | ||
15 | import cStringIO | |
16 | import filecmp | |
17 | import os | |
18 | import unittest | |
19 | ||
20 | import dns.exception | |
21 | import dns.rdata | |
22 | import dns.rdataclass | |
23 | import dns.rdatatype | |
24 | import dns.rrset | |
25 | import dns.zone | |
26 | ||
27 | example_text = """$TTL 3600 | |
28 | $ORIGIN example. | |
29 | @ soa foo bar 1 2 3 4 5 | |
30 | @ ns ns1 | |
31 | @ ns ns2 | |
32 | ns1 a 10.0.0.1 | |
33 | ns2 a 10.0.0.2 | |
34 | $TTL 300 | |
35 | $ORIGIN foo.example. | |
36 | bar mx 0 blaz | |
37 | """ | |
38 | ||
39 | example_text_output = """@ 3600 IN SOA foo bar 1 2 3 4 5 | |
40 | @ 3600 IN NS ns1 | |
41 | @ 3600 IN NS ns2 | |
42 | bar.foo 300 IN MX 0 blaz.foo | |
43 | ns1 3600 IN A 10.0.0.1 | |
44 | ns2 3600 IN A 10.0.0.2 | |
45 | """ | |
46 | ||
47 | something_quite_similar = """@ 3600 IN SOA foo bar 1 2 3 4 5 | |
48 | @ 3600 IN NS ns1 | |
49 | @ 3600 IN NS ns2 | |
50 | bar.foo 300 IN MX 0 blaz.foo | |
51 | ns1 3600 IN A 10.0.0.1 | |
52 | ns2 3600 IN A 10.0.0.3 | |
53 | """ | |
54 | ||
55 | something_different = """@ 3600 IN SOA fooa bar 1 2 3 4 5 | |
56 | @ 3600 IN NS ns11 | |
57 | @ 3600 IN NS ns21 | |
58 | bar.fooa 300 IN MX 0 blaz.fooa | |
59 | ns11 3600 IN A 10.0.0.11 | |
60 | ns21 3600 IN A 10.0.0.21 | |
61 | """ | |
62 | ||
63 | ttl_example_text = """$TTL 1h | |
64 | $ORIGIN example. | |
65 | @ soa foo bar 1 2 3 4 5 | |
66 | @ ns ns1 | |
67 | @ ns ns2 | |
68 | ns1 1d1s a 10.0.0.1 | |
69 | ns2 1w1D1h1m1S a 10.0.0.2 | |
70 | """ | |
71 | ||
72 | no_soa_text = """$TTL 1h | |
73 | $ORIGIN example. | |
74 | @ ns ns1 | |
75 | @ ns ns2 | |
76 | ns1 1d1s a 10.0.0.1 | |
77 | ns2 1w1D1h1m1S a 10.0.0.2 | |
78 | """ | |
79 | ||
80 | no_ns_text = """$TTL 1h | |
81 | $ORIGIN example. | |
82 | @ soa foo bar 1 2 3 4 5 | |
83 | """ | |
84 | ||
85 | include_text = """$INCLUDE "example" | |
86 | """ | |
87 | ||
88 | bad_directive_text = """$FOO bar | |
89 | $ORIGIN example. | |
90 | @ soa foo bar 1 2 3 4 5 | |
91 | @ ns ns1 | |
92 | @ ns ns2 | |
93 | ns1 1d1s a 10.0.0.1 | |
94 | ns2 1w1D1h1m1S a 10.0.0.2 | |
95 | """ | |
96 | ||
97 | _keep_output = False | |
98 | ||
99 | class ZoneTestCase(unittest.TestCase): | |
100 | ||
101 | def testFromFile1(self): | |
102 | z = dns.zone.from_file('example', 'example') | |
103 | ok = False | |
104 | try: | |
105 | z.to_file('example1.out', nl='\x0a') | |
106 | ok = filecmp.cmp('example1.out', 'example1.good') | |
107 | finally: | |
108 | if not _keep_output: | |
109 | os.unlink('example1.out') | |
110 | self.failUnless(ok) | |
111 | ||
112 | def testFromFile2(self): | |
113 | z = dns.zone.from_file('example', 'example', relativize=False) | |
114 | ok = False | |
115 | try: | |
116 | z.to_file('example2.out', relativize=False, nl='\x0a') | |
117 | ok = filecmp.cmp('example2.out', 'example2.good') | |
118 | finally: | |
119 | if not _keep_output: | |
120 | os.unlink('example2.out') | |
121 | self.failUnless(ok) | |
122 | ||
123 | def testFromText(self): | |
124 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
125 | f = cStringIO.StringIO() | |
126 | names = z.nodes.keys() | |
127 | names.sort() | |
128 | for n in names: | |
129 | print >> f, z[n].to_text(n) | |
130 | self.failUnless(f.getvalue() == example_text_output) | |
131 | ||
132 | def testTorture1(self): | |
133 | # | |
134 | # Read a zone containing all our supported RR types, and | |
135 | # for each RR in the zone, convert the rdata into wire format | |
136 | # and then back out, and see if we get equal rdatas. | |
137 | # | |
138 | f = cStringIO.StringIO() | |
139 | o = dns.name.from_text('example.') | |
140 | z = dns.zone.from_file('example', o) | |
141 | for (name, node) in z.iteritems(): | |
142 | for rds in node: | |
143 | for rd in rds: | |
144 | f.seek(0) | |
145 | f.truncate() | |
146 | rd.to_wire(f, origin=o) | |
147 | wire = f.getvalue() | |
148 | rd2 = dns.rdata.from_wire(rds.rdclass, rds.rdtype, | |
149 | wire, 0, len(wire), | |
150 | origin = o) | |
151 | self.failUnless(rd == rd2) | |
152 | ||
153 | def testEqual(self): | |
154 | z1 = dns.zone.from_text(example_text, 'example.', relativize=True) | |
155 | z2 = dns.zone.from_text(example_text_output, 'example.', | |
156 | relativize=True) | |
157 | self.failUnless(z1 == z2) | |
158 | ||
159 | def testNotEqual1(self): | |
160 | z1 = dns.zone.from_text(example_text, 'example.', relativize=True) | |
161 | z2 = dns.zone.from_text(something_quite_similar, 'example.', | |
162 | relativize=True) | |
163 | self.failUnless(z1 != z2) | |
164 | ||
165 | def testNotEqual2(self): | |
166 | z1 = dns.zone.from_text(example_text, 'example.', relativize=True) | |
167 | z2 = dns.zone.from_text(something_different, 'example.', | |
168 | relativize=True) | |
169 | self.failUnless(z1 != z2) | |
170 | ||
171 | def testNotEqual3(self): | |
172 | z1 = dns.zone.from_text(example_text, 'example.', relativize=True) | |
173 | z2 = dns.zone.from_text(something_different, 'example2.', | |
174 | relativize=True) | |
175 | self.failUnless(z1 != z2) | |
176 | ||
177 | def testFindRdataset1(self): | |
178 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
179 | rds = z.find_rdataset('@', 'soa') | |
180 | exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5') | |
181 | self.failUnless(rds == exrds) | |
182 | ||
183 | def testFindRdataset2(self): | |
184 | def bad(): | |
185 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
186 | rds = z.find_rdataset('@', 'loc') | |
187 | self.failUnlessRaises(KeyError, bad) | |
188 | ||
189 | def testFindRRset1(self): | |
190 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
191 | rrs = z.find_rrset('@', 'soa') | |
192 | exrrs = dns.rrset.from_text('@', 300, 'IN', 'SOA', 'foo bar 1 2 3 4 5') | |
193 | self.failUnless(rrs == exrrs) | |
194 | ||
195 | def testFindRRset2(self): | |
196 | def bad(): | |
197 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
198 | rrs = z.find_rrset('@', 'loc') | |
199 | self.failUnlessRaises(KeyError, bad) | |
200 | ||
201 | def testGetRdataset1(self): | |
202 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
203 | rds = z.get_rdataset('@', 'soa') | |
204 | exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5') | |
205 | self.failUnless(rds == exrds) | |
206 | ||
207 | def testGetRdataset2(self): | |
208 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
209 | rds = z.get_rdataset('@', 'loc') | |
210 | self.failUnless(rds == None) | |
211 | ||
212 | def testGetRRset1(self): | |
213 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
214 | rrs = z.get_rrset('@', 'soa') | |
215 | exrrs = dns.rrset.from_text('@', 300, 'IN', 'SOA', 'foo bar 1 2 3 4 5') | |
216 | self.failUnless(rrs == exrrs) | |
217 | ||
218 | def testGetRRset2(self): | |
219 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
220 | rrs = z.get_rrset('@', 'loc') | |
221 | self.failUnless(rrs == None) | |
222 | ||
223 | def testReplaceRdataset1(self): | |
224 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
225 | rdataset = dns.rdataset.from_text('in', 'ns', 300, 'ns3', 'ns4') | |
226 | z.replace_rdataset('@', rdataset) | |
227 | rds = z.get_rdataset('@', 'ns') | |
228 | self.failUnless(rds is rdataset) | |
229 | ||
230 | def testReplaceRdataset2(self): | |
231 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
232 | rdataset = dns.rdataset.from_text('in', 'txt', 300, '"foo"') | |
233 | z.replace_rdataset('@', rdataset) | |
234 | rds = z.get_rdataset('@', 'txt') | |
235 | self.failUnless(rds is rdataset) | |
236 | ||
237 | def testDeleteRdataset1(self): | |
238 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
239 | z.delete_rdataset('@', 'ns') | |
240 | rds = z.get_rdataset('@', 'ns') | |
241 | self.failUnless(rds is None) | |
242 | ||
243 | def testDeleteRdataset2(self): | |
244 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
245 | z.delete_rdataset('ns1', 'a') | |
246 | node = z.get_node('ns1') | |
247 | self.failUnless(node is None) | |
248 | ||
249 | def testNodeFindRdataset1(self): | |
250 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
251 | node = z['@'] | |
252 | rds = node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) | |
253 | exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5') | |
254 | self.failUnless(rds == exrds) | |
255 | ||
256 | def testNodeFindRdataset2(self): | |
257 | def bad(): | |
258 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
259 | node = z['@'] | |
260 | rds = node.find_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC) | |
261 | self.failUnlessRaises(KeyError, bad) | |
262 | ||
263 | def testNodeGetRdataset1(self): | |
264 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
265 | node = z['@'] | |
266 | rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) | |
267 | exrds = dns.rdataset.from_text('IN', 'SOA', 300, 'foo bar 1 2 3 4 5') | |
268 | self.failUnless(rds == exrds) | |
269 | ||
270 | def testNodeGetRdataset2(self): | |
271 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
272 | node = z['@'] | |
273 | rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC) | |
274 | self.failUnless(rds == None) | |
275 | ||
276 | def testNodeDeleteRdataset1(self): | |
277 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
278 | node = z['@'] | |
279 | rds = node.delete_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) | |
280 | rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) | |
281 | self.failUnless(rds == None) | |
282 | ||
283 | def testNodeDeleteRdataset2(self): | |
284 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
285 | node = z['@'] | |
286 | rds = node.delete_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC) | |
287 | rds = node.get_rdataset(dns.rdataclass.IN, dns.rdatatype.LOC) | |
288 | self.failUnless(rds == None) | |
289 | ||
290 | def testIterateRdatasets(self): | |
291 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
292 | ns = [n for n, r in z.iterate_rdatasets('A')] | |
293 | ns.sort() | |
294 | self.failUnless(ns == [dns.name.from_text('ns1', None), | |
295 | dns.name.from_text('ns2', None)]) | |
296 | ||
297 | def testIterateAllRdatasets(self): | |
298 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
299 | ns = [n for n, r in z.iterate_rdatasets()] | |
300 | ns.sort() | |
301 | self.failUnless(ns == [dns.name.from_text('@', None), | |
302 | dns.name.from_text('@', None), | |
303 | dns.name.from_text('bar.foo', None), | |
304 | dns.name.from_text('ns1', None), | |
305 | dns.name.from_text('ns2', None)]) | |
306 | ||
307 | def testIterateRdatas(self): | |
308 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
309 | l = list(z.iterate_rdatas('A')) | |
310 | l.sort() | |
311 | exl = [(dns.name.from_text('ns1', None), | |
312 | 3600, | |
313 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
314 | '10.0.0.1')), | |
315 | (dns.name.from_text('ns2', None), | |
316 | 3600, | |
317 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
318 | '10.0.0.2'))] | |
319 | self.failUnless(l == exl) | |
320 | ||
321 | def testIterateAllRdatas(self): | |
322 | z = dns.zone.from_text(example_text, 'example.', relativize=True) | |
323 | l = list(z.iterate_rdatas()) | |
324 | l.sort() | |
325 | exl = [(dns.name.from_text('@', None), | |
326 | 3600, | |
327 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
328 | 'ns1')), | |
329 | (dns.name.from_text('@', None), | |
330 | 3600, | |
331 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, | |
332 | 'ns2')), | |
333 | (dns.name.from_text('@', None), | |
334 | 3600, | |
335 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA, | |
336 | 'foo bar 1 2 3 4 5')), | |
337 | (dns.name.from_text('bar.foo', None), | |
338 | 300, | |
339 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.MX, | |
340 | '0 blaz.foo')), | |
341 | (dns.name.from_text('ns1', None), | |
342 | 3600, | |
343 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
344 | '10.0.0.1')), | |
345 | (dns.name.from_text('ns2', None), | |
346 | 3600, | |
347 | dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, | |
348 | '10.0.0.2'))] | |
349 | self.failUnless(l == exl) | |
350 | ||
351 | def testTTLs(self): | |
352 | z = dns.zone.from_text(ttl_example_text, 'example.', relativize=True) | |
353 | n = z['@'] | |
354 | rds = n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.SOA) | |
355 | self.failUnless(rds.ttl == 3600) | |
356 | n = z['ns1'] | |
357 | rds = n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A) | |
358 | self.failUnless(rds.ttl == 86401) | |
359 | n = z['ns2'] | |
360 | rds = n.get_rdataset(dns.rdataclass.IN, dns.rdatatype.A) | |
361 | self.failUnless(rds.ttl == 694861) | |
362 | ||
363 | def testNoSOA(self): | |
364 | def bad(): | |
365 | z = dns.zone.from_text(no_soa_text, 'example.', | |
366 | relativize=True) | |
367 | self.failUnlessRaises(dns.zone.NoSOA, bad) | |
368 | ||
369 | def testNoNS(self): | |
370 | def bad(): | |
371 | z = dns.zone.from_text(no_ns_text, 'example.', | |
372 | relativize=True) | |
373 | self.failUnlessRaises(dns.zone.NoNS, bad) | |
374 | ||
375 | def testInclude(self): | |
376 | z1 = dns.zone.from_text(include_text, 'example.', relativize=True, | |
377 | allow_include=True) | |
378 | z2 = dns.zone.from_file('example', 'example.', relativize=True) | |
379 | self.failUnless(z1 == z2) | |
380 | ||
381 | def testBadDirective(self): | |
382 | def bad(): | |
383 | z = dns.zone.from_text(bad_directive_text, 'example.', | |
384 | relativize=True) | |
385 | self.failUnlessRaises(dns.exception.SyntaxError, bad) | |
386 | ||
387 | if __name__ == '__main__': | |
388 | unittest.main() |