summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README14
-rw-r--r--backends/couch.py1
-rw-r--r--backends/leap_backend.py1
-rw-r--r--backends/openstack.py98
-rw-r--r--backends/sqlcipher.py7
-rw-r--r--tests/test_couch.py2
-rw-r--r--tests/test_sqlcipher.py61
7 files changed, 75 insertions, 109 deletions
diff --git a/README b/README
index 3bf62494..b14d5932 100644
--- a/README
+++ b/README
@@ -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