src/JavaMonitorsTests.st
branchjk_new_structure
changeset 1143 5e1de8c6b43e
parent 1142 1a1ce9fd0a16
child 1144 c1c59b13340e
--- 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>"
 ! !