]> granicus.if.org Git - pdns/commitdiff
Add initial testsuite for Auth. REST API
authorChristian Hofstaedtler <christian@hofstaedtler.name>
Tue, 7 Jan 2014 16:12:54 +0000 (17:12 +0100)
committerChristian Hofstaedtler <christian@hofstaedtler.name>
Mon, 27 Jan 2014 21:28:48 +0000 (22:28 +0100)
.travis.yml
regression-tests.api/.gitignore [new file with mode: 0644]
regression-tests.api/requirements.txt [new file with mode: 0644]
regression-tests.api/runtests [new file with mode: 0755]
regression-tests.api/runtests.py [new file with mode: 0755]
regression-tests.api/test_Basics.py [new file with mode: 0644]
regression-tests.api/test_Servers.py [new file with mode: 0644]
regression-tests.api/test_Zones.py [new file with mode: 0644]
regression-tests.api/test_helper.py [new file with mode: 0644]

index 19b9cab58228a0657d026431b39c862b8fe8f652..b4d71c28f8b87ec7dd1232d5824c9a71c0a702b5 100644 (file)
@@ -6,7 +6,7 @@ before_script:
  - sudo /sbin/ip addr add 10.0.3.0/24 dev lo
  - sudo rm /etc/apt/sources.list.d/travis_ci_zeromq3-source.list
  - sudo apt-get update
- - sudo apt-get install libboost-all-dev libtolua-dev bc libcdb-dev libnet-dns-perl unbound-host ldnsutils dnsutils bind9utils libtool libcdb-dev xmlto dblatex links asciidoc ruby-json ruby-sqlite3 rubygems libcurl4-openssl-dev ruby1.9.1 socat time libzmq1 libzmq-dev pkg-config daemontools authbind liblua5.1-posix1 libopendbx1-dev libopendbx1-sqlite3
+ - sudo apt-get install libboost-all-dev libtolua-dev bc libcdb-dev libnet-dns-perl unbound-host ldnsutils dnsutils bind9utils libtool libcdb-dev xmlto dblatex links asciidoc ruby-json ruby-sqlite3 rubygems libcurl4-openssl-dev ruby1.9.1 socat time libzmq1 libzmq-dev pkg-config daemontools authbind liblua5.1-posix1 libopendbx1-dev libopendbx1-sqlite3 python-virtualenv
  - sudo update-alternatives --set ruby /usr/bin/ruby1.9.1
  - sudo touch /etc/authbind/byport/53
  - sudo chmod 755 /etc/authbind/byport/53
@@ -40,6 +40,8 @@ script:
  - ./stop.sh
  - sleep 3
  - ./clean.sh
+ - cd ../regression-tests.api
+ - ./runtests
  - cd ../regression-tests
  - touch tests/verify-dnssec-zone/allow-missing
  - ./start-test-stop 5300 bind-both
diff --git a/regression-tests.api/.gitignore b/regression-tests.api/.gitignore
new file mode 100644 (file)
index 0000000..b5d3e23
--- /dev/null
@@ -0,0 +1,7 @@
+/.venv
+/*.xml
+/*.pid
+/pdns.sqlite3
+/*.controlsocket
+/named.conf
+/*.pyc
diff --git a/regression-tests.api/requirements.txt b/regression-tests.api/requirements.txt
new file mode 100644 (file)
index 0000000..9dbd889
--- /dev/null
@@ -0,0 +1,2 @@
+requests==2.1.0
+nose==1.3.0
diff --git a/regression-tests.api/runtests b/regression-tests.api/runtests
new file mode 100755 (executable)
index 0000000..9680de8
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+if [ ! -d .venv ]; then
+       virtualenv .venv
+fi
+. .venv/bin/activate
+python -V
+pip install -r requirements.txt
+
+set -e
+set -x
+exec ./runtests.py
diff --git a/regression-tests.api/runtests.py b/regression-tests.api/runtests.py
new file mode 100755 (executable)
index 0000000..c17909d
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+#
+# Shell-script style.
+
+import os
+import subprocess
+import sys
+import tempfile
+
+SQLITE_DB = 'pdns.sqlite3'
+WEBPORT = '5556'
+WEBPASSWORD = '12345'
+
+NAMED_CONF_TPL = """
+# Generated by runtests.py
+options { directory "../regression-tests/zones/"; };
+zone "example.com" { type master; file "example.com"; };
+"""
+
+# Prepare sqlite DB with a single zone.
+subprocess.check_call(["rm", "-f", SQLITE_DB])
+subprocess.check_call(["make", "-C", "../pdns", "zone2sql"])
+
+with open('../modules/gsqlite3backend/no-dnssec.schema.sqlite3.sql', 'r') as schema_file:
+    subprocess.check_call(["sqlite3", SQLITE_DB], stdin=schema_file)
+with open('../modules/gsqlite3backend/dnssec.schema.sqlite3.sql', 'r') as schema_file:
+    subprocess.check_call(["sqlite3", SQLITE_DB], stdin=schema_file)
+
+with open('named.conf', 'w') as named_conf:
+    named_conf.write(NAMED_CONF_TPL)
+with tempfile.TemporaryFile() as tf:
+    p = subprocess.Popen(["../pdns/zone2sql", "--transactions", "--gsqlite", "--named-conf=named.conf"], stdout=tf)
+    p.communicate()
+    if p.returncode != 0:
+        raise Exception("zone2sql failed")
+    tf.seek(0, os.SEEK_SET)  # rewind
+    subprocess.check_call(["sqlite3", SQLITE_DB], stdin=tf)
+
+
+# Now run pdns and the tests.
+print "Launching pdns_server and running tests..."
+pdnsargs = ("--daemon=no --local-port=5300 --socket-dir=./ --no-shuffle --launch=gsqlite3 --gsqlite3-dnssec --send-root-referral --allow-2136-from=127.0.0.0/8 --experimental-rfc2136=yes --cache-ttl=0 --no-config --gsqlite3-database="+SQLITE_DB+" --experimental-json-interface=yes --webserver=yes --webserver-port="+WEBPORT+" --webserver-address=127.0.0.1 --query-logging  --webserver-password="+WEBPASSWORD).split()
+pdns = subprocess.Popen(["../pdns/pdns_server"] + pdnsargs, close_fds=True)
+
+rc = 0
+test_env = {}
+test_env.update(os.environ)
+test_env.update({'WEBPORT': WEBPORT, 'WEBPASSWORD': WEBPASSWORD})
+
+try:
+    print ""
+    p = subprocess.check_call(["nosetests", "--with-xunit"], env=test_env)
+except subprocess.CalledProcessError as ex:
+    rc = ex.returncode
+finally:
+    pdns.terminate()
+    pdns.wait()
+
+sys.exit(rc)
diff --git a/regression-tests.api/test_Basics.py b/regression-tests.api/test_Basics.py
new file mode 100644 (file)
index 0000000..ece0e3e
--- /dev/null
@@ -0,0 +1,10 @@
+import unittest
+import requests
+from test_helper import ApiTestCase
+
+
+class TestBasics(ApiTestCase):
+
+    def test_Unauth(self):
+        r = requests.get(self.url("/servers/localhost"))
+        self.assertEquals(r.status_code, requests.codes.unauthorized)
diff --git a/regression-tests.api/test_Servers.py b/regression-tests.api/test_Servers.py
new file mode 100644 (file)
index 0000000..561be5a
--- /dev/null
@@ -0,0 +1,34 @@
+import unittest
+import requests
+from test_helper import ApiTestCase
+
+
+class Servers(ApiTestCase):
+
+    def test_ListServers(self):
+        r = self.session.get(self.url("/servers"))
+        self.assertSuccessJson(r)
+        lst = r.json()
+        self.assertEquals(len(lst), 1)  # only localhost allowed in there
+        data = lst[0]
+        for k in ('id', 'daemon_type', 'url'):
+            self.assertIn(k, data)
+        self.assertEquals(data['id'], 'localhost')
+
+    def test_ServersLocalhost(self):
+        r = self.session.get(self.url("/servers/localhost"))
+        self.assertSuccessJson(r)
+        data = r.json()
+        for k in ('id', 'type', 'version', 'daemon_type', 'url', 'zones_url', 'config_url'):
+            self.assertIn(k, data)
+        self.assertEquals(data['id'], 'localhost')
+        self.assertEquals(data['type'], 'Server')
+        # or 'recursor' for recursors
+        self.assertEquals(data['daemon_type'], 'authoritative')
+
+    def test_ReadConfig(self):
+        r = self.session.get(self.url("/servers/localhost/config"))
+        self.assertSuccessJson(r)
+        data = dict(r.json())
+        self.assertIn('version', data)
+        print data
diff --git a/regression-tests.api/test_Zones.py b/regression-tests.api/test_Zones.py
new file mode 100644 (file)
index 0000000..046f9e2
--- /dev/null
@@ -0,0 +1,18 @@
+import unittest
+import requests
+from test_helper import ApiTestCase
+
+
+class Servers(ApiTestCase):
+
+    def test_ListZones(self):
+        r = self.session.get(self.url("/servers/localhost/zones"))
+        self.assertSuccessJson(r)
+        data = r.json()
+        self.assertIn('domains', data)
+        domains = data['domains']
+        example_com = [domain for domain in domains if domain['name'] == u'example.com']
+        self.assertEquals(len(example_com), 1)
+        example_com = example_com[0]
+        for k in ('name', 'masters', 'kind', 'last_check', 'notified_serial', 'serial'):
+            self.assertIn(k, example_com)
diff --git a/regression-tests.api/test_helper.py b/regression-tests.api/test_helper.py
new file mode 100644 (file)
index 0000000..846f33e
--- /dev/null
@@ -0,0 +1,19 @@
+import requests
+import urlparse
+import unittest
+import os
+
+class ApiTestCase(unittest.TestCase):
+
+    def setUp(self):
+        # TODO: config
+        self.server_url = 'http://127.0.0.1:%s/' % (os.environ.get('WEBPORT','5580'))
+        self.session = requests.Session()
+        self.session.auth = ('admin', os.environ.get('WEBPASSWORD','changeme'))
+
+    def url(self, relative_url):
+        return urlparse.urljoin(self.server_url, relative_url)
+
+    def assertSuccessJson(self, result):
+        result.raise_for_status()
+        self.assertEquals(result.headers['Content-Type'], 'application/json')