]> git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.api/runtests.py
rec: Add a regression test for the RPZ updates with several deltas
[thirdparty/pdns.git] / regression-tests.api / runtests.py
1 #!/usr/bin/env python
2 #
3 # Shell-script style.
4
5 from __future__ import print_function
6 import os
7 import requests
8 import shutil
9 import subprocess
10 import sys
11 import tempfile
12 import time
13
14 try:
15 raw_input
16 except NameError:
17 raw_input = input
18
19 SQLITE_DB = 'pdns.sqlite3'
20 WEBPORT = 5556
21 DNSPORT = 5300
22 APIKEY = '1234567890abcdefghijklmnopq-key'
23 WEBPASSWORD = 'something'
24 PDNSUTIL_CMD = [os.environ.get("PDNSUTIL", "../pdns/pdnsutil"), "--config-dir=."]
25
26 NAMED_CONF_TPL = """
27 # Generated by runtests.py
28 options { directory "../regression-tests/zones/"; };
29 zone "example.com" { type master; file "example.com"; };
30 zone "powerdnssec.org" { type master; file "powerdnssec.org"; };
31 zone "cryptokeys.org" { type master; file "cryptokeys.org"; };
32 """
33
34 AUTH_CONF_TPL = """
35 # Generated by runtests.py
36 launch=gsqlite3,bind
37 gsqlite3-dnssec=on
38 gsqlite3-database="""+SQLITE_DB+"""
39 module-dir=../regression-tests/modules
40 bind-config=bindbackend.conf
41 default-soa-edit=INCEPTION-INCREMENT
42 """
43
44 BINDBACKEND_CONF_TPL = """
45 # Generated by runtests.py
46 """
47
48 ACL_LIST_TPL = """
49 # Generated by runtests.py
50 # local host
51 127.0.0.1
52 ::1
53 """
54
55 REC_EXAMPLE_COM_CONF_TPL = """
56 # Generated by runtests.py
57 auth-zones+=example.com=../regression-tests/zones/example.com
58 """
59
60 REC_CONF_TPL = """
61 # Generated by runtests.py
62 auth-zones=
63 forward-zones=
64 forward-zones-recurse=
65 allow-from-file=acl.list
66 api-config-dir=%(conf_dir)s
67 include-dir=%(conf_dir)s
68 """
69
70
71 def ensure_empty_dir(name):
72 if os.path.exists(name):
73 shutil.rmtree(name)
74 os.mkdir(name)
75
76
77 def format_call_args(cmd):
78 return "$ '%s'" % ("' '".join(cmd))
79
80
81 def run_check_call(cmd, *args, **kwargs):
82 print(format_call_args(cmd))
83 subprocess.check_call(cmd, *args, **kwargs)
84
85
86 wait = ('--wait' in sys.argv)
87 if wait:
88 sys.argv.remove('--wait')
89
90 tests = [opt for opt in sys.argv if opt.startswith('--tests=')]
91 if tests:
92 for opt in tests:
93 sys.argv.remove(opt)
94 tests = [opt.split('=', 1)[1] for opt in tests]
95
96 daemon = (len(sys.argv) == 2) and sys.argv[1] or None
97 if daemon not in ('authoritative', 'recursor'):
98 print("Usage: ./runtests (authoritative|recursor)")
99 sys.exit(2)
100
101 daemon = sys.argv[1]
102
103 pdns_server = os.environ.get("PDNSSERVER", "../pdns/pdns_server")
104 pdns_recursor = os.environ.get("PDNSRECURSOR", "../pdns/recursordist/pdns_recursor")
105 common_args = [
106 "--daemon=no", "--socket-dir=.", "--config-dir=.",
107 "--local-address=127.0.0.1", "--local-port="+str(DNSPORT),
108 "--webserver=yes", "--webserver-port="+str(WEBPORT), "--webserver-address=127.0.0.1",
109 "--webserver-password="+WEBPASSWORD,
110 "--api-key="+APIKEY
111 ]
112
113 # Take sdig if it exists (recursor in travis), otherwise build it from Authoritative source.
114 sdig = os.environ.get("SDIG", "")
115 if sdig:
116 sdig = os.path.abspath(sdig)
117 if not sdig or not os.path.exists(sdig):
118 run_check_call(["make", "-C", "../pdns", "sdig"])
119 sdig = "../pdns/sdig"
120
121
122 if daemon == 'authoritative':
123 zone2sql = os.environ.get("ZONE2SQL", "../pdns/zone2sql")
124
125 # Prepare sqlite DB with some zones.
126 run_check_call(["rm", "-f", SQLITE_DB])
127 if zone2sql == "../pdns/zone2sql":
128 run_check_call(["make", "-C", "../pdns", "zone2sql"])
129
130 with open('../modules/gsqlite3backend/schema.sqlite3.sql', 'r') as schema_file:
131 run_check_call(["sqlite3", SQLITE_DB], stdin=schema_file)
132
133 with open('named.conf', 'w') as named_conf:
134 named_conf.write(NAMED_CONF_TPL)
135 with tempfile.TemporaryFile() as tf:
136 p = subprocess.Popen([zone2sql, "--transactions", "--gsqlite", "--named-conf=named.conf"], stdout=tf)
137 p.communicate()
138 if p.returncode != 0:
139 raise Exception("zone2sql failed")
140 tf.seek(0, os.SEEK_SET) # rewind
141 run_check_call(["sqlite3", SQLITE_DB], stdin=tf)
142
143 with open('bindbackend.conf', 'w') as bindbackend_conf:
144 bindbackend_conf.write(BINDBACKEND_CONF_TPL)
145
146 with open('pdns.conf', 'w') as pdns_conf:
147 pdns_conf.write(AUTH_CONF_TPL)
148
149 run_check_call(PDNSUTIL_CMD + ["secure-zone", "powerdnssec.org"])
150 servercmd = [pdns_server] + common_args + ["--no-shuffle", "--dnsupdate=yes", "--cache-ttl=0", "--api=yes"]
151
152 else:
153 conf_dir = 'rec-conf.d'
154 ensure_empty_dir(conf_dir)
155 with open('acl.list', 'w') as acl_list:
156 acl_list.write(ACL_LIST_TPL)
157 with open('recursor.conf', 'w') as recursor_conf:
158 recursor_conf.write(REC_CONF_TPL % locals())
159 with open(conf_dir+'/example.com..conf', 'w') as conf_file:
160 conf_file.write(REC_EXAMPLE_COM_CONF_TPL)
161
162 servercmd = [pdns_recursor] + common_args
163
164
165 # Now run pdns and the tests.
166 print("Launching server...")
167 print(format_call_args(servercmd))
168 serverproc = subprocess.Popen(servercmd, close_fds=True)
169
170 print("Waiting for webserver port to become available...")
171 available = False
172 for try_number in range(0, 10):
173 try:
174 res = requests.get('http://127.0.0.1:%s/' % WEBPORT)
175 available = True
176 break
177 except:
178 time.sleep(0.5)
179
180 if not available:
181 print("Webserver port not reachable after 10 tries, giving up.")
182 serverproc.terminate()
183 serverproc.wait()
184 sys.exit(2)
185
186 print("Query for example.com/A to create statistic data...")
187 run_check_call([sdig, "127.0.0.1", str(DNSPORT), "example.com", "A"])
188
189 print("Running tests...")
190 returncode = 0
191 test_env = {}
192 test_env.update(os.environ)
193 test_env.update({
194 'WEBPASSWORD': WEBPASSWORD,
195 'WEBPORT': str(WEBPORT),
196 'APIKEY': APIKEY,
197 'DAEMON': daemon,
198 'SQLITE_DB': SQLITE_DB,
199 'PDNSUTIL_CMD': ' '.join(PDNSUTIL_CMD),
200 'SDIG': sdig,
201 'DNSPORT': str(DNSPORT)
202 })
203
204 try:
205 print("")
206 run_check_call(["nosetests", "--with-xunit", "-v"] + tests, env=test_env)
207 except subprocess.CalledProcessError as ex:
208 returncode = ex.returncode
209 finally:
210 if wait:
211 print("Waiting as requested, press ENTER to stop.")
212 raw_input()
213 serverproc.terminate()
214 serverproc.wait()
215
216 sys.exit(returncode)