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