def test_storage_single_put_get_delete(self): """Exercise storing and getting a single object""" collection = 'foo' wbo_data = { "id": "abcd-1", "sortindex": 1, "payload": simplejson.dumps({ 'foo':1, 'bar':2 }), "modified": WBO.get_time_now() } auth_header = self.build_auth_header() storage_url = '/sync/1.0/%s/storage/%s/%s' % ( self.USER_NAME, collection, wbo_data['id'] ) resp = self.app.get(storage_url, headers=auth_header, status=404) resp = self.app.put(storage_url, headers=auth_header, status=400, params="THIS IS NOT JSON") self.assertEqual('400 Bad Request', resp.status) resp = self.app.put(storage_url, headers=auth_header, params=simplejson.dumps(wbo_data)) self.assertEqual('200 OK', resp.status) self.assert_(WBO.get_time_now() >= float(resp.body)) resp = self.app.get(storage_url, headers=auth_header) resp_wbo_data = simplejson.loads(resp.body) self.assertEqual(wbo_data['payload'], resp_wbo_data['payload']) resp = self.app.delete(storage_url, headers=auth_header) self.assertEqual('200 OK', resp.status) self.assert_(WBO.get_time_now() >= float(resp.body)) resp = self.app.get(storage_url, headers=auth_header, status=404)
def test_item_validation(self): """Exercise WBO data validation""" (p, c, ah) = (self.profile, self.collection, self.auth_header) too_long_id = ''.join('x' for x in range(100)) self.assert_('invalid id' in WBO.validate({ 'id': '' })) self.assert_('invalid id' in WBO.validate({ 'id': 'foo/bar' })) self.assert_('invalid id' in WBO.validate({ 'id': too_long_id })) self.assert_('invalid id' not in WBO.validate({ 'id': 'abcd' })) self.assert_('invalid collection' in WBO.validate({ })) self.assert_('invalid collection' in WBO.validate({ 'collection': Collection(name=too_long_id, profile=p) })) self.assert_('invalid predecessorid' in WBO.validate({ 'collection':c, 'predecessorid': too_long_id })) self.assert_('invalid predecessorid' in WBO.validate({ 'collection':c, 'predecessorid': 'abcdef' })) w = WBO( parent=c, collection=c, wbo_id='abcdef', modified=WBO.get_time_now(), payload='test' ) w.put() self.assert_('invalid predecessorid' not in WBO.validate({ 'collection':c, 'predecessorid': 'abcdef' })) self.assert_('invalid predecessorid' in WBO.validate({ 'collection':c, 'predecessorid': too_long_id })) self.assert_('invalid predecessorid' in WBO.validate({ 'collection':c, 'predecessorid': 'defghi' })) w = WBO( parent=c, collection=c, wbo_id='defghi', modified=WBO.get_time_now(), payload='test' ) w.put() self.assert_('invalid predecessorid' not in WBO.validate({ 'collection':c, 'predecessorid': 'abcdef' })) self.assert_('invalid modified date' in WBO.validate({ 'modified': 'abc' })) self.assert_('no modification date' in WBO.validate({ })) self.assert_('no modification date' in WBO.validate({ 'modified': '' })) self.assert_('invalid sortindex' in WBO.validate({ 'sortindex': 'abcd' })) self.assert_('invalid sortindex' in WBO.validate({ 'sortindex': -1000000000 })) self.assert_('invalid sortindex' in WBO.validate({ 'sortindex': 1000000000 })) self.assert_('payload needs to be json-encoded' in WBO.validate({ 'payload': 'abcd' })) self.assert_('payload too large' in WBO.validate({ 'payload': 'x'.join('x' for x in range(500000)) }))
def test_retrieval_by_id(self): """Exercise collection retrieval with a single ID""" (p, c, ah) = (self.profile, self.collection, self.auth_header) wbo_id = '1234' w = WBO(wbo_id=wbo_id, parent=c, collection=c, modified=WBO.get_time_now(), sortindex=1000, payload='payload-%s' % wbo_id, payload_size=9) w.put() url = '/sync/1.0/%s/storage/%s?id=%s' % (p.user_name, c.name, w.wbo_id) resp = self.app.get(url, headers=ah) result_data = simplejson.loads(resp.body) self.log.debug('RESPONSE %s' % resp.body) self.assertEqual(w.wbo_id, result_data[0]) url = '/sync/1.0/%s/storage/%s?id=%s&full=1' % (p.user_name, c.name, w.wbo_id) resp = self.app.get(url, headers=ah) result_data = simplejson.loads(resp.body) self.log.debug('RESPONSE %s' % resp.body) self.assertEqual(w.payload, result_data[0]['payload'])
def test_retrieval_by_multiple_ids(self): """Exercise collection retrieval with multiple IDs""" (p, c, ah) = (self.profile, self.collection, self.auth_header) wbos = [ WBO(wbo_id='%s' % wbo_id, parent=c, collection=c, modified=WBO.get_time_now(), sortindex=1000, payload='payload-%s' % wbo_id, payload_size=9 ) for wbo_id in range(10) ] for w in wbos: w.put() wbo_ids = [w.wbo_id for w in wbos] url = '/sync/1.0/%s/storage/%s?ids=%s' % ( p.user_name, c.name, ','.join(wbo_ids) ) resp = self.app.get(url, headers=ah) result_data = simplejson.loads(resp.body) wbo_ids.sort() result_data.sort() self.assertEqual(wbo_ids, result_data) self.assertEqual(len(wbo_ids), int(resp.headers['X-Weave-Records'])) url = '/sync/1.0/%s/storage/%s?ids=%s&full=1' % ( p.user_name, c.name, ','.join(wbo_ids) ) resp = self.app.get(url, headers=ah) result_data = simplejson.loads(resp.body) result_data.sort(lambda a,b: cmp(a['id'], b['id'])) for idx in range(len(wbos)): self.assertEqual(wbos[idx].payload, result_data[idx]['payload']) self.assertEqual(len(wbo_ids), int(resp.headers['X-Weave-Records']))
def test_retrieval_by_id(self): """Exercise collection retrieval with a single ID""" (p, c, ah) = (self.profile, self.collection, self.auth_header) wbo_id = '1234' w = WBO(wbo_id=wbo_id, parent=c, collection=c, modified=WBO.get_time_now(), sortindex=1000, payload='payload-%s' % wbo_id, payload_size=9) w.put() url = '/sync/1.0/%s/storage/%s?id=%s' % ( p.user_name, c.name, w.wbo_id ) resp = self.app.get(url, headers=ah) result_data = simplejson.loads(resp.body) self.log.debug('RESPONSE %s' % resp.body) self.assertEqual(w.wbo_id, result_data[0]) url = '/sync/1.0/%s/storage/%s?id=%s&full=1' % ( p.user_name, c.name, w.wbo_id ) resp = self.app.get(url, headers=ah) result_data = simplejson.loads(resp.body) self.log.debug('RESPONSE %s' % resp.body) self.assertEqual(w.payload, result_data[0]['payload'])
def delete(self, user_name, collection_name, wbo_id): """Delete an item from the collection""" collection = Collection.get_by_profile_and_name( self.request.profile, collection_name) wbo = WBO.get_by_collection_and_wbo_id(collection, wbo_id) if not wbo: return self.error(404) wbo.delete() self.response.out.write('%s' % WBO.get_time_now())
def delete(self, user_name, collection_name): """Bulk deletion of WBOs from a collection""" collection = Collection.get_by_profile_and_name( self.request.profile, collection_name) params = self.normalize_retrieval_parameters() params['wbo'] = True out = collection.retrieve(**params) db.delete(out) return WBO.get_time_now()
def delete(self, user_name, collection_name, wbo_id): """Delete an item from the collection""" collection = Collection.get_by_profile_and_name( self.request.profile, collection_name ) wbo = WBO.get_by_collection_and_wbo_id(collection, wbo_id) if not wbo: return self.error(404) wbo.delete() self.response.out.write('%s' % WBO.get_time_now())
def delete(self, user_name, collection_name): """Bulk deletion of WBOs from a collection""" collection = Collection.get_by_profile_and_name( self.request.profile, collection_name ) params = self.normalize_retrieval_parameters() params['wbo'] = True out = collection.retrieve(**params) db.delete(out) return WBO.get_time_now()
def test_storage_single_put_get_delete(self): """Exercise storing and getting a single object""" collection = 'foo' wbo_data = { "id": "abcd-1", "sortindex": 1, "payload": simplejson.dumps({ 'foo': 1, 'bar': 2 }), "modified": WBO.get_time_now() } auth_header = self.build_auth_header() storage_url = '/sync/1.0/%s/storage/%s/%s' % ( self.USER_NAME, collection, wbo_data['id']) resp = self.app.get(storage_url, headers=auth_header, status=404) resp = self.app.put(storage_url, headers=auth_header, status=400, params="THIS IS NOT JSON") self.assertEqual('400 Bad Request', resp.status) resp = self.app.put(storage_url, headers=auth_header, params=simplejson.dumps(wbo_data)) self.assertEqual('200 OK', resp.status) self.assert_(WBO.get_time_now() >= float(resp.body)) resp = self.app.get(storage_url, headers=auth_header) resp_wbo_data = simplejson.loads(resp.body) self.assertEqual(wbo_data['payload'], resp_wbo_data['payload']) resp = self.app.delete(storage_url, headers=auth_header) self.assertEqual('200 OK', resp.status) self.assert_(WBO.get_time_now() >= float(resp.body)) resp = self.app.get(storage_url, headers=auth_header, status=404)
def build_wbo_parents_and_predecessors(self): (p, c, ah) = (self.profile, self.collection, self.auth_header) id_sets = dict([(kind, set([w[kind] for w in self.wbo_values])) for kind in ('parentid', 'predecessorid')]) for kind, id_set in id_sets.items(): for wbo_id in id_set: w = WBO(parent=c, collection=c, modified=WBO.get_time_now(), wbo_id=wbo_id, payload=simplejson.dumps({'random': 'xxx'})) w.put()
def test_bulk_update(self): """Exercise bulk collection update""" (p, c, ah) = (self.profile, self.collection, self.auth_header) auth_header = self.build_auth_header() storage_url = '/sync/1.0/%s/storage/%s' % (p.user_name, c.name) self.build_wbo_parents_and_predecessors() bulk_data = [ { 'id': '' }, { 'id': 'foo/bar', 'sortindex': 'abcd' }, { 'id': 'a-1000', 'sortindex':-1000000000 }, { 'id': 'a-1001', 'sortindex': 1000000000 }, { 'id': 'a-1002', 'parentid': 'notfound' }, { 'id': 'a-1003', 'predecessorid': 'notfound' }, { 'id': 'a-1004', 'payload': 'invalid' }, ] bulk_data.extend(self.wbo_values) self.log.debug("DATA %s" % simplejson.dumps(bulk_data)) resp = self.app.post( storage_url, headers=auth_header, params=simplejson.dumps(bulk_data) ) self.assertEqual('200 OK', resp.status) result_data = simplejson.loads(resp.body) self.log.debug("RESULT %s" % resp.body) self.assert_(WBO.get_time_now() >= float(result_data['modified'])) expected_ids = [ w['id'] for w in self.wbo_values ] self.assertEqual(expected_ids, result_data['success']) expected_failures = { "": ["invalid id"], "a-1004": ["payload needs to be json-encoded"], "a-1003": ["invalid predecessorid"], "a-1002": ["invalid parentid"], "a-1001": ["invalid sortindex"], "a-1000": ["invalid sortindex"], "foo/bar": ["invalid id", "invalid sortindex"] } self.assertEqual(expected_failures, result_data['failed']) stored_ids = [ w.wbo_id for w in WBO.all() ] for wbo_id in expected_ids: self.assert_(wbo_id in stored_ids)
def build_wbo_parents_and_predecessors(self): (p, c, ah) = (self.profile, self.collection, self.auth_header) id_sets = dict([ (kind, set([ w[kind] for w in self.wbo_values ])) for kind in ('parentid', 'predecessorid') ]) for kind, id_set in id_sets.items(): for wbo_id in id_set: w = WBO( parent=c, collection=c, modified = WBO.get_time_now(), wbo_id = wbo_id, payload = simplejson.dumps({'random':'xxx'}) ) w.put()
def test_deletion_by_multiple_ids(self): """Exercise bulk deletion with a set of IDs""" (p, c, ah) = (self.profile, self.collection, self.auth_header) wbos = self.build_wbo_set() wbo_ids = [w.wbo_id for w in wbos] to_delete_ids = wbo_ids[0:len(wbo_ids) / 2] url = '/sync/1.0/%s/storage/%s?ids=%s' % (p.user_name, c.name, ','.join(to_delete_ids)) resp = self.app.delete(url, headers=ah) self.assertEqual('200 OK', resp.status) self.assert_(WBO.get_time_now() >= float(resp.body)) result_ids = [w.wbo_id for w in WBO.all()] for wbo_id in to_delete_ids: self.assert_(wbo_id not in result_ids)
def test_deletion_by_multiple_ids(self): """Exercise bulk deletion with a set of IDs""" (p, c, ah) = (self.profile, self.collection, self.auth_header) wbos = self.build_wbo_set() wbo_ids = [w.wbo_id for w in wbos] to_delete_ids = wbo_ids[0:len(wbo_ids)/2] url = '/sync/1.0/%s/storage/%s?ids=%s' % ( p.user_name, c.name, ','.join(to_delete_ids) ) resp = self.app.delete(url, headers=ah) self.assertEqual('200 OK', resp.status) self.assert_(WBO.get_time_now() >= float(resp.body)) result_ids = [w.wbo_id for w in WBO.all()] for wbo_id in to_delete_ids: self.assert_(wbo_id not in result_ids)
def build_wbo_set(self, num_wbos=15): (p, c, ah) = (self.profile, self.collection, self.auth_header) self.build_wbo_parents_and_predecessors() wbos = [] for values in self.wbo_values: w = WBO(parent=c, collection=c, modified=WBO.get_time_now(), wbo_id=values['id'], parentid=values['parentid'], predecessorid=values['predecessorid'], sortindex=values['sortindex'], payload=values['payload']) w.put() wbos.append(w) time.sleep(0.1) # HACK: Delay to ensure modified stamps vary return wbos
def test_retrieval_by_index_above_and_below(self): """Exercise collection retrieval on sortindex range""" (p, c, ah) = (self.profile, self.collection, self.auth_header) wbo_sortindexes = (-100, -10, -1, 0, 1, 10, 23, 100, 999, 1000, 9999) wbos = [] for idx in range(len(wbo_sortindexes)): sortindex = wbo_sortindexes[idx] wbo_id = '%s' % idx w = WBO(wbo_id=wbo_id, parent=c, collection=c, modified=WBO.get_time_now(), sortindex=sortindex, payload='payload-%s' % wbo_id, payload_size=9) w.put() self.log.debug("WBO %s" % simplejson.dumps(w.to_dict())) wbos.append(w) # TODO: Try a variety of ranges here? (index_above, index_below) = (-10, 1000) expected_ids = [ w.wbo_id for w in wbos if index_above < w.sortindex and w.sortindex < index_below ] url = '/sync/1.0/%s/storage/%s?index_above=%s&index_below=%s' % ( p.user_name, c.name, index_above, index_below) resp = self.app.get(url, headers=ah) result_data = simplejson.loads(resp.body) expected_ids.sort() result_data.sort() self.log.debug("URL %s" % url) self.log.debug("EXPECTED %s" % simplejson.dumps(expected_ids)) self.log.debug("RESULT %s" % resp.body) self.assertEqual(expected_ids, result_data)
def build_wbo_set(self, num_wbos=15): (p, c, ah) = (self.profile, self.collection, self.auth_header) self.build_wbo_parents_and_predecessors() wbos = [] for values in self.wbo_values: w = WBO( parent=c, collection=c, modified=WBO.get_time_now(), wbo_id = values['id'], parentid = values['parentid'], predecessorid = values['predecessorid'], sortindex = values['sortindex'], payload = values['payload'] ) w.put() wbos.append(w) time.sleep(0.1) # HACK: Delay to ensure modified stamps vary return wbos
def test_retrieval_by_index_above_and_below(self): """Exercise collection retrieval on sortindex range""" (p, c, ah) = (self.profile, self.collection, self.auth_header) wbo_sortindexes = ( -100, -10, -1, 0, 1, 10, 23, 100, 999, 1000, 9999 ) wbos = [ ] for idx in range(len(wbo_sortindexes)): sortindex = wbo_sortindexes[idx] wbo_id = '%s' % idx w = WBO(wbo_id=wbo_id, parent=c, collection=c, modified=WBO.get_time_now(), sortindex=sortindex, payload='payload-%s' % wbo_id, payload_size=9) w.put() self.log.debug("WBO %s" % simplejson.dumps(w.to_dict())) wbos.append(w) # TODO: Try a variety of ranges here? (index_above, index_below) = (-10, 1000) expected_ids = [ w.wbo_id for w in wbos if index_above < w.sortindex and w.sortindex < index_below ] url = '/sync/1.0/%s/storage/%s?index_above=%s&index_below=%s' % ( p.user_name, c.name, index_above, index_below ) resp = self.app.get(url, headers=ah) result_data = simplejson.loads(resp.body) expected_ids.sort() result_data.sort() self.log.debug("URL %s" % url) self.log.debug("EXPECTED %s" % simplejson.dumps(expected_ids)) self.log.debug("RESULT %s" % resp.body) self.assertEqual(expected_ids, result_data)
def test_retrieval_by_multiple_ids(self): """Exercise collection retrieval with multiple IDs""" (p, c, ah) = (self.profile, self.collection, self.auth_header) wbos = [ WBO(wbo_id='%s' % wbo_id, parent=c, collection=c, modified=WBO.get_time_now(), sortindex=1000, payload='payload-%s' % wbo_id, payload_size=9) for wbo_id in range(10) ] for w in wbos: w.put() wbo_ids = [w.wbo_id for w in wbos] url = '/sync/1.0/%s/storage/%s?ids=%s' % (p.user_name, c.name, ','.join(wbo_ids)) resp = self.app.get(url, headers=ah) result_data = simplejson.loads(resp.body) wbo_ids.sort() result_data.sort() self.assertEqual(wbo_ids, result_data) self.assertEqual(len(wbo_ids), int(resp.headers['X-Weave-Records'])) url = '/sync/1.0/%s/storage/%s?ids=%s&full=1' % (p.user_name, c.name, ','.join(wbo_ids)) resp = self.app.get(url, headers=ah) result_data = simplejson.loads(resp.body) result_data.sort(lambda a, b: cmp(a['id'], b['id'])) for idx in range(len(wbos)): self.assertEqual(wbos[idx].payload, result_data[idx]['payload']) self.assertEqual(len(wbo_ids), int(resp.headers['X-Weave-Records']))
def initialize(self, req, resp): webapp.RequestHandler.initialize(self, req, resp) self.log = logging.getLogger() self.response.headers['X-Weave-Timestamp'] = str(WBO.get_time_now())
def test_collection_counts_and_timestamps(self): """Exercise collection counts and timestamps""" profile = Profile(user_name = 'tester-1', user_id='8675309', password = '******') profile.put() auth_header = self.build_auth_header( profile.user_name, profile.password ) expected_count_all = 0 expected_counts = { 'clients':2, 'crypto':0, 'forms':6, 'history':0, 'keys':10, 'meta':12, 'bookmarks':14, 'prefs':16, 'tabs':18, 'passwords':20, 'foo':12, 'bar':14, 'baz':16 } expected_dates = {} # Insert objects with random contents to satisfy the expected counts for collection_name, curr_count in expected_counts.items(): base_url = '/sync/1.0/%s/storage/%s' % ( profile.user_name, collection_name ) for i in range(curr_count): resp = self.put_random_wbo(base_url, auth_header) expected_dates[collection_name] = float(resp.body) expected_count_all += 1 # Ensure the counts match expected resp = self.app.get( '/sync/1.0/%s/info/collection_counts' % (profile.user_name), headers=auth_header ) resp_data = simplejson.loads(resp.body) self.assertEqual(expected_counts, resp_data) # Ensure all timestamps are same or newer than expected. resp = self.app.get( '/sync/1.0/%s/info/collections' % (profile.user_name), headers=auth_header ) resp_data = simplejson.loads(resp.body) for k,v in expected_dates.items(): self.assert_(k in resp_data) self.assert_(resp_data[k] >= expected_dates[k]) # Verify the count of all objects after creating result_count = WBO.all().count() self.assertEqual(expected_count_all, result_count) # Delete each collection and verify the count after for collection_name, curr_count in expected_counts.items(): url = '/sync/1.0/%s/storage/%s' % ( profile.user_name, collection_name ) resp = self.app.delete(url, headers=auth_header) self.assert_(WBO.get_time_now() >= float(resp.body)) expected_count_all -= curr_count result_count = WBO.all().count() self.assertEqual(expected_count_all, result_count) # No WBOs should be left after all collections deleted. result_count = WBO.all().count() self.assertEqual(0, result_count)
def test_item_validation(self): """Exercise WBO data validation""" (p, c, ah) = (self.profile, self.collection, self.auth_header) too_long_id = ''.join('x' for x in range(100)) self.assert_('invalid id' in WBO.validate({'id': ''})) self.assert_('invalid id' in WBO.validate({'id': 'foo/bar'})) self.assert_('invalid id' in WBO.validate({'id': too_long_id})) self.assert_('invalid id' not in WBO.validate({'id': 'abcd'})) self.assert_('invalid collection' in WBO.validate({})) self.assert_('invalid collection' in WBO.validate( {'collection': Collection(name=too_long_id, profile=p)})) self.assert_('invalid predecessorid' in WBO.validate( { 'collection': c, 'predecessorid': too_long_id })) self.assert_( 'invalid predecessorid' in WBO.validate({ 'collection': c, 'predecessorid': 'abcdef' })) w = WBO(parent=c, collection=c, wbo_id='abcdef', modified=WBO.get_time_now(), payload='test') w.put() self.assert_('invalid predecessorid' not in WBO.validate( { 'collection': c, 'predecessorid': 'abcdef' })) self.assert_('invalid predecessorid' in WBO.validate( { 'collection': c, 'predecessorid': too_long_id })) self.assert_( 'invalid predecessorid' in WBO.validate({ 'collection': c, 'predecessorid': 'defghi' })) w = WBO(parent=c, collection=c, wbo_id='defghi', modified=WBO.get_time_now(), payload='test') w.put() self.assert_('invalid predecessorid' not in WBO.validate( { 'collection': c, 'predecessorid': 'abcdef' })) self.assert_( 'invalid modified date' in WBO.validate({'modified': 'abc'})) self.assert_('no modification date' in WBO.validate({})) self.assert_('no modification date' in WBO.validate({'modified': ''})) self.assert_( 'invalid sortindex' in WBO.validate({'sortindex': 'abcd'})) self.assert_( 'invalid sortindex' in WBO.validate({'sortindex': -1000000000})) self.assert_( 'invalid sortindex' in WBO.validate({'sortindex': 1000000000})) self.assert_('payload needs to be json-encoded' in WBO.validate( {'payload': 'abcd'})) self.assert_('payload too large' in WBO.validate( {'payload': 'x'.join('x' for x in range(500000))}))
def test_bulk_update(self): """Exercise bulk collection update""" (p, c, ah) = (self.profile, self.collection, self.auth_header) auth_header = self.build_auth_header() storage_url = '/sync/1.0/%s/storage/%s' % (p.user_name, c.name) self.build_wbo_parents_and_predecessors() bulk_data = [ { 'id': '' }, { 'id': 'foo/bar', 'sortindex': 'abcd' }, { 'id': 'a-1000', 'sortindex': -1000000000 }, { 'id': 'a-1001', 'sortindex': 1000000000 }, { 'id': 'a-1002', 'parentid': 'notfound' }, { 'id': 'a-1003', 'predecessorid': 'notfound' }, { 'id': 'a-1004', 'payload': 'invalid' }, ] bulk_data.extend(self.wbo_values) self.log.debug("DATA %s" % simplejson.dumps(bulk_data)) resp = self.app.post(storage_url, headers=auth_header, params=simplejson.dumps(bulk_data)) self.assertEqual('200 OK', resp.status) result_data = simplejson.loads(resp.body) self.log.debug("RESULT %s" % resp.body) self.assert_(WBO.get_time_now() >= float(result_data['modified'])) expected_ids = [w['id'] for w in self.wbo_values] self.assertEqual(expected_ids, result_data['success']) expected_failures = { "": ["invalid id"], "a-1004": ["payload needs to be json-encoded"], "a-1003": ["invalid predecessorid"], "a-1002": ["invalid parentid"], "a-1001": ["invalid sortindex"], "a-1000": ["invalid sortindex"], "foo/bar": ["invalid id", "invalid sortindex"] } self.assertEqual(expected_failures, result_data['failed']) stored_ids = [w.wbo_id for w in WBO.all()] for wbo_id in expected_ids: self.assert_(wbo_id in stored_ids)
def test_collection_counts_and_timestamps(self): """Exercise collection counts and timestamps""" profile = Profile(user_name='tester-1', user_id='8675309', password='******') profile.put() auth_header = self.build_auth_header(profile.user_name, profile.password) expected_count_all = 0 expected_counts = { 'clients': 2, 'crypto': 0, 'forms': 6, 'history': 0, 'keys': 10, 'meta': 12, 'bookmarks': 14, 'prefs': 16, 'tabs': 18, 'passwords': 20, 'foo': 12, 'bar': 14, 'baz': 16 } expected_dates = {} # Insert objects with random contents to satisfy the expected counts for collection_name, curr_count in expected_counts.items(): base_url = '/sync/1.0/%s/storage/%s' % (profile.user_name, collection_name) for i in range(curr_count): resp = self.put_random_wbo(base_url, auth_header) expected_dates[collection_name] = float(resp.body) expected_count_all += 1 # Ensure the counts match expected resp = self.app.get('/sync/1.0/%s/info/collection_counts' % (profile.user_name), headers=auth_header) resp_data = simplejson.loads(resp.body) self.assertEqual(expected_counts, resp_data) # Ensure all timestamps are same or newer than expected. resp = self.app.get('/sync/1.0/%s/info/collections' % (profile.user_name), headers=auth_header) resp_data = simplejson.loads(resp.body) for k, v in expected_dates.items(): self.assert_(k in resp_data) self.assert_(resp_data[k] >= expected_dates[k]) # Verify the count of all objects after creating result_count = WBO.all().count() self.assertEqual(expected_count_all, result_count) # Delete each collection and verify the count after for collection_name, curr_count in expected_counts.items(): url = '/sync/1.0/%s/storage/%s' % (profile.user_name, collection_name) resp = self.app.delete(url, headers=auth_header) self.assert_(WBO.get_time_now() >= float(resp.body)) expected_count_all -= curr_count result_count = WBO.all().count() self.assertEqual(expected_count_all, result_count) # No WBOs should be left after all collections deleted. result_count = WBO.all().count() self.assertEqual(0, result_count)
def initialize(self, req, resp): webapp.RequestHandler.initialize(self, req, resp) self.log = logging.getLogger() self.response.headers['X-Weave-Timestamp'] = str(WBO.get_time_now())