Skip to content

Commit 876b114

Browse files
committed
Add search method
1 parent aac8df5 commit 876b114

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

aiodns/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,22 @@ def query(self, host: str, qtype: str, qclass: str=None) -> asyncio.Future:
9090
self._channel.query(host, qtype, cb, query_class=qclass)
9191
return fut
9292

93+
def search(self, host: str, qtype: str, qclass: str=None) -> asyncio.Future:
94+
try:
95+
qtype = query_type_map[qtype]
96+
except KeyError:
97+
raise ValueError('invalid query type: {}'.format(qtype))
98+
if qclass is not None:
99+
try:
100+
qclass = query_class_map[qclass]
101+
except KeyError:
102+
raise ValueError('invalid query class: {}'.format(qclass))
103+
104+
fut = asyncio.Future(loop=self.loop) # type: asyncio.Future
105+
cb = functools.partial(self._callback, fut)
106+
self._channel.search(host, qtype, cb, query_class=qclass)
107+
return fut
108+
93109
def gethostbyname(self, host: str, family: socket.AddressFamily) -> asyncio.Future:
94110
fut = asyncio.Future(loop=self.loop) # type: asyncio.Future
95111
cb = functools.partial(self._callback, fut)

tests.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,118 @@ async def coro(self, host, qtype, n=2):
130130
self.assertTrue(result)
131131
self.loop.run_until_complete(coro(self, 'gmail.com', 'MX'))
132132

133+
def test_search_a(self):
134+
f = self.resolver.search('google.com', 'A')
135+
result = self.loop.run_until_complete(f)
136+
self.assertTrue(result)
137+
138+
def test_search_async_await(self):
139+
async def f():
140+
return await self.resolver.search('google.com', 'A')
141+
result = self.loop.run_until_complete(f())
142+
self.assertTrue(result)
143+
144+
def test_search_a_bad(self):
145+
f = self.resolver.search('hgf8g2od29hdohid.com', 'A')
146+
try:
147+
self.loop.run_until_complete(f)
148+
except aiodns.error.DNSError as e:
149+
self.assertEqual(e.args[0], aiodns.error.ARES_ENOTFOUND)
150+
151+
def test_search_aaaa(self):
152+
f = self.resolver.search('ipv6.google.com', 'AAAA')
153+
result = self.loop.run_until_complete(f)
154+
self.assertTrue(result)
155+
156+
def test_search_cname(self):
157+
f = self.resolver.search('www.amazon.com', 'CNAME')
158+
result = self.loop.run_until_complete(f)
159+
self.assertTrue(result)
160+
161+
def test_search_mx(self):
162+
f = self.resolver.search('google.com', 'MX')
163+
result = self.loop.run_until_complete(f)
164+
self.assertTrue(result)
165+
166+
def test_search_ns(self):
167+
f = self.resolver.search('google.com', 'NS')
168+
result = self.loop.run_until_complete(f)
169+
self.assertTrue(result)
170+
171+
def test_search_txt(self):
172+
f = self.resolver.search('google.com', 'TXT')
173+
result = self.loop.run_until_complete(f)
174+
self.assertTrue(result)
175+
176+
def test_search_soa(self):
177+
f = self.resolver.search('google.com', 'SOA')
178+
result = self.loop.run_until_complete(f)
179+
self.assertTrue(result)
180+
181+
def test_search_srv(self):
182+
f = self.resolver.search('_xmpp-server._tcp.jabber.org', 'SRV')
183+
result = self.loop.run_until_complete(f)
184+
self.assertTrue(result)
185+
186+
def test_search_naptr(self):
187+
f = self.resolver.search('sip2sip.info', 'NAPTR')
188+
result = self.loop.run_until_complete(f)
189+
self.assertTrue(result)
190+
191+
def test_search_ptr(self):
192+
ip = '8.8.8.8'
193+
f = self.resolver.search(ipaddress.ip_address(ip).reverse_pointer, 'PTR')
194+
result = self.loop.run_until_complete(f)
195+
self.assertTrue(result)
196+
197+
def test_search_bad_type(self):
198+
self.assertRaises(ValueError, self.resolver.search, 'google.com', 'XXX')
199+
200+
def test_search_txt_chaos(self):
201+
self.resolver = aiodns.DNSResolver(loop=self.loop)
202+
self.resolver.nameservers = ['1.1.1.1']
203+
f = self.resolver.search('id.server', 'TXT', 'CHAOS')
204+
result = self.loop.run_until_complete(f)
205+
self.assertTrue(result)
206+
207+
def test_search_bad_class(self):
208+
self.assertRaises(ValueError, self.resolver.search, 'google.com', 'A', "INVALIDCLASS")
209+
210+
def test_search_timeout(self):
211+
self.resolver = aiodns.DNSResolver(timeout=0.1, loop=self.loop)
212+
self.resolver.nameservers = ['1.2.3.4']
213+
f = self.resolver.search('google.com', 'A')
214+
try:
215+
self.loop.run_until_complete(f)
216+
except aiodns.error.DNSError as e:
217+
self.assertEqual(e.args[0], aiodns.error.ARES_ETIMEOUT)
218+
219+
def test_search_cancel(self):
220+
f = self.resolver.search('google.com', 'A')
221+
self.resolver.cancel()
222+
try:
223+
self.loop.run_until_complete(f)
224+
except aiodns.error.DNSError as e:
225+
self.assertEqual(e.args[0], aiodns.error.ARES_ECANCELLED)
226+
227+
def test_search_future_cancel(self):
228+
f = self.resolver.search('google.com', 'A')
229+
f.cancel()
230+
async def coro():
231+
await asyncio.sleep(0.1)
232+
await f
233+
try:
234+
self.loop.run_until_complete(coro())
235+
except asyncio.CancelledError as e:
236+
self.assertTrue(e)
237+
238+
def test_search_twice(self):
239+
async def coro(self, host, qtype, n=2):
240+
for i in range(n):
241+
result = await self.resolver.search(host, qtype)
242+
self.assertTrue(result)
243+
self.loop.run_until_complete(coro(self, 'gmail.com', 'MX'))
244+
133245
def test_gethostbyname(self):
134246
f = self.resolver.gethostbyname('google.com', socket.AF_INET)
135247
result = self.loop.run_until_complete(f)

0 commit comments

Comments
 (0)