def test_multiple_profiles(self):
        """Exercise multiple profiles and collections"""
        expected_count_all = 0
        profiles_count = 5
        collection_names = ( 'testing', 'keys', 'tabs', 'history', 'bookmarks' )
        collection_counts = {}

        # Produce a set of Profiles in the datastore
        profiles = []
        for i in range(profiles_count):
            profile = Profile(user_name='t-%s'%i, user_id='id-%s'%i, password='p-%s'%i)
            profile.put()
            profiles.append(profile)

        # Generate collections for each profile.
        for p in profiles:
            auth_header = self.build_auth_header(p.user_name, p.password)
            collection_counts[p.user_name] = {}

            # Run through several collections and make WBOs
            for cn in collection_names:

                curr_count = random.randint(1,10)
                collection_counts[p.user_name][cn] = curr_count
                expected_count_all += curr_count

                # Generate a bunch of random-content WBOs
                base_url = '/sync/1.0/%s/storage/%s' % (p.user_name, cn)
                for i in range(curr_count):
                    resp = self.put_random_wbo(base_url, auth_header)

        # Ensure the total number of WBOs is correct.
        result_count_all = WBO.all().count()
        self.assertEqual(expected_count_all, result_count_all)

        # Ensure the counts for each profile collection matches inserts.
        for profile in profiles:
            counts = Collection.get_counts(profile)
            for name in collection_names:
                c = Collection.get_by_profile_and_name(profile, name)
                self.assertEqual(
                    collection_counts[profile.user_name][name],
                    WBO.get_by_collection(c).count()
                )

        # Delete each of the collections for each user.
        for profile in profiles:
            auth_header = self.build_auth_header(
                profile.user_name, profile.password
            )
            for name in collection_names:
                url = '/sync/1.0/%s/storage/%s' % (profile.user_name, name)
                resp = self.app.delete(url, headers=auth_header)
                # Ensure the individual collection is now empty.
                c = Collection.get_by_profile_and_name(profile, name)
                self.assertEqual(0, WBO.get_by_collection(c).count())

        # Ensure there are no more WBOs
        result_count_all = WBO.all().count()
        self.assertEqual(0, result_count_all)
    def test_cascading_profile_delete(self):
        """Ensure that profile deletion cascades down to collections and WBOs"""
        (p, c, ah) = (self.profile, self.collection, self.auth_header)
        wbos = self.build_wbo_set()

        self.assert_(WBO.all().count() > 0)
        self.assert_(Collection.all().count() > 0)
        self.assert_(Profile.all().count() > 0)

        p.delete()

        self.assertEquals(0, WBO.all().count())
        self.assertEquals(0, Collection.all().count())
        self.assertEquals(0, Profile.all().count())
    def setUp(self):
        """Prepare for unit test"""
        self.log = logging.getLogger()
        self.log.setLevel(logging.DEBUG)
        
        # There shouldn't already be a profile, but just in case...
        profile = Profile.get_by_user_name(self.USER_NAME)
        if profile: profile.delete()

        # Create a new profile for tests.
        self.profile = p = Profile(
            user_name = self.USER_NAME,
            user_id   = '8675309',
            password  = self.PASSWD
        )
        self.profile.put()

        self.auth_header = self.build_auth_header(p.user_name, p.password)

        self.collection = Collection.get_by_profile_and_name(p, 'testing')

        self.wbo_values = [
            dict(zip(self.value_keys, value_set))
            for value_set in self.value_sets
        ]
        for w in self.wbo_values:
            w['payload'] = simplejson.dumps({ 'stuff': w['payload'] })
        
        # Build the app test harness.
        self.app = webtest.TestApp(sync_api.application())
Пример #4
0
    def post(self, user_name, collection_name):
        """Bulk update of WBOs in a collection"""
        out = { 'modified': None, 'success': [], 'failed': {} }

        collection = Collection.get_by_profile_and_name(
            self.request.profile, collection_name
        )

        wbos = []
        for wbo_data in self.request.body_json:
            if 'id' not in wbo_data: continue
            wbo_data['collection'] = collection
            wbo_id = wbo_data['id']
            (wbo, errors) = WBO.from_json(wbo_data)
            if wbo:
                out['modified'] = wbo.modified
                out['success'].append(wbo_id)
                wbos.append(wbo)
            else:
                out['failed'][wbo_id] = errors

        if (len(wbos) > 0):
            db.put(wbos)

        return out
Пример #5
0
    def get(self, user_name, collection_name):
        """Filtered retrieval of WBOs from a collection"""
        collection = Collection.get_by_profile_and_name(
            self.request.profile, collection_name
        )

        # TODO: Need a generator here? 
        # TODO: Find out how not to load everything into memory.
        params = self.normalize_retrieval_parameters()
        self.response.headers['X-Weave-Records'] = \
            str(collection.retrieve(count=True, **params))
        out = collection.retrieve(**params)

        accept = ('Accept' not in self.request.headers 
            and 'application/json' or self.request.headers['Accept'])

        if 'application/newlines' == accept:
            self.response.headers['Content-Type'] = 'application/newlines'
            for x in out:
                self.response.out.write("%s\n" % simplejson.dumps(x))

        elif 'application/whoisi' == accept:
            self.response.headers['Content-Type'] = 'application/whoisi'
            for x in out:
                rec = simplejson.dumps(x)
                self.response.out.write('%s%s' % (
                    struct.pack('!I', len(rec)), rec
                ))

        else:
            self.response.headers['Content-Type'] = 'application/json'
            rv = [x for x in out]
            self.response.out.write(simplejson.dumps(rv))
 def tearDown(self):
     """Clean up after unit test"""
     # Is this actually needed, since storage is mocked?
     self.profile.delete()
     q = WBO.all()
     for o in q: o.delete()
     q = Collection.all()
     for o in q: o.delete()
Пример #7
0
 def get(self, user_name, collection_name, wbo_id):
     """Get 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)
     return wbo.to_dict()
Пример #8
0
 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())
Пример #9
0
 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()
Пример #10
0
    def test_cascading_collection_delete(self):
        """Ensure that collection deletion cascades down to WBOs"""
        (p, c, ah) = (self.profile, self.collection, self.auth_header)
        wbos = self.build_wbo_set()

        count_all = WBO.all().count()
        collections = [c for c in Collection.all().ancestor(p)]
        for c in collections:
            c_count = len([x for x in c.retrieve()])
            c.delete()
            count_all -= c_count
            self.assertEqual(count_all, WBO.all().count())

        self.assertEqual(0, WBO.all().count())
Пример #11
0
 def get(self, user_name):
     """Get counts for a user's collections"""
     return Collection.get_counts(self.request.profile)
Пример #12
0
 def get(self, user_name):
     """List user's collections and last modified times"""
     return Collection.get_timestamps(self.request.profile)