commit b920bee584cd860e90c7cae961031eb5b47c4432 Author: kudrom kudrom@riseup.net Date: Mon Aug 25 23:10:45 2014 +0200
Review of policy aware changes --- data/bouncer.yaml | 2 +- data/policy.yaml | 2 +- oonib/test/handler_helpers.py | 19 +- oonib/test/test_bouncer.py | 440 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 459 insertions(+), 4 deletions(-)
diff --git a/data/bouncer.yaml b/data/bouncer.yaml index acf2a9a..eb30cc9 100644 --- a/data/bouncer.yaml +++ b/data/bouncer.yaml @@ -8,7 +8,7 @@ collector: - {name: dns_consistency, version: '0.5'} - {name: http_requests_test, version: 0.2.3} - {name: tcp_connect, version: '0.1'} - - {name: captivep, version: '0.2'} + - {name: captiveportal, version: '0.2'} - {name: daphn3, version: '0.1'} - {name: dns_spoof, version: '0.2'} - {name: http_header_field_manipulation, version: 0.1.3} diff --git a/data/policy.yaml b/data/policy.yaml index fcc1df4..22a14e9 100644 --- a/data/policy.yaml +++ b/data/policy.yaml @@ -5,7 +5,7 @@ nettest: - {name: dns_consistency, version: 0.5} - {name: http_requests_test, version: 0.2.3} - {name: tcp_connect, version: 0.1} -- {name: captivep, version: 0.2} +- {name: captiveportal, version: 0.2} - {name: daphne3, version: 0.1} - {name: dns_spoof, version: 0.2} - {name: http_header_field_manipulation, version: 0.1.3} diff --git a/oonib/test/handler_helpers.py b/oonib/test/handler_helpers.py index 843d5c5..e6dc0ba 100644 --- a/oonib/test/handler_helpers.py +++ b/oonib/test/handler_helpers.py @@ -1,3 +1,4 @@ +import sys import os import socket import json @@ -6,6 +7,8 @@ import shutil from twisted.internet import reactor, defer from twisted.trial import unittest
+from oonib.config import config + from cyclone import httpclient
@@ -32,6 +35,7 @@ class HandlerTestCase(unittest.TestCase): app = None _port = None _listener = None + config_filename = ''
@property def port(self): @@ -39,16 +43,27 @@ class HandlerTestCase(unittest.TestCase): self._port = random_unused_port() return self._port
+ def make_dir(self, dir): + if not os.path.exists(dir): + os.mkdir(dir) + self.directories.add(dir) + def setUp(self, *args, **kw): self.filenames = set() self.directories = set() + self.old_arguments = sys.argv + if self.config_filename != '': + sys.argv = ['test_oonib', '-c', self.config_filename] + config.load() if self.app: self._listener = reactor.listenTCP(self.port, self.app) - return unittest.TestCase.setUp(self, *args, **kw) + return super(HandlerTestCase, self).setUp()
def tearDown(self): + sys.argv = self.old_arguments for filename in self.filenames: - os.remove(filename) + if os.path.exists(filename): + os.remove(filename) for dir in self.directories: shutil.rmtree(dir) if self._listener: diff --git a/oonib/test/test_bouncer.py b/oonib/test/test_bouncer.py new file mode 100644 index 0000000..6785c2f --- /dev/null +++ b/oonib/test/test_bouncer.py @@ -0,0 +1,440 @@ +# -*- encoding: utf8 -*- +import json + +from twisted.internet import defer + +from cyclone import web + +from oonib.bouncer.api import bouncerAPI +from oonib.test.handler_helpers import HandlerTestCase + +fake_bouncer_file = """ +collector: + fake_address: + policy: + input: + - {id: fake_id} + nettest: + - {name: fake_nettest, version: 1.0} + - {name: another_fake_nettest, version: 2.0} + test-helper: {fake_test_helper: 'fake_hostname'} +""" + +fake_default_collector = """ +collector: + fake_address: + policy: + input: + - {id: fake_id} + nettest: + - {name: fake_nettest, version: 1.0} + - {name: another_fake_nettest, version: 2.0} + test-helper: {fake_test_helper: 'fake_hostname'} + default_collector: + test-helper: {fake_test_helper: 'fake_hostname'} +""" + +fake_bouncer_file_multiple_collectors = """ +collector: + fake_addressA: + policy: + input: + - {id: fake_id} + nettest: + - {name: fake_nettest, version: 1.0} + - {name: another_fake_nettest, version: 2.0} + test-helper: {fake_test_helper: 'fake_hostname'} + + fake_addressB: + policy: + input: + - {id: fake_id} + nettest: + - {name: fake_nettest, version: 1.0} + - {name: another_fake_nettest, version: 2.0} + test-helper: {fake_test_helper: 'fake_hostname'} +""" + +fake_for_test_helper_request = """ +collector: + fake_addressA: + policy: + input: + - {id: fake_id} + nettest: + - {name: fake_nettest, version: 1.0} + test-helper: {fake_test_helper: 'fake_hostname', exotic_test_helper: 'fake_hostname'} + + fake_addressB: + test-helper: {fake_test_helper: 'fake_hostname'} +""" + +reports_dir = 'data/reports' +archive_dir = 'data/archive' +input_dir = 'data/inputs' +decks_dir = 'data/decks' +bouncer_filename = 'fake_bouncer_file.yaml' +fake_config_file = """ +main: + report_dir: %s + archive_dir: %s + input_dir: %s + deck_dir: %s + bouncer_file: %s + +helpers: + fake_test_helper: + attribute: value +""" % (reports_dir, archive_dir, input_dir, decks_dir, bouncer_filename) + + +class BaseTestBouncer(HandlerTestCase): + def setUp(self, *args, **kw): + self.make_dir(reports_dir) + self.make_dir(archive_dir) + self.make_dir(input_dir) + self.make_dir(decks_dir) + + self.config_filename = 'fake_config.conf' + with open(self.config_filename, 'w') as config_file: + config_file.write(fake_config_file) + + super(BaseTestBouncer, self).setUp() + self.filenames.add(bouncer_filename) + self.filenames.add(self.config_filename) + + +class TestBouncer(BaseTestBouncer): + app = web.Application(bouncerAPI, name='bouncerAPI') + + def setUp(self, *args, **kw): + with open(bouncer_filename, 'w') as bouncer_file: + bouncer_file.write(fake_bouncer_file) + super(TestBouncer, self).setUp() + + @defer.inlineCallbacks + def test_void_net_tests(self): + data = { + 'net-tests': [ + { + "test-helpers": ['fake_test_helper'], + "input-hashes": [], + "name": '', + "version": '', + }, + ] + } + + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertIn('error', response_body) + self.assertEqual('collector-not-found', response_body['error']) + + @defer.inlineCallbacks + def test_net_tests(self): + data = { + 'net-tests': [ + { + "test-helpers": [], + "input-hashes": [], + "name": 'fake_nettest', + "version": '1.0', + }, + ] + } + + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertIn('net-tests', response_body) + self.assertEqual(len(response_body['net-tests']), 1) + self.assertIn('name', response_body['net-tests'][0]) + self.assertEqual(response_body['net-tests'][0]['name'], 'fake_nettest') + self.assertIn('version', response_body['net-tests'][0]) + self.assertEqual(response_body['net-tests'][0]['version'], '1.0') + self.assertIn('input-hashes', response_body['net-tests'][0]) + self.assertEqual(len(response_body['net-tests'][0]['input-hashes']), 0) + self.assertIn('test-helpers', response_body['net-tests'][0]) + self.assertEqual(len(response_body['net-tests'][0]['test-helpers']), 0) + self.assertIn('collector', response_body['net-tests'][0]) + self.assertEqual(response_body['net-tests'][0]['collector'], 'fake_address') + + @defer.inlineCallbacks + def test_multiple_net_tests(self): + data = { + 'net-tests': [ + { + "test-helpers": [], + "input-hashes": [], + "name": 'fake_nettest', + "version": '1.0', + }, + { + "test-helpers": [], + "input-hashes": [], + "name": 'another_fake_nettest', + "version": '1.0', + } + ] + } + + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertIn('net-tests', response_body) + self.assertEqual(len(response_body['net-tests']), 2) + self.assertIn('name', response_body['net-tests'][0]) + self.assertEqual(response_body['net-tests'][0]['name'], 'fake_nettest') + self.assertIn('name', response_body['net-tests'][1]) + self.assertEqual(response_body['net-tests'][1]['name'], 'another_fake_nettest') + + @defer.inlineCallbacks + def test_invalid_net_test(self): + data = { + 'net-tests': [ + { + "test-helpers": [], + "input-hashes": [], + "name": 'invalid_nettest', + "version": '1.0', + }, + ] + } + + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertIn('error', response_body) + self.assertEqual('collector-not-found', response_body['error']) + + @defer.inlineCallbacks + def test_net_tests_with_input(self): + data = { + 'net-tests': [ + { + "test-helpers": [], + "input-hashes": ['fake_id'], + "name": 'fake_nettest', + "version": '1.0', + }, + ] + } + + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertIn('net-tests', response_body) + self.assertEqual(len(response_body['net-tests']), 1) + self.assertIn('name', response_body['net-tests'][0]) + self.assertEqual(response_body['net-tests'][0]['name'], 'fake_nettest') + self.assertIn('input-hashes', response_body['net-tests'][0]) + self.assertEqual(len(response_body['net-tests'][0]['input-hashes']), 1) + self.assertEqual(response_body['net-tests'][0]['input-hashes'][0], 'fake_id') + + @defer.inlineCallbacks + def test_net_tests_with_input(self): + data = { + 'net-tests': [ + { + "test-helpers": [], + "input-hashes": ['invalid_id'], + "name": 'fake_nettest', + "version": '1.0', + }, + ] + } + + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertIn('error', response_body) + self.assertEqual('collector-not-found', response_body['error']) + + @defer.inlineCallbacks + def test_net_tests_with_test_helper(self): + data = { + 'net-tests': [ + { + "test-helpers": ['fake_test_helper'], + "input-hashes": [], + "name": 'fake_nettest', + "version": '1.0', + }, + ] + } + + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertIn('net-tests', response_body) + self.assertEqual(len(response_body['net-tests']), 1) + self.assertIn('name', response_body['net-tests'][0]) + self.assertEqual(response_body['net-tests'][0]['name'], 'fake_nettest') + self.assertIn('test-helpers', response_body['net-tests'][0]) + self.assertEqual(len(response_body['net-tests'][0]['test-helpers']), 1) + self.assertEqual(response_body['net-tests'][0]['test-helpers']['fake_test_helper'], 'fake_hostname') + + @defer.inlineCallbacks + def test_net_tests_with_invalid_test_helper(self): + data = { + 'net-tests': [ + { + "test-helpers": ['invalid_test_helper'], + "input-hashes": [], + "name": 'fake_nettest', + "version": '1.0', + }, + ] + } + + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertIn('error', response_body) + self.assertEqual('collector-not-found', response_body['error']) + + @defer.inlineCallbacks + def test_invalid_request(self): + data = { + 'something_weird': 'nsa' + } + + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertIn('error', response_body) + self.assertEqual('test-helpers-or-net-test-key-missing', response_body['error']) + + +class TestDefaultCollector(BaseTestBouncer): + app = web.Application(bouncerAPI, name='bouncerAPI') + + def setUp(self, *args, **kw): + with open(bouncer_filename, 'w') as bouncer_file: + bouncer_file.write(fake_default_collector) + super(TestDefaultCollector, self).setUp() + + @defer.inlineCallbacks + def test_default_collector(self): + data = { + 'net-tests': [ + { + "test-helpers": [], + "input-hashes": [], + "name": 'imaginary_nettest', + "version": '1.0', + }, + ] + } + + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertIn('net-tests', response_body) + self.assertEqual(len(response_body['net-tests']), 1) + self.assertIn('name', response_body['net-tests'][0]) + self.assertEqual(response_body['net-tests'][0]['name'], 'imaginary_nettest') + self.assertIn('version', response_body['net-tests'][0]) + self.assertEqual(response_body['net-tests'][0]['version'], '1.0') + self.assertIn('input-hashes', response_body['net-tests'][0]) + self.assertEqual(len(response_body['net-tests'][0]['input-hashes']), 0) + self.assertIn('test-helpers', response_body['net-tests'][0]) + self.assertEqual(len(response_body['net-tests'][0]['test-helpers']), 0) + self.assertIn('collector', response_body['net-tests'][0]) + self.assertEqual(response_body['net-tests'][0]['collector'], 'default_collector') + + +class TestMultipleCollectors(BaseTestBouncer): + app = web.Application(bouncerAPI, name='bouncerAPI') + + def setUp(self, *args, **kw): + with open(bouncer_filename, 'w') as bouncer_file: + bouncer_file.write(fake_bouncer_file_multiple_collectors) + super(TestMultipleCollectors, self).setUp() + + @defer.inlineCallbacks + def test_multiple_collectors(self): + data = { + 'net-tests': [ + { + "test-helpers": [], + "input-hashes": [], + "name": 'fake_nettest', + "version": '1.0', + }, + ] + } + + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertIn('net-tests', response_body) + self.assertEqual(len(response_body['net-tests']), 1) + self.assertIn('name', response_body['net-tests'][0]) + self.assertEqual(response_body['net-tests'][0]['name'], 'fake_nettest') + self.assertIn('version', response_body['net-tests'][0]) + self.assertEqual(response_body['net-tests'][0]['version'], '1.0') + self.assertIn('input-hashes', response_body['net-tests'][0]) + self.assertEqual(len(response_body['net-tests'][0]['input-hashes']), 0) + self.assertIn('test-helpers', response_body['net-tests'][0]) + self.assertEqual(len(response_body['net-tests'][0]['test-helpers']), 0) + self.assertIn('collector', response_body['net-tests'][0]) + self.assertIn(response_body['net-tests'][0]['collector'], ['fake_addressA', 'fake_addressB']) + + +class TestHelperTests(BaseTestBouncer): + app = web.Application(bouncerAPI, name='bouncerAPI') + + def setUp(self, *args, **kw): + with open(bouncer_filename, 'w') as bouncer_file: + bouncer_file.write(fake_for_test_helper_request) + super(TestHelperTests, self).setUp() + + @defer.inlineCallbacks + def test_invalid_helper(self): + data = { + 'test-helpers': ['invalid_test_helper'] + } + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertIn('error', response_body) + self.assertEqual('test-helper-not-found', response_body['error']) + + @defer.inlineCallbacks + def test_multiple_collectors(self): + data = { + 'test-helpers': ['fake_test_helper'] + } + + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertEqual(len(response_body), 2) + self.assertIn('fake_test_helper', response_body) + self.assertIn('collector', response_body['fake_test_helper']) + self.assertIn(response_body['fake_test_helper']['collector'], ['fake_addressA', 'fake_addressB']) + self.assertIn('address', response_body['fake_test_helper']) + self.assertEqual('fake_hostname', response_body['fake_test_helper']['address']) + + self.assertIn('default', response_body) + self.assertIn('collector', response_body['default']) + self.assertEqual('fake_addressB', response_body['default']['collector']) + + @defer.inlineCallbacks + def test_multiple_helpers(self): + data = { + 'test-helpers': ['fake_test_helper', 'exotic_test_helper'] + } + + response = yield self.request('/bouncer', 'POST', data) + response_body = json.loads(response.body) + + self.assertEqual(len(response_body), 3) + self.assertIn('fake_test_helper', response_body) + self.assertIn('exotic_test_helper', response_body) + self.assertIn('default', response_body) + self.assertIn(response_body['fake_test_helper']['collector'], ['fake_addressA', 'fake_addressB']) + self.assertEqual(response_body['exotic_test_helper']['collector'], 'fake_addressA') + self.assertEqual('fake_addressB', response_body['default']['collector'])
tor-commits@lists.torproject.org