About testing that ensure works

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
19 messages Options
Reply | Threaded
Open this post in threaded view
|

About testing that ensure works

Stéphane Ducasse
Hi guys

in RPackage there is a method named withOrganizer:do:  defined as follows and I would like to test it to understand really if it does
what it says.

withOrganizer: aNewOrganizer do: aBlock
        "Perform an action locally to aNewOrganizer. Does not impact any other organizers."
       
        | old shouldRegisterAtTheEnd|
        [
        old := self organizer.
        shouldRegisterAtTheEnd := false.
        old hasRegistered ifTrue: [
                old unregister.
                shouldRegisterAtTheEnd := true.
                ].
        self organizer: aNewOrganizer.
        aBlock cull: aNewOrganizer.] ensure: [
                self organizer: old.
                shouldRegisterAtTheEnd ifTrue: [
                        self organizer register.
                        ].
                aNewOrganizer unregister.
                ]


So I wrote two tests

testWithDoIsCorrectlyReinstallingDefault
        "self debug: #testWithDoIsCorrectlyReinstallingDefault"
       
        | current empty |
        current := RPackageOrganizer default.  
        empty := RPackageOrganizer basicNew initialize.
        RPackage withOrganizer: empty
                 do: [ self assert: (SystemAnnouncer announcer hasSubscriber: empty).
                        self deny: (SystemAnnouncer announcer hasSubscriber: current)].
        self assert: (SystemAnnouncer announcer hasSubscriber: current).
        self deny: (SystemAnnouncer announcer hasSubscriber: empty)
               

and


testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt
        "self debug: #testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt"
       
        | current empty |
        current := RPackageOrganizer default.  
        empty := RPackageOrganizer basicNew initialize.
        RPackage withOrganizer: empty
                 do: [ self error.
                        self assert: (SystemAnnouncer announcer hasSubscriber: empty).
                        self deny: (SystemAnnouncer announcer hasSubscriber: current)].
        self assert: (SystemAnnouncer announcer hasSubscriber: current).
        self deny: (SystemAnnouncer announcer hasSubscriber: empty)

Now I would like to make sure that I raise an error or whaever to make sure that the ensure: block argument
is executed. Does anybody have an idea how I can do that. because self error does not work.

Stef




Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Igor Stasenko
First question what i wanna ask is:
- why do you need to play with two different instances of organizer,
and especially in such manner (temporary swapping forth and back)?

This code doesn't looks to be good.


On 24 April 2011 00:44, Stéphane Ducasse <[hidden email]> wrote:

> Hi guys
>
> in RPackage there is a method named withOrganizer:do:  defined as follows and I would like to test it to understand really if it does
> what it says.
>
> withOrganizer: aNewOrganizer do: aBlock
>        "Perform an action locally to aNewOrganizer. Does not impact any other organizers."
>
>        | old shouldRegisterAtTheEnd|
>        [
>        old := self organizer.
>        shouldRegisterAtTheEnd := false.
>        old hasRegistered ifTrue: [
>                old unregister.
>                shouldRegisterAtTheEnd := true.
>                ].
>        self organizer: aNewOrganizer.
>        aBlock cull: aNewOrganizer.] ensure: [
>                self organizer: old.
>                shouldRegisterAtTheEnd ifTrue: [
>                        self organizer register.
>                        ].
>                aNewOrganizer unregister.
>                ]
>
>
> So I wrote two tests
>
> testWithDoIsCorrectlyReinstallingDefault
>        "self debug: #testWithDoIsCorrectlyReinstallingDefault"
>
>        | current empty |
>        current := RPackageOrganizer default.
>        empty := RPackageOrganizer basicNew initialize.
>        RPackage withOrganizer: empty
>                 do: [ self assert: (SystemAnnouncer announcer hasSubscriber: empty).
>                        self deny: (SystemAnnouncer announcer hasSubscriber: current)].
>        self assert: (SystemAnnouncer announcer hasSubscriber: current).
>        self deny: (SystemAnnouncer announcer hasSubscriber: empty)
>
>
> and
>
>
> testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt
>        "self debug: #testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt"
>
>        | current empty |
>        current := RPackageOrganizer default.
>        empty := RPackageOrganizer basicNew initialize.
>        RPackage withOrganizer: empty
>                 do: [ self error.
>                        self assert: (SystemAnnouncer announcer hasSubscriber: empty).
>                        self deny: (SystemAnnouncer announcer hasSubscriber: current)].
>        self assert: (SystemAnnouncer announcer hasSubscriber: current).
>        self deny: (SystemAnnouncer announcer hasSubscriber: empty)
>
> Now I would like to make sure that I raise an error or whaever to make sure that the ensure: block argument
> is executed. Does anybody have an idea how I can do that. because self error does not work.
>
> Stef
>
>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Stéphane Ducasse
> First question what i wanna ask is:
> - why do you need to play with two different instances of organizer,
> and especially in such manner (temporary swapping forth and back)?
>
> This code doesn't looks to be good.

Igor can you reply to my question instead of questioning because it just slows me down.

Now the answer:
        when we run  the tests we do not run them in the default organizer because if something wrong happens
        then this is simply harakiri.
        So all the tests are performed in a separated created on the fly organizer.
        And I think that this is good to do it like that else I have to have a global variable and the rest.
        This design is the result of changes doru pushed me to do and they are good.
        Now this good is bad and not written my me and I'm trying to clean it and this is why I need to
        write tests because I want the Package code to be bullet proof.

Stef

>
>
> On 24 April 2011 00:44, Stéphane Ducasse <[hidden email]> wrote:
>> Hi guys
>>
>> in RPackage there is a method named withOrganizer:do:  defined as follows and I would like to test it to understand really if it does
>> what it says.
>>
>> withOrganizer: aNewOrganizer do: aBlock
>>        "Perform an action locally to aNewOrganizer. Does not impact any other organizers."
>>
>>        | old shouldRegisterAtTheEnd|
>>        [
>>        old := self organizer.
>>        shouldRegisterAtTheEnd := false.
>>        old hasRegistered ifTrue: [
>>                old unregister.
>>                shouldRegisterAtTheEnd := true.
>>                ].
>>        self organizer: aNewOrganizer.
>>        aBlock cull: aNewOrganizer.] ensure: [
>>                self organizer: old.
>>                shouldRegisterAtTheEnd ifTrue: [
>>                        self organizer register.
>>                        ].
>>                aNewOrganizer unregister.
>>                ]
>>
>>
>> So I wrote two tests
>>
>> testWithDoIsCorrectlyReinstallingDefault
>>        "self debug: #testWithDoIsCorrectlyReinstallingDefault"
>>
>>        | current empty |
>>        current := RPackageOrganizer default.
>>        empty := RPackageOrganizer basicNew initialize.
>>        RPackage withOrganizer: empty
>>                 do: [ self assert: (SystemAnnouncer announcer hasSubscriber: empty).
>>                        self deny: (SystemAnnouncer announcer hasSubscriber: current)].
>>        self assert: (SystemAnnouncer announcer hasSubscriber: current).
>>        self deny: (SystemAnnouncer announcer hasSubscriber: empty)
>>
>>
>> and
>>
>>
>> testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt
>>        "self debug: #testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt"
>>
>>        | current empty |
>>        current := RPackageOrganizer default.
>>        empty := RPackageOrganizer basicNew initialize.
>>        RPackage withOrganizer: empty
>>                 do: [ self error.
>>                        self assert: (SystemAnnouncer announcer hasSubscriber: empty).
>>                        self deny: (SystemAnnouncer announcer hasSubscriber: current)].
>>        self assert: (SystemAnnouncer announcer hasSubscriber: current).
>>        self deny: (SystemAnnouncer announcer hasSubscriber: empty)
>>
>> Now I would like to make sure that I raise an error or whaever to make sure that the ensure: block argument
>> is executed. Does anybody have an idea how I can do that. because self error does not work.
>>
>> Stef
>>
>>
>>
>>
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>


Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Igor Stasenko
On 24 April 2011 11:59, Stéphane Ducasse <[hidden email]> wrote:

>> First question what i wanna ask is:
>> - why do you need to play with two different instances of organizer,
>> and especially in such manner (temporary swapping forth and back)?
>>
>> This code doesn't looks to be good.
>
> Igor can you reply to my question instead of questioning because it just slows me down.
>
> Now the answer:
>        when we run  the tests we do not run them in the default organizer because if something wrong happens
>        then this is simply harakiri.
>        So all the tests are performed in a separated created on the fly organizer.
>        And I think that this is good to do it like that else I have to have a global variable and the rest.
>        This design is the result of changes doru pushed me to do and they are good.
>        Now this good is bad and not written my me and I'm trying to clean it and this is why I need to
>        write tests because I want the Package code to be bullet proof.
>

i am puzzled. You wanna to be sure that ensure block are executed?
It is.
However if error was triggered during ensure block evaluation, it may
not complete everything you put there.

And for test you can use non-local return to trigger ensure block:


 testWithDoIsCorrectlyReinstallingDefault
        "self debug: #testWithDoIsCorrectlyReinstallingDefault"

        | current empty |
        current := RPackageOrganizer default.
        empty := RPackageOrganizer basicNew initialize.

        self doWith:current and:empty.

        self assert: (SystemAnnouncer announcer hasSubscriber: current).
        self deny: (SystemAnnouncer announcer hasSubscriber: empty)


doWith:current and:empty

        RPackage withOrganizer: empty
                 do: [  ^ self  ].


Or with error:

testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt
        "self debug: #testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt"

        | current empty |
        current := RPackageOrganizer default.
        empty := RPackageOrganizer basicNew initialize.

[
        RPackage withOrganizer: empty
                 do: [ self error ].
] on: Error do: [:ex |  ].

        self assert: (SystemAnnouncer announcer hasSubscriber: current).
        self deny: (SystemAnnouncer announcer hasSubscriber: empty)


> Stef
>>
>>
>> On 24 April 2011 00:44, Stéphane Ducasse <[hidden email]> wrote:
>>> Hi guys
>>>
>>> in RPackage there is a method named withOrganizer:do:  defined as follows and I would like to test it to understand really if it does
>>> what it says.
>>>
>>> withOrganizer: aNewOrganizer do: aBlock
>>>        "Perform an action locally to aNewOrganizer. Does not impact any other organizers."
>>>
>>>        | old shouldRegisterAtTheEnd|
>>>        [
>>>        old := self organizer.
>>>        shouldRegisterAtTheEnd := false.
>>>        old hasRegistered ifTrue: [
>>>                old unregister.
>>>                shouldRegisterAtTheEnd := true.
>>>                ].
>>>        self organizer: aNewOrganizer.
>>>        aBlock cull: aNewOrganizer.] ensure: [
>>>                self organizer: old.
>>>                shouldRegisterAtTheEnd ifTrue: [
>>>                        self organizer register.
>>>                        ].
>>>                aNewOrganizer unregister.
>>>                ]
>>>
>>>
>>> So I wrote two tests
>>>
>>> testWithDoIsCorrectlyReinstallingDefault
>>>        "self debug: #testWithDoIsCorrectlyReinstallingDefault"
>>>
>>>        | current empty |
>>>        current := RPackageOrganizer default.
>>>        empty := RPackageOrganizer basicNew initialize.
>>>        RPackage withOrganizer: empty
>>>                 do: [ self assert: (SystemAnnouncer announcer hasSubscriber: empty).
>>>                        self deny: (SystemAnnouncer announcer hasSubscriber: current)].
>>>        self assert: (SystemAnnouncer announcer hasSubscriber: current).
>>>        self deny: (SystemAnnouncer announcer hasSubscriber: empty)
>>>
>>>
>>> and
>>>
>>>
>>> testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt
>>>        "self debug: #testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt"
>>>
>>>        | current empty |
>>>        current := RPackageOrganizer default.
>>>        empty := RPackageOrganizer basicNew initialize.
>>>        RPackage withOrganizer: empty
>>>                 do: [ self error.
>>>                        self assert: (SystemAnnouncer announcer hasSubscriber: empty).
>>>                        self deny: (SystemAnnouncer announcer hasSubscriber: current)].
>>>        self assert: (SystemAnnouncer announcer hasSubscriber: current).
>>>        self deny: (SystemAnnouncer announcer hasSubscriber: empty)
>>>
>>> Now I would like to make sure that I raise an error or whaever to make sure that the ensure: block argument
>>> is executed. Does anybody have an idea how I can do that. because self error does not work.
>>>
>>> Stef
>>>
>>>
>>>
>>>
>>>
>>
>>
>>
>> --
>> Best regards,
>> Igor Stasenko AKA sig.
>>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Stéphane Ducasse
>>>
> i am puzzled. You wanna to be sure that ensure block are executed?
> It is.

I want to write a test that shows and tests the withOrganizer:do: semantics.
In particular that the ensure is executed and that the context set by the withOrganizer: is only present
in the do: block.



> However if error was triggered during ensure block evaluation, it may
> not complete everything you put there.

Sure this is normal.

> And for test you can use non-local return to trigger ensure block:
>  


>        | current empty |
>        current := RPackageOrganizer default.
>        empty := RPackageOrganizer basicNew initialize.
>
> [
>        RPackage withOrganizer: empty
>                 do: [ self error ].
> ] on: Error do: [:ex |  ].
>
>        self assert: (SystemAnnouncer announcer hasSubscriber: current).
>        self deny: (SystemAnnouncer announcer hasSubscriber: empty)

Yes this is what I was thinking to do. because a self error alone was not.

Stef




Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Stéphane Ducasse
In reply to this post by Igor Stasenko
>
> testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt
>        "self debug: #testWithDoIsCorrectlyReinstallingDefaultEvenIfHalt"
>
>        | current empty |
>        current := RPackageOrganizer default.
>        empty := RPackageOrganizer basicNew initialize.
>
> [
>        RPackage withOrganizer: empty
>                 do: [ self error ].
> ] on: Error do: [:ex |  ].
>
>        self assert: (SystemAnnouncer announcer hasSubscriber: current).
>        self deny: (SystemAnnouncer announcer hasSubscriber: empty)

Igor but how can I specify that I want an error to occur in the do: and that I do not want to trap it but that the ensure
should trap it. Is the ensure execute if I trap the error like that?

Stef
Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Stéphane Ducasse
In reply to this post by Igor Stasenko
here is a simpler case

do: aBlock
       
        x := 5.
        [aBlock value]  ensure: [x :=3]

testDo
        "self run: #testDo"
       
        self do: [ self error].
        self assert: x = 3


and I do not understand why ensure is not executed :(
because I always want the ensure to happen not only on ifCurtailed:

Stef



Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Igor Stasenko
On 24 April 2011 13:26, Stéphane Ducasse <[hidden email]> wrote:

> here is a simpler case
>
> do: aBlock
>
>        x := 5.
>        [aBlock value]  ensure: [x :=3]
>
> testDo
>        "self run: #testDo"
>
>        self do: [ self error].
>        self assert: x = 3
>
>
> and I do not understand why ensure is not executed :(
> because I always want the ensure to happen not only on ifCurtailed:
>

error are not causing ensure block to trigger.
only after you either abandon or proceed, an ensure block will be executed.


> Stef
>

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Stéphane Ducasse

On Apr 24, 2011, at 12:43 PM, Igor Stasenko wrote:

> On 24 April 2011 13:26, Stéphane Ducasse <[hidden email]> wrote:
>> here is a simpler case
>>
>> do: aBlock
>>
>>        x := 5.
>>        [aBlock value]  ensure: [x :=3]
>>
>> testDo
>>        "self run: #testDo"
>>
>>        self do: [ self error].
>>        self assert: x = 3
>>
>>
>> and I do not understand why ensure is not executed :(
>> because I always want the ensure to happen not only on ifCurtailed:
>>
>
> error are not causing ensure block to trigger.

so what is causing them to trigger.
I always thought ensure: was really giving that warranty. So this is really scary to me.

I wrote that and this is green.

testDo2
        "self run: #testDo2 1 run, 1 passes, 0 expected failures, 0 failures, 0 errors, 0 unexpected passes"
       
        [self do: [ self error]
                ] on: Error do: [:ex | ].
        self assert: x = 3.

To me it means that I should not use ensure because it makes no sense to wrap the withOrganizer in a on: do: block
outside. So I do not see the real use of ensure:

Shit.....

Stef





> only after you either abandon or proceed, an ensure block will be executed.
>
>
>> Stef
>>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>


Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Stéphane Ducasse
In reply to this post by Igor Stasenko
I read what I wrote on the exception chapter and also the comments of the ensure: method
and I do not get why

>>
> error are not causing ensure block to trigger.
> only after you either abandon or proceed, an ensure block will be executed.

to me it completely defeats the purpose of ensure: or ifCurtailed:

Evaluate a termination block after evaluating the receiver, regardless of
         whether the receiver's evaluation completes.

So when should ensure: be used?
if I get an error because of a file problem will it be triggered?

I do not see how this is working in that case
       


Stef

PastedGraphic-1.pdf (86K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Stéphane Ducasse
In reply to this post by Igor Stasenko
How can I ensure that really in case of error or not a piece of code is executed.
Now I'm totally confused by the semantics of ensure:

So I wrote that:

testOnDo
        "self run: #testOnDo "
       
        self doOnDo: [ self error].
        self assert: x = 3.
        x := 77.
        self doOnDo: [x = 21].
        self assert: x = 3



ensure
        x := 3

doOnDo: aBlock
        x := 5.
        [aBlock value.
        self ensure] on: Error do:  [:ex | self ensure].
Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Stéphane Ducasse
In reply to this post by Igor Stasenko
Ok I got it I ws confused by SUnit interference

testDo
        "self run: #testDo"
       
        self do: [ Error signal].
        self assert: x = 3



self run: #testDo -> red tests
       
self debug: #testDo + proceed -> green tests






Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Igor Stasenko
On 24 April 2011 15:13, Stéphane Ducasse <[hidden email]> wrote:
> Ok I got it I ws confused by SUnit interference
>

:))

> testDo
>        "self run: #testDo"
>
>        self do: [ Error signal].
>        self assert: x = 3
>
>
>
> self run: #testDo -> red tests
>
> self debug: #testDo + proceed -> green tests
>

Yes, sunit interrupts execution at the moment when error was triggered,
before unwinding the stack.


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Henrik Sperre Johansen
In reply to this post by Stéphane Ducasse
On 24.04.2011 14:13, Stéphane Ducasse wrote:

> Ok I got it I ws confused by SUnit interference
>
> testDo
> "self run: #testDo"
>
> self do: [ Error signal].
> self assert: x = 3
>
>
>
> self run: #testDo ->  red tests
>
> self debug: #testDo + proceed ->  green tests

The ensure runs, but at that point the test already failed, see it says
"1 errors", not "1 failures" :)

To see it manually, you could put
Transcript show: 'Foo' or some such in the ensure block instead, and
notice how the Transcript is written :)

Cheers,
Henry

ps.
It's easier to just write
aBlock ensure: [blabla]
instead of
[aBlock value] ensure: [blabla]

... if aBlock REALLY is a block, and not aValuable, of course :=

Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Henrik Sperre Johansen
In reply to this post by Stéphane Ducasse
On 24.04.2011 12:05, Stéphane Ducasse wrote:
>> i am puzzled. You wanna to be sure that ensure block are executed?
>> It is.
> I want to write a test that shows and tests the withOrganizer:do: semantics.
> In particular that the ensure is executed and that the context set by the withOrganizer: is only present
> in the do: block.
>
In other words, another use case probably written more cleanly using the
non-existing
Announcer >> #suspend: subscriber while: aBlock

;)

Cheers,
Henry

Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Stéphane Ducasse
good suggestion.
I will check that.

Stef

On Apr 26, 2011, at 3:11 PM, Henrik Sperre Johansen wrote:

> On 24.04.2011 12:05, Stéphane Ducasse wrote:
>>> i am puzzled. You wanna to be sure that ensure block are executed?
>>> It is.
>> I want to write a test that shows and tests the withOrganizer:do: semantics.
>> In particular that the ensure is executed and that the context set by the withOrganizer: is only present
>> in the do: block.
>>
> In other words, another use case probably written more cleanly using the non-existing
> Announcer >> #suspend: subscriber while: aBlock
>
> ;)
>
> Cheers,
> Henry
>


Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Igor Stasenko
In reply to this post by Henrik Sperre Johansen
On 26 April 2011 15:11, Henrik Sperre Johansen
<[hidden email]> wrote:

> On 24.04.2011 12:05, Stéphane Ducasse wrote:
>>>
>>> i am puzzled. You wanna to be sure that ensure block are executed?
>>> It is.
>>
>> I want to write a test that shows and tests the withOrganizer:do:
>> semantics.
>> In particular that the ensure is executed and that the context set by the
>> withOrganizer: is only present
>> in the do: block.
>>
> In other words, another use case probably written more cleanly using the
> non-existing
> Announcer >> #suspend: subscriber while: aBlock
>

What is potential implementation?

Announcer >>suspend: subscriber while: aBlock
 | subscriptions |

subscriptions := OrderedCollection new.

registry subscriptionsOf: subscriber do: [:each |
  subscriptions add: each
].
registry removeSubscriber: subscriber.

^ aBlock ensure: [ subscriptions do: [:ea | registry add: ea ] ]


The problem is that its not doing exactly what is said:
 - it suspends existing subscriptions instead of suspending subscriber.

The difference between those are subtle but important:
  a suspended subscriber should not receive any announcements during
block evaluation,
even if it may want to subscribe to new ones during given block evaluation.
And the code above not handling this case , as well as it doesn't
handling the case when subscriber may want
to occasionally unsubscribe from some announcements during block evaluation.

So, for doing this correctly, a subscription registry should keep a
list of suspended subscribers somewhere,
and then in #deliver:
it should check if subscription's subscriber are not in that list, and
only then let it deliver an announcement.

The problem is that delivery time will slowdown considerably, because
for every subscription you should check
if it's subscriber are not in 'suspended subscribers' list.


So, it is really depends on intent. Suspending a concrete subscription
will require adding 'suspended' flag to subscription state.
But suspending a concrete subscriber and to guarantee that it won't
receive any announcements (even if it will subscribe for
a new ones during suspension time), can't be solved by having
'suspended' ivar on subscription. You have to manage suspended
subscribers list separately.

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Henrik Sperre Johansen
On 26.04.2011 17:37, Igor Stasenko wrote:

> On 26 April 2011 15:11, Henrik Sperre Johansen
> <[hidden email]>  wrote:
>> On 24.04.2011 12:05, Stéphane Ducasse wrote:
>>>> i am puzzled. You wanna to be sure that ensure block are executed?
>>>> It is.
>>> I want to write a test that shows and tests the withOrganizer:do:
>>> semantics.
>>> In particular that the ensure is executed and that the context set by the
>>> withOrganizer: is only present
>>> in the do: block.
>>>
>> In other words, another use case probably written more cleanly using the
>> non-existing
>> Announcer>>  #suspend: subscriber while: aBlock
>>
> What is potential implementation?
>
> Announcer>>suspend: subscriber while: aBlock
>   | subscriptions |
>
> subscriptions := OrderedCollection new.
>
> registry subscriptionsOf: subscriber do: [:each |
>    subscriptions add: each
> ].
> registry removeSubscriber: subscriber.
>
> ^ aBlock ensure: [ subscriptions do: [:ea | registry add: ea ] ]
>
>
> The problem is that its not doing exactly what is said:
>   - it suspends existing subscriptions instead of suspending subscriber.
>
> The difference between those are subtle but important:
>    a suspended subscriber should not receive any announcements during
> block evaluation,
> even if it may want to subscribe to new ones during given block evaluation.
> And the code above not handling this case , as well as it doesn't
> handling the case when subscriber may want
> to occasionally unsubscribe from some announcements during block evaluation.
>
> So, for doing this correctly, a subscription registry should keep a
> list of suspended subscribers somewhere,
> and then in #deliver:
> it should check if subscription's subscriber are not in that list, and
> only then let it deliver an announcement.
>
> The problem is that delivery time will slowdown considerably, because
> for every subscription you should check
> if it's subscriber are not in 'suspended subscribers' list.
>
>
> So, it is really depends on intent. Suspending a concrete subscription
> will require adding 'suspended' flag to subscription state.
> But suspending a concrete subscriber and to guarantee that it won't
> receive any announcements (even if it will subscribe for
> a new ones during suspension time), can't be solved by having
> 'suspended' ivar on subscription. You have to manage suspended
> subscribers list separately.
>
That'a a rather farfetched usecase it'd be nice to note in a method
comment is NOT supported at the moment, nothing more imho :)
Simply providing something like:

suspend(SubscriptionsOf): subscriber while: aBlock
|oldSubs|
oldSubs := subscriptionRegistry removeSubscriber: subscriber.
aBlock ensure: [oldSubs do: [ :each | subscriptionRegistry add: each]]

is better than nothing.

Cheers,
Henry

Reply | Threaded
Open this post in threaded view
|

Re: About testing that ensure works

Stéphane Ducasse
In reply to this post by Igor Stasenko
I see. Subtle. May be a solution not slowing everything but more limited is the way to go.


>>>>
>>>> i am puzzled. You wanna to be sure that ensure block are executed?
>>>> It is.
>>>
>>> I want to write a test that shows and tests the withOrganizer:do:
>>> semantics.
>>> In particular that the ensure is executed and that the context set by the
>>> withOrganizer: is only present
>>> in the do: block.
>>>
>> In other words, another use case probably written more cleanly using the
>> non-existing
>> Announcer >> #suspend: subscriber while: aBlock
>>
>
> What is potential implementation?
>
> Announcer >>suspend: subscriber while: aBlock
> | subscriptions |
>
> subscriptions := OrderedCollection new.
>
> registry subscriptionsOf: subscriber do: [:each |
>  subscriptions add: each
> ].
> registry removeSubscriber: subscriber.
>
> ^ aBlock ensure: [ subscriptions do: [:ea | registry add: ea ] ]
>
>
> The problem is that its not doing exactly what is said:
> - it suspends existing subscriptions instead of suspending subscriber.
>
> The difference between those are subtle but important:
>  a suspended subscriber should not receive any announcements during
> block evaluation,
> even if it may want to subscribe to new ones during given block evaluation.
> And the code above not handling this case , as well as it doesn't
> handling the case when subscriber may want
> to occasionally unsubscribe from some announcements during block evaluation.
>
> So, for doing this correctly, a subscription registry should keep a
> list of suspended subscribers somewhere,
> and then in #deliver:
> it should check if subscription's subscriber are not in that list, and
> only then let it deliver an announcement.
>
> The problem is that delivery time will slowdown considerably, because
> for every subscription you should check
> if it's subscriber are not in 'suspended subscribers' list.
>
>
> So, it is really depends on intent. Suspending a concrete subscription
> will require adding 'suspended' flag to subscription state.
> But suspending a concrete subscriber and to guarantee that it won't
> receive any announcements (even if it will subscribe for
> a new ones during suspension time), can't be solved by having
> 'suspended' ivar on subscription. You have to manage suspended
> subscribers list separately.
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>