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