From 7afba469b437980f16fac73d943a2c315dabc05e Mon Sep 17 00:00:00 2001 From: Feike Steenbergen Date: Thu, 21 May 2015 13:56:08 +0200 Subject: [PATCH 1/5] Add Tests for testing the statuspage, extend the PostgreSQL test to return a wider result. --- tests/test_postgresql.py | 4 +-- tests/test_statuspage.py | 53 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 tests/test_statuspage.py diff --git a/tests/test_postgresql.py b/tests/test_postgresql.py index 7fa5dcf7..1ee6d890 100644 --- a/tests/test_postgresql.py +++ b/tests/test_postgresql.py @@ -37,9 +37,9 @@ class MockCursor: elif sql.startswith('SELECT pg_last_xlog_replay_location()'): self.results = [(0,)] elif sql.startswith('SELECT pg_is_in_recovery()'): - self.results = [(False, )] + self.results = [(False, None, None, None, None, None, None, None, None, None)] else: - self.results = [] + self.results = [(None, None, None, None, None, None, None, None, None, None)] def fetchone(self): return self.results[0] diff --git a/tests/test_statuspage.py b/tests/test_statuspage.py new file mode 100644 index 00000000..7039ccc6 --- /dev/null +++ b/tests/test_statuspage.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import unittest + +from helpers.statuspage import StatusPage +from test_postgresql import MockConnect +from StringIO import StringIO as IO + + +class TestStatusPage(unittest.TestCase): + + def __init__(self, method_name='runTest'): + self.setUp = self.set_up + self.tearDown = self.tear_down + super(TestStatusPage, self).__init__(method_name) + + def set_up(self): + pass + + def tear_down(self): + pass + + def test_statuspage_main(self): + pass + + def test_statuspage_initialize(self): + pass + + def test_do_GET(self): + self.http_server = MockServer(('0.0.0.0', 8888), StatusPage, '/pg_master') + self.http_server = MockServer(('0.0.0.0', 8888), StatusPage, '/pg_slave') + self.http_server = MockServer(('0.0.0.0', 8888), StatusPage, '/pg_status') + self.http_server = MockServer(('0.0.0.0', 8888), StatusPage, '/not_found') + +class MockRequest(object): + + def __init__(self, path): + self.path = path + + def makefile(self, *args, **kwargs): + return IO(b"GET " + self.path) + + +class MockServer(object): + + def __init__(self, ip_port, Handler, path): + self.postgresql = MockConnect() + Handler(MockRequest(path), ip_port, self) + + +if __name__ == '__main__': + unittest.main() From 836a68115761180965ba9cf4c43df5d689d6c872 Mon Sep 17 00:00:00 2001 From: Feike Steenbergen Date: Thu, 21 May 2015 14:40:07 +0200 Subject: [PATCH 2/5] Fixed the tests, by testing also found an squashed a bug in the StatusPage on python 3. --- helpers/statuspage.py | 11 +++++--- tests/test_postgresql.py | 61 +++++++++++++++++++++++++++++++--------- tests/test_statuspage.py | 20 ++++++++----- 3 files changed, 68 insertions(+), 24 deletions(-) diff --git a/helpers/statuspage.py b/helpers/statuspage.py index 4e97f17a..cb2d1b83 100644 --- a/helpers/statuspage.py +++ b/helpers/statuspage.py @@ -33,7 +33,7 @@ class StatusPage(BaseHTTPRequestHandler): self.send_response(response) self.send_header('Content-Type', content_type) self.end_headers() - self.wfile.write(content) + self.wfile.write(content.encode('utf-8')) def pg_is_in_recovery(self): cursor = self.server.postgresql.cursor() @@ -64,9 +64,7 @@ def getHTTPServer(postgresql, http_port=8081, listen_address='0.0.0.0'): return server - -if __name__ == '__main__': - import sys +def main(): import logging logging.basicConfig(format='%(levelname)-6s %(asctime)s - %(message)s', level=logging.DEBUG) @@ -92,3 +90,8 @@ if __name__ == '__main__': http_port = int(sys.argv[2]) getHTTPServer(postgresql, http_port, '0.0.0.0').serve_forever() + + + +if __name__ == '__main__': + main() diff --git a/tests/test_postgresql.py b/tests/test_postgresql.py index 1ee6d890..e23020ae 100644 --- a/tests/test_postgresql.py +++ b/tests/test_postgresql.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + import os import psycopg2 import unittest @@ -21,25 +24,48 @@ def false(*args, **kwargs): class MockCursor: - def __init__(self): + def __init__(self, server): self.current = 0 self.results = [] + self.server = server def execute(self, sql, *params): if sql.startswith('blabla'): raise psycopg2.OperationalError() elif sql.startswith('SELECT slot_name'): - self.results = [('blabla'), ('foobar')] + self.results = ['blabla', 'foobar'] elif sql.startswith('SELECT pg_current_xlog_location()'): - self.results = [(0,)] + self.results = [(0, )] elif sql.startswith('SELECT %s - (pg_last_xlog_replay_location()'): - self.results = [(0,)] + self.results = [(0, )] elif sql.startswith('SELECT pg_last_xlog_replay_location()'): - self.results = [(0,)] + self.results = [(0, )] elif sql.startswith('SELECT pg_is_in_recovery()'): - self.results = [(False, None, None, None, None, None, None, None, None, None)] + self.results = [( + self.server.mock_values['mock_recovery'], + None, + None, + None, + None, + None, + None, + None, + None, + None, + )] else: - self.results = [(None, None, None, None, None, None, None, None, None, None)] + self.results = [( + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + )] def fetchone(self): return self.results[0] @@ -56,9 +82,10 @@ class MockConnect: def __init__(self): self.autocommit = False + self.mock_values = {'mock_recovery': False} def cursor(self): - return MockCursor() + return MockCursor(self) def close(self): if not self.autocommit: @@ -84,11 +111,17 @@ class TestPostgresql(unittest.TestCase): def set_up(self): os.system = os_system shutil.copy = nop - self.p = Postgresql({'name': 'test0', 'data_dir': 'data/test0', 'listen': '127.0.0.1, 127.0.0.2:5432', - 'connect_address': '127.0.0.2:5432', 'superuser': {'password': ''}, - 'admin': {'username': 'admin', 'password': 'admin'}, 'replication': { - 'username': 'replicator', 'password': 'rep-pass', 'network': '127.0.0.1/32'}, - 'parameters': {'foo': 'bar'}, 'recovery_conf': {'foo': 'bar'}}) + self.p = Postgresql({ + 'name': 'test0', + 'data_dir': 'data/test0', + 'listen': '127.0.0.1, 127.0.0.2:5432', + 'connect_address': '127.0.0.2:5432', + 'superuser': {'password': ''}, + 'admin': {'username': 'admin', 'password': 'admin'}, + 'replication': {'username': 'replicator', 'password': 'rep-pass', 'network': '127.0.0.1/32'}, + 'parameters': {'foo': 'bar'}, + 'recovery_conf': {'foo': 'bar'}, + }) psycopg2.connect = psycopg2_connect if not os.path.exists(self.p.data_dir): os.makedirs(self.p.data_dir) @@ -156,3 +189,5 @@ class TestPostgresql(unittest.TestCase): def test_last_operation(self): self.assertEquals(self.p.last_operation(), 0) + + diff --git a/tests/test_statuspage.py b/tests/test_statuspage.py index 7039ccc6..b7cd29d0 100644 --- a/tests/test_statuspage.py +++ b/tests/test_statuspage.py @@ -2,10 +2,15 @@ # -*- coding: utf-8 -*- import unittest +import sys from helpers.statuspage import StatusPage from test_postgresql import MockConnect -from StringIO import StringIO as IO + +if sys.hexversion >= 0x03000000: + from io import BytesIO as IO +else: + from StringIO import StringIO as IO class TestStatusPage(unittest.TestCase): @@ -28,10 +33,10 @@ class TestStatusPage(unittest.TestCase): pass def test_do_GET(self): - self.http_server = MockServer(('0.0.0.0', 8888), StatusPage, '/pg_master') - self.http_server = MockServer(('0.0.0.0', 8888), StatusPage, '/pg_slave') - self.http_server = MockServer(('0.0.0.0', 8888), StatusPage, '/pg_status') - self.http_server = MockServer(('0.0.0.0', 8888), StatusPage, '/not_found') + for mock_recovery in [True, False]: + for page in [b'GET /pg_master', b'GET /pg_slave', b'GET /pg_status', b'GET /not_found']: + self.http_server = MockServer(('0.0.0.0', 8888), StatusPage, page, mock_recovery) + class MockRequest(object): @@ -39,13 +44,14 @@ class MockRequest(object): self.path = path def makefile(self, *args, **kwargs): - return IO(b"GET " + self.path) + return IO(self.path) class MockServer(object): - def __init__(self, ip_port, Handler, path): + def __init__(self, ip_port, Handler, path, mock_recovery=False): self.postgresql = MockConnect() + self.postgresql.mock_values['mock_recovery'] = mock_recovery Handler(MockRequest(path), ip_port, self) From 7f458a84bb56545ceaf3f53e6d8a73e4ce8259fb Mon Sep 17 00:00:00 2001 From: Feike Steenbergen Date: Thu, 21 May 2015 14:53:25 +0200 Subject: [PATCH 3/5] Remove unnessecary functions from unittest, fix one bug (return tuples) in cursor. --- tests/test_postgresql.py | 2 +- tests/test_statuspage.py | 17 ----------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/tests/test_postgresql.py b/tests/test_postgresql.py index e23020ae..6e70dd89 100644 --- a/tests/test_postgresql.py +++ b/tests/test_postgresql.py @@ -33,7 +33,7 @@ class MockCursor: if sql.startswith('blabla'): raise psycopg2.OperationalError() elif sql.startswith('SELECT slot_name'): - self.results = ['blabla', 'foobar'] + self.results = [('blabla',), ('foobar',)] elif sql.startswith('SELECT pg_current_xlog_location()'): self.results = [(0, )] elif sql.startswith('SELECT %s - (pg_last_xlog_replay_location()'): diff --git a/tests/test_statuspage.py b/tests/test_statuspage.py index b7cd29d0..c63aecad 100644 --- a/tests/test_statuspage.py +++ b/tests/test_statuspage.py @@ -15,23 +15,6 @@ else: class TestStatusPage(unittest.TestCase): - def __init__(self, method_name='runTest'): - self.setUp = self.set_up - self.tearDown = self.tear_down - super(TestStatusPage, self).__init__(method_name) - - def set_up(self): - pass - - def tear_down(self): - pass - - def test_statuspage_main(self): - pass - - def test_statuspage_initialize(self): - pass - def test_do_GET(self): for mock_recovery in [True, False]: for page in [b'GET /pg_master', b'GET /pg_slave', b'GET /pg_status', b'GET /not_found']: From ebfa29b89b12f23923caf6975d20228ec3102264 Mon Sep 17 00:00:00 2001 From: Feike Steenbergen Date: Thu, 21 May 2015 14:58:24 +0200 Subject: [PATCH 4/5] Remove "testing" code from the helpers --- helpers/statuspage.py | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/helpers/statuspage.py b/helpers/statuspage.py index cb2d1b83..6fcd9462 100644 --- a/helpers/statuspage.py +++ b/helpers/statuspage.py @@ -63,35 +63,3 @@ def getHTTPServer(postgresql, http_port=8081, listen_address='0.0.0.0'): server.postgresql = postgresql return server - -def main(): - import logging - - logging.basicConfig(format='%(levelname)-6s %(asctime)s - %(message)s', level=logging.DEBUG) - logging.debug('Starting as a standalone application') - - # Create a dummy configuration to be able to use the Postgresql class - from postgresql import Postgresql - postgres_config = { - 'name': 'dummy', - 'listen': 'localhost:5432', - 'data_dir': 'nonsense', - 'replication': {'username': None, 'password': None}, - 'superuser': None, - 'admin': None, - } - aws_host_address = None - if len(sys.argv) > 1: - postgres_config['listen'] = sys.argv[1] - postgresql = Postgresql(postgres_config, aws_host_address) - - http_port = 8081 - if len(sys.argv) > 2: - http_port = int(sys.argv[2]) - - getHTTPServer(postgresql, http_port, '0.0.0.0').serve_forever() - - - -if __name__ == '__main__': - main() From f3e1c74d9b85814cd56397560c5023e7ef536caa Mon Sep 17 00:00:00 2001 From: Feike Steenbergen Date: Thu, 21 May 2015 14:59:54 +0200 Subject: [PATCH 5/5] Unittests: Remove some more unneccesary code. --- tests/test_statuspage.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/test_statuspage.py b/tests/test_statuspage.py index c63aecad..dcebd651 100644 --- a/tests/test_statuspage.py +++ b/tests/test_statuspage.py @@ -36,7 +36,3 @@ class MockServer(object): self.postgresql = MockConnect() self.postgresql.mock_values['mock_recovery'] = mock_recovery Handler(MockRequest(path), ip_port, self) - - -if __name__ == '__main__': - unittest.main()