diff --git a/g/os/gmlock/gmlock_unit_lock_test.go b/g/os/gmlock/gmlock_unit_lock_test.go index 6ebd23109..da7c4f7df 100644 --- a/g/os/gmlock/gmlock_unit_lock_test.go +++ b/g/os/gmlock/gmlock_unit_lock_test.go @@ -7,21 +7,23 @@ package gmlock_test import ( + "testing" + "time" + "github.com/gogf/gf/g/container/garray" "github.com/gogf/gf/g/os/gmlock" "github.com/gogf/gf/g/test/gtest" - "testing" - "time" ) -func TestLocker_Lock_Unlock(t *testing.T) { +func Test_Locker_Lock(t *testing.T) { + //no expire gtest.Case(t, func() { - key := "test1" + key := "testLock" array := garray.New() go func() { gmlock.Lock(key) array.Append(1) - time.Sleep(100 * time.Millisecond) + time.Sleep(50 * time.Millisecond) array.Append(1) gmlock.Unlock(key) }() @@ -29,24 +31,22 @@ func TestLocker_Lock_Unlock(t *testing.T) { time.Sleep(10 * time.Millisecond) gmlock.Lock(key) array.Append(1) - time.Sleep(200 * time.Millisecond) + time.Sleep(100 * time.Millisecond) array.Append(1) gmlock.Unlock(key) }() - time.Sleep(50 * time.Millisecond) + time.Sleep(10 * time.Millisecond) gtest.Assert(array.Len(), 1) - time.Sleep(80 * time.Millisecond) + time.Sleep(50 * time.Millisecond) gtest.Assert(array.Len(), 3) - time.Sleep(100 * time.Millisecond) + time.Sleep(50 * time.Millisecond) gtest.Assert(array.Len(), 3) - time.Sleep(100 * time.Millisecond) + time.Sleep(50 * time.Millisecond) gtest.Assert(array.Len(), 4) }) -} - -func TestLocker_Lock_Expire(t *testing.T) { + //expire gtest.Case(t, func() { - key := "test2" + key := "testLockExpire" array := garray.New() go func() { gmlock.Lock(key, 100*time.Millisecond) @@ -66,13 +66,14 @@ func TestLocker_Lock_Expire(t *testing.T) { }) } -func TestLocker_TryLock_Expire(t *testing.T) { +func Test_Locker_TryLock(t *testing.T) { gtest.Case(t, func() { - key := "test3" + key := "testTryLock" array := garray.New() go func() { - gmlock.Lock(key, 200*time.Millisecond) - array.Append(1) + if gmlock.TryLock(key, 200*time.Millisecond) { + array.Append(1) + } }() go func() { time.Sleep(100 * time.Millisecond) @@ -97,3 +98,136 @@ func TestLocker_TryLock_Expire(t *testing.T) { gtest.Assert(array.Len(), 3) }) } + +func Test_Locker_LockFunc(t *testing.T) { + //no expire + gtest.Case(t, func() { + key := "testLockFunc" + array := garray.New() + go func() { + gmlock.LockFunc(key, func() { + array.Append(1) + time.Sleep(50 * time.Millisecond) + }) // + }() + go func() { + time.Sleep(10 * time.Millisecond) + gmlock.LockFunc(key, func() { + array.Append(1) + }) + }() + time.Sleep(10 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(20 * time.Millisecond) + gtest.Assert(array.Len(), 1) // + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 2) + }) + + //expire + gtest.Case(t, func() { + key := "testLockFuncExpire" + array := garray.New() + go func() { + gmlock.LockFunc(key, func() { + array.Append(1) + time.Sleep(200 * time.Millisecond) + }, 100*time.Millisecond) // + }() + go func() { + time.Sleep(50 * time.Millisecond) + gmlock.LockFunc(key, func() { + array.Append(1) + }) + }() + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(100 * time.Millisecond) + gtest.Assert(array.Len(), 2) // + time.Sleep(350 * time.Millisecond) + gtest.Assert(array.Len(), 2) + }) +} +func Test_Locker_TryLockFunc(t *testing.T) { + //no expire + gtest.Case(t, func() { + key := "testTryLockFunc" + array := garray.New() + go func() { + gmlock.TryLockFunc(key, func() { + array.Append(1) + time.Sleep(50 * time.Millisecond) + }) + }() + go func() { + time.Sleep(10 * time.Millisecond) + gmlock.TryLockFunc(key, func() { + array.Append(1) + }) + }() + go func() { + time.Sleep(70 * time.Millisecond) + gmlock.TryLockFunc(key, func() { + array.Append(1) + }) + }() + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(100 * time.Millisecond) + gtest.Assert(array.Len(), 2) + }) + //expire1 + gtest.Case(t, func() { + key := "testTryLockFuncExpire1" + array := garray.New() + go func() { + gmlock.TryLockFunc(key, func() { + array.Append(1) + }, 50*time.Millisecond) + }() + go func() { + time.Sleep(10 * time.Millisecond) + gmlock.TryLockFunc(key, func() { + array.Append(1) + }) + }() + go func() { + time.Sleep(70 * time.Millisecond) + gmlock.TryLockFunc(key, func() { + array.Append(1) + }) + }() + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 2) + time.Sleep(100 * time.Millisecond) + gtest.Assert(array.Len(), 3) + }) + + //expire2 + gtest.Case(t, func() { + key := "testTryLockFuncExpire2" + array := garray.New() + go func() { + gmlock.TryLockFunc(key, func() { + array.Append(1) + time.Sleep(100 * time.Millisecond) + }, 50*time.Millisecond) //unlock after expire, before func finish. + }() + go func() { + time.Sleep(10 * time.Millisecond) + gmlock.TryLockFunc(key, func() { + array.Append(1) + }) + }() + go func() { + time.Sleep(70 * time.Millisecond) + gmlock.TryLockFunc(key, func() { + array.Append(1) + }) + }() + time.Sleep(10 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(70 * time.Millisecond) + gtest.Assert(array.Len(), 2) + }) +} diff --git a/g/os/gmlock/gmlock_unit_mutex_test.go b/g/os/gmlock/gmlock_unit_mutex_test.go new file mode 100644 index 000000000..87f13154a --- /dev/null +++ b/g/os/gmlock/gmlock_unit_mutex_test.go @@ -0,0 +1,258 @@ +// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gmlock_test + +import ( + "testing" + "time" + + "github.com/gogf/gf/g/container/garray" + "github.com/gogf/gf/g/os/gmlock" + "github.com/gogf/gf/g/test/gtest" +) + +func Test_Mutex_RUnlock(t *testing.T) { + gtest.Case(t, func() { + mu := gmlock.NewMutex() + for index := 0; index < 1000; index++ { + go func() { + mu.RLockFunc(func() { + time.Sleep(100 * time.Millisecond) + }) + }() + } + time.Sleep(10 * time.Millisecond) + gtest.Assert(mu.IsRLocked(), true) + gtest.Assert(mu.IsLocked(), true) + gtest.Assert(mu.IsWLocked(), false) + for index := 0; index < 1000; index++ { + go func() { + mu.RUnlock() + }() + } + time.Sleep(150 * time.Millisecond) + gtest.Assert(mu.IsRLocked(), false) + + }) +} + +func Test_Mutex_IsLocked(t *testing.T) { + gtest.Case(t, func() { + mu := gmlock.NewMutex() + go func() { + mu.LockFunc(func() { + time.Sleep(100 * time.Millisecond) + }) + }() + time.Sleep(10 * time.Millisecond) + gtest.Assert(mu.IsLocked(), true) + gtest.Assert(mu.IsWLocked(), true) + gtest.Assert(mu.IsRLocked(), false) + time.Sleep(110 * time.Millisecond) + gtest.Assert(mu.IsLocked(), false) + gtest.Assert(mu.IsWLocked(), false) + + go func() { + mu.RLockFunc(func() { + time.Sleep(100 * time.Millisecond) + }) + }() + time.Sleep(10 * time.Millisecond) + gtest.Assert(mu.IsRLocked(), true) + gtest.Assert(mu.IsLocked(), true) + gtest.Assert(mu.IsWLocked(), false) + time.Sleep(110 * time.Millisecond) + gtest.Assert(mu.IsRLocked(), false) + }) +} + +func Test_Mutex_Unlock(t *testing.T) { + gtest.Case(t, func() { + mu := gmlock.NewMutex() + array := garray.New() + go func() { + mu.LockFunc(func() { + array.Append(1) + time.Sleep(100 * time.Millisecond) + }) + }() + go func() { + time.Sleep(50 * time.Millisecond) + mu.LockFunc(func() { + array.Append(1) + }) + }() + go func() { + time.Sleep(50 * time.Millisecond) + mu.LockFunc(func() { + array.Append(1) + }) + }() + + go func() { + time.Sleep(60 * time.Millisecond) + mu.Unlock() + mu.Unlock() + mu.Unlock() + }() + + time.Sleep(20 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 3) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 3) + }) +} + +func Test_Mutex_LockFunc(t *testing.T) { + gtest.Case(t, func() { + mu := gmlock.NewMutex() + array := garray.New() + go func() { + mu.LockFunc(func() { + array.Append(1) + time.Sleep(100 * time.Millisecond) + }) + }() + go func() { + time.Sleep(50 * time.Millisecond) + mu.LockFunc(func() { + array.Append(1) + }) + }() + time.Sleep(20 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 2) + }) +} + +func Test_Mutex_TryLockFunc(t *testing.T) { + gtest.Case(t, func() { + mu := gmlock.NewMutex() + array := garray.New() + go func() { + mu.LockFunc(func() { + array.Append(1) + time.Sleep(100 * time.Millisecond) + }) + }() + go func() { + time.Sleep(50 * time.Millisecond) + mu.TryLockFunc(func() { + array.Append(1) + }) + }() + go func() { + time.Sleep(110 * time.Millisecond) + mu.TryLockFunc(func() { + array.Append(1) + }) + }() + time.Sleep(20 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 2) + }) +} + +func Test_Mutex_RLockFunc(t *testing.T) { + gtest.Case(t, func() { + mu := gmlock.NewMutex() + array := garray.New() + go func() { + mu.LockFunc(func() { + array.Append(1) + time.Sleep(100 * time.Millisecond) + }) + }() + go func() { + time.Sleep(50 * time.Millisecond) + mu.RLockFunc(func() { + array.Append(1) + time.Sleep(100 * time.Millisecond) + }) + }() + time.Sleep(20 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 2) + }) + + gtest.Case(t, func() { + mu := gmlock.NewMutex() + array := garray.New() + go func() { + time.Sleep(50 * time.Millisecond) + mu.RLockFunc(func() { + array.Append(1) + time.Sleep(100 * time.Millisecond) + }) + }() + go func() { + time.Sleep(50 * time.Millisecond) + mu.RLockFunc(func() { + array.Append(1) + time.Sleep(100 * time.Millisecond) + }) + }() + go func() { + time.Sleep(50 * time.Millisecond) + mu.RLockFunc(func() { + array.Append(1) + time.Sleep(100 * time.Millisecond) + }) + }() + gtest.Assert(array.Len(), 0) + time.Sleep(80 * time.Millisecond) + gtest.Assert(array.Len(), 3) + }) +} + +func Test_Mutex_TryRLockFunc(t *testing.T) { + gtest.Case(t, func() { + mu := gmlock.NewMutex() + array := garray.New() + go func() { + mu.LockFunc(func() { + array.Append(1) + time.Sleep(50 * time.Millisecond) + }) + }() + go func() { + time.Sleep(20 * time.Millisecond) + mu.TryRLockFunc(func() { + array.Append(1) + }) + }() + go func() { + time.Sleep(70 * time.Millisecond) + mu.TryRLockFunc(func() { + array.Append(1) + }) + }() + go func() { + time.Sleep(70 * time.Millisecond) + mu.TryRLockFunc(func() { + array.Append(1) + }) + }() + time.Sleep(10 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 3) + }) +} diff --git a/g/os/gmlock/gmlock_unit_rlock_test.go b/g/os/gmlock/gmlock_unit_rlock_test.go index 6529114aa..6363195ad 100644 --- a/g/os/gmlock/gmlock_unit_rlock_test.go +++ b/g/os/gmlock/gmlock_unit_rlock_test.go @@ -7,16 +7,18 @@ package gmlock_test import ( + "testing" + "time" + "github.com/gogf/gf/g/container/garray" "github.com/gogf/gf/g/os/gmlock" "github.com/gogf/gf/g/test/gtest" - "testing" - "time" ) -func TestLocker_RLock1(t *testing.T) { +func Test_Locker_RLock(t *testing.T) { + //RLock before Lock gtest.Case(t, func() { - key := "test100" + key := "testRLockBeforeLock" array := garray.New() go func() { gmlock.RLock(key) @@ -36,16 +38,15 @@ func TestLocker_RLock1(t *testing.T) { time.Sleep(80 * time.Millisecond) gtest.Assert(array.Len(), 3) }) -} -func TestLocker_RLock2(t *testing.T) { + //Lock before RLock gtest.Case(t, func() { - key := "test200" + key := "testLockBeforeRLock" array := garray.New() go func() { gmlock.Lock(key) array.Append(1) - time.Sleep(100 * time.Millisecond) + time.Sleep(50 * time.Millisecond) gmlock.Unlock(key) }() go func() { @@ -54,10 +55,223 @@ func TestLocker_RLock2(t *testing.T) { array.Append(1) gmlock.RUnlock(key) }() + time.Sleep(20 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 2) + }) + //Lock before RLocks + gtest.Case(t, func() { + key := "testLockBeforeRLocks" + array := garray.New() + go func() { + gmlock.Lock(key) + array.Append(1) + time.Sleep(50 * time.Millisecond) + gmlock.Unlock(key) + }() + go func() { + time.Sleep(10 * time.Millisecond) + gmlock.RLock(key) + array.Append(1) + time.Sleep(70 * time.Millisecond) + gmlock.RUnlock(key) + }() + go func() { + time.Sleep(10 * time.Millisecond) + gmlock.RLock(key) + array.Append(1) + time.Sleep(70 * time.Millisecond) + gmlock.RUnlock(key) + }() time.Sleep(20 * time.Millisecond) gtest.Assert(array.Len(), 1) time.Sleep(120 * time.Millisecond) + gtest.Assert(array.Len(), 3) + }) +} + +func Test_Locker_TryRLock(t *testing.T) { + //Lock before TryRLock + gtest.Case(t, func() { + key := "testLockBeforeTryRLock" + array := garray.New() + go func() { + gmlock.Lock(key) + array.Append(1) + time.Sleep(50 * time.Millisecond) + gmlock.Unlock(key) + }() + go func() { + time.Sleep(10 * time.Millisecond) + if gmlock.TryRLock(key) { + array.Append(1) + gmlock.RUnlock(key) + } + }() + time.Sleep(20 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 1) + }) + + //Lock before TryRLocks + gtest.Case(t, func() { + key := "testLockBeforeTryRLocks" + array := garray.New() + go func() { + gmlock.Lock(key) + array.Append(1) + time.Sleep(50 * time.Millisecond) + gmlock.Unlock(key) + }() + go func() { + time.Sleep(10 * time.Millisecond) + if gmlock.TryRLock(key) { + array.Append(1) + gmlock.RUnlock(key) + } + }() + go func() { + time.Sleep(70 * time.Millisecond) + if gmlock.TryRLock(key) { + array.Append(1) + gmlock.RUnlock(key) + } + }() + time.Sleep(20 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(80 * time.Millisecond) + gtest.Assert(array.Len(), 2) + }) +} + +func Test_Locker_RLockFunc(t *testing.T) { + //RLockFunc before Lock + gtest.Case(t, func() { + key := "testRLockFuncBeforeLock" + array := garray.New() + go func() { + gmlock.RLockFunc(key, func() { + array.Append(1) + time.Sleep(50 * time.Millisecond) + array.Append(1) + }) + }() + go func() { + time.Sleep(10 * time.Millisecond) + gmlock.Lock(key) + array.Append(1) + gmlock.Unlock(key) + }() + time.Sleep(20 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(80 * time.Millisecond) + gtest.Assert(array.Len(), 3) + }) + + //Lock before RLockFunc + gtest.Case(t, func() { + key := "testLockBeforeRLockFunc" + array := garray.New() + go func() { + gmlock.Lock(key) + array.Append(1) + time.Sleep(50 * time.Millisecond) + gmlock.Unlock(key) + }() + go func() { + time.Sleep(10 * time.Millisecond) + gmlock.RLockFunc(key, func() { + array.Append(1) + }) + }() + time.Sleep(20 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 2) + }) + + //Lock before RLockFuncs + gtest.Case(t, func() { + key := "testLockBeforeRLockFuncs" + array := garray.New() + go func() { + gmlock.Lock(key) + array.Append(1) + time.Sleep(50 * time.Millisecond) + gmlock.Unlock(key) + }() + go func() { + time.Sleep(10 * time.Millisecond) + gmlock.RLockFunc(key, func() { + array.Append(1) + time.Sleep(70 * time.Millisecond) + }) + }() + go func() { + time.Sleep(10 * time.Millisecond) + gmlock.RLockFunc(key, func() { + array.Append(1) + time.Sleep(70 * time.Millisecond) + }) + }() + time.Sleep(20 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(70 * time.Millisecond) + gtest.Assert(array.Len(), 3) + }) +} + +func Test_Locker_TryRLockFunc(t *testing.T) { + //Lock before TryRLockFunc + gtest.Case(t, func() { + key := "testLockBeforeTryRLockFunc" + array := garray.New() + go func() { + gmlock.Lock(key) + array.Append(1) + time.Sleep(50 * time.Millisecond) + gmlock.Unlock(key) + }() + go func() { + time.Sleep(10 * time.Millisecond) + gmlock.TryRLockFunc(key, func() { + array.Append(1) + }) + }() + time.Sleep(20 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(50 * time.Millisecond) + gtest.Assert(array.Len(), 1) + }) + + //Lock before TryRLockFuncs + gtest.Case(t, func() { + key := "testLockBeforeTryRLockFuncs" + array := garray.New() + go func() { + gmlock.Lock(key) + array.Append(1) + time.Sleep(50 * time.Millisecond) + gmlock.Unlock(key) + }() + go func() { + time.Sleep(10 * time.Millisecond) + gmlock.TryRLockFunc(key, func() { + array.Append(1) + }) + }() + go func() { + time.Sleep(70 * time.Millisecond) + gmlock.TryRLockFunc(key, func() { + array.Append(1) + }) + }() + time.Sleep(20 * time.Millisecond) + gtest.Assert(array.Len(), 1) + time.Sleep(70 * time.Millisecond) gtest.Assert(array.Len(), 2) }) }