--- a/src/JavaMonitorsTests.st Sun Nov 20 15:28:53 2011 +0000
+++ b/src/JavaMonitorsTests.st Sun Nov 20 19:40:45 2011 +0000
@@ -42,7 +42,7 @@
"{ Package: 'stx:libjava' }"
TestCase subclass:#JavaMonitorsTests
- instanceVariableNames:''
+ instanceVariableNames:'result reason thisProcess assertionAccess'
classVariableNames:''
poolDictionaries:''
category:'Languages-Java-Tests-Synchronization'
@@ -95,53 +95,206 @@
"
! !
+!JavaMonitorsTests methodsFor:'mh exploratory tests'!
+
+testAssertInAnotherThreadShouldFail
+ | t |
+ "i thought so"
+ t := [
+ self assert: false message: 'I just want it to fail'.
+ self waitForAndResumeThisProcess
+ ] newProcess.
+ t resume.
+ self stop.
+ self validateResult.
+
+ "Created: / 20-11-2011 / 19:09:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+!
+
+testIssSemaphoreSignalledAutomaticallyOnStop
+ | t1 t2 mon |
+ mon := JavaMonitor new.
+ t1 := [
+ mon enter.
+ self assert: (mon isOwnedBy: t1) message: 'mon was not owned by t1 in t1'.
+ t1 stop.
+ mon exit
+ ] newProcess.
+ t2 := [
+ [ t1 isStopped ] whileFalse: [ Delay waitForMilliseconds: 100 ].
+ self assert: (mon isOwnedBy: t1)
+ message: 'mon was not owned by t1 after t1 isStopped'.
+ t1 resume.
+ [ t1 isDead ] whileFalse: [ Delay waitForMilliseconds: 100. ].
+ self waitForAndResumeThisProcess.
+ ] newProcess.
+ t1 resume.
+ t2 resume.
+ self stop.
+ self validateResult.
+
+ "Created: / 20-11-2011 / 17:28:16 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+! !
+
+!JavaMonitorsTests methodsFor:'multithreading testing support'!
+
+assert: aBoolean message: message
+ assertionAccess critical: [
+ result ifTrue: [
+ result := aBoolean.
+ reason := message.
+ ].].
+
+ "Created: / 20-11-2011 / 18:54:44 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+!
+
+setUp
+ result := true.
+ reason := 'Everything went just fine'.
+ thisProcess := Processor activeProcess.
+ assertionAccess := Semaphore forMutualExclusion.
+
+ "Created: / 20-11-2011 / 18:55:39 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+!
+
+stop
+ thisProcess stop.
+
+ "Created: / 20-11-2011 / 19:07:12 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+!
+
+validateResult
+ super assert: result message: reason.
+
+ "Created: / 20-11-2011 / 18:55:17 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+!
+
+waitForAndResumeThisProcess
+ self waitForStoppingThread: thisProcess.
+ thisProcess resume.
+
+ "Created: / 20-11-2011 / 19:17:53 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+!
+
+waitForDyingThread: aThread
+
+[ aThread isDead ] whileFalse: [ Delay waitForMilliseconds: 100 ].
+
+ "Created: / 20-11-2011 / 19:27:54 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+!
+
+waitForStoppingThread: aThread
+ [ aThread isStopped ] whileFalse: [ Delay waitForMilliseconds: 100 ].
+
+ "Created: / 20-11-2011 / 19:17:02 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+! !
+
!JavaMonitorsTests methodsFor:'tests'!
+testBruteForceEnter
+ | mon threads cleanupThread |
+ mon := JavaMonitor new.
+ threads := OrderedCollection new.
+ 20 timesRepeat: [
+ | t |
+ t := [
+ 200 timesRepeat: [
+ mon enter.
+ self assert: (mon isOwnedBy: t)
+ message: 'monitor was not owned by t after enter'.
+ Delay waitForMilliseconds: 2.
+ mon exit.
+ self assert: (mon isOwnedBy: t) not
+ message: 'monitor was still owned by t after exit'.
+ ]
+ ] newProcess.
+ threads add: t
+ ].
+ cleanupThread := [
+ threads do: [:each | self waitForDyingThread: each ].
+ self waitForAndResumeThisProcess.
+ ] newProcess.
+ threads do: [:each | each resume ].
+ cleanupThread resume.
+ self stop.
+ self validateResult.
+
+ "Created: / 20-11-2011 / 19:37:28 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+!
+
testOneThread
| mon thread |
mon := JavaMonitor new.
thread := [
- self assertTrue: mon isAcquired not.
+ self assert: mon isAcquired not
+ message: 'monitor was acquired at the beginning'.
mon enter.
- self assertTrue: mon isAcquired.
- self assertTrue: (mon isOwnedBy: Processor activeProcess).
+ self assert: mon isAcquired
+ message: 'monitor was not acquired after monitor enter'.
+ self assert: (mon isOwnedBy: Processor activeProcess)
+ message: 'somebody else owned monitor after monitor enter'.
mon release.
- self assertTrue: mon isAcquired not.
- self assertTrue: (mon processesEntered includes: Processor activeProcess).
+ self assert: mon isAcquired not
+ message: 'monitor was still acquired after monitor release'.
+ self assert: (mon processesEntered includes: Processor activeProcess)
+ message: 'thread was not in the processesEntered after release'.
mon acquire.
- self assertTrue: mon isAcquired.
+ self assert: mon isAcquired
+ message: 'monitor was not acquired after monitor acquire'.
mon exit.
- self assertTrue: mon isAcquired not.
- self
- assertTrue: (mon processesEntered includes: Processor activeProcess) not.
+ self assert: mon isAcquired not
+ message: 'monitor stayed acquired after monitor exit'.
+ self assert: (mon processesEntered includes: Processor activeProcess) not
+ message: 'process was still in the processesEntered after monitorExit'.
+ self waitForAndResumeThisProcess.
] newProcess.
- thread start.
+ thread resume.
+ self stop.
+ self validateResult.
"Created: / 20-11-2011 / 13:20:59 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
testTwoThreads
- | mon thread anotherThread |
+ "this took me a while :)"
+
+ | mon t1 t2 |
mon := JavaMonitor new.
- thread := [
- mon enter.
- self assertTrue: (mon isOwnedBy: thread).
- anotherThread resume.
+ t1 := [
+ t1 stop.
+ mon enter.
+ t2 resume.
+ t1 stop.
+ self assert: (mon processesEntered includes: t2)
+ message: 't2 was not in processesEntered after entering monitor'.
mon release.
- self assertFalse: (mon isOwnedBy: thread).
- self assertTrue: (mon isOwnedBy: anotherThread).
- mon enter.
- self assertTrue: (mon isOwnedBy: thread).
- self assertFalse: (mon processesEntered includes: anotherThread).
+ t1 stop.
+ mon acquire.
+ self assert: (mon isOwnedBy: t1)
+ message: 'monitor was not owned by t1 after t2 exitted it'.
mon exit.
] newProcess.
- anotherThread := [
- anotherThread stop.
+ t2 := [
+ self waitForStoppingThread: t1.
+ t1 resume.
+ t2 stop.
+ self assert: mon isAcquired
+ message: 'monitor was not acquired after t1 entered it'.
+ self assert: (mon isOwnedBy: t1)
+ message: 'monitor was not owned by t1 after it entered it'.
+ t1 resume.
mon enter.
+ self assert: (mon isOwnedBy: t2)
+ message: 'monitor was not owned by t2 after waiting on enter'.
mon exit.
+ t1 resume.
+ self waitForDyingThread: t1.
+ self waitForAndResumeThisProcess
] newProcess.
- thread start.
- anotherThread start.
+ t1 resume.
+ t2 resume.
+ self stop.
+ self validateResult.
"Created: / 20-11-2011 / 14:51:22 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
! !