Extreme Programming Challenge Fourteen Smalltalk Test

'Here's what I have so far. These tests are running. I haven't found the bug yet. (I do understand correctly that there is one, right?)

Recoded the BoundedBuffer in Smalltalk, along the lines I described, making the methods just return if there was no data for them. Wrote a test that cycles put and take once, twice, n-th up to the size of the object array I'm sending in (Strings of various sizes). Coding details below.

The test fails if you get more calls to put than the buffer size. It overwrites buffer items since the buffering is done mod the size of the buffer. The test handles the concurrency issue by checking whether the put and take returned having done something or not. Weird but valid, I think.

Right. That's why the Java code has its concurrency control. --tc

Not sure I take your point. I'm preserving the concurrency control in my test, though up till this version not correctly. Or am I missing something else?


BoundedBuffer code

"Filed out from Dolphin Smalltalk/Version 2.1"!

 Object subclass: #BoundedBuffer
instanceVariableNames: 'putAt takeAt occupied buffer'
classVariableNames: ''
poolDictionaries: ''!

!BoundedBuffer methodsFor!

initialize buffer := Array new: 4. occupied := 0. putAt := 0. takeAt := 0!

put: anObject occupied = buffer size ifTrue: [^nil]. occupied := occupied + 1. putAt := putAt \\ buffer size. buffer at: putAt + 1 put: anObject. putAt := putAt + 1!

take | result | occupied = 0 ifTrue: [^nil]. occupied := occupied - 1. takeAt := takeAt \\ buffer size. result := buffer at: takeAt + 1. takeAt := takeAt + 1. ^result! !

!BoundedBuffer class methodsFor!

new ^super new initialize! !

Test Code

 "Filed out from Dolphin Smalltalk/Version 2.1"!

TestCase subclass: #BoundedBufferTest instanceVariableNames: 'boundedBuffer sequence' classVariableNames: '' poolDictionaries: ''!

!BoundedBufferTest methodsFor!

cycle: anInteger read: readStream write: writeStream | done result | done := 0. [done < sequence size] whileTrue: [1 to: anInteger do: [ :each | | char consumed | readStream atEnd ifFalse: [char := readStream peek. consumed := boundedBuffer put: char. consumed isNil ifFalse: [readStream next. done := done + 1]]].
  1. to: anInteger do:
[ :each | | char | char := boundedBuffer take. char isNil ifFalse: [writeStream nextPut: char]]]. result := writeStream contents. self should: [result = sequence]!

setUp boundedBuffer := BoundedBuffer new!

test
  1. to: sequence size do:
[ :each | | read write |
read := ReadStream on: sequence.
write := WriteStream on: String new.
self
cycle: each
read: read
write: write]!

testString10 sequence := 'abcdefghij'. self test!

testString3 sequence := 'abc'. self test!

testString4 sequence := 'abcd'. self test! !


EditText of this page (last edited June 15, 2001) or FindPage with title or text search