Browse Source

增加部分单测

pull/1/head
Sydonian 3 years ago
parent
commit
c6faf1db1f
7 changed files with 276 additions and 1 deletions
  1. +113
    -0
      pkg/distlock/lockprovider/ipfs_lock_test.go
  2. +1
    -0
      pkg/distlock/lockprovider/lock_compatibility_table.go
  3. +41
    -0
      pkg/distlock/lockprovider/lock_compatibility_table_test.go
  4. +4
    -0
      pkg/distlock/lockprovider/string_lock_target.go
  5. +60
    -0
      pkg/distlock/lockprovider/string_lock_target_test.go
  6. +1
    -1
      utils/lo/lo.go
  7. +56
    -0
      utils/lo/lo_test.go

+ 113
- 0
pkg/distlock/lockprovider/ipfs_lock_test.go View File

@@ -0,0 +1,113 @@
package lockprovider

import (
"testing"

. "github.com/smartystreets/goconvey/convey"
"gitlink.org.cn/cloudream/common/pkg/distlock"
)

func Test_IPFSLock(t *testing.T) {
cases := []struct {
title string
initLocks []distlock.Lock
doLock distlock.Lock
wantOK bool
}{
{
title: "同节点,同一个Read锁",
initLocks: []distlock.Lock{
{
Path: []string{distlock.IPFS_LOCK_PATH_PREFIX, "node1"},
Name: IPFS_SET_READ_LOCK,
},
},
doLock: distlock.Lock{
Path: []string{distlock.IPFS_LOCK_PATH_PREFIX, "node1"},
Name: IPFS_SET_READ_LOCK,
},
wantOK: true,
},
{
title: "同节点,同一个Write锁",
initLocks: []distlock.Lock{
{
Path: []string{distlock.IPFS_LOCK_PATH_PREFIX, "node1"},
Name: IPFS_SET_WRITE_LOCK,
},
},
doLock: distlock.Lock{
Path: []string{distlock.IPFS_LOCK_PATH_PREFIX, "node1"},
Name: IPFS_SET_WRITE_LOCK,
},
wantOK: false,
},
{
title: "不同节点,同一个Write锁",
initLocks: []distlock.Lock{
{
Path: []string{distlock.IPFS_LOCK_PATH_PREFIX, "node1"},
Name: IPFS_SET_WRITE_LOCK,
},
},
doLock: distlock.Lock{
Path: []string{distlock.IPFS_LOCK_PATH_PREFIX, "node2"},
Name: IPFS_SET_WRITE_LOCK,
},
wantOK: true,
},
{
title: "相同对象的Read、Write锁",
initLocks: []distlock.Lock{
{
Path: []string{distlock.IPFS_LOCK_PATH_PREFIX, "node1"},
Name: IPFS_ELEMENT_WRITE_LOCK,
Target: *NewStringLockTarget(),
},
},
doLock: distlock.Lock{
Path: []string{distlock.IPFS_LOCK_PATH_PREFIX, "node1"},
Name: IPFS_ELEMENT_WRITE_LOCK,
Target: *NewStringLockTarget(),
},
wantOK: false,
},
}

for _, ca := range cases {
Convey(ca.title, t, func() {
ipfsLock := NewIPFSLock()

for _, l := range ca.initLocks {
ipfsLock.Lock("req1", l)
}

err := ipfsLock.CanLock(ca.doLock)
if ca.wantOK {
So(err, ShouldBeNil)
} else {
So(err, ShouldNotBeNil)
}
})
}

Convey("解锁", t, func() {
ipfsLock := NewIPFSLock()

lock := distlock.Lock{
Path: []string{distlock.IPFS_LOCK_PATH_PREFIX, "node1"},
Name: IPFS_SET_WRITE_LOCK,
}

ipfsLock.Lock("req1", lock)

err := ipfsLock.CanLock(lock)
So(err, ShouldNotBeNil)

ipfsLock.Unlock("req1", lock)

err = ipfsLock.CanLock(lock)
So(err, ShouldBeNil)
})

}

+ 1
- 0
pkg/distlock/lockprovider/lock_compatibility_table.go View File

@@ -15,6 +15,7 @@ const (

type HasSuchLockFn = func() bool

// LockCompatibilitySpecialFn 判断锁与指定的锁名是否兼容
type LockCompatibilitySpecialFn func(lock distlock.Lock, testLockName string) bool

type LockCompatibilityType string


+ 41
- 0
pkg/distlock/lockprovider/lock_compatibility_table_test.go View File

@@ -0,0 +1,41 @@
package lockprovider

import (
"testing"

. "github.com/smartystreets/goconvey/convey"
"gitlink.org.cn/cloudream/common/pkg/distlock"
)

func Test_LockCompatibilityTable(t *testing.T) {
Convey("兼容,互斥,特殊比较", t, func() {
table := LockCompatibilityTable{}

table.
Column("l1", func() bool { return true }).
Column("l2", func() bool { return true }).
Column("l3", func() bool { return false })

comp := LockCompatible()
uncp := LockUncompatible()
spcl := LockSpecial(func(lock distlock.Lock, testLockName string) bool { return true })
table.Row(comp, comp, comp)
table.Row(comp, uncp, comp)
table.Row(comp, comp, spcl)

err := table.Test(distlock.Lock{
Name: "l1",
})
So(err, ShouldBeNil)

err = table.Test(distlock.Lock{
Name: "l2",
})
So(err, ShouldNotBeNil)

err = table.Test(distlock.Lock{
Name: "l3",
})
So(err, ShouldBeNil)
})
}

+ 4
- 0
pkg/distlock/lockprovider/string_lock_target.go View File

@@ -30,6 +30,10 @@ func (t *StringLockTarget) IsConflict(other *StringLockTarget) bool {
return false
}

if len(t.Components) == 0 {
return true
}

for i := 0; i < len(t.Components); i++ {
if t.Components[i].IsEquals(&other.Components[i]) {
return true


+ 60
- 0
pkg/distlock/lockprovider/string_lock_target_test.go View File

@@ -0,0 +1,60 @@
package lockprovider

import (
"testing"

. "github.com/smartystreets/goconvey/convey"
)

func Test_StringLockTarget(t *testing.T) {
cases := []struct {
title string
target1 *StringLockTarget
target2 *StringLockTarget
wantIsConflict bool
}{
{
title: "没有任何段算冲突",
target1: NewStringLockTarget(),
target2: NewStringLockTarget(),
wantIsConflict: true,
},
{
title: "有段,但段内为空,算冲突",
target1: NewStringLockTarget().Add(),
target2: NewStringLockTarget().Add(),
wantIsConflict: true,
},
{
title: "每一段不同才不冲突",
target1: NewStringLockTarget().Add("a").Add("b"),
target2: NewStringLockTarget().Add("b").Add("c"),
wantIsConflict: false,
},
{
title: "只要有一段相同就冲突",
target1: NewStringLockTarget().Add("a").Add("b"),
target2: NewStringLockTarget().Add("a").Add("c"),
wantIsConflict: true,
},
{
title: "同段内,只要有一个数据不同就不冲突",
target1: NewStringLockTarget().Add("a", "b"),
target2: NewStringLockTarget().Add("b", "b"),
wantIsConflict: false,
},
{
title: "同段内,只要每个数据都相同才不冲突",
target1: NewStringLockTarget().Add("a", "b"),
target2: NewStringLockTarget().Add("a", "b"),
wantIsConflict: true,
},
}

for _, ca := range cases {
Convey(ca.title, t, func() {
ret := ca.target1.IsConflict(ca.target2)
So(ret, ShouldEqual, ca.wantIsConflict)
})
}
}

+ 1
- 1
utils/lo/lo.go View File

@@ -16,7 +16,7 @@ func RemoveAt[T any](arr []T, index int) []T {
return arr
}

return append(arr[:index], arr[:index+1]...)
return append(arr[:index], arr[index+1:]...)
}

func ArrayClone[T any](arr []T) []T {


+ 56
- 0
utils/lo/lo_test.go View File

@@ -0,0 +1,56 @@
package lo

import (
"testing"

. "github.com/smartystreets/goconvey/convey"
)

func Test_Remove(t *testing.T) {
Convey("删除数组元素", t, func() {
arr := []string{"a", "b", "c"}
arr = Remove(arr, "b")
So(arr, ShouldResemble, []string{"a", "c"})
})

Convey("删除最后一个元素", t, func() {
arr := []string{"a", "b", "c"}
arr = Remove(arr, "c")
So(arr, ShouldResemble, []string{"a", "b"})
})

Convey("删除第一个元素", t, func() {
arr := []string{"a", "b", "c"}
arr = Remove(arr, "a")
So(arr, ShouldResemble, []string{"b", "c"})
})

Convey("删除不存在的元素", t, func() {
arr := []string{"a", "b", "c"}
arr = Remove(arr, "d")
So(arr, ShouldResemble, []string{"a", "b", "c"})
})
}

func Test_ArrayClone(t *testing.T) {
Convey("复制数组", t, func() {
arr := []string{"a", "b", "c"}
arr2 := ArrayClone(arr)

arr2[1] = "a"

So(arr, ShouldResemble, []string{"a", "b", "c"})
So(arr2, ShouldResemble, []string{"a", "a", "c"})
})

Convey("复制出来的数组进行append", t, func() {
arr := []string{"a", "b", "c"}
arr2 := ArrayClone(arr)

arr = append(arr, "d")
arr2 = append(arr2, "c")

So(arr, ShouldResemble, []string{"a", "b", "c", "d"})
So(arr2, ShouldResemble, []string{"a", "b", "c", "c"})
})
}

Loading…
Cancel
Save