-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathdnsq_test.py
146 lines (114 loc) · 5.2 KB
/
dnsq_test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import socket
import time
import dns
import dns.resolver
import dnsq
from mock import Mock, patch
from nose.tools import eq_, ok_, assert_raises
def test_dns_query():
# note: we're not mocking DNS, i.e. you need to have internet connection to run this
# test. perhaps we should change it?
answer = dnsq.query_dns('mailgun.net', 'mx')
eq_(2, len(answer))
ok_("10 mxa.mailgun.org." in answer)
ok_("10 mxb.mailgun.org." in answer)
# test TXT concatenation:
with patch.object(dns.resolver.Resolver, 'query') as query:
query.reset_mock()
query.return_value = [Mock()]
query.return_value[0].to_text = Mock(return_value="\"Hello\" \"world\"")
eq_(['Helloworld'], dnsq.query_dns('mailgun.us', 'txt'))
# specify the name server
eq_(['Helloworld'], dnsq.query_dns('mailgun.us', 'txt',
name_srv='ns1.com'))
# socket error
query.side_effect = socket.error
eq_([], dnsq.query_dns('mailgun.us', 'txt'))
# test fallback to default nameserver
query.side_effect = dns.exception.Timeout
eq_([], dnsq.query_dns('mailgun.us', 'txt', name_srv='ns1.com'))
# test errors:
with patch.object(dns.resolver.Resolver, 'query') as query:
query.side_effect = dns.resolver.NoNameservers()
eq_([], dnsq.query_dns('mailgun.net', 'mx'))
query.side_effect = dns.resolver.NXDOMAIN()
eq_([], dnsq.query_dns('mailgun.net', 'mx'))
query.side_effect = dns.resolver.NoAnswer()
eq_([], dnsq.query_dns('mailgun.net', 'mx'))
def test_mx_lookup():
# query against live DNS server:
answer = dnsq.mx_hosts_for('gmail.com')[0]
ok_('google.com' in answer)
with patch.object(dnsq, '_get_default_resolver') as get_resolver:
r = Mock()
get_resolver.return_value = r
# makes a fake MX reply
def fake_mx(name):
class FakeEntry(object):
@property
def preference(self): return 1
@property
def exchange(self):
class Value(object):
def to_text(self): return name
return Value()
return FakeEntry()
# test MX timeout failure:
with patch.object(r, 'query', Mock(side_effect=dns.exception.Timeout)):
eq_([], dnsq.mx_hosts_for('host.com'))
# test querying an invalid domain:
with patch.object(r, 'query',
Mock(side_effect=dns.resolver.NXDOMAIN())):
eq_([], dnsq.mx_hosts_for('invalid-siteeeee.com'))
# test querying a domain without MX:
with patch.object(r, 'query',
Mock(side_effect=dns.resolver.NoAnswer())):
eq_(['host.com'], dnsq.mx_hosts_for('host.com'))
# test querying a domain with MX:
with patch.object(r, 'query') as query_mock:
query_mock.return_value = [fake_mx('mx.host.com.'),
fake_mx('mx2.host.com.')]
eq_(set(['mx.host.com', 'mx2.host.com']),
set(dnsq.mx_hosts_for('host.com')))
# test failure:
with patch.object(r, 'query', Mock(side_effect=Exception('bam!'))):
assert_raises(Exception, dnsq.mx_hosts_for, 'host.com')
# test dns failure
with patch.object(dnsq, '_exec_query') as exec_query:
exec_query.side_effect = dns.exception.Timeout
assert_raises(Exception, dnsq.mx_hosts_for, 'host.com')
@patch.object(dnsq, 'get_primary_nameserver', Mock(return_value='ns.com'))
@patch.object(dnsq, 'query_dns')
def test_spf_record_for(dns):
# No SPF records
dns.return_value = ["blah"]
eq_('', dnsq.spf_record_for('host.com'))
# Multiple SPF records
dns.return_value = ["v=spf1 +all", "blah", "v=spf1 -all"]
eq_('', dnsq.spf_record_for('host.com'))
# OK - one SPF record
dns.return_value = ["blah", "v=spf1 +all", "blahblah"]
eq_("v=spf1 +all", dnsq.spf_record_for('host.com'))
def test_ptr_record_for():
eq_(dnsq.ptr_record_for('127.0.0.1'), 'localhost')
# Ev: this one actually "calls the internet". Which is pretty bad from the maintenance
# perspective, but I am not sure how else to reliably cover it:
eq_(dnsq.ptr_record_for('50.56.21.178'),
socket.gethostbyaddr('50.56.21.178')[0])
# lets test caching:
with patch.object(dnsq, 'query_dns') as query_dns:
query_dns.return_value = []
eq_(None, dnsq.ptr_record_for('1.1.1.1'))
then = time.time() # measure time
eq_(None, dnsq.ptr_record_for('1.1.1.1'))
eq_(1, query_dns.call_count, "query_dns() should be called only once!" \
"... otherwise the PTR cache is not working!")
time_elapsed = (time.time() - then)
ok_(time_elapsed < 0.001,
"PTR lookup was too slow. The cache is not working?")
query_dns.side_effect = Exception('Bam!')
eq_(None, dnsq.ptr_record_for('1.1.1.2'))
@patch.object(dnsq, 'query_dns')
def test_get_primary_nameserver(query_dns):
query_dns.side_effect = [[], ['srv1.com.', 'srv2.com.']]
eq_('srv1.com', dnsq.get_primary_nameserver('tratata.ololo.com'))