Merge lp:~diane-trout/py3dns/py3dns into lp:py3dns

Proposed by Diane Trout
Status: Merged
Merged at revision: 108
Proposed branch: lp:~diane-trout/py3dns/py3dns
Merge into: lp:py3dns
Diff against target: 197 lines (+153/-1)
6 files modified
.bzrignore (+3/-0)
DNS/Base.py (+5/-1)
DNS/tests/__init__.py (+13/-0)
DNS/tests/testPackers.py (+3/-0)
DNS/tests/test_base.py (+123/-0)
test.py (+6/-0)
To merge this branch: bzr merge lp:~diane-trout/py3dns/py3dns
Reviewer Review Type Date Requested Status
Scott Kitterman Approve
Review via email: mp+155048@code.launchpad.net

Commit message

Diane Trout on 2013-03-22

Add a unittest based test driver.

To make testing ParseResolvConf easier split it into two functions. The first takes a filename and opens it, and then passes it to a new function ParseResolvConfFromIterable which actually does the parsing. This makes it possible to test the parsing code without actually needing a valid file.

Added tests to check the A, AAAA, MX, SRV return values and DKIM txt records and IDN domain names

Ignore some common auto-generated python

Description of the change

I added a test driver that uses unittest to do some basic sanity checks for the DnsResolv api. I moved the one unittest style test case form py3dns/tests into DNS/tests to make it more like the dkim test code.

Undoubtibly it needs more test coverage.

What do you think of that test layout?

The next feature is should it return a byte string for names? E.g.

b'mail.ietf.org' instead of 'mail.ietf.org'?

To post a comment you must log in.
lp:~diane-trout/py3dns/py3dns updated
107. By Diane Trout

Test DKIM txt records and IDN domain names.

108. By Diane Trout

Ignore some common auto-generated python

Revision history for this message
Scott Kitterman (kitterman) wrote :

Looks good. I've just merged and pushed this as well os some other test related changes I had locally I'd found I forgot to commit. You can see in tests/test7.py the start of an idea for returning different types based on what hte application asks for that Stuart mentioned in one of his earlier replies.

Thank you for your contribution to py3dns. I look forward to more. Sorry it took a little while to get it merged.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.bzrignore'
2--- .bzrignore 1970-01-01 00:00:00 +0000
3+++ .bzrignore 2013-03-25 18:24:21 +0000
4@@ -0,0 +1,3 @@
5+__pycache__
6+*.py[co~]
7+
8
9=== modified file 'DNS/Base.py'
10--- DNS/Base.py 2012-07-22 05:58:00 +0000
11+++ DNS/Base.py 2013-03-25 18:24:21 +0000
12@@ -47,8 +47,12 @@
13
14 def ParseResolvConf(resolv_path="/etc/resolv.conf"):
15 "parses the /etc/resolv.conf file and sets defaults for name servers"
16+ with open(resolv_path, 'r') as stream:
17+ return ParseResolvConfFromIterable(stream)
18+
19+def ParseResolvConfFromIterable(lines):
20+ "parses a resolv.conf formatted stream and sets defaults for name servers"
21 global defaults
22- lines=open(resolv_path).readlines()
23 for line in lines:
24 line = line.strip()
25 if not line or line[0]==';' or line[0]=='#':
26
27=== added directory 'DNS/tests'
28=== added file 'DNS/tests/__init__.py'
29--- DNS/tests/__init__.py 1970-01-01 00:00:00 +0000
30+++ DNS/tests/__init__.py 2013-03-25 18:24:21 +0000
31@@ -0,0 +1,13 @@
32+import unittest
33+import importlib
34+
35+def test_suite():
36+ module_names = [
37+ '.testPackers',
38+ '.test_base',
39+ ]
40+ suites = []
41+ for m in module_names:
42+ module = importlib.import_module(m, 'DNS.tests')
43+ suites.append(module.test_suite())
44+ return unittest.TestSuite(suites)
45
46=== renamed file 'tests/testPackers.py' => 'DNS/tests/testPackers.py'
47--- tests/testPackers.py 2012-07-22 06:38:10 +0000
48+++ DNS/tests/testPackers.py 2013-03-25 18:24:21 +0000
49@@ -367,6 +367,9 @@
50 # def doPack(self, p):
51 # self.assertEquals(0,"NotImplemented")
52
53+def test_suite():
54+ from unittest import TestLoader
55+ return TestLoader().loadTestsFromName(__name__)
56
57 if __name__ == "__main__":
58 unittest.main()
59
60=== added file 'DNS/tests/test_base.py'
61--- DNS/tests/test_base.py 1970-01-01 00:00:00 +0000
62+++ DNS/tests/test_base.py 2013-03-25 18:24:21 +0000
63@@ -0,0 +1,123 @@
64+#!/usr/bin/python3
65+# -*- coding: utf-8 -*-
66+
67+import DNS
68+import unittest
69+
70+def assertIsByte(b):
71+ assert b >= 0
72+ assert b <= 255
73+
74+class TestBase(unittest.TestCase):
75+ def testParseResolvConf(self):
76+ # reset elments set by Base._DiscoverNameServers
77+ DNS.defaults['server'] = []
78+ del DNS.defaults['domain']
79+ self.assertEqual(len(DNS.defaults['server']), 0)
80+ resolv = ['# a comment',
81+ 'domain example.org',
82+ 'nameserver 127.0.0.1',
83+ ]
84+ DNS.ParseResolvConfFromIterable(resolv)
85+ self.assertEqual(len(DNS.defaults['server']), 1)
86+ self.assertEqual(DNS.defaults['server'][0], '127.0.0.1')
87+ self.assertEqual(DNS.defaults['domain'], 'example.org')
88+
89+ def testDnsRequestA(self):
90+ # try with asking for strings, and asking for bytes
91+ dnsobj = DNS.DnsRequest('example.org')
92+
93+ a_response = dnsobj.req(qtype='A', resulttype='text')
94+ self.assertTrue(a_response.answers)
95+ # is the result vaguely ipv4 like?
96+ self.assertEqual(a_response.answers[0]['data'].count('.'), 3)
97+
98+ ad_response = dnsobj.req(qtype='A')
99+ self.assertTrue(ad_response.answers)
100+ # is the result vaguely ipv4 like?
101+ self.assertEqual(ad_response.answers[0]['data'].count('.'), 3)
102+
103+ ab_response = dnsobj.req(qtype='A', resulttype='binary')
104+ self.assertTrue(ab_response.answers)
105+ # is the result ipv4 binary like?
106+ self.assertEqual(len(ab_response.answers[0]['data']), 4)
107+ for b in ab_response.answers[0]['data']:
108+ assertIsByte(b)
109+
110+
111+ def testDnsRequestAAAA(self):
112+ dnsobj = DNS.DnsRequest('example.org')
113+
114+ aaaa_response = dnsobj.req(qtype='AAAA', resulttype='text')
115+ self.assertTrue(aaaa_response.answers)
116+ # does the result look like an ipv6 address?
117+ self.assertTrue(':' in aaaa_response.answers[0]['data'])
118+
119+ # default is returning binary instead of text
120+ aaaad_response = dnsobj.req(qtype='AAAA')
121+ self.assertTrue(aaaad_response.answers)
122+ # does the result look like a binary ipv6 address?
123+ self.assertEqual(len(aaaad_response.answers[0]['data']) , 16)
124+ for b in aaaad_response.answers[0]['data']:
125+ assertIsByte(b)
126+
127+ aaaab_response = dnsobj.req(qtype='AAAA', resulttype='binary')
128+ self.assertTrue(aaaab_response.answers)
129+ # is it ipv6 looking?
130+ self.assertEqual(len(aaaab_response.answers[0]['data']) , 16)
131+ for b in aaaab_response.answers[0]['data']:
132+ assertIsByte(b)
133+
134+ def testDnsRequestEmptyMX(self):
135+ dnsobj = DNS.DnsRequest('example.org')
136+
137+ mx_empty_response = dnsobj.req(qtype='MX')
138+ self.assertFalse(mx_empty_response.answers)
139+
140+ def testDnsRequestMX(self):
141+ dnsobj = DNS.DnsRequest('ietf.org')
142+ mx_response = dnsobj.req(qtype='MX')
143+ self.assertTrue(mx_response.answers[0])
144+ # is hard coding a remote address a good idea?
145+ self.assertEqual(mx_response.answers[0]['data'], (0, 'mail.ietf.org'))
146+
147+ m = DNS.mxlookup('ietf.org')
148+ self.assertEqual(mx_response.answers[0]['data'], m[0])
149+
150+ def testDnsRequestSrv(self):
151+ dnsobj = DNS.Request(qtype='srv')
152+ resp = dnsobj.req('_ldap._tcp.openldap.org', resulttype='text')
153+ self.assertTrue(resp.answers)
154+ data = resp.answers[0]['data']
155+ self.assertEqual(len(data), 4)
156+ self.assertEqual(data[2], 389)
157+ self.assertTrue('openldap.org' in data[3])
158+
159+ def testDkimRequest(self):
160+ q = '20120113._domainkey.google.com'
161+ dnsobj = DNS.Request(q, qtype='txt')
162+ resp = dnsobj.req()
163+
164+ self.assertTrue(resp.answers)
165+ # should the result be bytes or a string?
166+ data = resp.answers[0]['data']
167+ self.assertTrue(isinstance(data[0], str))
168+ self.assertTrue(data[0].startswith('k='))
169+
170+ def testIDN(self):
171+ """Can we lookup an internationalized domain name?"""
172+ dnsobj = DNS.DnsRequest('xn--hxajbheg2az3al.xn--jxalpdlp')
173+ unidnsobj = DNS.DnsRequest('παράδειγμα.δοκιμή')
174+ a_resp = dnsobj.req(qtype='AAAA', resulttype='text')
175+ ua_resp = unidnsobj.req(qtype='AAAA', resulttype='text')
176+ self.assertTrue(a_resp.answers)
177+ self.assertTrue(ua_resp.answers)
178+ self.assertEqual(ua_resp.answers[0]['data'],
179+ a_resp.answers[0]['data'])
180+
181+def test_suite():
182+ from unittest import TestLoader
183+ return TestLoader().loadTestsFromName(__name__)
184+
185+if __name__ == "__main__":
186+ unittest.main()
187
188=== added file 'test.py'
189--- test.py 1970-01-01 00:00:00 +0000
190+++ test.py 2013-03-25 18:24:21 +0000
191@@ -0,0 +1,6 @@
192+import unittest
193+import doctest
194+import DNS
195+from DNS.tests import test_suite
196+
197+unittest.TextTestRunner().run(test_suite())

Subscribers

People subscribed via source and target branches

to all changes: