]> git.ipfire.org Git - thirdparty/pdns.git/blame - regression-tests.ixfrdist/ixfrdisttests.py
Merge pull request #7909 from qvr/expungebyname-stats
[thirdparty/pdns.git] / regression-tests.ixfrdist / ixfrdisttests.py
CommitLineData
eb353acc
RG
1#!/usr/bin/env python2
2
3import errno
4import shutil
5import os
6import socket
7import struct
8import subprocess
9import sys
10import time
11import unittest
12import dns
13import dns.message
14
15class IXFRDistTest(unittest.TestCase):
16
17 _ixfrDistStartupDelay = 2.0
18 _ixfrDistPort = 5342
19
20 _config_template = """
21listen:
22 - '127.0.0.1:%d'
23acl:
24 - '127.0.0.0/8'
25axfr-timeout: 20
26keep: 20
27tcp-in-threads: 10
28work-dir: 'ixfrdist.dir'
29failed-soa-retry: 3
30"""
31 _config_domains = None
32 _config_params = ['_ixfrDistPort']
33
34 @classmethod
35 def startIXFRDist(cls):
36 print("Launching ixfrdist..")
37 conffile = 'ixfrdist.yml'
38 params = tuple([getattr(cls, param) for param in cls._config_params])
39 print(params)
40 with open(conffile, 'w') as conf:
41 conf.write("# Autogenerated by ixfrdisttests.py\n")
42 conf.write(cls._config_template % params)
43
44 if cls._config_domains is not None:
45 conf.write("domains:\n")
46
47 for domain, master in cls._config_domains.items():
48 conf.write(" - domain: %s\n" % (domain))
49 conf.write(" master: %s\n" % (master))
50
51 ixfrdistcmd = [os.environ['IXFRDISTBIN'], '--config', conffile, '--debug']
52
53 logFile = 'ixfrdist.log'
54 with open(logFile, 'w') as fdLog:
55 cls._ixfrdist = subprocess.Popen(ixfrdistcmd, close_fds=True,
56 stdout=fdLog, stderr=fdLog)
57
58 if 'IXFRDIST_FAST_TESTS' in os.environ:
59 delay = 0.5
60 else:
61 delay = cls._ixfrDistStartupDelay
62
63 time.sleep(delay)
64
65 if cls._ixfrdist.poll() is not None:
66 cls._ixfrdist.kill()
67 sys.exit(cls._ixfrdist.returncode)
68
69 @classmethod
70 def setUpSockets(cls):
71 print("Setting up UDP socket..")
72 cls._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
73 cls._sock.settimeout(2.0)
74 cls._sock.connect(("127.0.0.1", cls._ixfrDistPort))
75
76 @classmethod
77 def setUpClass(cls):
78 cls.startIXFRDist()
79 cls.setUpSockets()
80
81 print("Launching tests..")
82
83 @classmethod
84 def tearDownClass(cls):
85 cls.tearDownIXFRDist()
86
87 @classmethod
88 def tearDownIXFRDist(cls):
89 if 'IXFRDIST_FAST_TESTS' in os.environ:
90 delay = 0.1
91 else:
92 delay = 1.0
93
94 try:
95 if cls._ixfrdist:
96 cls._ixfrdist.terminate()
97 if cls._ixfrdist.poll() is None:
98 time.sleep(delay)
99 if cls._ixfrdist.poll() is None:
100 cls._ixfrdist.kill()
101 cls._ixfrdist.wait()
102 except OSError as e:
103 # There is a race-condition with the poll() and
104 # kill() statements, when the process is dead on the
105 # kill(), this is fine
106 if e.errno != errno.ESRCH:
107 raise
108
109 @classmethod
110 def sendUDPQuery(cls, query, timeout=2.0, decode=True, fwparams=dict()):
111 if timeout:
112 cls._sock.settimeout(timeout)
113
114 try:
115 cls._sock.send(query.to_wire())
116 data = cls._sock.recv(4096)
117 except socket.timeout:
118 data = None
119 finally:
120 if timeout:
121 cls._sock.settimeout(None)
122
123 message = None
124 if data:
125 if not decode:
126 return data
127 message = dns.message.from_wire(data, **fwparams)
128 return message
129
130 # FIXME: sendTCPQuery and sendTCPQueryMultiResponse, when they are done reading
131 # should wait for a short while on the socket to see if more data is coming
132 # and error if it does!
133 @classmethod
134 def sendTCPQuery(cls, query, timeout=2.0):
135 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
136 if timeout:
137 sock.settimeout(timeout)
138
139 sock.connect(("127.0.0.1", cls._ixfrDistPort))
140
141 try:
142 wire = query.to_wire()
143 sock.send(struct.pack("!H", len(wire)))
144 sock.send(wire)
145 data = sock.recv(2)
146 if data:
147 (datalen,) = struct.unpack("!H", data)
148 data = sock.recv(datalen)
149 except socket.timeout as e:
150 print("Timeout: %s" % (str(e)))
151 data = None
152 except socket.error as e:
153 print("Network error: %s" % (str(e)))
154 data = None
155 finally:
156 sock.close()
157
158 message = None
159 if data:
160 message = dns.message.from_wire(data)
161 return message
162
163 @classmethod
164 def sendTCPQueryMultiResponse(cls, query, timeout=2.0, count=1):
165 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
166 if timeout:
167 sock.settimeout(timeout)
168
169 sock.connect(("127.0.0.1", cls._ixfrDistPort))
170
171 try:
172 wire = query.to_wire()
173 sock.send(struct.pack("!H", len(wire)))
174 sock.send(wire)
175 except socket.timeout as e:
176 raise Exception("Timeout: %s" % (str(e)))
177 except socket.error as e:
178 raise Exception("Network error: %s" % (str(e)))
179
180 messages = []
181 for i in range(count):
182 try:
183 data = sock.recv(2)
184 if data:
185 (datalen,) = struct.unpack("!H", data)
186 data = sock.recv(datalen)
187 messages.append(dns.message.from_wire(data))
188 else:
189 break
190 except socket.timeout as e:
191 raise Exception("Timeout: %s" % (str(e)))
192 except socket.error as e:
193 raise Exception("Network error: %s" % (str(e)))
194
195 return messages
196
197 def setUp(self):
198 # This function is called before every tests
199 return
200