diff options
| -rw-r--r-- | src/leap/soledad/tests/test_leap_backend.py | 213 | 
1 files changed, 207 insertions, 6 deletions
| diff --git a/src/leap/soledad/tests/test_leap_backend.py b/src/leap/soledad/tests/test_leap_backend.py index 4c76bbb9..1f84cd5a 100644 --- a/src/leap/soledad/tests/test_leap_backend.py +++ b/src/leap/soledad/tests/test_leap_backend.py @@ -25,6 +25,7 @@ try:      import simplejson as json  except ImportError:      import json  # noqa +import cStringIO  from leap.soledad.backends import leap_backend @@ -105,6 +106,10 @@ class TestLeapPyDocument(test_document.TestPyDocument, BaseSoledadTest):  class TestLeapSyncTargetBasics(          test_remote_sync_target.TestHTTPSyncTargetBasics): +    """ +    Some tests had to be copied to this class so we can instantiate our own +    target. +    """      def test_parse_url(self):          remote_target = leap_backend.LeapSyncTarget('http://127.0.0.1:12345/') @@ -114,12 +119,13 @@ class TestLeapSyncTargetBasics(          self.assertEqual('/', remote_target._url.path) -# Monkey patch test class so it uses our sync target. -test_remote_sync_target.http_target.HTTPSyncTarget = leap_backend.LeapSyncTarget -  class TestLeapParsingSyncStream(          test_remote_sync_target.TestParsingSyncStream,          BaseSoledadTest): +    """ +    Some tests had to be copied to this class so we can instantiate our own +    target. +    """      def setUp(self):          test_remote_sync_target.TestParsingSyncStream.setUp(self) @@ -149,9 +155,65 @@ class TestLeapParsingSyncStream(                            ',\r\n]' % json.dumps(enc_json),                            lambda doc, gen, trans_id: None) +    def test_wrong_start(self): +        tgt = leap_backend.LeapSyncTarget("http://foo/foo") + +        self.assertRaises(u1db.errors.BrokenSyncStream, +                          tgt._parse_sync_stream, "{}\r\n]", None) + +        self.assertRaises(u1db.errors.BrokenSyncStream, +                          tgt._parse_sync_stream, "\r\n{}\r\n]", None) + +        self.assertRaises(u1db.errors.BrokenSyncStream, +                          tgt._parse_sync_stream, "", None) + +    def test_wrong_end(self): +        tgt = leap_backend.LeapSyncTarget("http://foo/foo") + +        self.assertRaises(u1db.errors.BrokenSyncStream, +                          tgt._parse_sync_stream, "[\r\n{}", None) + +        self.assertRaises(u1db.errors.BrokenSyncStream, +                          tgt._parse_sync_stream, "[\r\n", None) + +    def test_missing_comma(self): +        tgt = leap_backend.LeapSyncTarget("http://foo/foo") + +        self.assertRaises(u1db.errors.BrokenSyncStream, +                          tgt._parse_sync_stream, +                          '[\r\n{}\r\n{"id": "i", "rev": "r", ' +                          '"content": "c", "gen": 3}\r\n]', None) + +    def test_no_entries(self): +        tgt = leap_backend.LeapSyncTarget("http://foo/foo") + +        self.assertRaises(u1db.errors.BrokenSyncStream, +                          tgt._parse_sync_stream, "[\r\n]", None) + +    def test_error_in_stream(self): +        tgt = leap_backend.LeapSyncTarget("http://foo/foo") + +        self.assertRaises(u1db.errors.Unavailable, +                          tgt._parse_sync_stream, +                          '[\r\n{"new_generation": 0},' +                          '\r\n{"error": "unavailable"}\r\n', None) + +        self.assertRaises(u1db.errors.Unavailable, +                          tgt._parse_sync_stream, +                          '[\r\n{"error": "unavailable"}\r\n', None) + +        self.assertRaises(u1db.errors.BrokenSyncStream, +                          tgt._parse_sync_stream, +                          '[\r\n{"error": "?"}\r\n', None) + + +# +# functions for TestRemoteSyncTargets +#  def leap_sync_target(test, path): -    return leap_backend.LeapSyncTarget(test.getURL(path)) +    return leap_backend.LeapSyncTarget( +        test.getURL(path), crypto=test._soledad._crypto)  def oauth_leap_sync_target(test, path): @@ -161,7 +223,8 @@ def oauth_leap_sync_target(test, path):      return st -class TestRemoteSyncTargets(tests.TestCaseWithServer): +class TestLeapSyncTarget( +    test_remote_sync_target.TestRemoteSyncTargets, BaseSoledadTest):      scenarios = [          ('http', {'make_app_with_state': make_soledad_app, @@ -172,6 +235,142 @@ class TestRemoteSyncTargets(tests.TestCaseWithServer):                          'sync_target': oauth_leap_sync_target}),      ] +    def test_sync_exchange_send(self): +        """ +        Test for sync exchanging send of document. + +        This test was adapted to decrypt remote content before assert. +        """ +        self.startServer() +        db = self.request_state._create_database('test') +        remote_target = self.getSyncTarget('test') +        other_docs = [] + +        def receive_doc(doc): +            other_docs.append((doc.doc_id, doc.rev, doc.get_json())) + +        doc = self.make_document('doc-here', 'replica:1', '{"value": "here"}') +        new_gen, trans_id = remote_target.sync_exchange( +            [(doc, 10, 'T-sid')], 'replica', last_known_generation=0, +            last_known_trans_id=None, return_doc_cb=receive_doc) +        self.assertEqual(1, new_gen) +        # (possibly) decrypt and compare +        doc2 = db.get_doc('doc-here') +        if leap_backend.ENC_SCHEME_KEY in doc2.content: +            doc2.set_json( +                leap_backend.decrypt_doc_json( +                    self._soledad._crypto, doc2.doc_id, doc2.get_json())) +        self.assertEqual(doc, doc2) + +    def test_sync_exchange_send_failure_and_retry_scenario(self): +        """ +        Test for sync exchange failure and retry. + +        This test was adapted to decrypt remote content before assert. +        """ +        self.startServer() + +        def blackhole_getstderr(inst): +            return cStringIO.StringIO() + +        self.patch(self.server.RequestHandlerClass, 'get_stderr', +                   blackhole_getstderr) +        db = self.request_state._create_database('test') +        _put_doc_if_newer = db._put_doc_if_newer +        trigger_ids = ['doc-here2'] + +        def bomb_put_doc_if_newer(doc, save_conflict, +                                  replica_uid=None, replica_gen=None, +                                  replica_trans_id=None): +            if doc.doc_id in trigger_ids: +                raise Exception +            return _put_doc_if_newer(doc, save_conflict=save_conflict, +                                     replica_uid=replica_uid, +                                     replica_gen=replica_gen, +                                     replica_trans_id=replica_trans_id) +        self.patch(db, '_put_doc_if_newer', bomb_put_doc_if_newer) +        remote_target = self.getSyncTarget('test') +        other_changes = [] + +        def receive_doc(doc, gen, trans_id): +            other_changes.append( +                (doc.doc_id, doc.rev, doc.get_json(), gen, trans_id)) + +        doc1 = self.make_document('doc-here', 'replica:1', '{"value": "here"}') +        doc2 = self.make_document('doc-here2', 'replica:1', +                                  '{"value": "here2"}') +        self.assertRaises( +            u1db.errors.HTTPError, +            remote_target.sync_exchange, +            [(doc1, 10, 'T-sid'), (doc2, 11, 'T-sud')], +            'replica', last_known_generation=0, last_known_trans_id=None, +            return_doc_cb=receive_doc) +        # -- (possibly) decrypt and compare +        tmpdoc = db.get_doc('doc-here') +        if leap_backend.ENC_SCHEME_KEY in tmpdoc.content: +            tmpdoc.set_json( +                leap_backend.decrypt_doc_json( +                    self._soledad._crypto, tmpdoc.doc_id, tmpdoc.get_json())) +        self.assertEqual(doc1, tmpdoc) +        # -- end of decrypt and compare +        self.assertEqual( +            (10, 'T-sid'), db._get_replica_gen_and_trans_id('replica')) +        self.assertEqual([], other_changes) +        # retry +        trigger_ids = [] +        new_gen, trans_id = remote_target.sync_exchange( +            [(doc2, 11, 'T-sud')], 'replica', last_known_generation=0, +            last_known_trans_id=None, return_doc_cb=receive_doc) +        # -- (possibly) decrypt and compare +        tmpdoc = db.get_doc('doc-here2') +        if leap_backend.ENC_SCHEME_KEY in tmpdoc.content: +            tmpdoc.set_json( +                leap_backend.decrypt_doc_json( +                    self._soledad._crypto, tmpdoc.doc_id, tmpdoc.get_json())) +        self.assertEqual(doc2, tmpdoc) +        # -- end of decrypt and compare +        self.assertEqual( +            (11, 'T-sud'), db._get_replica_gen_and_trans_id('replica')) +        self.assertEqual(2, new_gen) +        # bounced back to us +        self.assertEqual( +            ('doc-here', 'replica:1', '{"value": "here"}', 1), +            other_changes[0][:-1]) + +    def test_sync_exchange_send_ensure_callback(self): +        """ +        Test for sync exchange failure and retry. + +        This test was adapted to decrypt remote content before assert. +        """ +        self.startServer() +        remote_target = self.getSyncTarget('test') +        other_docs = [] +        replica_uid_box = [] + +        def receive_doc(doc): +            other_docs.append((doc.doc_id, doc.rev, doc.get_json())) + +        def ensure_cb(replica_uid): +            replica_uid_box.append(replica_uid) + +        doc = self.make_document('doc-here', 'replica:1', '{"value": "here"}') +        new_gen, trans_id = remote_target.sync_exchange( +            [(doc, 10, 'T-sid')], 'replica', last_known_generation=0, +            last_known_trans_id=None, return_doc_cb=receive_doc, +            ensure_callback=ensure_cb) +        self.assertEqual(1, new_gen) +        db = self.request_state.open_database('test') +        self.assertEqual(1, len(replica_uid_box)) +        self.assertEqual(db._replica_uid, replica_uid_box[0]) +        # -- (possibly) decrypt and compare +        tmpdoc = db.get_doc('doc-here') +        if leap_backend.ENC_SCHEME_KEY in tmpdoc.content: +            tmpdoc.set_json( +                leap_backend.decrypt_doc_json( +                    self._soledad._crypto, tmpdoc.doc_id, tmpdoc.get_json())) +        self.assertEqual(doc, tmpdoc) +        # -- end of decrypt and compare  #-----------------------------------------------------------------------------  # The following tests come from `u1db.tests.test_https`. @@ -179,7 +378,9 @@ class TestRemoteSyncTargets(tests.TestCaseWithServer):  def oauth_https_sync_target(test, host, path):      _, port = test.server.server_address -    st = leap_backend.LeapSyncTarget('https://%s:%d/~/%s' % (host, port, path)) +    st = leap_backend.LeapSyncTarget( +        'https://%s:%d/~/%s' % (host, port, path), +        crypto=test._soledad._crypto)      st.set_oauth_credentials(tests.consumer1.key, tests.consumer1.secret,                               tests.token1.key, tests.token1.secret)      return st | 
