init
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
package unit
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
// IPMatcherTestSuite IP 匹配器测试套件
|
||||
type IPMatcherTestSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func TestIPMatcherTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(IPMatcherTestSuite))
|
||||
}
|
||||
|
||||
func (s *IPMatcherTestSuite) SetupTest() {
|
||||
}
|
||||
|
||||
func (s *IPMatcherTestSuite) TearDownTest() {
|
||||
}
|
||||
|
||||
// isIPInRange 检查 IP 是否在指定范围内
|
||||
func isIPInRange(ip, startIP, endIP net.IP) bool {
|
||||
ipBytes := ip.To4()
|
||||
startBytes := startIP.To4()
|
||||
endBytes := endIP.To4()
|
||||
|
||||
if ipBytes == nil || startBytes == nil || endBytes == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
ipInt := uint32(ipBytes[0])<<24 | uint32(ipBytes[1])<<16 | uint32(ipBytes[2])<<8 | uint32(ipBytes[3])
|
||||
startInt := uint32(startBytes[0])<<24 | uint32(startBytes[1])<<16 | uint32(startBytes[2])<<8 | uint32(startBytes[3])
|
||||
endInt := uint32(endBytes[0])<<24 | uint32(endBytes[1])<<16 | uint32(endBytes[2])<<8 | uint32(endBytes[3])
|
||||
|
||||
return ipInt >= startInt && ipInt <= endInt
|
||||
}
|
||||
|
||||
// TestIsIPInRange_InRange 测试 IP 在范围内
|
||||
func (s *IPMatcherTestSuite) TestIsIPInRange_InRange() {
|
||||
ip := net.ParseIP("192.168.1.50")
|
||||
startIP := net.ParseIP("192.168.1.1")
|
||||
endIP := net.ParseIP("192.168.1.100")
|
||||
|
||||
s.True(isIPInRange(ip, startIP, endIP))
|
||||
}
|
||||
|
||||
// TestIsIPInRange_AtStart 测试 IP 在范围起点
|
||||
func (s *IPMatcherTestSuite) TestIsIPInRange_AtStart() {
|
||||
ip := net.ParseIP("192.168.1.1")
|
||||
startIP := net.ParseIP("192.168.1.1")
|
||||
endIP := net.ParseIP("192.168.1.100")
|
||||
|
||||
s.True(isIPInRange(ip, startIP, endIP))
|
||||
}
|
||||
|
||||
// TestIsIPInRange_AtEnd 测试 IP 在范围终点
|
||||
func (s *IPMatcherTestSuite) TestIsIPInRange_AtEnd() {
|
||||
ip := net.ParseIP("192.168.1.100")
|
||||
startIP := net.ParseIP("192.168.1.1")
|
||||
endIP := net.ParseIP("192.168.1.100")
|
||||
|
||||
s.True(isIPInRange(ip, startIP, endIP))
|
||||
}
|
||||
|
||||
// TestIsIPInRange_OutOfRange 测试 IP 超出范围
|
||||
func (s *IPMatcherTestSuite) TestIsIPInRange_OutOfRange() {
|
||||
ip := net.ParseIP("192.168.1.101")
|
||||
startIP := net.ParseIP("192.168.1.1")
|
||||
endIP := net.ParseIP("192.168.1.100")
|
||||
|
||||
s.False(isIPInRange(ip, startIP, endIP))
|
||||
}
|
||||
|
||||
// TestIsIPInRange_BeforeRange 测试 IP 在范围之前
|
||||
func (s *IPMatcherTestSuite) TestIsIPInRange_BeforeRange() {
|
||||
ip := net.ParseIP("192.168.0.255")
|
||||
startIP := net.ParseIP("192.168.1.1")
|
||||
endIP := net.ParseIP("192.168.1.100")
|
||||
|
||||
s.False(isIPInRange(ip, startIP, endIP))
|
||||
}
|
||||
|
||||
// TestIsIPInRange_InvalidIP 测试无效 IP
|
||||
func (s *IPMatcherTestSuite) TestIsIPInRange_InvalidIP() {
|
||||
startIP := net.ParseIP("192.168.1.1")
|
||||
endIP := net.ParseIP("192.168.1.100")
|
||||
|
||||
s.False(isIPInRange(nil, startIP, endIP))
|
||||
}
|
||||
|
||||
// TestCIDRMatch 测试 CIDR 匹配
|
||||
func (s *IPMatcherTestSuite) TestCIDRMatch() {
|
||||
tests := []struct {
|
||||
name string
|
||||
ip string
|
||||
cidr string
|
||||
match bool
|
||||
}{
|
||||
{"匹配 /24", "192.168.1.100", "192.168.1.0/24", true},
|
||||
{"不匹配 /24", "192.168.2.1", "192.168.1.0/24", false},
|
||||
{"/32 精确匹配", "192.168.1.1", "192.168.1.1/32", true},
|
||||
{"/32 不匹配", "192.168.1.2", "192.168.1.1/32", false},
|
||||
{"/16 匹配", "192.168.100.50", "192.168.0.0/16", true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
s.Run(tt.name, func() {
|
||||
ip := net.ParseIP(tt.ip)
|
||||
_, ipNet, _ := net.ParseCIDR(tt.cidr)
|
||||
|
||||
if tt.match {
|
||||
s.True(ipNet.Contains(ip))
|
||||
} else {
|
||||
s.False(ipNet.Contains(ip))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestIPParsing 测试 IP 解析
|
||||
func (s *IPMatcherTestSuite) TestIPParsing() {
|
||||
tests := []struct {
|
||||
name string
|
||||
ip string
|
||||
valid bool
|
||||
}{
|
||||
{"有效 IPv4", "192.168.1.1", true},
|
||||
{"有效 IPv4 边界", "255.255.255.255", true},
|
||||
{"有效 IPv4 零", "0.0.0.0", true},
|
||||
{"无效 IP", "invalid-ip", false},
|
||||
{"空字符串", "", false},
|
||||
{"超出范围", "256.1.1.1", false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
s.Run(tt.name, func() {
|
||||
ip := net.ParseIP(tt.ip)
|
||||
if tt.valid {
|
||||
s.NotNil(ip)
|
||||
} else {
|
||||
s.Nil(ip)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package unit
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
// 单元测试不需要完整的应用初始化
|
||||
// 如果需要数据库等资源,请在 tests/feature 中编写功能测试
|
||||
|
||||
// 执行测试
|
||||
exit := m.Run()
|
||||
|
||||
os.Exit(exit)
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package unit
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
// PaginationTestSuite 分页测试套件
|
||||
type PaginationTestSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func TestPaginationTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(PaginationTestSuite))
|
||||
}
|
||||
|
||||
func (s *PaginationTestSuite) SetupTest() {
|
||||
}
|
||||
|
||||
func (s *PaginationTestSuite) TearDownTest() {
|
||||
}
|
||||
|
||||
// paginateSlice 模拟分页函数
|
||||
func paginateSlice[T any](slice []T, page, pageSize int) ([]T, int64) {
|
||||
total := int64(len(slice))
|
||||
if total == 0 {
|
||||
return []T{}, 0
|
||||
}
|
||||
|
||||
start := (page - 1) * pageSize
|
||||
end := start + pageSize
|
||||
|
||||
if start >= len(slice) {
|
||||
return []T{}, total
|
||||
}
|
||||
|
||||
if end > len(slice) {
|
||||
end = len(slice)
|
||||
}
|
||||
|
||||
return slice[start:end], total
|
||||
}
|
||||
|
||||
// validatePagination 模拟分页参数验证
|
||||
func validatePagination(page, pageSize int) (int, int) {
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize < 1 {
|
||||
pageSize = 10
|
||||
}
|
||||
const maxPageSize = 100
|
||||
if pageSize > maxPageSize {
|
||||
pageSize = maxPageSize
|
||||
}
|
||||
return page, pageSize
|
||||
}
|
||||
|
||||
// TestPaginateSlice_EmptySlice 测试空切片
|
||||
func (s *PaginationTestSuite) TestPaginateSlice_EmptySlice() {
|
||||
result, total := paginateSlice([]int{}, 1, 10)
|
||||
|
||||
s.Empty(result)
|
||||
s.Equal(int64(0), total)
|
||||
}
|
||||
|
||||
// TestPaginateSlice_FirstPage 测试第一页
|
||||
func (s *PaginationTestSuite) TestPaginateSlice_FirstPage() {
|
||||
slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||
result, total := paginateSlice(slice, 1, 3)
|
||||
|
||||
s.Equal([]int{1, 2, 3}, result)
|
||||
s.Equal(int64(10), total)
|
||||
}
|
||||
|
||||
// TestPaginateSlice_MiddlePage 测试中间页
|
||||
func (s *PaginationTestSuite) TestPaginateSlice_MiddlePage() {
|
||||
slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||
result, total := paginateSlice(slice, 2, 3)
|
||||
|
||||
s.Equal([]int{4, 5, 6}, result)
|
||||
s.Equal(int64(10), total)
|
||||
}
|
||||
|
||||
// TestPaginateSlice_LastPage 测试最后一页(不满)
|
||||
func (s *PaginationTestSuite) TestPaginateSlice_LastPage() {
|
||||
slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||
result, total := paginateSlice(slice, 4, 3)
|
||||
|
||||
s.Equal([]int{10}, result)
|
||||
s.Equal(int64(10), total)
|
||||
}
|
||||
|
||||
// TestPaginateSlice_OutOfRange 测试超出范围的页码
|
||||
func (s *PaginationTestSuite) TestPaginateSlice_OutOfRange() {
|
||||
slice := []int{1, 2, 3, 4, 5}
|
||||
result, total := paginateSlice(slice, 10, 3)
|
||||
|
||||
s.Empty(result)
|
||||
s.Equal(int64(5), total)
|
||||
}
|
||||
|
||||
// TestValidatePagination 测试分页参数验证
|
||||
func (s *PaginationTestSuite) TestValidatePagination() {
|
||||
tests := []struct {
|
||||
name string
|
||||
page int
|
||||
pageSize int
|
||||
wantPage int
|
||||
wantPageSize int
|
||||
}{
|
||||
{"正常值", 1, 10, 1, 10},
|
||||
{"page 小于 1", 0, 10, 1, 10},
|
||||
{"page 为负数", -5, 10, 1, 10},
|
||||
{"pageSize 小于 1", 1, 0, 1, 10},
|
||||
{"pageSize 超过最大值", 1, 200, 1, 100},
|
||||
{"两者都异常", -1, -1, 1, 10},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
s.Run(tt.name, func() {
|
||||
gotPage, gotPageSize := validatePagination(tt.page, tt.pageSize)
|
||||
s.Equal(tt.wantPage, gotPage)
|
||||
s.Equal(tt.wantPageSize, gotPageSize)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package unit
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/goravel/framework/support/path"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPathResource(t *testing.T) {
|
||||
resourcePath := path.Resource()
|
||||
fmt.Println(resourcePath)
|
||||
assert.True(t, strings.HasPrefix(resourcePath, "/"))
|
||||
assert.True(t, strings.HasSuffix(resourcePath, "/resources"))
|
||||
|
||||
resourcePath = path.Resource("test.txt")
|
||||
fmt.Println(resourcePath)
|
||||
assert.True(t, strings.HasPrefix(resourcePath, "/"))
|
||||
assert.True(t, strings.HasSuffix(resourcePath, "/resources/test.txt"))
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package unit
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
// TokenServiceTestSuite Token 服务测试套件
|
||||
type TokenServiceTestSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func TestTokenServiceTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(TokenServiceTestSuite))
|
||||
}
|
||||
|
||||
// SetupTest 每个测试前执行
|
||||
func (s *TokenServiceTestSuite) SetupTest() {
|
||||
}
|
||||
|
||||
// TearDownTest 每个测试后执行
|
||||
func (s *TokenServiceTestSuite) TearDownTest() {
|
||||
}
|
||||
|
||||
// hashToken 模拟 TokenService 的哈希函数
|
||||
func hashToken(token string) string {
|
||||
hash := sha256.Sum256([]byte(token))
|
||||
return hex.EncodeToString(hash[:])
|
||||
}
|
||||
|
||||
// TestHashToken_NormalToken 测试正常 token 哈希
|
||||
func (s *TokenServiceTestSuite) TestHashToken_NormalToken() {
|
||||
token := "test-token-123"
|
||||
result := hashToken(token)
|
||||
|
||||
s.Len(result, 64, "SHA256 应产生 64 个十六进制字符")
|
||||
}
|
||||
|
||||
// TestHashToken_EmptyToken 测试空 token 哈希
|
||||
func (s *TokenServiceTestSuite) TestHashToken_EmptyToken() {
|
||||
token := ""
|
||||
result := hashToken(token)
|
||||
|
||||
s.Len(result, 64, "空 token 也应产生 64 个十六进制字符")
|
||||
}
|
||||
|
||||
// TestHashToken_Consistency 测试哈希一致性
|
||||
func (s *TokenServiceTestSuite) TestHashToken_Consistency() {
|
||||
token := "test-token"
|
||||
result1 := hashToken(token)
|
||||
result2 := hashToken(token)
|
||||
|
||||
s.Equal(result1, result2, "相同输入应产生相同输出")
|
||||
}
|
||||
|
||||
// TestHashToken_Uniqueness 测试不同输入产生不同哈希
|
||||
func (s *TokenServiceTestSuite) TestHashToken_Uniqueness() {
|
||||
result1 := hashToken("token1")
|
||||
result2 := hashToken("token2")
|
||||
|
||||
s.NotEqual(result1, result2, "不同输入应产生不同输出")
|
||||
}
|
||||
|
||||
// TestHashToken_TableDriven 表格驱动测试
|
||||
func (s *TokenServiceTestSuite) TestHashToken_TableDriven() {
|
||||
tests := []struct {
|
||||
name string
|
||||
token string
|
||||
wantLen int
|
||||
}{
|
||||
{"正常 token", "test-token-123", 64},
|
||||
{"空 token", "", 64},
|
||||
{"长 token", "this-is-a-very-long-token-that-should-still-work", 64},
|
||||
{"特殊字符", "token@#$%^&*()", 64},
|
||||
{"Unicode", "中文token测试", 64},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
s.Run(tt.name, func() {
|
||||
got := hashToken(tt.token)
|
||||
s.Len(got, tt.wantLen)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestGenerateRandomToken_Length 测试生成随机 token 的长度
|
||||
func (s *TokenServiceTestSuite) TestGenerateRandomToken_Length() {
|
||||
// 注意:这里无法直接测试 generateRandomToken,因为它是私有方法
|
||||
// 但可以通过 CreateToken 间接测试
|
||||
// 这个测试需要在 feature 测试中完成,因为需要数据库
|
||||
}
|
||||
|
||||
// TestGenerateRandomToken_Uniqueness 测试生成的 token 唯一性
|
||||
func (s *TokenServiceTestSuite) TestGenerateRandomToken_Uniqueness() {
|
||||
// 注意:这个测试需要在 feature 测试中完成
|
||||
// 因为需要数据库来创建 token 并验证唯一性
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package unit
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
// TreeServiceTestSuite 树形服务测试套件
|
||||
type TreeServiceTestSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func TestTreeServiceTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(TreeServiceTestSuite))
|
||||
}
|
||||
|
||||
func (s *TreeServiceTestSuite) SetupTest() {
|
||||
}
|
||||
|
||||
func (s *TreeServiceTestSuite) TearDownTest() {
|
||||
}
|
||||
|
||||
// TreeNode 测试用树形节点
|
||||
type TreeNode struct {
|
||||
ID uint
|
||||
ParentID uint
|
||||
Name string
|
||||
Children []TreeNode
|
||||
}
|
||||
|
||||
// buildTree 构建树形结构
|
||||
func buildTree(nodes []TreeNode) []TreeNode {
|
||||
if len(nodes) == 0 {
|
||||
return []TreeNode{}
|
||||
}
|
||||
|
||||
// 先创建所有节点的映射
|
||||
nodeMap := make(map[uint]*TreeNode)
|
||||
for i := range nodes {
|
||||
nodes[i].Children = []TreeNode{}
|
||||
nodeMap[nodes[i].ID] = &nodes[i]
|
||||
}
|
||||
|
||||
// 构建父子关系
|
||||
for i := range nodes {
|
||||
if nodes[i].ParentID != 0 {
|
||||
if parent, ok := nodeMap[nodes[i].ParentID]; ok {
|
||||
parent.Children = append(parent.Children, nodes[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 收集根节点(从 map 中获取,确保 Children 已更新)
|
||||
var roots []TreeNode
|
||||
for i := range nodes {
|
||||
if nodes[i].ParentID == 0 {
|
||||
roots = append(roots, *nodeMap[nodes[i].ID])
|
||||
}
|
||||
}
|
||||
|
||||
return roots
|
||||
}
|
||||
|
||||
// flattenTree 展平树形结构
|
||||
func flattenTree(nodes []TreeNode) []TreeNode {
|
||||
var result []TreeNode
|
||||
for _, node := range nodes {
|
||||
result = append(result, node)
|
||||
if len(node.Children) > 0 {
|
||||
result = append(result, flattenTree(node.Children)...)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// contains 检查切片是否包含元素
|
||||
func contains(slice []uint, item uint) bool {
|
||||
for _, v := range slice {
|
||||
if v == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// uniqueUint 去重
|
||||
func uniqueUint(slice []uint) []uint {
|
||||
seen := make(map[uint]bool)
|
||||
var result []uint
|
||||
for _, v := range slice {
|
||||
if !seen[v] {
|
||||
seen[v] = true
|
||||
result = append(result, v)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// TestBuildTree_EmptyList 测试空列表
|
||||
func (s *TreeServiceTestSuite) TestBuildTree_EmptyList() {
|
||||
result := buildTree([]TreeNode{})
|
||||
s.Empty(result)
|
||||
}
|
||||
|
||||
// TestBuildTree_SingleRoot 测试单个根节点
|
||||
func (s *TreeServiceTestSuite) TestBuildTree_SingleRoot() {
|
||||
nodes := []TreeNode{
|
||||
{ID: 1, ParentID: 0, Name: "Root"},
|
||||
}
|
||||
result := buildTree(nodes)
|
||||
|
||||
s.Len(result, 1)
|
||||
s.Equal("Root", result[0].Name)
|
||||
}
|
||||
|
||||
// TestBuildTree_MultipleRoots 测试多个根节点
|
||||
func (s *TreeServiceTestSuite) TestBuildTree_MultipleRoots() {
|
||||
nodes := []TreeNode{
|
||||
{ID: 1, ParentID: 0, Name: "Root1"},
|
||||
{ID: 2, ParentID: 0, Name: "Root2"},
|
||||
{ID: 3, ParentID: 0, Name: "Root3"},
|
||||
}
|
||||
result := buildTree(nodes)
|
||||
|
||||
s.Len(result, 3)
|
||||
}
|
||||
|
||||
// TestBuildTree_ParentChild 测试父子关系
|
||||
func (s *TreeServiceTestSuite) TestBuildTree_ParentChild() {
|
||||
nodes := []TreeNode{
|
||||
{ID: 1, ParentID: 0, Name: "Root"},
|
||||
{ID: 2, ParentID: 1, Name: "Child1"},
|
||||
{ID: 3, ParentID: 1, Name: "Child2"},
|
||||
{ID: 4, ParentID: 2, Name: "Grandchild"},
|
||||
}
|
||||
result := buildTree(nodes)
|
||||
|
||||
s.Len(result, 1, "应该只有 1 个根节点")
|
||||
s.Len(result[0].Children, 2, "根节点应该有 2 个子节点")
|
||||
}
|
||||
|
||||
// TestFlattenTree 测试树形展平
|
||||
func (s *TreeServiceTestSuite) TestFlattenTree() {
|
||||
tree := []TreeNode{
|
||||
{
|
||||
ID: 1,
|
||||
Name: "Root",
|
||||
Children: []TreeNode{
|
||||
{ID: 2, Name: "Child1"},
|
||||
{ID: 3, Name: "Child2"},
|
||||
},
|
||||
},
|
||||
}
|
||||
result := flattenTree(tree)
|
||||
|
||||
s.Len(result, 3)
|
||||
s.Equal("Root", result[0].Name)
|
||||
s.Equal("Child1", result[1].Name)
|
||||
s.Equal("Child2", result[2].Name)
|
||||
}
|
||||
|
||||
// TestContains 测试 contains 函数
|
||||
func (s *TreeServiceTestSuite) TestContains() {
|
||||
tests := []struct {
|
||||
name string
|
||||
slice []uint
|
||||
item uint
|
||||
want bool
|
||||
}{
|
||||
{"空切片", []uint{}, 1, false},
|
||||
{"存在的元素", []uint{1, 2, 3}, 2, true},
|
||||
{"不存在的元素", []uint{1, 2, 3}, 4, false},
|
||||
{"单元素存在", []uint{5}, 5, true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
s.Run(tt.name, func() {
|
||||
s.Equal(tt.want, contains(tt.slice, tt.item))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestUniqueUint 测试去重函数
|
||||
func (s *TreeServiceTestSuite) TestUniqueUint() {
|
||||
tests := []struct {
|
||||
name string
|
||||
slice []uint
|
||||
want int // 期望的长度
|
||||
}{
|
||||
{"空切片", []uint{}, 0},
|
||||
{"无重复", []uint{1, 2, 3}, 3},
|
||||
{"有重复", []uint{1, 2, 2, 3, 3, 3}, 3},
|
||||
{"全部重复", []uint{5, 5, 5}, 1},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
s.Run(tt.name, func() {
|
||||
got := uniqueUint(tt.slice)
|
||||
s.Len(got, tt.want)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user