diff options
| author | drebs <drebs@leap.se> | 2013-02-06 20:05:50 -0200 | 
|---|---|---|
| committer | drebs <drebs@leap.se> | 2013-02-06 20:05:50 -0200 | 
| commit | bc6d05f8333ee775aa373817e2ece6323c62186f (patch) | |
| tree | e7ec5eb02de6d0f0eb0f77ef139527c8a9268d9c | |
| parent | 4e058b62589defe7a15d633a20b17bed75484d56 (diff) | |
| parent | ce322fe3c12af877f9d7d40a6a3ccc4001fdf2b6 (diff) | |
Merge branch 'feature/soledad-api' of ssh://code.leap.se/leap_client into feature/soledad-api
| -rw-r--r-- | README | 14 | ||||
| -rw-r--r-- | backends/couch.py | 1 | ||||
| -rw-r--r-- | backends/leap_backend.py | 1 | ||||
| -rw-r--r-- | backends/openstack.py | 98 | ||||
| -rw-r--r-- | backends/sqlcipher.py | 7 | ||||
| -rw-r--r-- | tests/test_couch.py | 2 | ||||
| -rw-r--r-- | tests/test_sqlcipher.py | 61 | 
7 files changed, 75 insertions, 109 deletions
| @@ -9,16 +9,14 @@ Dependencies  Soledad depends on the following python libraries:    * u1db 0.1.4 [1] -  * python-swiftclient 1.2.0 [2] -  * python-gnupg 0.3.1 [3] -  * CouchDB 0.8 [4] -  * hmac 20101005 [5] +  * python-gnupg 0.3.1 [2] +  * CouchDB 0.8 [3] +  * hmac 20101005 [4]  [1] http://pypi.python.org/pypi/u1db/0.1.4 -[2] http://pypi.python.org/pypi/python-swiftclient/1.2.0 -[3] http://pypi.python.org/pypi/python-gnupg/0.3.1 -[4] http://pypi.python.org/pypi/CouchDB/0.8 -[5] http://pypi.python.org/pypi/hmac/20101005 +[2] http://pypi.python.org/pypi/python-gnupg/0.3.1 +[3] http://pypi.python.org/pypi/CouchDB/0.8 +[4] http://pypi.python.org/pypi/hmac/20101005  Tests diff --git a/backends/couch.py b/backends/couch.py index 11122aa8..8757f5af 100644 --- a/backends/couch.py +++ b/backends/couch.py @@ -243,6 +243,7 @@ class CouchSyncTarget(LocalSyncTarget):              source_replica_uid, source_replica_generation,              source_replica_transaction_id) +  class CouchServerState(ServerState):      """      Inteface of the WSGI server with the CouchDB backend. diff --git a/backends/leap_backend.py b/backends/leap_backend.py index f9d37e19..41027e50 100644 --- a/backends/leap_backend.py +++ b/backends/leap_backend.py @@ -200,4 +200,3 @@ class LeapSyncTarget(HTTPSyncTarget):          res = self._parse_sync_stream(data, return_doc_cb, ensure_callback)          data = None          return res['new_generation'], res['new_transaction_id'] - diff --git a/backends/openstack.py b/backends/openstack.py deleted file mode 100644 index a9615736..00000000 --- a/backends/openstack.py +++ /dev/null @@ -1,98 +0,0 @@ -# TODO: this backend is not tested yet. -from u1db.remote.http_target import HTTPSyncTarget -import swiftclient -from soledad.backends.objectstore import ObjectStore - - -class OpenStackDatabase(ObjectStore): -    """A U1DB implementation that uses OpenStack as its persistence layer.""" - -    def __init__(self, auth_url, user, auth_key, container): -        """Create a new OpenStack data container.""" -        self._auth_url = auth_url -        self._user = user -        self._auth_key = auth_key -        self._container = container -        self._connection = swiftclient.Connection(self._auth_url, self._user, -                                                  self._auth_key) -        self._get_auth() -        # this will ensure transaction and sync logs exist and are up-to-date. -        super(OpenStackDatabase, self).__init__() - -    #------------------------------------------------------------------------- -    # implemented methods from Database -    #------------------------------------------------------------------------- - -    def _get_doc(self, doc_id, check_for_conflicts=False): -        """Get just the document content, without fancy handling. - -        Conflicts do not happen on server side, so there's no need to check -        for them. -        """ -        try: -            response, contents = self._connection.get_object(self._container, -                                                             doc_id) -            # TODO: change revision to be a dictionary element? -            rev = response['x-object-meta-rev'] -            return self._factory(doc_id, rev, contents) -        except swiftclient.ClientException: -            return None - -    def get_all_docs(self, include_deleted=False): -        """Get all documents from the database.""" -        generation = self._get_generation() -        results = [] -        _, doc_ids = self._connection.get_container(self._container, -                                                    full_listing=True) -        for doc_id in doc_ids: -            doc = self._get_doc(doc_id) -            if doc.content is None and not include_deleted: -                continue -            results.append(doc) -        return (generation, results) - -    def _put_doc(self, doc, new_rev): -        new_rev = self._allocate_doc_rev(doc.rev) -        # TODO: change revision to be a dictionary element? -        headers = {'X-Object-Meta-Rev': new_rev} -        self._connection.put_object(self._container, doc_id, doc.get_json(), -                                    headers=headers) - -    def get_sync_target(self): -        return OpenStackSyncTarget(self) - -    def close(self): -        raise NotImplementedError(self.close) - -    def sync(self, url, creds=None, autocreate=True): -        from u1db.sync import Synchronizer -        from u1db.remote.http_target import OpenStackSyncTarget -        return Synchronizer(self, OpenStackSyncTarget(url, creds=creds)).sync( -            autocreate=autocreate) - -    #------------------------------------------------------------------------- -    # OpenStack specific methods -    #------------------------------------------------------------------------- - -    def _get_auth(self): -        self._url, self._auth_token = self._connection.get_auth() -        return self._url, self.auth_token - - -class OpenStackSyncTarget(HTTPSyncTarget): - -    def get_sync_info(self, source_replica_uid): -        source_gen, source_trans_id = self._db._get_replica_gen_and_trans_id( -            source_replica_uid) -        my_gen, my_trans_id = self._db._get_generation_info() -        return ( -            self._db._replica_uid, my_gen, my_trans_id, source_gen, -            source_trans_id) - -    def record_sync_info(self, source_replica_uid, source_replica_generation, -                         source_replica_transaction_id): -        if self._trace_hook: -            self._trace_hook('record_sync_info') -        self._db._set_replica_gen_and_trans_id( -            source_replica_uid, source_replica_generation, -            source_replica_transaction_id) diff --git a/backends/sqlcipher.py b/backends/sqlcipher.py index 6cebcf7d..354fcd31 100644 --- a/backends/sqlcipher.py +++ b/backends/sqlcipher.py @@ -131,8 +131,11 @@ class SQLCipherDatabase(SQLitePartialExpandDatabase):          """          from u1db.sync import Synchronizer          from leap.soledad.backends.leap_backend import LeapSyncTarget -        return Synchronizer(self, LeapSyncTarget(url, creds=creds), -                            soledad=self._soledad).sync(autocreate=autocreate) +        return Synchronizer( +            self, +            LeapSyncTarget(url, +                           creds=creds, +                           soledad=self._soledad)).sync(autocreate=autocreate)      def _extra_schema_init(self, c):          c.execute( diff --git a/tests/test_couch.py b/tests/test_couch.py index 6eb5501c..55bcf442 100644 --- a/tests/test_couch.py +++ b/tests/test_couch.py @@ -27,6 +27,8 @@ import time  import unittest +# from: https://github.com/smcq/paisley/blob/master/paisley/test/util.py +# TODO: include license of above project.  class CouchDBWrapper(object):      """      Wrapper for external CouchDB instance which is started and stopped for diff --git a/tests/test_sqlcipher.py b/tests/test_sqlcipher.py index 18b9173e..38ad09ed 100644 --- a/tests/test_sqlcipher.py +++ b/tests/test_sqlcipher.py @@ -11,6 +11,7 @@ import threading  from u1db import (      errors,      query_parser, +    sync,  )  from u1db.backends.sqlite_backend import SQLitePartialExpandDatabase @@ -27,6 +28,8 @@ from leap.soledad.tests import u1db_tests as tests  from leap.soledad.tests.u1db_tests import test_sqlite_backend  from leap.soledad.tests.u1db_tests import test_backends  from leap.soledad.tests.u1db_tests import test_open +from leap.soledad.tests.u1db_tests import test_sync +from leap.soledad.backends.leap_backend import LeapSyncTarget  PASSWORD = '123456' @@ -322,6 +325,63 @@ class SQLCipherOpen(test_open.TestU1DBOpen):  #----------------------------------------------------------------------------- +# The following tests come from `u1db.tests.test_sync`. +#----------------------------------------------------------------------------- + +sync_scenarios = [] +for name, scenario in SQLCIPHER_SCENARIOS: +    scenario = dict(scenario) +    scenario['do_sync'] = test_sync.sync_via_synchronizer +    sync_scenarios.append((name, scenario)) +    scenario = dict(scenario) + + +def sync_via_synchronizer_and_leap(test, db_source, db_target, +                                   trace_hook=None, trace_hook_shallow=None): +    if trace_hook: +        test.skipTest("full trace hook unsupported over http") +    path = test._http_at[db_target] +    target = LeapSyncTarget.connect(test.getURL(path)) +    if trace_hook_shallow: +        target._set_trace_hook_shallow(trace_hook_shallow) +    return sync.Synchronizer(db_source, target).sync() + + +sync_scenarios.append(('pyleap', { +    'make_database_for_test': test_sync.make_database_for_http_test, +    'copy_database_for_test': test_sync.copy_database_for_http_test, +    'make_document_for_test': tests.make_document_for_test, +    'make_app_with_state': tests.test_remote_sync_target.make_http_app, +    'do_sync': sync_via_synchronizer_and_leap, +})) + + +class SQLCipherDatabaseSyncTests(test_sync.DatabaseSyncTests): + +    scenarios = sync_scenarios + + +def _make_local_db_and_leap_target(test, path='test'): +    test.startServer() +    db = test.request_state._create_database(os.path.basename(path)) +    st = LeapSyncTarget.connect(test.getURL(path)) +    return db, st + + +target_scenarios = [ +    ('leap', { +        'create_db_and_target': _make_local_db_and_leap_target, +        'make_app_with_state': tests.test_remote_sync_target.make_http_app}), +] + + +class SQLCipherSyncTargetTests(test_sync.DatabaseSyncTargetTests): + +    scenarios = (tests.multiply_scenarios(SQLCIPHER_SCENARIOS, +                                          target_scenarios)) + + +#-----------------------------------------------------------------------------  # Tests for actual encryption of the database  #----------------------------------------------------------------------------- @@ -373,4 +433,5 @@ class SQLCipherEncryptionTest(unittest.TestCase):          except DatabaseIsNotEncrypted:              pass +  load_tests = tests.load_with_scenarios | 
