diff options
-rw-r--r-- | common/src/leap/soledad/common/tests/server_state.py | 81 | ||||
-rw-r--r-- | common/src/leap/soledad/common/tests/u1db_tests/test_https.py | 114 | ||||
-rw-r--r-- | testing/setup.py | 9 | ||||
-rw-r--r-- | testing/test_soledad/__init__.py | 5 | ||||
-rw-r--r-- | testing/test_soledad/fixture_soledad.conf (renamed from common/src/leap/soledad/common/tests/fixture_soledad.conf) | 0 | ||||
-rw-r--r-- | testing/test_soledad/u1db_tests/README (renamed from common/src/leap/soledad/common/tests/u1db_tests/README) | 2 | ||||
-rw-r--r-- | testing/test_soledad/u1db_tests/__init__.py (renamed from common/src/leap/soledad/common/tests/u1db_tests/__init__.py) | 46 | ||||
-rw-r--r-- | testing/test_soledad/u1db_tests/test_backends.py (renamed from common/src/leap/soledad/common/tests/u1db_tests/test_backends.py) | 31 | ||||
-rw-r--r-- | testing/test_soledad/u1db_tests/test_document.py (renamed from common/src/leap/soledad/common/tests/u1db_tests/test_document.py) | 2 | ||||
-rw-r--r-- | testing/test_soledad/u1db_tests/test_http_client.py (renamed from common/src/leap/soledad/common/tests/u1db_tests/test_http_client.py) | 58 | ||||
-rw-r--r-- | testing/test_soledad/u1db_tests/test_http_database.py (renamed from common/src/leap/soledad/common/tests/u1db_tests/test_http_database.py) | 24 | ||||
-rw-r--r-- | testing/test_soledad/u1db_tests/test_https.py | 105 | ||||
-rw-r--r-- | testing/test_soledad/u1db_tests/test_open.py (renamed from common/src/leap/soledad/common/tests/u1db_tests/test_open.py) | 4 | ||||
-rw-r--r-- | testing/test_soledad/u1db_tests/testing-certs/Makefile (renamed from common/src/leap/soledad/common/tests/u1db_tests/testing-certs/Makefile) | 0 | ||||
-rw-r--r-- | testing/test_soledad/u1db_tests/testing-certs/cacert.pem (renamed from common/src/leap/soledad/common/tests/u1db_tests/testing-certs/cacert.pem) | 0 | ||||
-rw-r--r-- | testing/test_soledad/u1db_tests/testing-certs/testing.cert (renamed from common/src/leap/soledad/common/tests/u1db_tests/testing-certs/testing.cert) | 0 | ||||
-rw-r--r-- | testing/test_soledad/u1db_tests/testing-certs/testing.key (renamed from common/src/leap/soledad/common/tests/u1db_tests/testing-certs/testing.key) | 0 | ||||
-rw-r--r-- | testing/test_soledad/util.py (renamed from common/src/leap/soledad/common/tests/util.py) | 13 | ||||
-rw-r--r-- | testing/tests/client/__init__.py | 0 | ||||
-rw-r--r-- | testing/tests/client/hacker_crackdown.txt (renamed from common/src/leap/soledad/common/tests/hacker_crackdown.txt) | 0 | ||||
-rw-r--r-- | testing/tests/client/test_app.py (renamed from common/src/leap/soledad/common/tests/test_soledad_app.py) | 24 | ||||
-rw-r--r-- | testing/tests/client/test_async.py (renamed from common/src/leap/soledad/common/tests/test_async.py) | 2 | ||||
-rw-r--r-- | testing/tests/client/test_aux_methods.py | 147 | ||||
-rw-r--r-- | testing/tests/client/test_crypto.py (renamed from common/src/leap/soledad/common/tests/test_crypto.py) | 2 | ||||
-rw-r--r-- | testing/tests/client/test_doc.py | 46 | ||||
-rw-r--r-- | testing/tests/client/test_http.py (renamed from common/src/leap/soledad/common/tests/test_http.py) | 6 | ||||
-rw-r--r-- | testing/tests/client/test_http_client.py (renamed from common/src/leap/soledad/common/tests/test_http_client.py) | 35 | ||||
-rw-r--r-- | testing/tests/client/test_https.py (renamed from common/src/leap/soledad/common/tests/test_https.py) | 14 | ||||
-rw-r--r-- | testing/tests/client/test_shared_db.py | 50 | ||||
-rw-r--r-- | testing/tests/client/test_signals.py (renamed from common/src/leap/soledad/common/tests/test_soledad.py) | 197 | ||||
-rw-r--r-- | testing/tests/client/test_soledad_doc.py (renamed from common/src/leap/soledad/common/tests/test_soledad_doc.py) | 6 | ||||
-rw-r--r-- | testing/tests/client/test_sqlcipher.py (renamed from common/src/leap/soledad/common/tests/test_sqlcipher.py) | 34 | ||||
-rw-r--r-- | testing/tests/client/test_sqlcipher_sync.py (renamed from common/src/leap/soledad/common/tests/test_sqlcipher_sync.py) | 23 | ||||
-rw-r--r-- | testing/tests/couch/__init__.py | 0 | ||||
-rw-r--r-- | testing/tests/couch/couchdb.ini.template (renamed from common/src/leap/soledad/common/tests/couchdb.ini.template) | 0 | ||||
-rw-r--r-- | testing/tests/couch/test_couch.py (renamed from common/src/leap/soledad/common/tests/test_couch.py) | 12 | ||||
-rw-r--r-- | testing/tests/couch/test_couch_operations_atomicity.py (renamed from common/src/leap/soledad/common/tests/test_couch_operations_atomicity.py) | 6 | ||||
-rw-r--r-- | testing/tests/server/__init__.py | 0 | ||||
-rw-r--r-- | testing/tests/server/test_server.py (renamed from common/src/leap/soledad/common/tests/test_server.py) | 11 | ||||
-rw-r--r-- | testing/tests/sync/__init__.py | 0 | ||||
-rw-r--r-- | testing/tests/sync/test_encdecpool.py (renamed from common/src/leap/soledad/common/tests/test_encdecpool.py) | 2 | ||||
-rw-r--r-- | testing/tests/sync/test_sync.py (renamed from common/src/leap/soledad/common/tests/test_sync.py) | 18 | ||||
-rw-r--r-- | testing/tests/sync/test_sync_deferred.py (renamed from common/src/leap/soledad/common/tests/test_sync_deferred.py) | 10 | ||||
-rw-r--r-- | testing/tests/sync/test_sync_mutex.py (renamed from common/src/leap/soledad/common/tests/test_sync_mutex.py) | 12 | ||||
-rw-r--r-- | testing/tests/sync/test_sync_target.py (renamed from common/src/leap/soledad/common/tests/test_sync_target.py) | 28 | ||||
-rw-r--r-- | testing/tox.ini | 21 |
46 files changed, 510 insertions, 690 deletions
diff --git a/common/src/leap/soledad/common/tests/server_state.py b/common/src/leap/soledad/common/tests/server_state.py deleted file mode 100644 index 26838f89..00000000 --- a/common/src/leap/soledad/common/tests/server_state.py +++ /dev/null @@ -1,81 +0,0 @@ -# -*- coding: utf-8 -*- -# server_state.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - - -""" -State for servers to be used in tests. -""" - - -import os -import errno -import tempfile - - -from leap.soledad.common.l2db.remote.server_state import ServerState -from leap.soledad.common.tests.util import ( - copy_sqlcipher_database_for_test, -) - - -class ServerStateForTests(ServerState): - - """Passed to a Request when it is instantiated. - - This is used to track server-side state, such as working-directory, open - databases, etc. - """ - - def __init__(self): - self._workingdir = tempfile.mkdtemp() - - def _relpath(self, relpath): - return os.path.join(self._workingdir, relpath) - - def open_database(self, path): - """Open a database at the given location.""" - from leap.soledad.client.sqlcipher import SQLCipherDatabase - return SQLCipherDatabase.open_database(path, '123', False) - - def create_database(self, path): - """Create a database at the given location.""" - from leap.soledad.client.sqlcipher import SQLCipherDatabase - return SQLCipherDatabase.open_database(path, '123', True) - - def check_database(self, path): - """Check if the database at the given location exists. - - Simply returns if it does or raises DatabaseDoesNotExist. - """ - db = self.open_database(path) - db.close() - - def ensure_database(self, path): - """Ensure database at the given location.""" - from leap.soledad.client.sqlcipher import SQLCipherDatabase - full_path = self._relpath(path) - db = SQLCipherDatabase.open_database(full_path, '123', False) - return db, db._replica_uid - - def delete_database(self, path): - """Delete database at the given location.""" - from leap.u1db.backends import sqlite_backend - full_path = self._relpath(path) - sqlite_backend.SQLiteDatabase.delete_database(full_path) - - def _copy_database(self, db): - return copy_sqlcipher_database_for_test(None, db) diff --git a/common/src/leap/soledad/common/tests/u1db_tests/test_https.py b/common/src/leap/soledad/common/tests/u1db_tests/test_https.py deleted file mode 100644 index 8a5743e7..00000000 --- a/common/src/leap/soledad/common/tests/u1db_tests/test_https.py +++ /dev/null @@ -1,114 +0,0 @@ -"""Test support for client-side https support.""" - -import os -import ssl -import sys - -#from paste import httpserver -from unittest import skip - -from leap.soledad.common.l2db.remote import http_client -#from leap.soledad.common.l2db.remote import http_target - -from leap import soledad -from leap.soledad.common.tests import u1db_tests as tests -from leap.soledad.common.tests.u1db_tests import make_oauth_http_app - - -#def https_server_def(): - #def make_server(host_port, application): - #from OpenSSL import SSL - #cert_file = os.path.join(os.path.dirname(__file__), 'testing-certs', - #'testing.cert') - #key_file = os.path.join(os.path.dirname(__file__), 'testing-certs', - #'testing.key') - #ssl_context = SSL.Context(SSL.SSLv23_METHOD) - #ssl_context.use_privatekey_file(key_file) - #ssl_context.use_certificate_chain_file(cert_file) - #srv = httpserver.WSGIServerBase(application, host_port, - #httpserver.WSGIHandler, - #ssl_context=ssl_context - #) -# - #def shutdown_request(req): - #req.shutdown() - #srv.close_request(req) -# - #srv.shutdown_request = shutdown_request - #application.base_url = "https://localhost:%s" % srv.server_address[1] - #return srv - #return make_server, "shutdown", "https" - - -#@skip("Skiping tests imported from U1DB.") -#class TestHttpSyncTargetHttpsSupport(tests.TestCaseWithServer): -# - #scenarios = [ - #('oauth_https', {'server_def': https_server_def, - #'make_app_with_state': make_oauth_http_app, - #'make_document_for_test': - #tests.make_document_for_test, - #'sync_target': oauth_https_sync_target - #}), - #] -# - #def setUp(self): - #try: - #import OpenSSL # noqa - #except ImportError: - #self.skipTest("Requires pyOpenSSL") - #self.cacert_pem = os.path.join(os.path.dirname(__file__), - #'testing-certs', 'cacert.pem') - # The default u1db http_client class for doing HTTPS only does HTTPS - # if the platform is linux. Because of this, soledad replaces that - # class with one that will do HTTPS independent of the platform. In - # order to maintain the compatibility with u1db default tests, we undo - # that replacement here. - #http_client._VerifiedHTTPSConnection = \ - #soledad.client.api.old__VerifiedHTTPSConnection - #super(TestHttpSyncTargetHttpsSupport, self).setUp() -# - #def getSyncTarget(self, host, path=None, cert_file=None): - #if self.server is None: - #self.startServer() - #return self.sync_target(self, host, path, cert_file=cert_file) -# - #def test_working(self): - #self.startServer() - #db = self.request_state._create_database('test') - #self.patch(http_client, 'CA_CERTS', self.cacert_pem) - #remote_target = self.getSyncTarget('localhost', 'test') - #remote_target.record_sync_info('other-id', 2, 'T-id') - #self.assertEqual( - #(2, 'T-id'), db._get_replica_gen_and_trans_id('other-id')) -# - #def test_cannot_verify_cert(self): - #if not sys.platform.startswith('linux'): - #self.skipTest( - #"XXX certificate verification happens on linux only for now") - #self.startServer() - # don't print expected traceback server-side - #self.server.handle_error = lambda req, cli_addr: None - #self.request_state._create_database('test') - #remote_target = self.getSyncTarget('localhost', 'test') - #try: - #remote_target.record_sync_info('other-id', 2, 'T-id') - #except ssl.SSLError, e: - #self.assertIn("certificate verify failed", str(e)) - #else: - #self.fail("certificate verification should have failed.") -# - #def test_host_mismatch(self): - #if not sys.platform.startswith('linux'): - #self.skipTest( - #"XXX certificate verification happens on linux only for now") - #self.startServer() - #self.request_state._create_database('test') - #self.patch(http_client, 'CA_CERTS', self.cacert_pem) - #remote_target = self.getSyncTarget('127.0.0.1', 'test') - #self.assertRaises( - #http_client.CertificateError, remote_target.record_sync_info, - #'other-id', 2, 'T-id') -# -# -#load_tests = tests.load_with_scenarios diff --git a/testing/setup.py b/testing/setup.py new file mode 100644 index 00000000..059b2489 --- /dev/null +++ b/testing/setup.py @@ -0,0 +1,9 @@ +from setuptools import setup +from setuptools import find_packages + + +setup( + name='test_soledad', + packages=find_packages('.'), + package_data={'': ['*.conf']} +) diff --git a/testing/test_soledad/__init__.py b/testing/test_soledad/__init__.py new file mode 100644 index 00000000..c07c8b0e --- /dev/null +++ b/testing/test_soledad/__init__.py @@ -0,0 +1,5 @@ +from test_soledad import util + +__all__ = [ + 'util', +] diff --git a/common/src/leap/soledad/common/tests/fixture_soledad.conf b/testing/test_soledad/fixture_soledad.conf index 8d8161c3..8d8161c3 100644 --- a/common/src/leap/soledad/common/tests/fixture_soledad.conf +++ b/testing/test_soledad/fixture_soledad.conf diff --git a/common/src/leap/soledad/common/tests/u1db_tests/README b/testing/test_soledad/u1db_tests/README index 0525cfdb..546dfdc9 100644 --- a/common/src/leap/soledad/common/tests/u1db_tests/README +++ b/testing/test_soledad/u1db_tests/README @@ -17,9 +17,7 @@ u1db tests depend on the following python packages: hgtools testtools discover - oauth testscenarios - dirspec paste routes cython diff --git a/common/src/leap/soledad/common/tests/u1db_tests/__init__.py b/testing/test_soledad/u1db_tests/__init__.py index 7f334b4a..ba776864 100644 --- a/common/src/leap/soledad/common/tests/u1db_tests/__init__.py +++ b/testing/test_soledad/u1db_tests/__init__.py @@ -26,7 +26,6 @@ import json from wsgiref import simple_server -from oauth import oauth from pysqlcipher import dbapi2 from StringIO import StringIO @@ -394,44 +393,6 @@ def socket_pair(): return server_sock, client_sock -# OAuth related testing - -consumer1 = oauth.OAuthConsumer('K1', 'S1') -token1 = oauth.OAuthToken('kkkk1', 'XYZ') -consumer2 = oauth.OAuthConsumer('K2', 'S2') -token2 = oauth.OAuthToken('kkkk2', 'ZYX') -token3 = oauth.OAuthToken('kkkk3', 'ZYX') - - -class TestingOAuthDataStore(oauth.OAuthDataStore): - - """In memory predefined OAuthDataStore for testing.""" - - consumers = { - consumer1.key: consumer1, - consumer2.key: consumer2, - } - - tokens = { - token1.key: token1, - token2.key: token2 - } - - def lookup_consumer(self, key): - return self.consumers.get(key) - - def lookup_token(self, token_type, token_token): - return self.tokens.get(token_token) - - def lookup_nonce(self, oauth_consumer, oauth_token, nonce): - return None - -testingOAuthStore = TestingOAuthDataStore() - -sign_meth_HMAC_SHA1 = oauth.OAuthSignatureMethod_HMAC_SHA1() -sign_meth_PLAINTEXT = oauth.OAuthSignatureMethod_PLAINTEXT() - - def load_with_scenarios(loader, standard_tests, pattern): """Load the tests in a given module. @@ -452,10 +413,3 @@ def make_http_app(state): def http_sync_target(test, path): return http_target.HTTPSyncTarget(test.getURL(path)) - - -def make_oauth_http_app(state): - app = http_app.HTTPApp(state) - application = oauth_middleware.OAuthMiddleware(app, None, prefix='/~/') - application.get_oauth_data_store = lambda: tests.testingOAuthStore - return application diff --git a/common/src/leap/soledad/common/tests/u1db_tests/test_backends.py b/testing/test_soledad/u1db_tests/test_backends.py index c0c6ea6b..10dcdff9 100644 --- a/common/src/leap/soledad/common/tests/u1db_tests/test_backends.py +++ b/testing/test_soledad/u1db_tests/test_backends.py @@ -26,9 +26,7 @@ from leap.soledad.common.l2db import errors from leap.soledad.common.l2db import vectorclock from leap.soledad.common.l2db.remote import http_database -from leap.soledad.common.tests import u1db_tests as tests -from leap.soledad.common.tests.u1db_tests import make_http_app -from leap.soledad.common.tests.u1db_tests import make_oauth_http_app +from test_soledad import u1db_tests as tests from unittest import skip @@ -51,25 +49,6 @@ def copy_http_database_for_test(test, db): return test.request_state._copy_database(db) -def make_oauth_http_database_for_test(test, replica_uid): - http_db = make_http_database_for_test(test, replica_uid, '~/test') - http_db.set_oauth_credentials(tests.consumer1.key, tests.consumer1.secret, - tests.token1.key, tests.token1.secret) - return http_db - - -def copy_oauth_http_database_for_test(test, db): - # DO NOT COPY OR REUSE THIS CODE OUTSIDE TESTS: COPYING U1DB DATABASES IS - # THE WRONG THING TO DO, THE ONLY REASON WE DO SO HERE IS TO TEST THAT WE - # CORRECTLY DETECT IT HAPPENING SO THAT WE CAN RAISE ERRORS RATHER THAN - # CORRUPT USER DATA. USE SYNC INSTEAD, OR WE WILL SEND NINJA TO YOUR - # HOUSE. - http_db = test.request_state._copy_database(db) - http_db.set_oauth_credentials(tests.consumer1.key, tests.consumer1.secret, - tests.token1.key, tests.token1.secret) - return http_db - - class TestAlternativeDocument(DocumentBase): """A (not very) alternative implementation of Document.""" @@ -82,13 +61,7 @@ class AllDatabaseTests(tests.DatabaseBaseTests, tests.TestCaseWithServer): ('http', {'make_database_for_test': make_http_database_for_test, 'copy_database_for_test': copy_http_database_for_test, 'make_document_for_test': tests.make_document_for_test, - 'make_app_with_state': make_http_app}), - ('oauth_http', {'make_database_for_test': - make_oauth_http_database_for_test, - 'copy_database_for_test': - copy_oauth_http_database_for_test, - 'make_document_for_test': tests.make_document_for_test, - 'make_app_with_state': make_oauth_http_app}) + 'make_app_with_state': tests.make_http_app}), ] def test_close(self): diff --git a/common/src/leap/soledad/common/tests/u1db_tests/test_document.py b/testing/test_soledad/u1db_tests/test_document.py index 4e8bcaf9..a7ead2d1 100644 --- a/common/src/leap/soledad/common/tests/u1db_tests/test_document.py +++ b/testing/test_soledad/u1db_tests/test_document.py @@ -18,7 +18,7 @@ from unittest import skip from leap.soledad.common.l2db import errors -from leap.soledad.common.tests import u1db_tests as tests +from test_soledad import u1db_tests as tests @skip("Skiping tests imported from U1DB.") diff --git a/common/src/leap/soledad/common/tests/u1db_tests/test_http_client.py b/testing/test_soledad/u1db_tests/test_http_client.py index 344dcb29..e9516236 100644 --- a/common/src/leap/soledad/common/tests/u1db_tests/test_http_client.py +++ b/testing/test_soledad/u1db_tests/test_http_client.py @@ -25,7 +25,7 @@ from unittest import skip from leap.soledad.common.l2db import errors from leap.soledad.common.l2db.remote import http_client -from leap.soledad.common.tests import u1db_tests as tests +from test_soledad import u1db_tests as tests @skip("Skiping tests imported from U1DB.") @@ -106,26 +106,6 @@ class TestHTTPClientBase(tests.TestCaseWithServer): else: start_response(status, [('Content-Type', 'application/json')]) return [json.dumps(response)] - elif '/oauth' in environ['PATH_INFO']: - base_url = self.getURL('').rstrip('/') - oauth_req = oauth.OAuthRequest.from_request( - http_method=environ['REQUEST_METHOD'], - http_url=base_url + environ['PATH_INFO'], - headers={'Authorization': environ['HTTP_AUTHORIZATION']}, - query_string=environ['QUERY_STRING'] - ) - oauth_server = oauth.OAuthServer(tests.testingOAuthStore) - oauth_server.add_signature_method(tests.sign_meth_HMAC_SHA1) - try: - consumer, token, params = oauth_server.verify_request( - oauth_req) - except oauth.OAuthError, e: - start_response("401 Unauthorized", - [('Content-Type', 'application/json')]) - return [json.dumps({"error": "unauthorized", - "message": e.message})] - start_response("200 OK", [('Content-Type', 'application/json')]) - return [json.dumps([environ['PATH_INFO'], token.key, params])] def make_app(self): return self.app @@ -317,44 +297,8 @@ class TestHTTPClientBase(tests.TestCaseWithServer): self.assertEqual("<Bad Request>", e.message) self.assertTrue("content-type" in e.headers) - def test_oauth(self): - cli = self.getClient() - cli.set_oauth_credentials(tests.consumer1.key, tests.consumer1.secret, - tests.token1.key, tests.token1.secret) - params = {'x': u'\xf0', 'y': "foo"} - res, headers = cli._request('GET', ['doc', 'oauth'], params) - self.assertEqual( - ['/dbase/doc/oauth', tests.token1.key, params], json.loads(res)) - - # oauth does its own internal quoting - params = {'x': u'\xf0', 'y': "foo"} - res, headers = cli._request('GET', ['doc', 'oauth', 'foo bar'], params) - self.assertEqual( - ['/dbase/doc/oauth/foo bar', tests.token1.key, params], - json.loads(res)) - - def test_oauth_ctr_creds(self): - cli = self.getClient(creds={'oauth': { - 'consumer_key': tests.consumer1.key, - 'consumer_secret': tests.consumer1.secret, - 'token_key': tests.token1.key, - 'token_secret': tests.token1.secret, - }}) - params = {'x': u'\xf0', 'y': "foo"} - res, headers = cli._request('GET', ['doc', 'oauth'], params) - self.assertEqual( - ['/dbase/doc/oauth', tests.token1.key, params], json.loads(res)) - def test_unknown_creds(self): self.assertRaises(errors.UnknownAuthMethod, self.getClient, creds={'foo': {}}) self.assertRaises(errors.UnknownAuthMethod, self.getClient, creds={}) - - def test_oauth_Unauthorized(self): - cli = self.getClient() - cli.set_oauth_credentials(tests.consumer1.key, tests.consumer1.secret, - tests.token1.key, "WRONG") - params = {'y': 'foo'} - self.assertRaises(errors.Unauthorized, cli._request, 'GET', - ['doc', 'oauth'], params) diff --git a/common/src/leap/soledad/common/tests/u1db_tests/test_http_database.py b/testing/test_soledad/u1db_tests/test_http_database.py index 001aebd4..a3ed9361 100644 --- a/common/src/leap/soledad/common/tests/u1db_tests/test_http_database.py +++ b/testing/test_soledad/u1db_tests/test_http_database.py @@ -25,8 +25,8 @@ from leap.soledad.common.l2db import errors from leap.soledad.common.l2db import Document from leap.soledad.common.l2db.remote import http_database from leap.soledad.common.l2db.remote import http_target -from leap.soledad.common.tests import u1db_tests as tests -from leap.soledad.common.tests.u1db_tests import make_http_app +from test_soledad import u1db_tests as tests +from test_soledad.u1db_tests import make_http_app @skip("Skiping tests imported from U1DB.") @@ -174,26 +174,6 @@ class TestHTTPDatabaseSimpleOperations(tests.TestCase): self.assertIsInstance(st, http_target.HTTPSyncTarget) self.assertEqual(st._url, self.db._url) - def test_get_sync_target_inherits_oauth_credentials(self): - self.db.set_oauth_credentials(tests.consumer1.key, - tests.consumer1.secret, - tests.token1.key, tests.token1.secret) - st = self.db.get_sync_target() - self.assertEqual(self.db._creds, st._creds) - - -@skip("Skiping tests imported from U1DB.") -class TestHTTPDatabaseCtrWithCreds(tests.TestCase): - - def test_ctr_with_creds(self): - db1 = http_database.HTTPDatabase('http://dbs/db', creds={'oauth': { - 'consumer_key': tests.consumer1.key, - 'consumer_secret': tests.consumer1.secret, - 'token_key': tests.token1.key, - 'token_secret': tests.token1.secret - }}) - self.assertIn('oauth', db1._creds) - @skip("Skiping tests imported from U1DB.") class TestHTTPDatabaseIntegration(tests.TestCaseWithServer): diff --git a/testing/test_soledad/u1db_tests/test_https.py b/testing/test_soledad/u1db_tests/test_https.py new file mode 100644 index 00000000..baffa723 --- /dev/null +++ b/testing/test_soledad/u1db_tests/test_https.py @@ -0,0 +1,105 @@ +"""Test support for client-side https support.""" + +import os +import ssl +import sys + +from paste import httpserver +from unittest import skip + +from leap.soledad.common.l2db.remote import http_client + +from leap import soledad +from test_soledad import u1db_tests as tests + + +def https_server_def(): + def make_server(host_port, application): + from OpenSSL import SSL + cert_file = os.path.join(os.path.dirname(__file__), 'testing-certs', + 'testing.cert') + key_file = os.path.join(os.path.dirname(__file__), 'testing-certs', + 'testing.key') + ssl_context = SSL.Context(SSL.SSLv23_METHOD) + ssl_context.use_privatekey_file(key_file) + ssl_context.use_certificate_chain_file(cert_file) + srv = httpserver.WSGIServerBase(application, host_port, + httpserver.WSGIHandler, + ssl_context=ssl_context + ) + + def shutdown_request(req): + req.shutdown() + srv.close_request(req) + + srv.shutdown_request = shutdown_request + application.base_url = "https://localhost:%s" % srv.server_address[1] + return srv + return make_server, "shutdown", "https" + + +@skip("Skiping tests imported from U1DB.") +class TestHttpSyncTargetHttpsSupport(tests.TestCaseWithServer): + + scenarios = [] + + def setUp(self): + try: + import OpenSSL # noqa + except ImportError: + self.skipTest("Requires pyOpenSSL") + self.cacert_pem = os.path.join(os.path.dirname(__file__), + 'testing-certs', 'cacert.pem') + # The default u1db http_client class for doing HTTPS only does HTTPS + # if the platform is linux. Because of this, soledad replaces that + # class with one that will do HTTPS independent of the platform. In + # order to maintain the compatibility with u1db default tests, we undo + # that replacement here. + http_client._VerifiedHTTPSConnection = \ + soledad.client.api.old__VerifiedHTTPSConnection + super(TestHttpSyncTargetHttpsSupport, self).setUp() + + def getSyncTarget(self, host, path=None, cert_file=None): + if self.server is None: + self.startServer() + return self.sync_target(self, host, path, cert_file=cert_file) + + def test_working(self): + self.startServer() + db = self.request_state._create_database('test') + self.patch(http_client, 'CA_CERTS', self.cacert_pem) + remote_target = self.getSyncTarget('localhost', 'test') + remote_target.record_sync_info('other-id', 2, 'T-id') + self.assertEqual( + (2, 'T-id'), db._get_replica_gen_and_trans_id('other-id')) + + def test_cannot_verify_cert(self): + if not sys.platform.startswith('linux'): + self.skipTest( + "XXX certificate verification happens on linux only for now") + self.startServer() + # don't print expected traceback server-side + self.server.handle_error = lambda req, cli_addr: None + self.request_state._create_database('test') + remote_target = self.getSyncTarget('localhost', 'test') + try: + remote_target.record_sync_info('other-id', 2, 'T-id') + except ssl.SSLError, e: + self.assertIn("certificate verify failed", str(e)) + else: + self.fail("certificate verification should have failed.") + + def test_host_mismatch(self): + if not sys.platform.startswith('linux'): + self.skipTest( + "XXX certificate verification happens on linux only for now") + self.startServer() + self.request_state._create_database('test') + self.patch(http_client, 'CA_CERTS', self.cacert_pem) + remote_target = self.getSyncTarget('127.0.0.1', 'test') + self.assertRaises( + http_client.CertificateError, remote_target.record_sync_info, + 'other-id', 2, 'T-id') + + +load_tests = tests.load_with_scenarios diff --git a/common/src/leap/soledad/common/tests/u1db_tests/test_open.py b/testing/test_soledad/u1db_tests/test_open.py index 2fc04e38..30d4de00 100644 --- a/common/src/leap/soledad/common/tests/u1db_tests/test_open.py +++ b/testing/test_soledad/u1db_tests/test_open.py @@ -23,9 +23,9 @@ from unittest import skip from leap.soledad.common.l2db import ( errors, open as u1db_open, ) -from leap.soledad.common.tests import u1db_tests as tests +from test_soledad import u1db_tests as tests from leap.soledad.common.l2db.backends import sqlite_backend -from leap.soledad.common.tests.u1db_tests.test_backends \ +from test_soledad.u1db_tests.test_backends \ import TestAlternativeDocument diff --git a/common/src/leap/soledad/common/tests/u1db_tests/testing-certs/Makefile b/testing/test_soledad/u1db_tests/testing-certs/Makefile index 2385e75b..2385e75b 100644 --- a/common/src/leap/soledad/common/tests/u1db_tests/testing-certs/Makefile +++ b/testing/test_soledad/u1db_tests/testing-certs/Makefile diff --git a/common/src/leap/soledad/common/tests/u1db_tests/testing-certs/cacert.pem b/testing/test_soledad/u1db_tests/testing-certs/cacert.pem index c019a730..c019a730 100644 --- a/common/src/leap/soledad/common/tests/u1db_tests/testing-certs/cacert.pem +++ b/testing/test_soledad/u1db_tests/testing-certs/cacert.pem diff --git a/common/src/leap/soledad/common/tests/u1db_tests/testing-certs/testing.cert b/testing/test_soledad/u1db_tests/testing-certs/testing.cert index 985684fb..985684fb 100644 --- a/common/src/leap/soledad/common/tests/u1db_tests/testing-certs/testing.cert +++ b/testing/test_soledad/u1db_tests/testing-certs/testing.cert diff --git a/common/src/leap/soledad/common/tests/u1db_tests/testing-certs/testing.key b/testing/test_soledad/u1db_tests/testing-certs/testing.key index d83d4920..d83d4920 100644 --- a/common/src/leap/soledad/common/tests/u1db_tests/testing-certs/testing.key +++ b/testing/test_soledad/u1db_tests/testing-certs/testing.key diff --git a/common/src/leap/soledad/common/tests/util.py b/testing/test_soledad/util.py index abe531ce..f81001b9 100644 --- a/common/src/leap/soledad/common/tests/util.py +++ b/testing/test_soledad/util.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# -*- CODING: UTF-8 -*- # util.py # Copyright (C) 2013 LEAP # @@ -70,6 +70,10 @@ def make_local_db_and_target(test): return db, st +def make_document_for_test(test, doc_id, rev, content, has_conflicts=False): + return SoledadDocument(doc_id, rev, content, has_conflicts=has_conflicts) + + def make_sqlcipher_database_for_test(test, replica_uid): db = SQLCipherDatabase( SQLCipherOptions(':memory:', PASSWORD)) @@ -97,6 +101,13 @@ def copy_sqlcipher_database_for_test(test, db): return new_db +SQLCIPHER_SCENARIOS = [ + ('sqlcipher', {'make_database_for_test': make_sqlcipher_database_for_test, + 'copy_database_for_test': copy_sqlcipher_database_for_test, + 'make_document_for_test': make_document_for_test, }), +] + + def make_soledad_app(state): return SoledadApp(state) diff --git a/testing/tests/client/__init__.py b/testing/tests/client/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/testing/tests/client/__init__.py diff --git a/common/src/leap/soledad/common/tests/hacker_crackdown.txt b/testing/tests/client/hacker_crackdown.txt index a01eb509..a01eb509 100644 --- a/common/src/leap/soledad/common/tests/hacker_crackdown.txt +++ b/testing/tests/client/hacker_crackdown.txt diff --git a/common/src/leap/soledad/common/tests/test_soledad_app.py b/testing/tests/client/test_app.py index 7f9a58d3..fef2f371 100644 --- a/common/src/leap/soledad/common/tests/test_soledad_app.py +++ b/testing/tests/client/test_app.py @@ -19,32 +19,22 @@ Test ObjectStore and Couch backend bits. """ from testscenarios import TestWithScenarios -from leap.soledad.common.tests.util import BaseSoledadTest -from leap.soledad.common.tests.util import make_soledad_document_for_test -from leap.soledad.common.tests.util import make_soledad_app -from leap.soledad.common.tests.util import make_token_soledad_app -from leap.soledad.common.tests.util import make_token_http_database_for_test -from leap.soledad.common.tests.util import copy_token_http_database_for_test -from leap.soledad.common.tests.u1db_tests import test_backends +from test_soledad.util import BaseSoledadTest +from test_soledad.util import make_soledad_document_for_test +from test_soledad.util import make_token_soledad_app +from test_soledad.util import make_token_http_database_for_test +from test_soledad.util import copy_token_http_database_for_test +from test_soledad.u1db_tests import test_backends # ----------------------------------------------------------------------------- # The following tests come from `u1db.tests.test_backends`. # ----------------------------------------------------------------------------- -LEAP_SCENARIOS = [ - ('http', { - 'make_database_for_test': test_backends.make_http_database_for_test, - 'copy_database_for_test': test_backends.copy_http_database_for_test, - 'make_document_for_test': make_soledad_document_for_test, - 'make_app_with_state': make_soledad_app}), -] - - class SoledadTests( TestWithScenarios, test_backends.AllDatabaseTests, BaseSoledadTest): - scenarios = LEAP_SCENARIOS + [ + scenarios = [ ('token_http', { 'make_database_for_test': make_token_http_database_for_test, 'copy_database_for_test': copy_token_http_database_for_test, diff --git a/common/src/leap/soledad/common/tests/test_async.py b/testing/tests/client/test_async.py index 52be4ff3..2ff70864 100644 --- a/common/src/leap/soledad/common/tests/test_async.py +++ b/testing/tests/client/test_async.py @@ -19,7 +19,7 @@ import hashlib from twisted.internet import defer -from leap.soledad.common.tests.util import BaseSoledadTest +from test_soledad.util import BaseSoledadTest from leap.soledad.client import adbapi from leap.soledad.client.sqlcipher import SQLCipherOptions diff --git a/testing/tests/client/test_aux_methods.py b/testing/tests/client/test_aux_methods.py new file mode 100644 index 00000000..c25ff8ca --- /dev/null +++ b/testing/tests/client/test_aux_methods.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +# test_soledad.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +""" +Tests for general Soledad functionality. +""" +import os + +from twisted.internet import defer + +from leap.soledad.common.errors import DatabaseAccessError +from leap.soledad.client import Soledad +from leap.soledad.client.adbapi import U1DBConnectionPool +from leap.soledad.client.secrets import PassphraseTooShort + +from test_soledad.util import BaseSoledadTest + + +class AuxMethodsTestCase(BaseSoledadTest): + + def test__init_dirs(self): + sol = self._soledad_instance(prefix='_init_dirs') + local_db_dir = os.path.dirname(sol.local_db_path) + secrets_path = os.path.dirname(sol.secrets.secrets_path) + self.assertTrue(os.path.isdir(local_db_dir)) + self.assertTrue(os.path.isdir(secrets_path)) + + def _close_soledad(results): + sol.close() + + d = sol.create_doc({}) + d.addCallback(_close_soledad) + return d + + def test__init_u1db_sqlcipher_backend(self): + sol = self._soledad_instance(prefix='_init_db') + self.assertIsInstance(sol._dbpool, U1DBConnectionPool) + self.assertTrue(os.path.isfile(sol.local_db_path)) + sol.close() + + def test__init_config_with_defaults(self): + """ + Test if configuration defaults point to the correct place. + """ + + class SoledadMock(Soledad): + + def __init__(self): + pass + + # instantiate without initializing so we just test + # _init_config_with_defaults() + sol = SoledadMock() + sol._passphrase = u'' + sol._server_url = '' + sol._init_config_with_defaults() + # assert value of local_db_path + self.assertEquals( + os.path.join(sol.default_prefix, 'soledad.u1db'), + sol.local_db_path) + + def test__init_config_from_params(self): + """ + Test if configuration is correctly read from file. + """ + sol = self._soledad_instance( + 'leap@leap.se', + passphrase=u'123', + secrets_path='value_3', + local_db_path='value_2', + server_url='value_1', + cert_file=None) + self.assertEqual( + os.path.join(self.tempdir, 'value_3'), + sol.secrets.secrets_path) + self.assertEqual( + os.path.join(self.tempdir, 'value_2'), + sol.local_db_path) + self.assertEqual('value_1', sol._server_url) + sol.close() + + @defer.inlineCallbacks + def test_change_passphrase(self): + """ + Test if passphrase can be changed. + """ + prefix = '_change_passphrase' + sol = self._soledad_instance( + 'leap@leap.se', + passphrase=u'123', + prefix=prefix, + ) + + doc1 = yield sol.create_doc({'simple': 'doc'}) + sol.change_passphrase(u'654321') + sol.close() + + with self.assertRaises(DatabaseAccessError): + self._soledad_instance( + 'leap@leap.se', + passphrase=u'123', + prefix=prefix) + + sol2 = self._soledad_instance( + 'leap@leap.se', + passphrase=u'654321', + prefix=prefix) + doc2 = yield sol2.get_doc(doc1.doc_id) + + self.assertEqual(doc1, doc2) + + sol2.close() + + def test_change_passphrase_with_short_passphrase_raises(self): + """ + Test if attempt to change passphrase passing a short passphrase + raises. + """ + sol = self._soledad_instance( + 'leap@leap.se', + passphrase=u'123') + # check that soledad complains about new passphrase length + self.assertRaises( + PassphraseTooShort, + sol.change_passphrase, u'54321') + sol.close() + + def test_get_passphrase(self): + """ + Assert passphrase getter works fine. + """ + sol = self._soledad_instance() + self.assertEqual('123', sol._passphrase) + sol.close() diff --git a/common/src/leap/soledad/common/tests/test_crypto.py b/testing/tests/client/test_crypto.py index 5ced024b..77252b46 100644 --- a/common/src/leap/soledad/common/tests/test_crypto.py +++ b/testing/tests/client/test_crypto.py @@ -23,7 +23,7 @@ import binascii from leap.soledad.client import crypto from leap.soledad.common.document import SoledadDocument -from leap.soledad.common.tests.util import BaseSoledadTest +from test_soledad.util import BaseSoledadTest from leap.soledad.common.crypto import WrongMacError from leap.soledad.common.crypto import UnknownMacMethodError from leap.soledad.common.crypto import ENC_JSON_KEY diff --git a/testing/tests/client/test_doc.py b/testing/tests/client/test_doc.py new file mode 100644 index 00000000..e158d768 --- /dev/null +++ b/testing/tests/client/test_doc.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# test_soledad_doc.py +# Copyright (C) 2013, 2014 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +""" +Test Leap backend bits: soledad docs +""" +from testscenarios import TestWithScenarios + +from test_soledad.u1db_tests import test_document +from test_soledad.util import BaseSoledadTest +from test_soledad.util import make_soledad_document_for_test + + +# ----------------------------------------------------------------------------- +# The following tests come from `u1db.tests.test_document`. +# ----------------------------------------------------------------------------- + +class TestSoledadDocument( + TestWithScenarios, + test_document.TestDocument, BaseSoledadTest): + + scenarios = ([( + 'leap', { + 'make_document_for_test': make_soledad_document_for_test})]) + + +class TestSoledadPyDocument( + TestWithScenarios, + test_document.TestPyDocument, BaseSoledadTest): + + scenarios = ([( + 'leap', { + 'make_document_for_test': make_soledad_document_for_test})]) diff --git a/common/src/leap/soledad/common/tests/test_http.py b/testing/tests/client/test_http.py index 2351748d..47df4b4a 100644 --- a/common/src/leap/soledad/common/tests/test_http.py +++ b/testing/tests/client/test_http.py @@ -18,8 +18,9 @@ Test Leap backend bits: test http database """ +from twisted.trial import unittest + from leap.soledad.client import auth -from leap.soledad.common.tests.u1db_tests import test_http_database from leap.soledad.common.l2db.remote import http_database @@ -41,8 +42,7 @@ class _HTTPDatabase(http_database.HTTPDatabase, auth.TokenBasedAuth): self, method, url_query, params) -class TestHTTPDatabaseWithCreds( - test_http_database.TestHTTPDatabaseCtrWithCreds): +class TestHTTPDatabaseWithCreds(unittest.TestCase): def test_get_sync_target_inherits_token_credentials(self): # this test was from TestDatabaseSimpleOperations but we put it here diff --git a/common/src/leap/soledad/common/tests/test_http_client.py b/testing/tests/client/test_http_client.py index d932b2b0..a107930a 100644 --- a/common/src/leap/soledad/common/tests/test_http_client.py +++ b/testing/tests/client/test_http_client.py @@ -23,7 +23,7 @@ from testscenarios import TestWithScenarios from leap.soledad.client import auth from leap.soledad.common.l2db.remote import http_client -from leap.soledad.common.tests.u1db_tests import test_http_client +from test_soledad.u1db_tests import test_http_client from leap.soledad.server.auth import SoledadTokenAuthMiddleware @@ -39,6 +39,12 @@ class TestSoledadClientBase( This class should be used to test Token auth. """ + def getClient(self, **kwds): + cli = self.getClientWithToken(**kwds) + if 'creds' not in kwds: + cli.set_token_credentials('user-uuid', 'auth-token') + return cli + def getClientWithToken(self, **kwds): self.startServer() @@ -54,24 +60,6 @@ class TestSoledadClientBase( return _HTTPClientWithToken(self.getURL('dbase'), **kwds) - def test_oauth(self): - """ - Suppress oauth test (we test for token auth here). - """ - pass - - def test_oauth_ctr_creds(self): - """ - Suppress oauth test (we test for token auth here). - """ - pass - - def test_oauth_Unauthorized(self): - """ - Suppress oauth test (we test for token auth here). - """ - pass - def app(self, environ, start_response): res = test_http_client.TestHTTPClientBase.app( self, environ, start_response) @@ -83,14 +71,17 @@ class TestSoledadClientBase( if not auth: start_response("401 Unauthorized", [('Content-Type', 'application/json')]) - return [json.dumps({"error": "unauthorized", - "message": e.message})] + return [ + json.dumps( + {"error": "unauthorized", + "message": "no token found in environment"}) + ] scheme, encoded = auth.split(None, 1) if scheme.lower() != 'token': start_response("401 Unauthorized", [('Content-Type', 'application/json')]) return [json.dumps({"error": "unauthorized", - "message": e.message})] + "message": "unknown scheme: %s" % scheme})] uuid, token = encoded.decode('base64').split(':', 1) if uuid != 'user-uuid' and token != 'auth-token': return Exception("Incorrect address or token.") diff --git a/common/src/leap/soledad/common/tests/test_https.py b/testing/tests/client/test_https.py index 8d9b8d92..caac16da 100644 --- a/common/src/leap/soledad/common/tests/test_https.py +++ b/testing/tests/client/test_https.py @@ -24,9 +24,9 @@ from testscenarios import TestWithScenarios from leap.soledad import client from leap.soledad.common.l2db.remote import http_client -from leap.soledad.common.tests.u1db_tests import test_backends -from leap.soledad.common.tests.u1db_tests import test_https -from leap.soledad.common.tests.util import ( +from test_soledad.u1db_tests import test_backends +from test_soledad.u1db_tests import test_https +from test_soledad.util import ( BaseSoledadTest, make_soledad_document_for_test, make_soledad_app, @@ -71,10 +71,10 @@ class TestSoledadHTTPSyncTargetHttpsSupport( scenarios = [ ('token_soledad_https', { - #'server_def': test_https.https_server_def, - 'make_app_with_state': make_token_soledad_app, - 'make_document_for_test': make_soledad_document_for_test, - 'sync_target': token_leap_https_sync_target}), + # 'server_def': test_https.https_server_def, + 'make_app_with_state': make_token_soledad_app, + 'make_document_for_test': make_soledad_document_for_test, + 'sync_target': token_leap_https_sync_target}), ] def setUp(self): diff --git a/testing/tests/client/test_shared_db.py b/testing/tests/client/test_shared_db.py new file mode 100644 index 00000000..aac766c2 --- /dev/null +++ b/testing/tests/client/test_shared_db.py @@ -0,0 +1,50 @@ +from leap.soledad.common.document import SoledadDocument +from leap.soledad.client.shared_db import SoledadSharedDatabase + +from test_soledad.util import BaseSoledadTest +from test_soledad.util import ADDRESS + + +class SoledadSharedDBTestCase(BaseSoledadTest): + + """ + These tests ensure the functionalities of the shared recovery database. + """ + + def setUp(self): + BaseSoledadTest.setUp(self) + self._shared_db = SoledadSharedDatabase( + 'https://provider/', ADDRESS, document_factory=SoledadDocument, + creds=None) + + def tearDown(self): + BaseSoledadTest.tearDown(self) + + def test__get_secrets_from_shared_db(self): + """ + Ensure the shared db is queried with the correct doc_id. + """ + doc_id = self._soledad.secrets._shared_db_doc_id() + self._soledad.secrets._get_secrets_from_shared_db() + self.assertTrue( + self._soledad.shared_db.get_doc.assert_called_with( + doc_id) is None, + 'Wrong doc_id when fetching recovery document.') + + def test__put_secrets_in_shared_db(self): + """ + Ensure recovery document is put into shared recover db. + """ + doc_id = self._soledad.secrets._shared_db_doc_id() + self._soledad.secrets._put_secrets_in_shared_db() + self.assertTrue( + self._soledad.shared_db.get_doc.assert_called_with( + doc_id) is None, + 'Wrong doc_id when fetching recovery document.') + self.assertTrue( + self._soledad.shared_db.put_doc.assert_called_with( + self._doc_put) is None, + 'Wrong document when putting recovery document.') + self.assertTrue( + self._doc_put.doc_id == doc_id, + 'Wrong doc_id when putting recovery document.') diff --git a/common/src/leap/soledad/common/tests/test_soledad.py b/testing/tests/client/test_signals.py index aa52a733..4e9ebfd0 100644 --- a/common/src/leap/soledad/common/tests/test_soledad.py +++ b/testing/tests/client/test_signals.py @@ -1,203 +1,12 @@ -# -*- coding: utf-8 -*- -# test_soledad.py -# Copyright (C) 2013 LEAP -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -""" -Tests for general Soledad functionality. -""" -import os - from mock import Mock - from twisted.internet import defer -from leap.common.events import catalog -from leap.soledad.common.tests.util import ( - BaseSoledadTest, - ADDRESS, -) from leap import soledad +from leap.common.events import catalog from leap.soledad.common.document import SoledadDocument -from leap.soledad.common.errors import DatabaseAccessError -from leap.soledad.client import Soledad -from leap.soledad.client.adbapi import U1DBConnectionPool -from leap.soledad.client.secrets import PassphraseTooShort -from leap.soledad.client.shared_db import SoledadSharedDatabase - - -class AuxMethodsTestCase(BaseSoledadTest): - - def test__init_dirs(self): - sol = self._soledad_instance(prefix='_init_dirs') - local_db_dir = os.path.dirname(sol.local_db_path) - secrets_path = os.path.dirname(sol.secrets.secrets_path) - self.assertTrue(os.path.isdir(local_db_dir)) - self.assertTrue(os.path.isdir(secrets_path)) - - def _close_soledad(results): - sol.close() - - d = sol.create_doc({}) - d.addCallback(_close_soledad) - return d - - def test__init_u1db_sqlcipher_backend(self): - sol = self._soledad_instance(prefix='_init_db') - self.assertIsInstance(sol._dbpool, U1DBConnectionPool) - self.assertTrue(os.path.isfile(sol.local_db_path)) - sol.close() - - def test__init_config_with_defaults(self): - """ - Test if configuration defaults point to the correct place. - """ - - class SoledadMock(Soledad): - - def __init__(self): - pass - - # instantiate without initializing so we just test - # _init_config_with_defaults() - sol = SoledadMock() - sol._passphrase = u'' - sol._server_url = '' - sol._init_config_with_defaults() - # assert value of local_db_path - self.assertEquals( - os.path.join(sol.default_prefix, 'soledad.u1db'), - sol.local_db_path) - - def test__init_config_from_params(self): - """ - Test if configuration is correctly read from file. - """ - sol = self._soledad_instance( - 'leap@leap.se', - passphrase=u'123', - secrets_path='value_3', - local_db_path='value_2', - server_url='value_1', - cert_file=None) - self.assertEqual( - os.path.join(self.tempdir, 'value_3'), - sol.secrets.secrets_path) - self.assertEqual( - os.path.join(self.tempdir, 'value_2'), - sol.local_db_path) - self.assertEqual('value_1', sol._server_url) - sol.close() - - @defer.inlineCallbacks - def test_change_passphrase(self): - """ - Test if passphrase can be changed. - """ - prefix = '_change_passphrase' - sol = self._soledad_instance( - 'leap@leap.se', - passphrase=u'123', - prefix=prefix, - ) - - doc1 = yield sol.create_doc({'simple': 'doc'}) - sol.change_passphrase(u'654321') - sol.close() - with self.assertRaises(DatabaseAccessError): - self._soledad_instance( - 'leap@leap.se', - passphrase=u'123', - prefix=prefix) - - sol2 = self._soledad_instance( - 'leap@leap.se', - passphrase=u'654321', - prefix=prefix) - doc2 = yield sol2.get_doc(doc1.doc_id) - - self.assertEqual(doc1, doc2) - - sol2.close() - - def test_change_passphrase_with_short_passphrase_raises(self): - """ - Test if attempt to change passphrase passing a short passphrase - raises. - """ - sol = self._soledad_instance( - 'leap@leap.se', - passphrase=u'123') - # check that soledad complains about new passphrase length - self.assertRaises( - PassphraseTooShort, - sol.change_passphrase, u'54321') - sol.close() - - def test_get_passphrase(self): - """ - Assert passphrase getter works fine. - """ - sol = self._soledad_instance() - self.assertEqual('123', sol._passphrase) - sol.close() - - -class SoledadSharedDBTestCase(BaseSoledadTest): - - """ - These tests ensure the functionalities of the shared recovery database. - """ - - def setUp(self): - BaseSoledadTest.setUp(self) - self._shared_db = SoledadSharedDatabase( - 'https://provider/', ADDRESS, document_factory=SoledadDocument, - creds=None) - - def tearDown(self): - BaseSoledadTest.tearDown(self) - - def test__get_secrets_from_shared_db(self): - """ - Ensure the shared db is queried with the correct doc_id. - """ - doc_id = self._soledad.secrets._shared_db_doc_id() - self._soledad.secrets._get_secrets_from_shared_db() - self.assertTrue( - self._soledad.shared_db.get_doc.assert_called_with( - doc_id) is None, - 'Wrong doc_id when fetching recovery document.') - - def test__put_secrets_in_shared_db(self): - """ - Ensure recovery document is put into shared recover db. - """ - doc_id = self._soledad.secrets._shared_db_doc_id() - self._soledad.secrets._put_secrets_in_shared_db() - self.assertTrue( - self._soledad.shared_db.get_doc.assert_called_with( - doc_id) is None, - 'Wrong doc_id when fetching recovery document.') - self.assertTrue( - self._soledad.shared_db.put_doc.assert_called_with( - self._doc_put) is None, - 'Wrong document when putting recovery document.') - self.assertTrue( - self._doc_put.doc_id == doc_id, - 'Wrong doc_id when putting recovery document.') +from test_soledad.util import ADDRESS +from test_soledad.util import BaseSoledadTest class SoledadSignalingTestCase(BaseSoledadTest): diff --git a/common/src/leap/soledad/common/tests/test_soledad_doc.py b/testing/tests/client/test_soledad_doc.py index df9fd09e..e158d768 100644 --- a/common/src/leap/soledad/common/tests/test_soledad_doc.py +++ b/testing/tests/client/test_soledad_doc.py @@ -19,9 +19,9 @@ Test Leap backend bits: soledad docs """ from testscenarios import TestWithScenarios -from leap.soledad.common.tests.u1db_tests import test_document -from leap.soledad.common.tests.util import BaseSoledadTest -from leap.soledad.common.tests.util import make_soledad_document_for_test +from test_soledad.u1db_tests import test_document +from test_soledad.util import BaseSoledadTest +from test_soledad.util import make_soledad_document_for_test # ----------------------------------------------------------------------------- diff --git a/common/src/leap/soledad/common/tests/test_sqlcipher.py b/testing/tests/client/test_sqlcipher.py index 2bcdf0fb..11472d46 100644 --- a/common/src/leap/soledad/common/tests/test_sqlcipher.py +++ b/testing/tests/client/test_sqlcipher.py @@ -29,7 +29,8 @@ from testscenarios import TestWithScenarios # l2db stuff. from leap.soledad.common.l2db import errors from leap.soledad.common.l2db import query_parser -from leap.soledad.common.l2db.backends.sqlite_backend import SQLitePartialExpandDatabase +from leap.soledad.common.l2db.backends.sqlite_backend \ + import SQLitePartialExpandDatabase # soledad stuff. from leap.soledad.common import soledad_assert @@ -39,13 +40,12 @@ from leap.soledad.client.sqlcipher import SQLCipherOptions from leap.soledad.client.sqlcipher import DatabaseIsNotEncrypted # u1db tests stuff. -from leap.soledad.common.tests import u1db_tests as tests -from leap.soledad.common.tests.u1db_tests import test_backends -from leap.soledad.common.tests.u1db_tests import test_open -from leap.soledad.common.tests.util import make_sqlcipher_database_for_test -from leap.soledad.common.tests.util import copy_sqlcipher_database_for_test -from leap.soledad.common.tests.util import PASSWORD -from leap.soledad.common.tests.util import BaseSoledadTest +from test_soledad import u1db_tests as tests +from test_soledad.u1db_tests import test_backends +from test_soledad.u1db_tests import test_open +from test_soledad.util import SQLCIPHER_SCENARIOS +from test_soledad.util import PASSWORD +from test_soledad.util import BaseSoledadTest def sqlcipher_open(path, passphrase, create=True, document_factory=None): @@ -73,17 +73,6 @@ class TestSQLCipherBackendImpl(tests.TestCase): # The following tests come from `u1db.tests.test_backends`. # ----------------------------------------------------------------------------- -def make_document_for_test(test, doc_id, rev, content, has_conflicts=False): - return SoledadDocument(doc_id, rev, content, has_conflicts=has_conflicts) - - -SQLCIPHER_SCENARIOS = [ - ('sqlcipher', {'make_database_for_test': make_sqlcipher_database_for_test, - 'copy_database_for_test': copy_sqlcipher_database_for_test, - 'make_document_for_test': make_document_for_test, }), -] - - class SQLCipherTests(TestWithScenarios, test_backends.AllDatabaseTests): scenarios = SQLCIPHER_SCENARIOS @@ -175,11 +164,6 @@ class TestSQLCipherDatabase(tests.TestCase): db1.close() -class TestAlternativeDocument(SoledadDocument): - - """A (not very) alternative implementation of Document.""" - - class TestSQLCipherPartialExpandDatabase(tests.TestCase): """ Tests from u1db.tests.test_sqlite_backend.TestSQLitePartialExpandDatabase. @@ -607,7 +591,7 @@ class SQLCipherOpen(test_open.TestU1DBOpen): def test_open_with_factory(self): db = sqlcipher_open(self.db_path, PASSWORD, create=True, - document_factory=TestAlternativeDocument) + document_factory=SoledadDocument) self.addCleanup(db.close) doc = db.create_doc({}) self.assertTrue(isinstance(doc, SoledadDocument)) diff --git a/common/src/leap/soledad/common/tests/test_sqlcipher_sync.py b/testing/tests/client/test_sqlcipher_sync.py index 42cfa6b7..3cbefc8b 100644 --- a/common/src/leap/soledad/common/tests/test_sqlcipher_sync.py +++ b/testing/tests/client/test_sqlcipher_sync.py @@ -31,13 +31,11 @@ from leap.soledad.common.crypto import ENC_SCHEME_KEY from leap.soledad.client.crypto import decrypt_doc_dict from leap.soledad.client.http_target import SoledadHTTPSyncTarget -from leap.soledad.common.tests import u1db_tests as tests -from leap.soledad.common.tests.test_sqlcipher import SQLCIPHER_SCENARIOS -from leap.soledad.common.tests.util import make_soledad_app -from leap.soledad.common.tests.test_sync_target import \ - SoledadDatabaseSyncTargetTests -from leap.soledad.common.tests.util import soledad_sync_target -from leap.soledad.common.tests.util import BaseSoledadTest +from test_soledad import u1db_tests as tests +from test_soledad.util import SQLCIPHER_SCENARIOS +from test_soledad.util import make_soledad_app +from test_soledad.util import soledad_sync_target +from test_soledad.util import BaseSoledadTest # ----------------------------------------------------------------------------- @@ -730,14 +728,3 @@ target_scenarios = [ 'make_app_with_state': make_soledad_app, 'do_sync': sync_via_synchronizer_and_soledad}), ] - - -class SQLCipherSyncTargetTests(SoledadDatabaseSyncTargetTests): - - # TODO: implement _set_trace_hook(_shallow) in SoledadHTTPSyncTarget so - # skipped tests can be succesfully executed. - - scenarios = (tests.multiply_scenarios(SQLCIPHER_SCENARIOS, - target_scenarios)) - - whitebox = False diff --git a/testing/tests/couch/__init__.py b/testing/tests/couch/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/testing/tests/couch/__init__.py diff --git a/common/src/leap/soledad/common/tests/couchdb.ini.template b/testing/tests/couch/couchdb.ini.template index 174d9d86..174d9d86 100644 --- a/common/src/leap/soledad/common/tests/couchdb.ini.template +++ b/testing/tests/couch/couchdb.ini.template diff --git a/common/src/leap/soledad/common/tests/test_couch.py b/testing/tests/couch/test_couch.py index eefefc5d..94c6ca92 100644 --- a/common/src/leap/soledad/common/tests/test_couch.py +++ b/testing/tests/couch/test_couch.py @@ -36,13 +36,13 @@ from leap.soledad.common import couch from leap.soledad.common.document import ServerDocument from leap.soledad.common.couch import errors -from leap.soledad.common.tests import u1db_tests as tests -from leap.soledad.common.tests.util import CouchDBTestCase -from leap.soledad.common.tests.util import make_local_db_and_target -from leap.soledad.common.tests.util import sync_via_synchronizer +from test_soledad import u1db_tests as tests +from test_soledad.util import CouchDBTestCase +from test_soledad.util import make_local_db_and_target +from test_soledad.util import sync_via_synchronizer -from leap.soledad.common.tests.u1db_tests import test_backends -from leap.soledad.common.tests.u1db_tests import DatabaseBaseTests +from test_soledad.u1db_tests import test_backends +from test_soledad.u1db_tests import DatabaseBaseTests # ----------------------------------------------------------------------------- diff --git a/common/src/leap/soledad/common/tests/test_couch_operations_atomicity.py b/testing/tests/couch/test_couch_operations_atomicity.py index 8cd3ae08..aec9c6cf 100644 --- a/common/src/leap/soledad/common/tests/test_couch_operations_atomicity.py +++ b/testing/tests/couch/test_couch_operations_atomicity.py @@ -29,13 +29,13 @@ from leap.soledad.client import Soledad from leap.soledad.common.couch.state import CouchServerState from leap.soledad.common.couch import CouchDatabase -from leap.soledad.common.tests.util import ( +from test_soledad.util import ( make_token_soledad_app, make_soledad_document_for_test, soledad_sync_target, ) -from leap.soledad.common.tests.test_couch import CouchDBTestCase -from leap.soledad.common.tests.u1db_tests import TestCaseWithServer +from test_soledad.util import CouchDBTestCase +from test_soledad.u1db_tests import TestCaseWithServer REPEAT_TIMES = 20 diff --git a/testing/tests/server/__init__.py b/testing/tests/server/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/testing/tests/server/__init__.py diff --git a/common/src/leap/soledad/common/tests/test_server.py b/testing/tests/server/test_server.py index 357027e9..b99d1939 100644 --- a/common/src/leap/soledad/common/tests/test_server.py +++ b/testing/tests/server/test_server.py @@ -21,7 +21,6 @@ import binascii import mock import os import tempfile -import time from hashlib import sha512 from pkg_resources import resource_filename @@ -33,9 +32,9 @@ from twisted.trial import unittest from leap.soledad.common.couch.state import CouchServerState from leap.soledad.common.couch import CouchDatabase -from leap.soledad.common.tests.u1db_tests import TestCaseWithServer -from leap.soledad.common.tests.test_couch import CouchDBTestCase -from leap.soledad.common.tests.util import ( +from test_soledad.u1db_tests import TestCaseWithServer +from test_soledad.util import CouchDBTestCase +from test_soledad.util import ( make_token_soledad_app, make_soledad_document_for_test, soledad_sync_target, @@ -507,7 +506,7 @@ class ConfigurationParsingTest(unittest.TestCase): def test_security_values_configuration(self): # given - config_path = resource_filename('leap.soledad.common.tests', + config_path = resource_filename('test_soledad', 'fixture_soledad.conf') # when config = load_configuration(config_path) @@ -521,7 +520,7 @@ class ConfigurationParsingTest(unittest.TestCase): def test_server_values_configuration(self): # given - config_path = resource_filename('leap.soledad.common.tests', + config_path = resource_filename('test_soledad', 'fixture_soledad.conf') # when config = load_configuration(config_path) diff --git a/testing/tests/sync/__init__.py b/testing/tests/sync/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/testing/tests/sync/__init__.py diff --git a/common/src/leap/soledad/common/tests/test_encdecpool.py b/testing/tests/sync/test_encdecpool.py index c626561d..82e99a47 100644 --- a/common/src/leap/soledad/common/tests/test_encdecpool.py +++ b/testing/tests/sync/test_encdecpool.py @@ -27,7 +27,7 @@ from leap.soledad.client.encdecpool import SyncEncrypterPool from leap.soledad.client.encdecpool import SyncDecrypterPool from leap.soledad.common.document import SoledadDocument -from leap.soledad.common.tests.util import BaseSoledadTest +from test_soledad.util import BaseSoledadTest from twisted.internet import defer from twisted.test.proto_helpers import MemoryReactorClock diff --git a/common/src/leap/soledad/common/tests/test_sync.py b/testing/tests/sync/test_sync.py index cc18d387..095884ce 100644 --- a/common/src/leap/soledad/common/tests/test_sync.py +++ b/testing/tests/sync/test_sync.py @@ -27,15 +27,15 @@ from testscenarios import TestWithScenarios from leap.soledad.common import couch from leap.soledad.client import sync -from leap.soledad.common.tests import u1db_tests as tests -from leap.soledad.common.tests.u1db_tests import TestCaseWithServer -from leap.soledad.common.tests.u1db_tests import simple_doc -from leap.soledad.common.tests.util import make_token_soledad_app -from leap.soledad.common.tests.util import make_soledad_document_for_test -from leap.soledad.common.tests.util import soledad_sync_target -from leap.soledad.common.tests.util import BaseSoledadTest -from leap.soledad.common.tests.util import SoledadWithCouchServerMixin -from leap.soledad.common.tests.test_couch import CouchDBTestCase +from test_soledad import u1db_tests as tests +from test_soledad.u1db_tests import TestCaseWithServer +from test_soledad.u1db_tests import simple_doc +from test_soledad.util import make_token_soledad_app +from test_soledad.util import make_soledad_document_for_test +from test_soledad.util import soledad_sync_target +from test_soledad.util import BaseSoledadTest +from test_soledad.util import SoledadWithCouchServerMixin +from test_soledad.util import CouchDBTestCase class InterruptableSyncTestCase( diff --git a/common/src/leap/soledad/common/tests/test_sync_deferred.py b/testing/tests/sync/test_sync_deferred.py index c62bd156..4948aaf8 100644 --- a/common/src/leap/soledad/common/tests/test_sync_deferred.py +++ b/testing/tests/sync/test_sync_deferred.py @@ -34,11 +34,11 @@ from leap.soledad.client.sqlcipher import SQLCipherDatabase from testscenarios import TestWithScenarios -from leap.soledad.common.tests import u1db_tests as tests -from leap.soledad.common.tests.util import ADDRESS -from leap.soledad.common.tests.util import SoledadWithCouchServerMixin -from leap.soledad.common.tests.util import make_soledad_app -from leap.soledad.common.tests.util import soledad_sync_target +from test_soledad import u1db_tests as tests +from test_soledad.util import ADDRESS +from test_soledad.util import SoledadWithCouchServerMixin +from test_soledad.util import make_soledad_app +from test_soledad.util import soledad_sync_target # Just to make clear how this test is different... :) diff --git a/common/src/leap/soledad/common/tests/test_sync_mutex.py b/testing/tests/sync/test_sync_mutex.py index 973a8587..787cfee8 100644 --- a/common/src/leap/soledad/common/tests/test_sync_mutex.py +++ b/testing/tests/sync/test_sync_mutex.py @@ -35,13 +35,13 @@ from leap.soledad.client.sync import SoledadSynchronizer from leap.soledad.common.couch.state import CouchServerState from leap.soledad.common.couch import CouchDatabase -from leap.soledad.common.tests.u1db_tests import TestCaseWithServer -from leap.soledad.common.tests.test_couch import CouchDBTestCase +from test_soledad.u1db_tests import TestCaseWithServer -from leap.soledad.common.tests.util import BaseSoledadTest -from leap.soledad.common.tests.util import make_token_soledad_app -from leap.soledad.common.tests.util import make_soledad_document_for_test -from leap.soledad.common.tests.util import soledad_sync_target +from test_soledad.util import CouchDBTestCase +from test_soledad.util import BaseSoledadTest +from test_soledad.util import make_token_soledad_app +from test_soledad.util import make_soledad_document_for_test +from test_soledad.util import soledad_sync_target # monkey-patch the soledad synchronizer so it stores start and finish times diff --git a/common/src/leap/soledad/common/tests/test_sync_target.py b/testing/tests/sync/test_sync_target.py index c9b705a3..964468ce 100644 --- a/common/src/leap/soledad/common/tests/test_sync_target.py +++ b/testing/tests/sync/test_sync_target.py @@ -38,14 +38,15 @@ from leap.soledad.client.sqlcipher import SQLCipherDatabase from leap.soledad.common import l2db from leap.soledad.common.document import SoledadDocument -from leap.soledad.common.tests import u1db_tests as tests -from leap.soledad.common.tests.util import make_sqlcipher_database_for_test -from leap.soledad.common.tests.util import make_soledad_app -from leap.soledad.common.tests.util import make_token_soledad_app -from leap.soledad.common.tests.util import make_soledad_document_for_test -from leap.soledad.common.tests.util import soledad_sync_target -from leap.soledad.common.tests.util import SoledadWithCouchServerMixin -from leap.soledad.common.tests.util import ADDRESS +from test_soledad import u1db_tests as tests +from test_soledad.util import make_sqlcipher_database_for_test +from test_soledad.util import make_soledad_app +from test_soledad.util import make_token_soledad_app +from test_soledad.util import make_soledad_document_for_test +from test_soledad.util import soledad_sync_target +from test_soledad.util import SoledadWithCouchServerMixin +from test_soledad.util import ADDRESS +from test_soledad.util import SQLCIPHER_SCENARIOS # ----------------------------------------------------------------------------- @@ -954,3 +955,14 @@ class TestSoledadDbSync( d.addCallback(_assert_successful_sync) return d + + +class SQLCipherSyncTargetTests(SoledadDatabaseSyncTargetTests): + + # TODO: implement _set_trace_hook(_shallow) in SoledadHTTPSyncTarget so + # skipped tests can be succesfully executed. + + scenarios = (tests.multiply_scenarios(SQLCIPHER_SCENARIOS, + target_scenarios)) + + whitebox = False diff --git a/testing/tox.ini b/testing/tox.ini new file mode 100644 index 00000000..0a8dda9d --- /dev/null +++ b/testing/tox.ini @@ -0,0 +1,21 @@ +[tox] +envlist = py27 + +[testenv] +commands = py.test {posargs} +changedir = tests +deps = + pytest + mock + testscenarios + setuptools-trial + pep8 + pdbpp + couchdb +# install soledad local packages + -e../common + -e../client + -e../server +setenv = + HOME=/tmp +install_command = pip install {opts} {packages} |