The Artima Developer Community
Sponsored Link

Agile Buzz Forum
Andale! Andale! Yeehaw!

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
James Robertson

Posts: 29924
Nickname: jarober61
Registered: Jun, 2003

David Buck, Smalltalker at large
Andale! Andale! Yeehaw! Posted: Nov 21, 2005 11:45 AM
Reply to this message Reply

This post originated from an RSS feed registered with Agile Buzz by James Robertson.
Original Post: Andale! Andale! Yeehaw!
Feed Title: Travis Griggs - Blog
Feed URL: http://www.cincomsmalltalk.com/rssBlog/travis-rss.xml
Feed Description: This TAG Line is Extra
Latest Agile Buzz Posts
Latest Agile Buzz Posts by James Robertson
Latest Posts From Travis Griggs - Blog

Advertisement

A colleague refactored some code the other day. And our tests broke of course. So it was time to fix them. One of the harder scenarios to test is objects which move from state to state by some other process. Usually, I like test driven design for this, because it usually results in a design where the state changes are message sends and the process that actually triggers them is dumbed down to something simple like:

[self tick] repeat
And the rest is handily tested. In this case it wasn't so easy though. It used Delay's in between state changes. We tried, but it was just hard. One might use a mock object or add some more instance variables or things. Then I had this zany idea. I'm still not sure what I think of this long term. But it seemed cool at the time, and I like to experiment with new things (and reinforce my coworkers opinions that I'm crazy when armed with messages).

What if I could change time for the process? What if I could change my mind and tell it something like "I know you're waiting for something, but let's just skip that this time and get right down to business, OK?" What I really need, is a way to tell a process to un-delay itself. Can we do that? Sure, this is Smalltalk. :)

Process>'>unDelay
	suspendedContext ifNotNil: 
			[:sc | 
			sc sender ifNotNil: 
					[:sender | 
					(sender receiver isKindOf: Delay) 
						ifTrue: [(sc receiver isKindOf: Semaphore) ifTrue: [sc receiver signal]]]]

Basically this checks a process to see if it is suspended. It then determines by examining the message send history if it is waiting on a Semaphore, and if that Semaphore was put in place by a Delay. If so, it's just a simple matter of signalling the Semaphore. Cool, huh? Oh, the nifty things you can do with messages.

So this is handy for testing, but can we test it? Sure, why not. First of all, we have a simple test:

testUndelay
	| proc |
	touched := false.
	proc := 
			[(Delay forSeconds: 1000) wait.
			touched := true] fork.
	
	[proc unDelay.
	self deny: touched.
	Processor activeProcess yield.
	proc unDelay.
	Processor activeProcess yield.
	self assert: touched] 
			ensure: [proc terminate]
Fork a process that waits for a LONG time. Since we haven't yielded to the forked process, we check that an initial unDelay doesn't UHE or anything to begin with. Then we yield and give the process a chance to come alive and get to it's delay. When it does, we get back to our test which should be able to successfully unDelay now. We yield again to give it a chance to do the "touch" and then assert that. In retrospect, if proc had been run at a higher priority, we wouldn't have needed the yielding.

We can put together some edge case tests too:

testUndelayWhenBlockedByNonDelay
	| proc untouched sem |
	untouched := true.
	sem := Semaphore new.
	proc := 
			[sem wait.
			untouched := false] 
					forkAt: Processor activeProcess priority - 1.
	
	[proc unDelay.
	self assert: untouched.
	(Delay forSeconds: 0.1) wait.
	proc unDelay.
	self assert: untouched] 
			ensure: [proc terminate]
and
testUndelayWhenNoDelay
	| proc |
	proc := [Time waste: 10000] forkAt: Processor activeProcess priority - 1.
	
	[proc unDelay.
	(Delay forSeconds: 0.1) wait.
	proc unDelay] 
			ensure: [proc terminate]
The first checks to make sure that our unDelay will only signal a semaphore blocking a thread, WHEN that semaphore came from a Delay. And the second makes sure that it's ok to hammer processes that aren't delayed at all with unDelay. In fact if you start explaining your code out load to your coworker, you might start chanting something like "...and then we take this process here and we just send unDelay unDelay unDelay Yeehaw and it just hurries right on through everything..." And then, they will think your crazy.

Sidenote: I was disappointed to learn that Speedy Gonzales has been banished from just about any mainstream TV in the US. Apparently, he was racist. I guess I can dump my childhood reinforced baggage that my south-of-the-border cousins are smarter than me and my fellow cats. Sigh.

Read: Andale! Andale! Yeehaw!

Topic: 100 Bonus Geek Points Previous Topic   Next Topic Topic: Technorati, with irony

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use