RegressionTests__RecursionLockTests.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Mon, 28 Aug 2017 21:05:24 +0100
branchjv
changeset 1954 f868e5f2043f
child 1962 19bb5e423587
permissions -rw-r--r--
Added tests for `RecursionLock`

"{ Package: 'stx:goodies/regression' }"

"{ NameSpace: RegressionTests }"

ProcessSpawningTestCase subclass:#RecursionLockTests
	instanceVariableNames:'lock'
	classVariableNames:''
	poolDictionaries:''
	category:'tests-Regression'
!


!RecursionLockTests methodsFor:'running'!

setUp
    super setUp.
    lock := RecursionLock new name: self printString

    "Created: / 28-08-2017 / 21:49:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!RecursionLockTests methodsFor:'tests'!

test_critical_01

    [
        | active |

        active := Processor activeProcess.

        self assert: lock owner isNil.
        self assert: lock count == 0.
        lock critical:[ 
            self assert: lock owner == active.
            self assert: lock count == 1.            
        ].
        self assert: lock owner isNil.
        self assert: lock count == 0.
    ] fork.

    "Created: / 28-08-2017 / 21:48:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

test_critical_02

    [
        | active |

        active := Processor activeProcess.

        self assert: lock owner isNil.
        self assert: lock count == 0.
        lock critical:[ 
            lock critical:[ 
                lock critical:[
                    self assert: lock owner == active.
                    self assert: lock count == 3.            
                ].
                self assert: lock owner == active.
                self assert: lock count == 2. 
            ].
            self assert: lock owner == active.
            self assert: lock count == 1. 
        ].
        self assert: lock owner isNil.
        self assert: lock count == 0.
    ] fork.

    "Created: / 28-08-2017 / 21:54:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

test_critical_03

    [
        | active |

        active := Processor activeProcess.

        self assert: lock owner isNil.
        self assert: lock count == 0.
        [
            lock critical:[ 
                self assert: lock owner == active.
                self assert: lock count == 1.            
                self error: 'Get out of here!!'.
            ].
            self assert: false.
        ] on: Error do:[:ex | 
            self assert: true.
        ].
            
        self assert: lock owner isNil.
        self assert: lock count == 0.
    ] fork.

    "Created: / 28-08-2017 / 21:56:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

test_critical_04a
    | p |
    p := [
        | active |

        active := Processor activeProcess.
        lock critical:[ 
            active terminate.
        ].
    ] newProcess.
    p resume.
    [ p isDead ] whileFalse:[ Delay waitForMilliseconds:100 ].

    self assert: lock owner isNil.
    self assert: lock count == 0.

    "Created: / 28-08-2017 / 23:08:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

test_critical_04b
    | p |
    p := [
        | active |

        active := Processor activeProcess.
        lock critical:[ 
            Processor yield.
            Delay waitForSeconds: 10.
        ].
    ] newProcess.
    p resume.
    self assert: p isDead not.
    p terminate.
    [ p isDead ] whileFalse:[ Delay waitForMilliseconds:100 ].

    self assert: lock owner isNil.
    self assert: lock count == 0.

    "Created: / 28-08-2017 / 23:09:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

test_critical_05

    | resource blocker |

    blocker := Semaphore new: (10 - 1) negated.
    resource := 0.
    10 timesRepeat:[  
        [
            | active |

            active := Processor activeProcess.
            10000 timesRepeat:[
                lock critical:[ 
                    resource := resource + 1.
                    self assert: lock owner == active.
                    self assert: lock count == 1.
                    Processor yield.
                ]            
            ].
            blocker signal.
        ] fork.
    ].
    blocker wait.
    self assert: resource == ( 10000 * 10)

    "Created: / 28-08-2017 / 23:10:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

test_critical_06a
    "
    This test makes sure that two threads cannot enter
    critical section of the lock at the same time.
    "

    | threadAstop threadAentered threadBstop threadBentered |

    threadAstop := false.
    threadBstop := false.

    threadAentered := false.
    threadBentered := false.

    "Thread A"
    [
       Stdout nextPutLine:'Thread A id: ', Processor activeProcess id printString.
       lock critical:[
            threadAentered := true.
            [ threadAstop ] whileFalse:[ Delay waitForMilliseconds: 100].
       ]
    ] fork.

    Delay waitForMilliseconds: 300.
    self assert: threadAentered.

    "Thread B"
    [
       Stdout nextPutLine:'Thread B id: ', Processor activeProcess id printString.
       lock critical:[
            threadBentered := true.
            [ threadBstop ] whileFalse:[ Delay waitForMilliseconds: 100].
       ]
    ] fork.

    Delay waitForMilliseconds: 300.
    self assert: threadBentered not.

    Delay waitForMilliseconds: 300.
    threadAstop := true.
    Delay waitForMilliseconds: 300.
    self assert: threadBentered.
    threadBstop := true.

    "Created: / 04-10-2017 / 08:14:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

test_critical_06b
    "
    Like #test_critical_06b, but with nesting.
    "

    | threadAstop1 threadAstop2 threadAentered threadBstop threadBentered |

    threadAstop1 := threadAstop2 := false.
    threadBstop := false.

    threadAentered := false.
    threadBentered := false.

    "Thread A"
    [
       Stdout nextPutLine:'Thread A id: ', Processor activeProcess id printString.
       lock critical:[
            lock critical:[
                threadAentered := true.
                [ threadAstop1 ] whileFalse:[ Delay waitForMilliseconds: 100].
            ].
            [ threadAstop2 ] whileFalse:[ Delay waitForMilliseconds: 100].
       ]
    ] fork.

    Delay waitForMilliseconds: 300.
    self assert: threadAentered.

    "Thread B"
    [
       Stdout nextPutLine:'Thread B id: ', Processor activeProcess id printString.
       lock critical:[lock critical:[
            threadBentered := true.
            [ threadBstop ] whileFalse:[ Delay waitForMilliseconds: 100].
       ]]
    ] fork.

    Delay waitForMilliseconds: 300.
    self assert: threadBentered not.

    Delay waitForMilliseconds: 300.
    threadAstop1 := true.
    Delay waitForMilliseconds: 300.
    self assert: threadBentered not.

    Delay waitForMilliseconds: 300.
    threadAstop2 := true.
    Delay waitForMilliseconds: 300.
    self assert: threadBentered.
    threadBstop := true.

    "Created: / 04-10-2017 / 08:16:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!RecursionLockTests class methodsFor:'documentation'!

version_HG

    ^ '$Changeset: <not expanded> $'
! !