1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
# -*- coding: utf-8 -*-
# util.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/>.
"""
Utilities used by multiple test suites.
"""
import tempfile
import shutil
from urlparse import urljoin
from StringIO import StringIO
from pysqlcipher import dbapi2
from u1db.errors import DatabaseDoesNotExist
from leap.soledad.common import soledad_assert
from leap.soledad.common.couch import CouchDatabase, CouchServerState
from leap.soledad.server import SoledadApp
from leap.soledad.server.auth import SoledadTokenAuthMiddleware
from leap.soledad.common.tests import u1db_tests as tests, BaseSoledadTest
from leap.soledad.common.tests.test_couch import CouchDBWrapper, CouchDBTestCase
from leap.soledad.client.sqlcipher import SQLCipherDatabase
PASSWORD = '123456'
def make_sqlcipher_database_for_test(test, replica_uid):
db = SQLCipherDatabase(
SQLCipherOptions(':memory:', PASSWORD))
db._set_replica_uid(replica_uid)
return db
def copy_sqlcipher_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.
new_db = SQLCipherDatabase(':memory:', PASSWORD)
tmpfile = StringIO()
for line in db._db_handle.iterdump():
if not 'sqlite_sequence' in line: # work around bug in iterdump
tmpfile.write('%s\n' % line)
tmpfile.seek(0)
new_db._db_handle = dbapi2.connect(':memory:')
new_db._db_handle.cursor().executescript(tmpfile.read())
new_db._db_handle.commit()
new_db._set_replica_uid(db._replica_uid)
new_db._factory = db._factory
return new_db
def make_soledad_app(state):
return SoledadApp(state)
def make_token_soledad_app(state):
app = SoledadApp(state)
def _verify_authentication_data(uuid, auth_data):
if uuid == 'user-uuid' and auth_data == 'auth-token':
return True
return False
# we test for action authorization in leap.soledad.common.tests.test_server
def _verify_authorization(uuid, environ):
return True
application = SoledadTokenAuthMiddleware(app)
application._verify_authentication_data = _verify_authentication_data
application._verify_authorization = _verify_authorization
return application
class CouchServerStateForTests(CouchServerState):
"""
This is a slightly modified CouchDB server state that allows for creating
a database.
Ordinarily, the CouchDB server state does not allow some operations,
because for security purposes the Soledad Server should not even have
enough permissions to perform them. For tests, we allow database creation,
otherwise we'd have to create those databases in setUp/tearDown methods,
which is less pleasant than allowing the db to be automatically created.
"""
def _create_database(self, dbname):
return CouchDatabase.open_database(
urljoin(self._couch_url, dbname),
True,
replica_uid=dbname,
ensure_ddocs=True)
def ensure_database(self, dbname):
db = self._create_database(dbname)
return db, db.replica_uid
class SoledadWithCouchServerMixin(
BaseSoledadTest,
CouchDBTestCase):
@classmethod
def setUpClass(cls):
"""
Make sure we have a CouchDB instance for a test.
"""
# from BaseLeapTest
cls.tempdir = tempfile.mkdtemp(prefix="leap_tests-")
# from CouchDBTestCase
cls.wrapper = CouchDBWrapper()
cls.wrapper.start()
#self.db = self.wrapper.db
@classmethod
def tearDownClass(cls):
"""
Stop CouchDB instance for test.
"""
# from BaseLeapTest
soledad_assert(
cls.tempdir.startswith('/tmp/leap_tests-'),
"beware! tried to remove a dir which does not "
"live in temporal folder!")
shutil.rmtree(cls.tempdir)
# from CouchDBTestCase
cls.wrapper.stop()
def setUp(self):
BaseSoledadTest.setUp(self)
CouchDBTestCase.setUp(self)
main_test_class = getattr(self, 'main_test_class', None)
if main_test_class is not None:
main_test_class.setUp(self)
self._couch_url = 'http://localhost:%d' % self.wrapper.port
def tearDown(self):
BaseSoledadTest.tearDown(self)
CouchDBTestCase.tearDown(self)
main_test_class = getattr(self, 'main_test_class', None)
if main_test_class is not None:
main_test_class.tearDown(self)
# delete the test database
try:
db = CouchDatabase(self._couch_url, 'test')
db.delete_database()
except DatabaseDoesNotExist:
pass
def make_app(self):
couch_url = urljoin(
'http://localhost:' + str(self.wrapper.port), 'tests')
self.request_state = CouchServerStateForTests(
couch_url, 'shared', 'tokens')
return self.make_app_with_state(self.request_state)
|