Merge lp:~kalikiana/u1db-qt/upstream-tests into lp:u1db-qt

Proposed by Cris Dywan
Status: Work in progress
Proposed branch: lp:~kalikiana/u1db-qt/upstream-tests
Merge into: lp:u1db-qt
Diff against target: 693 lines (+678/-0)
3 files modified
tests/bridged.py (+486/-0)
tests/setup.py (+6/-0)
tests/test-bridged.py (+186/-0)
To merge this branch: bzr merge lp:~kalikiana/u1db-qt/upstream-tests
Reviewer Review Type Date Requested Status
U1DB Qt developers Pending
Review via email: mp+182339@code.launchpad.net

Commit message

First attempt at implementing Python U1Db class for unit tests

To post a comment you must log in.

Unmerged revisions

68. By Cris Dywan

First attempt at implementing Python U1Db class for unit tests

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'tests/__init__.py'
=== added file 'tests/bridged.py'
--- tests/bridged.py 1970-01-01 00:00:00 +0000
+++ tests/bridged.py 2013-08-27 10:28:13 +0000
@@ -0,0 +1,486 @@
1import atexit
2import functools
3import inspect
4import json
5import os
6
7from u1db import (
8 Database as DbInterface,
9 SyncTarget as SyncTargetInterface,
10 Document,
11 errors
12)
13from tools import js_bridge
14
15
16_js_bridge = None
17
18XHR_IMPL = [
19 'platform/core.js',
20 'platform/rhino.js',
21 'console.js',
22 'dom.js',
23 'event.js',
24 'html.js',
25 'timer.js',
26 'xhr.js'
27 ]
28
29
30def get_u1db_js_bridge():
31 global _js_bridge
32 if _js_bridge is None:
33 _js_bridge = js_bridge.JsBridge()
34 if _js_bridge.rhino:
35 for xhr_impl_bit in XHR_IMPL:
36 _js_bridge.load(os.path.join('tests',
37 'dist-env-js', xhr_impl_bit))
38 _js_bridge.load('oauth/sha1.js')
39 _js_bridge.load('oauth/oauth.js')
40 _js_bridge.load('u1db.js')
41 _js_bridge._orig_globals = _js_bridge.global_names()
42 _js_bridge._check_escaped = os.getenv('CHECK_ESCAPED') is not None
43 atexit.register(_js_bridge.quit)
44 return _js_bridge
45
46
47to_js = json.dumps
48
49
50def apply_content(doc, content):
51 if content is None:
52 doc.set_json(None)
53 else:
54 doc.content = content
55
56
57def doc_from_dic(val):
58 doc = Document(doc_id=val['doc_id'], rev=val['rev'],
59 has_conflicts=val['has_conflicts'])
60 apply_content(doc, val['content'])
61 return doc
62
63
64class BridgedJsObject(object):
65
66 # medium level interface
67
68 def _check_for_escaped(self):
69 if self._js_bridge._check_escaped:
70 orig_globals = self._js_bridge._orig_globals
71 cur_globals = self._js_bridge.global_names()
72 if cur_globals != orig_globals:
73 raise Exception("escaped vars: %r" %
74 cur_globals.symmetric_difference(orig_globals))
75
76 _count = 1
77
78 def _fresh_count(self):
79 c = self._count
80 BridgedJsObject._count += 1
81 return c
82
83 def _make_db(self, dbname):
84 dbvar = "db%d" % self._fresh_count()
85 self._js_bridge.retain(dbvar, "new U1DB(%s, true)" % to_js(dbname))
86 self._check_for_escaped()
87 return dbvar
88
89 def _forget_ref(self, var):
90 self._js_bridge.forget([var])
91
92 _forget_db = _forget_ref
93
94 def _make_http_sync_target(self, url):
95 tgtvar = "tgt%d" % self._fresh_count()
96 self._js_bridge.retain(tgtvar, "new U1DBHTTPSyncTarget(%s)" % to_js(url))
97 self._check_for_escaped()
98 return tgtvar
99
100 _forget_http_sync_target = _forget_ref
101
102 def _make_synchronizer(self, db_ref, tgt_ref):
103 synchronizervar = "synchronizer%d" % self._fresh_count()
104 self._js_bridge.retain(synchronizervar, "new U1DBSynchronizer(%s, %s)" %
105 (db_ref, tgt_ref))
106 self._check_for_escaped()
107 return synchronizervar
108
109 _forget_synchronizer = _forget_ref
110
111 def _temp_doc_expr(self, doc):
112 return "new U1DBDocument(%s,%s,%s,%s)" % (
113 to_js(doc.doc_id), to_js(doc.rev),
114 to_js(doc.content), to_js(doc.has_conflicts))
115
116 def _make_doc(self, doc):
117 docvar = "doc%d" % self._fresh_count()
118 self._js_bridge.retain(docvar, self._temp_doc_expr(doc))
119 self._check_for_escaped()
120 return docvar
121
122 _forget_doc = _forget_ref
123
124 _nil_cb = "null"
125
126 def _make_cb(self, func):
127 cbvar = "cb%d" % self._fresh_count()
128 self._js_bridge.make_cb(cbvar, func)
129 return cbvar
130
131 def _make_cb_doc(self, func):
132 @functools.wraps(func)
133 def wrap(doc_dic, *args):
134 return func(doc_from_dic(doc_dic), *args)
135 return self._make_cb(wrap)
136
137 def _forget_cb(self, cb_ref):
138 self._js_bridge.forget_cb(cb_ref)
139
140 def _do_invoke(self, ref, meth_name, opts, js_args):
141 if opts:
142 js_args = js_args + [to_js(opts[0])]
143 try:
144 res = self._js_bridge.eval("%s.%s(%s)" % (ref, meth_name,
145 ', '.join(js_args)))
146 except js_bridge.JSError, js_err:
147 if hasattr(errors, js_err.name):
148 if js_err.name == "HTTPError":
149 raise errors.HTTPError(500, js_err.message) # xxx != 500
150 raise getattr(errors, js_err.name)(js_err.message)
151 raise
152 self._check_for_escaped()
153 return res
154
155 natural_calling = True
156
157 def _invoke(self, ref, meth_name, opts, args):
158 return self._do_invoke(ref, meth_name, opts, map(to_js, args))
159
160 def _invoke_varargs(self, ref, meth_name, opts, args, rest):
161 return self._do_invoke(ref, meth_name, opts,
162 map(to_js, args+list(rest)))
163
164 def _invoke_ret_tuple(self, ref, meth_name, opts, args):
165 return tuple(self._do_invoke(ref, meth_name, opts, map(to_js, args)))
166
167 def _invoke_ret_doc(self, ref, meth_name, opts, args):
168 dic = self._do_invoke(ref, meth_name, opts, map(to_js, args))
169 if dic is None:
170 return None
171 return doc_from_dic(dic)
172
173 def _invoke_ret_whats_changed(self, ref, meth_name, opts, args):
174 # one single optional arg, like whats_changed
175 if self.natural_calling and not args and opts:
176 if opts[0]:
177 args = [opts[0].values()[0]]
178 opts = None
179 gen, trans_id, changes = self._do_invoke(ref, meth_name, opts,
180 map(to_js, args))
181 return gen, trans_id, map(tuple, changes)
182
183 def _invoke_ret_docs(self, ref, meth_name, opts, args):
184 dics = self._do_invoke(ref, meth_name, opts, map(to_js, args))
185 return map(doc_from_dic, dics)
186
187 def _invoke_varargs_ret_docs(self, ref, meth_name, opts, args, rest):
188 dics = self._do_invoke(ref, meth_name, opts,
189 map(to_js, args+list(rest)))
190 return map(doc_from_dic, dics)
191
192 def _invoke_ret_tuples(self, ref, meth_name, opts, args):
193 lst = self._do_invoke(ref, meth_name, opts, map(to_js, args))
194 return map(tuple, lst)
195
196 def _invoke_ret_gen_docs(self, ref, meth_name, opts, args):
197 gen, dics = self._do_invoke(ref, meth_name, opts, map(to_js, args))
198 return gen, map(doc_from_dic, dics)
199
200 def _invoke_doc(self, ref, meth_name, opts, doc_ref, args):
201 return self._do_invoke(ref, meth_name, opts, [doc_ref] + map(to_js,
202 args))
203
204 def _invoke_doc_ret_tuple(self, ref, meth_name, opts, doc_ref, args):
205 return tuple(self._do_invoke(ref, meth_name, opts,
206 [doc_ref] + map(to_js, args)))
207
208 def _read_into_doc(self, doc_ref, doc):
209 doc.rev, doc.has_conflicts, content = self._js_bridge.eval(
210 "[%s.rev, %s.has_conflicts, %s.content]" % ((doc_ref,)*3))
211 apply_content(doc, content)
212
213 def _invoke_sync_exchange(self, ref, docs_by_generations,
214 source_replica_uid,
215 last_known_generation, last_known_trans_id,
216 return_doc_cb_ref, ensure_cb_ref):
217 docs_by_gen_exprs = []
218 for doc, gen, trans_id in docs_by_generations:
219 docs_by_gen_exprs.append("[%s, %s, %s]" % (
220 self._temp_doc_expr(doc), to_js(gen), to_js(trans_id)))
221 docs_by_gen_expr = "[%s]" % ', '.join(docs_by_gen_exprs)
222 return tuple(self._do_invoke(ref, 'sync_exchange', None,
223 [docs_by_gen_expr,
224 to_js(source_replica_uid),
225 to_js(last_known_generation),
226 to_js(last_known_trans_id),
227 return_doc_cb_ref,
228 ensure_cb_ref]))
229
230 def _invoke_cb(self, ref, meth_name, cb_ref):
231 return self._do_invoke(ref, meth_name, None, [cb_ref])
232
233 # end of medium level interface
234
235 def _parse_opts(self, opt_spec, *args):
236 if opt_spec is None:
237 return args, None
238 opt_args, defl_vals = opt_spec
239 opt = len(defl_vals)
240 opts, defl = {}, {}
241 for argname, argval, argdefl in zip(opt_args, args[-opt:], defl_vals):
242 if argval != argdefl:
243 opts[argname] = argval
244 else:
245 defl[argname] = argdefl
246 return args[:-opt], (opts, defl)
247
248 def _bridge_meth(self, name, opts, args):
249 return self._invoke(self._ref, name, opts, args)
250
251 def _bridge_meth_doc(self, name, opts, args, ret_kind=None):
252 invoke = self._invoke_doc
253 if ret_kind != None:
254 invoke = getattr(self, '_invoke_doc_ret_%s' % ret_kind)
255 doc = args[0]
256 doc_ref = self._make_doc(doc)
257 try:
258 res = invoke(self._ref, name, opts, doc_ref, args[1:])
259 self._read_into_doc(doc_ref, doc)
260 return res
261 finally:
262 self._forget_doc(doc_ref)
263
264 _bridge_meth_doc_conv = _bridge_meth_doc
265
266 def _bridge_meth_conv(self, name, opts, args, ret_kind):
267 invoke = getattr(self, '_invoke_ret_%s' % ret_kind)
268 return invoke(self._ref, name, opts, args)
269
270 def _bridge_meth_varargs(self, name, opts, args, rest, ret_kind=None):
271 invoke = self._invoke_varargs
272 if ret_kind != None:
273 invoke = getattr(self, '_invoke_varargs_ret_%s' % ret_kind)
274 return invoke(self._ref, name, opts, args, rest)
275
276 _bridge_meth_varargs_conv = _bridge_meth_varargs
277
278 def _bridge_meth_sync_exchange(self, docs_by_generations,
279 source_replica_uid,
280 last_known_generation, last_known_trans_id,
281 return_doc_cb, ensure_callback):
282 return_doc_cb_ref = self._make_cb_doc(return_doc_cb)
283 if ensure_callback is not None:
284 ensure_cb_ref = self._make_cb(ensure_callback)
285 else:
286 ensure_cb_ref = self._nil_cb
287 try:
288 return self._invoke_sync_exchange(self._ref, docs_by_generations,
289 source_replica_uid,
290 last_known_generation,
291 last_known_trans_id,
292 return_doc_cb_ref,
293 ensure_cb_ref)
294 finally:
295 if ensure_callback is not None:
296 self._forget_cb(ensure_cb_ref)
297 self._forget_cb(return_doc_cb_ref)
298
299
300_BRIDGE_METH_TEMPL = """
301def bridge_meth(self, %(args)s):
302 args, opts = self._parse_opts(%(opt_spec)r, %(args)s)
303 return self._bridge_meth%(sign)s(%(name)r, opts, args%(conv)s)
304"""
305
306
307def _complete_interface(interface_cls, bridge_cls, prot_exposed, skip, ret):
308 for name, val in interface_cls.__dict__.items():
309 if name.startswith('_') and name not in prot_exposed:
310 continue
311 if name in skip:
312 continue
313 if name in bridge_cls.__dict__:
314 continue
315 spec = inspect.getargspec(getattr(interface_cls, name))
316 assert spec.args[0] == 'self'
317 args = spec.args[1:]
318 if spec.varargs:
319 assert spec.keywords is None
320 assert False, "*args, not supported yet"
321 else:
322 opt_spec = None
323 if spec.defaults:
324 opt_spec = (args[-len(spec.defaults):], spec.defaults)
325 sign = ''
326 if args and args[0] == 'doc':
327 sign += '_doc'
328 ret_kind = ret.get(name)
329 if ret_kind:
330 sign += '_conv'
331 conv = ", %r" % ret_kind
332 else:
333 conv = ''
334 def_code = _BRIDGE_METH_TEMPL % dict(name=name, opt_spec=opt_spec,
335 sign=sign, args=', '.join(args),
336 conv=conv)
337 ns = {}
338 exec def_code in ns
339 bridge_meth = ns['bridge_meth']
340 bridge_meth.__name__ = name
341 bridge_meth.func_defaults = spec.defaults
342 setattr(bridge_cls, name, bridge_meth)
343
344
345class BridgedJsDatabase(BridgedJsObject):
346
347 def __init__(self, replica_uid):
348 self._js_bridge = get_u1db_js_bridge()
349 self._ref = self._make_db(replica_uid)
350
351 def _forget(self):
352 self._forget_db(self._ref)
353
354 def delete_db(self):
355 return self._bridge_meth('delete_db', None, [])
356
357 # testing/internal api
358
359 def _get_transaction_log(self):
360 return self._bridge_meth('_get_transaction_log', None, [])
361
362 def _validate_source(self, other_replica_uid, other_generation,
363 other_transaction_id):
364 return self._bridge_meth('_validate_source', None,
365 [other_replica_uid, other_generation,
366 other_transaction_id])
367
368 def validate_gen_and_trans_id(self, generation, trans_id):
369 return self._bridge_meth('validate_gen_and_trans_id', None,
370 [generation, trans_id])
371
372 def _get_generation_info(self):
373 return self._bridge_meth_conv('_get_generation_info',
374 None, [], ret_kind='tuple')
375
376 def create_index(self, name, *index_expressions):
377 return self._bridge_meth_varargs('create_index', None,
378 [name], index_expressions)
379
380 def get_from_index(self, name, *keys):
381 return self._bridge_meth_varargs_conv('get_from_index',
382 None, [name], keys,
383 ret_kind='docs')
384
385 def get_range_from_index(self, name, start_keys, end_keys=None):
386 return self._bridge_meth_conv('get_range_from_index',
387 None, [name, start_keys, end_keys],
388 ret_kind='docs')
389
390
391_complete_interface(DbInterface, BridgedJsDatabase,
392 prot_exposed=set([
393 '_put_doc_if_newer',
394 '_get_replica_gen_and_trans_id',
395 '_set_replica_gen_and_trans_id',
396 ]),
397 skip=set(['set_document_factory',]),
398 ret={
399 'create_doc_from_json': 'doc',
400 'create_doc': 'doc',
401 'get_doc': 'doc',
402 'get_doc_conflicts': 'docs',
403 'get_docs': 'docs',
404 'get_all_docs': 'gen_docs',
405 'whats_changed': 'whats_changed',
406 '_get_replica_gen_and_trans_id': 'tuple',
407 '_put_doc_if_newer': 'tuple',
408 'list_indexes': 'tuples',
409 'get_index_keys': 'tuples'
410 })
411
412
413class BridgedJsHTTPSyncTarget(BridgedJsObject):
414
415 def __init__(self, url):
416 self._js_bridge = get_u1db_js_bridge()
417 self._ref = self._make_http_sync_target(url)
418 self._cb_ref = None
419
420 def _forget(self):
421 if self._cb_ref:
422 self._forget_cb(self._cb_ref)
423 self._forget_http_sync_target(self._ref)
424
425 def set_oauth_credentials(self, consumer_key, consumer_secret,
426 token_key, token_secret):
427 self._bridge_meth('set_oauth_credentials', None,
428 [consumer_key, consumer_secret,
429 token_key, token_secret])
430
431 def sync_exchange(self, docs_by_generations, source_replica_uid,
432 last_known_generation, last_known_trans_id,
433 return_doc_cb, ensure_callback=None):
434 return self._bridge_meth_sync_exchange(docs_by_generations,
435 source_replica_uid,
436 last_known_generation,
437 last_known_trans_id,
438 return_doc_cb,
439 ensure_callback)
440
441 # testing/internal api
442
443 def _set_trace_hook_shallow(self, cb):
444 self._cb_ref = self._make_cb(cb)
445 self._invoke_cb(self._ref, '_set_trace_hook_shallow', self._cb_ref)
446
447
448_complete_interface(SyncTargetInterface, BridgedJsHTTPSyncTarget,
449 prot_exposed=set(),
450 skip=set(),
451 ret = {
452 'get_sync_info': 'tuple',
453 })
454
455
456class BridgedJsSynchronizer(BridgedJsObject):
457
458 def __init__(self, bridged_source_db, bridged_target):
459 self._js_bridge = get_u1db_js_bridge()
460 self._ref = self._make_synchronizer(bridged_source_db._ref,
461 bridged_target._ref)
462
463 def _forget(self):
464 self._forget_synchronizer(self._ref)
465
466 def sync(self):
467 return self._bridge_meth('sync', None, [])
468
469
470def make_database(test, replica_uid):
471 db = BridgedJsDatabase(replica_uid)
472 def cleanup():
473 db.delete_db()
474 db._forget()
475 test.addCleanup(cleanup)
476 return db
477
478def make_http_sync_target(test, path):
479 target = BridgedJsHTTPSyncTarget(test.getURL(path))
480 test.addCleanup(target._forget)
481 return target
482
483def make_synchronizer(test, source, target):
484 synchronizer = BridgedJsSynchronizer(source, target)
485 test.addCleanup(synchronizer._forget)
486 return synchronizer
0487
=== added file 'tests/setup.py'
--- tests/setup.py 1970-01-01 00:00:00 +0000
+++ tests/setup.py 2013-08-27 10:28:13 +0000
@@ -0,0 +1,6 @@
1from distutils.core import setup, Extension
2
3modul = Extension("u1dbqt", sources=["tests/qt-backend-wrapper.cpp"])
4setup(name = "U1DbQt", version = "1.0",
5 description = "", ext_modules = [modul])
6
07
=== added file 'tests/test-bridged.py'
--- tests/test-bridged.py 1970-01-01 00:00:00 +0000
+++ tests/test-bridged.py 2013-08-27 10:28:13 +0000
@@ -0,0 +1,186 @@
1import os
2
3from u1db import (
4 errors,
5 sync,
6 tests,
7 )
8from u1db.tests import (
9 test_backends,
10 test_remote_sync_target,
11 test_sync,
12 )
13from u1db.remote.cors_middleware import CORSMiddleware
14
15from tools import serving
16
17from bridged import (
18 get_u1db_js_bridge,
19 BridgedJsObject,
20 make_database,
21 make_http_sync_target,
22 make_synchronizer,
23 )
24
25_test_count = 0
26
27def setUp(self):
28 if FLAG:
29 global _test_count
30 _test_count += 1
31 get_u1db_js_bridge().flag("#%d %s" % (_test_count, self.id().split('.', 2)[2]))
32 super(self.__class__, self).setUp()
33
34def startServer(self):
35 app = self.make_app()
36 bridge = get_u1db_js_bridge()
37 if not SAME_ORIGIN or bridge.rhino:
38 (self.server_thread, self.server,
39 self.base_url) = serving.serve(app, 0, log_server=LOG_SERVER)
40 self.addCleanup(self.server_thread.join)
41 self.addCleanup(self.server.shutdown)
42 else:
43 self.server = bridge.get_server()
44 self.base_url = bridge.get_base_url()
45 bridge.set_fallback_app(app)
46 if getattr(app, 'base_url', 1) is None:
47 app.base_url = self.base_url
48
49SCENARIOS = [("jsbridged", {
50 "make_database_for_test": make_database,
51 })]
52
53def skip_test(test):
54 test.skipTest("skipped: not applicable/relevant")
55
56class BridgedAllDatabaseTests(test_backends.AllDatabaseTests):
57 scenarios = SCENARIOS
58 setUp = setUp
59
60class BridgedLocalDatabaseTests(test_backends.LocalDatabaseTests):
61 accept_fixed_trans_id = True
62 scenarios = SCENARIOS
63 setUp = setUp
64
65class BridgedLocalDatabaseValidateSourceGenTests(test_backends.LocalDatabaseValidateSourceGenTests):
66 scenarios = SCENARIOS
67 setUp = setUp
68
69class BridgedLocalDatabaseValidateGenNTransIdTests(test_backends.LocalDatabaseValidateGenNTransIdTests):
70 scenarios = SCENARIOS
71 setUp = setUp
72 test_validate_gen_and_trans_id_invalid_gen = skip_test
73
74class BridgedLocalDatabaseWithConflictsTests(test_backends.LocalDatabaseWithConflictsTests):
75 accept_fixed_trans_id = True
76 scenarios = SCENARIOS
77 setUp = setUp
78
79class BridgedDatabaseIndexTests(test_backends.DatabaseIndexTests):
80 scenarios = SCENARIOS
81 setUp = setUp
82
83class MyCORSMiddleware(CORSMiddleware):
84 _base_url = None
85
86 @property
87 def base_url(self):
88 return self._base_url
89
90 @base_url.setter
91 def base_url(self, value):
92 self.app.base_url = self._base_url = value
93
94def make_http_app(state):
95 app = test_remote_sync_target.make_http_app(state)
96 bridge = get_u1db_js_bridge()
97 if not SAME_ORIGIN:
98 return MyCORSMiddleware(app, ['*'])
99 return app
100
101def make_oauth_http_app(state):
102 app = test_remote_sync_target.make_oauth_http_app(state)
103 bridge = get_u1db_js_bridge()
104 if not SAME_ORIGIN:
105 return MyCORSMiddleware(app, ['*'])
106 return app
107
108def oauth_http_sync_target(test, path):
109 st = make_http_sync_target(test, '~/' + path)
110 st.set_oauth_credentials(tests.consumer1.key, tests.consumer1.secret,
111 tests.token1.key, tests.token1.secret)
112 return st
113
114class BridgedTestHttpSyncTarget(test_remote_sync_target.TestRemoteSyncTargets):
115 startServer = startServer
116 setUp = setUp
117
118 scenarios = [
119 ('http', {'make_app_with_state': make_http_app,
120 'make_document_for_test': tests.make_document_for_test,
121 'sync_target': make_http_sync_target}),
122 ('oauth_http', {'make_app_with_state':
123 make_oauth_http_app,
124 'make_document_for_test': tests.make_document_for_test,
125 'sync_target': oauth_http_sync_target}),
126 ]
127
128 if not SAME_ORIGIN:
129 failure_scenario_exceptions = (errors.UserQuotaExceeded,
130 errors.UserQuotaExceeded)
131
132def copy_database_for_test(test, db):
133 if isinstance(db, BridgedJsObject):
134 test.skipTest("js dbs cannot be copied")
135 return test_sync.copy_database_for_http_test(test, db)
136
137def sync_for_test(test, db_source, db_target, trace_hook=None, trace_hook_shallow=None):
138 if isinstance(db_source, BridgedJsObject):
139 if trace_hook:
140 test.skipTest("full trace hook not supported by http target")
141 path = test._http_at[db_target]
142 target = make_http_sync_target(test, path)
143 if trace_hook_shallow:
144 target._set_trace_hook_shallow(trace_hook_shallow)
145 return make_synchronizer(test, db_source, target).sync()
146 target = db_target.get_sync_target()
147 target._set_trace_hook_shallow(trace_hook or trace_hook_shallow)
148 return sync.Synchronizer(db_source, target).sync()
149
150class BridgedDatabaseSyncTests(test_sync.DatabaseSyncTests):
151 accept_fixed_trans_id = True
152 startServer = startServer
153
154 scenarios = [('jshttp', {
155 'make_database_for_test': None, # see create_database_for_role
156 'copy_database_for_test': copy_database_for_test,
157 'make_document_for_test': tests.make_document_for_test,
158 'make_app_with_state': make_http_app,
159 'do_sync': sync_for_test,
160 })]
161
162 def create_database_for_role(self, replica_uid, sync_role):
163 if sync_role == 'source':
164 js_db = make_database(self, replica_uid)
165 js_db._replica_uid = replica_uid
166 return js_db
167 return test_sync.make_database_for_http_test(self, replica_uid)
168
169 setUp = setUp
170 test_optional_sync_preserve_json = skip_test
171
172class BridgedTestDbSync(test_sync.TestDbSync):
173 startServer = startServer
174 scenarios = [
175 ('jshttp', {
176 'make_app_with_state': make_http_app,
177 'make_database_for_test': make_database,
178 }),
179 ('jsoauthhttp', {
180 'make_app_with_state': make_oauth_http_app,
181 'make_database_for_test': make_database,
182 'oauth': True
183 })]
184 setUp = setUp
185
186load_tests = tests.load_with_scenarios

Subscribers

People subscribed via source and target branches

to all changes: