~free.ekanayaka/storm/any-expr

« back to all changes in this revision

Viewing changes to tests/store/base.py

Merge variable-referenceset-leak [r=niemeyer,jkakar]

Change the way MutableValueVariable hooks up to the store event system, by
overriding get and set. This works around a leak discovered when using
PickleVariable in a ReferenceSet.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4237
4237
    def test_pickle_variable_unhook(self):
4238
4238
        """
4239
4239
        A variable instance must unhook itself from the store event system when
4240
 
        an object is deallocated: it prevents a leak if the object is never
4241
 
        removed from the store.
 
4240
        the store invalidates its objects.
4242
4241
        """
4243
4242
        # I create a custom PickleVariable, with no __slots__ definition, to be
4244
4243
        # able to get a weakref of it, thing that I can't do with
4268
4267
        gc.collect()
4269
4268
        self.assertTrue(var_ref() is None)
4270
4269
 
 
4270
    def test_pickle_variable_referenceset(self):
 
4271
        """
 
4272
        A variable instance must unhook itself from the store event system
 
4273
        explcitely when the store invalidates its objects: it's particulary
 
4274
        important when a ReferenceSet is used, because it keeps strong
 
4275
        references to objects involved.
 
4276
        """
 
4277
        class CustomPickleVariable(PickleVariable):
 
4278
            pass
 
4279
 
 
4280
        class CustomPickle(Pickle):
 
4281
            variable_class = CustomPickleVariable
 
4282
 
 
4283
        class PickleBlob(Blob):
 
4284
            bin = CustomPickle()
 
4285
            foo_id = Int()
 
4286
 
 
4287
        class FooBlobRefSet(Foo):
 
4288
            blobs = ReferenceSet(Foo.id, PickleBlob.foo_id)
 
4289
 
 
4290
        blob = self.store.get(Blob, 20)
 
4291
        blob.bin = "\x80\x02}q\x01U\x01aK\x01s."
 
4292
        self.store.flush()
 
4293
 
 
4294
        pickle_blob = self.store.get(PickleBlob, 20)
 
4295
 
 
4296
        foo = self.store.get(FooBlobRefSet, 10)
 
4297
        foo.blobs.add(pickle_blob)
 
4298
 
 
4299
        self.store.flush()
 
4300
        self.store.invalidate()
 
4301
 
 
4302
        obj_info = get_obj_info(pickle_blob)
 
4303
        variable =  obj_info.variables[PickleBlob.bin]
 
4304
        var_ref = weakref.ref(variable)
 
4305
        del variable, blob, pickle_blob, obj_info, foo
 
4306
        gc.collect()
 
4307
        self.assertTrue(var_ref() is None)
 
4308
 
 
4309
    def test_pickle_variable_referenceset_several_transactions(self):
 
4310
        """
 
4311
        Check that a pickle variable fires the changed event when used among
 
4312
        several transactions.
 
4313
        """
 
4314
        class PickleBlob(Blob):
 
4315
            bin = Pickle()
 
4316
            foo_id = Int()
 
4317
 
 
4318
        class FooBlobRefSet(Foo):
 
4319
            blobs = ReferenceSet(Foo.id, PickleBlob.foo_id)
 
4320
        blob = self.store.get(Blob, 20)
 
4321
        blob.bin = "\x80\x02}q\x01U\x01aK\x01s."
 
4322
        self.store.flush()
 
4323
 
 
4324
        pickle_blob = self.store.get(PickleBlob, 20)
 
4325
 
 
4326
        foo = self.store.get(FooBlobRefSet, 10)
 
4327
        foo.blobs.add(pickle_blob)
 
4328
 
 
4329
        self.store.flush()
 
4330
        self.store.invalidate()
 
4331
        self.store.reload(pickle_blob)
 
4332
 
 
4333
        pickle_blob.bin = "foo"
 
4334
        obj_info = get_obj_info(pickle_blob)
 
4335
        events = []
 
4336
        obj_info.event.hook("changed", lambda *args: events.append(args))
 
4337
        self.store.flush()
 
4338
        self.assertEquals(len(events), 1)
 
4339
 
4271
4340
    def test_undefined_variables_filled_on_find(self):
4272
4341
        """
4273
4342
        Check that when data is fetched from the database on a find,