Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
milvus
milvus
提交
dd20ab44
M
milvus
项目概览
milvus
/
milvus
10 个月 前同步成功
通知
260
Star
22476
Fork
2472
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
M
milvus
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
dd20ab44
编写于
3月 13, 2021
作者:
D
dragondriver
提交者:
yefu.chen
3月 13, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add interface of check param util
Signed-off-by:
N
dragondriver
<
jiquan.long@zilliz.com
>
上级
48522d72
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
679 addition
and
56 deletion
+679
-56
internal/proxynode/conf_adapter.go
internal/proxynode/conf_adapter.go
+446
-0
internal/proxynode/conf_adapter_mgr.go
internal/proxynode/conf_adapter_mgr.go
+61
-0
internal/proxynode/index_type.go
internal/proxynode/index_type.go
+19
-0
internal/proxynode/insert_channels.go
internal/proxynode/insert_channels.go
+0
-56
internal/proxynode/util.go
internal/proxynode/util.go
+56
-0
internal/proxynode/util_test.go
internal/proxynode/util_test.go
+97
-0
未找到文件。
internal/proxynode/conf_adapter.go
0 → 100644
浏览文件 @
dd20ab44
package
proxynode
import
(
"strconv"
)
const
(
L2
=
"L2"
IP
=
"IP"
HAMMING
=
"HAMMING"
JACCARD
=
"JACCARD"
TANIMOTO
=
"TANIMOTO"
SUBSTRUCTURE
=
"SUBSTRUCTURE"
SUPERSTRUCTURE
=
"SUPERSTRUCTURE"
MinNBits
=
1
MaxNBits
=
16
DefaultNBits
=
8
MinNList
=
1
MaxNList
=
65536
DefaultMinDim
=
1
DefaultMaxDim
=
32768
NgtMinEdgeSize
=
1
NgtMaxEdgeSize
=
200
HNSWMinEfConstruction
=
8
HNSWMaxEfConstruction
=
512
HNSWMinM
=
4
HNSWMaxM
=
64
MinKNNG
=
5
MaxKNNG
=
300
MinSearchLength
=
10
MaxSearchLength
=
300
MinOutDegree
=
5
MaxOutDegree
=
300
MinCandidatePoolSize
=
50
MaxCandidatePoolSize
=
1000
MinNTrees
=
1
// too large of n_trees takes much time, if there is real requirement, change this threshold.
MaxNTrees
=
1024
DIM
=
"dim"
Metric
=
"metric_type"
NLIST
=
"nlist"
NBITS
=
"nbits"
IVFM
=
"m"
KNNG
=
"knng"
SearchLength
=
"search_length"
OutDegree
=
"out_degree"
CANDIDATE
=
"candidate_pool_size"
EFConstruction
=
"efConstruction"
HNSWM
=
"M"
PQM
=
"PQM"
NTREES
=
"n_trees"
EdgeSize
=
"edge_size"
ForcedlyPrunedEdgeSize
=
"forcedly_pruned_edge_size"
SelectivelyPrunedEdgeSize
=
"selectively_pruned_edge_size"
OutgoingEdgeSize
=
"outgoing_edge_size"
IncomingEdgeSize
=
"incoming_edge_size"
IndexMode
=
"index_mode"
CPUMode
=
"CPU"
GPUMode
=
"GPU"
)
var
METRICS
=
[]
string
{
L2
,
IP
}
// const
var
BinIDMapMetrics
=
[]
string
{
HAMMING
,
JACCARD
,
TANIMOTO
,
SUBSTRUCTURE
,
SUBSTRUCTURE
}
// const
var
BinIvfMetrics
=
[]
string
{
HAMMING
,
JACCARD
,
TANIMOTO
}
// const
var
supportDimPerSubQuantizer
=
[]
int
{
32
,
28
,
24
,
20
,
16
,
12
,
10
,
8
,
6
,
4
,
3
,
2
,
1
}
// const
var
supportSubQuantizer
=
[]
int
{
96
,
64
,
56
,
48
,
40
,
32
,
28
,
24
,
20
,
16
,
12
,
8
,
4
,
3
,
2
,
1
}
// const
type
ConfAdapter
interface
{
CheckTrain
(
map
[
string
]
string
)
bool
}
func
CheckIntByRange
(
params
map
[
string
]
string
,
key
string
,
min
,
max
int
)
bool
{
valueStr
,
ok
:=
params
[
key
]
if
!
ok
{
return
false
}
value
,
err
:=
strconv
.
Atoi
(
valueStr
)
if
err
!=
nil
{
return
false
}
return
value
>=
min
&&
value
<=
max
}
func
CheckStrByValues
(
params
map
[
string
]
string
,
key
string
,
container
[]
string
)
bool
{
value
,
ok
:=
params
[
key
]
if
!
ok
{
return
false
}
return
SliceContain
(
container
,
value
)
}
type
BaseConfAdapter
struct
{
}
func
(
adapter
*
BaseConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
if
!
CheckIntByRange
(
params
,
DIM
,
DefaultMinDim
,
DefaultMaxDim
)
{
return
false
}
return
CheckStrByValues
(
params
,
Metric
,
METRICS
)
}
func
newBaseConfAdapter
()
*
BaseConfAdapter
{
return
&
BaseConfAdapter
{}
}
type
IVFConfAdapter
struct
{
BaseConfAdapter
}
func
(
adapter
*
IVFConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
if
!
CheckIntByRange
(
params
,
NLIST
,
MinNList
,
MaxNList
)
{
return
false
}
// skip check number of rows
return
adapter
.
BaseConfAdapter
.
CheckTrain
(
params
)
}
func
newIVFConfAdapter
()
*
IVFConfAdapter
{
return
&
IVFConfAdapter
{}
}
type
IVFPQConfAdapter
struct
{
IVFConfAdapter
}
func
(
adapter
*
IVFPQConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
if
!
adapter
.
IVFConfAdapter
.
CheckTrain
(
params
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
NBITS
,
MinNBits
,
MaxNBits
)
{
return
false
}
return
adapter
.
checkPQParams
(
params
)
}
func
(
adapter
*
IVFPQConfAdapter
)
checkPQParams
(
params
map
[
string
]
string
)
bool
{
dimension
,
_
:=
strconv
.
Atoi
(
params
[
DIM
])
nbits
,
_
:=
strconv
.
Atoi
(
params
[
NBITS
])
mStr
,
ok
:=
params
[
IVFM
]
if
!
ok
{
return
false
}
m
,
err
:=
strconv
.
Atoi
(
mStr
)
if
err
!=
nil
{
return
false
}
mode
,
ok
:=
params
[
IndexMode
]
if
!
ok
{
mode
=
CPUMode
}
if
mode
==
GPUMode
&&
!
adapter
.
checkGPUPQParams
(
dimension
,
m
,
nbits
)
{
return
false
}
return
adapter
.
checkCPUPQParams
(
dimension
,
m
)
}
func
(
adapter
*
IVFPQConfAdapter
)
checkGPUPQParams
(
dimension
,
m
,
nbits
int
)
bool
{
/*
* Faiss 1.6
* Only 1, 2, 3, 4, 6, 8, 10, 12, 16, 20, 24, 28, 32 dims per sub-quantizer are currently supported with
* no precomputed codes. Precomputed codes supports any number of dimensions, but will involve memory overheads.
*/
subDim
:=
dimension
/
m
return
SliceContain
(
supportSubQuantizer
,
m
)
&&
SliceContain
(
supportDimPerSubQuantizer
,
subDim
)
&&
nbits
==
8
}
func
(
adapter
*
IVFPQConfAdapter
)
checkCPUPQParams
(
dimension
,
m
int
)
bool
{
return
(
dimension
%
m
)
==
0
}
func
newIVFPQConfAdapter
()
*
IVFPQConfAdapter
{
return
&
IVFPQConfAdapter
{}
}
type
IVFSQConfAdapter
struct
{
IVFConfAdapter
}
func
(
adapter
*
IVFSQConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
params
[
NBITS
]
=
strconv
.
Itoa
(
DefaultNBits
)
return
adapter
.
IVFConfAdapter
.
CheckTrain
(
params
)
}
func
newIVFSQConfAdapter
()
*
IVFSQConfAdapter
{
return
&
IVFSQConfAdapter
{}
}
type
BinIDMAPConfAdapter
struct
{
}
func
(
adapter
*
BinIDMAPConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
if
!
CheckIntByRange
(
params
,
DIM
,
DefaultMinDim
,
DefaultMaxDim
)
{
return
false
}
return
CheckStrByValues
(
params
,
Metric
,
BinIDMapMetrics
)
}
func
newBinIDMAPConfAdapter
()
*
BinIDMAPConfAdapter
{
return
&
BinIDMAPConfAdapter
{}
}
type
BinIVFConfAdapter
struct
{
}
func
(
adapter
*
BinIVFConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
if
!
CheckIntByRange
(
params
,
DIM
,
DefaultMinDim
,
DefaultMaxDim
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
NLIST
,
MinNList
,
MaxNList
)
{
return
false
}
if
!
CheckStrByValues
(
params
,
Metric
,
BinIvfMetrics
)
{
return
false
}
// skip checking the number of rows
return
true
}
func
newBinIVFConfAdapter
()
*
BinIVFConfAdapter
{
return
&
BinIVFConfAdapter
{}
}
type
NSGConfAdapter
struct
{
}
func
(
adapter
*
NSGConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
if
!
CheckStrByValues
(
params
,
Metric
,
METRICS
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
KNNG
,
MinKNNG
,
MaxKNNG
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
SearchLength
,
MinSearchLength
,
MaxSearchLength
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
OutDegree
,
MinOutDegree
,
MaxOutDegree
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
CANDIDATE
,
MinCandidatePoolSize
,
MaxCandidatePoolSize
)
{
return
false
}
// skip checking the number of rows
return
true
}
func
newNSGConfAdapter
()
*
NSGConfAdapter
{
return
&
NSGConfAdapter
{}
}
type
HNSWConfAdapter
struct
{
BaseConfAdapter
}
func
(
adapter
*
HNSWConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
if
!
CheckIntByRange
(
params
,
EFConstruction
,
HNSWMinEfConstruction
,
HNSWMaxEfConstruction
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
HNSWM
,
HNSWMinM
,
HNSWMaxM
)
{
return
false
}
return
adapter
.
BaseConfAdapter
.
CheckTrain
(
params
)
}
func
newHNSWConfAdapter
()
*
HNSWConfAdapter
{
return
&
HNSWConfAdapter
{}
}
type
ANNOYConfAdapter
struct
{
BaseConfAdapter
}
func
(
adapter
*
ANNOYConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
if
!
CheckIntByRange
(
params
,
NTREES
,
MinNTrees
,
MaxNTrees
)
{
return
false
}
return
adapter
.
BaseConfAdapter
.
CheckTrain
(
params
)
}
func
newANNOYConfAdapter
()
*
ANNOYConfAdapter
{
return
&
ANNOYConfAdapter
{}
}
type
RHNSWFlatConfAdapter
struct
{
BaseConfAdapter
}
func
(
adapter
*
RHNSWFlatConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
if
!
CheckIntByRange
(
params
,
EFConstruction
,
HNSWMinEfConstruction
,
HNSWMaxEfConstruction
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
HNSWM
,
HNSWMinM
,
HNSWMaxM
)
{
return
false
}
return
adapter
.
BaseConfAdapter
.
CheckTrain
(
params
)
}
func
newRHNSWFlatConfAdapter
()
*
RHNSWFlatConfAdapter
{
return
&
RHNSWFlatConfAdapter
{}
}
type
RHNSWPQConfAdapter
struct
{
BaseConfAdapter
IVFPQConfAdapter
}
func
(
adapter
*
RHNSWPQConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
if
!
adapter
.
BaseConfAdapter
.
CheckTrain
(
params
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
EFConstruction
,
HNSWMinM
,
HNSWMaxM
)
{
return
false
}
dimension
,
_
:=
strconv
.
Atoi
(
params
[
DIM
])
pqmStr
,
ok
:=
params
[
PQM
]
if
!
ok
{
return
false
}
pqm
,
err
:=
strconv
.
Atoi
(
pqmStr
)
if
err
!=
nil
{
return
false
}
return
adapter
.
IVFPQConfAdapter
.
checkCPUPQParams
(
dimension
,
pqm
)
}
func
newRHNSWPQConfAdapter
()
*
RHNSWPQConfAdapter
{
return
&
RHNSWPQConfAdapter
{}
}
type
RHNSWSQConfAdapter
struct
{
BaseConfAdapter
}
func
(
adapter
*
RHNSWSQConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
if
!
CheckIntByRange
(
params
,
EFConstruction
,
HNSWMinEfConstruction
,
HNSWMaxEfConstruction
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
HNSWM
,
HNSWMinM
,
HNSWMaxM
)
{
return
false
}
return
adapter
.
BaseConfAdapter
.
CheckTrain
(
params
)
}
func
newRHNSWSQConfAdapter
()
*
RHNSWSQConfAdapter
{
return
&
RHNSWSQConfAdapter
{}
}
type
NGTPANNGConfAdapter
struct
{
BaseConfAdapter
}
func
(
adapter
*
NGTPANNGConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
if
!
CheckIntByRange
(
params
,
EdgeSize
,
NgtMinEdgeSize
,
NgtMaxEdgeSize
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
ForcedlyPrunedEdgeSize
,
NgtMinEdgeSize
,
NgtMaxEdgeSize
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
SelectivelyPrunedEdgeSize
,
NgtMinEdgeSize
,
NgtMaxEdgeSize
)
{
return
false
}
selectivelyPrunedEdgeSize
,
_
:=
strconv
.
Atoi
(
params
[
SelectivelyPrunedEdgeSize
])
forcedlyPrunedEdgeSize
,
_
:=
strconv
.
Atoi
(
params
[
ForcedlyPrunedEdgeSize
])
if
selectivelyPrunedEdgeSize
>=
forcedlyPrunedEdgeSize
{
return
false
}
return
adapter
.
BaseConfAdapter
.
CheckTrain
(
params
)
}
func
newNGTPANNGConfAdapter
()
*
NGTPANNGConfAdapter
{
return
&
NGTPANNGConfAdapter
{}
}
type
NGTONNGConfAdapter
struct
{
BaseConfAdapter
}
func
(
adapter
*
NGTONNGConfAdapter
)
CheckTrain
(
params
map
[
string
]
string
)
bool
{
if
!
CheckIntByRange
(
params
,
EdgeSize
,
NgtMinEdgeSize
,
NgtMaxEdgeSize
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
OutgoingEdgeSize
,
NgtMinEdgeSize
,
NgtMaxEdgeSize
)
{
return
false
}
if
!
CheckIntByRange
(
params
,
IncomingEdgeSize
,
NgtMinEdgeSize
,
NgtMaxEdgeSize
)
{
return
false
}
return
adapter
.
BaseConfAdapter
.
CheckTrain
(
params
)
}
func
newNGTONNGConfAdapter
()
*
NGTONNGConfAdapter
{
return
&
NGTONNGConfAdapter
{}
}
internal/proxynode/conf_adapter_mgr.go
0 → 100644
浏览文件 @
dd20ab44
package
proxynode
import
(
"errors"
"sync"
)
type
ConfAdapterMgr
interface
{
GetAdapter
(
indexType
string
)
(
ConfAdapter
,
error
)
}
type
ConfAdapterMgrImpl
struct
{
init
bool
adapters
map
[
string
]
ConfAdapter
}
func
(
mgr
*
ConfAdapterMgrImpl
)
GetAdapter
(
indexType
string
)
(
ConfAdapter
,
error
)
{
if
!
mgr
.
init
{
mgr
.
registerConfAdapter
()
}
adapter
,
ok
:=
mgr
.
adapters
[
indexType
]
if
ok
{
return
adapter
,
nil
}
return
nil
,
errors
.
New
(
"Can not find conf adapter: "
+
indexType
)
}
func
(
mgr
*
ConfAdapterMgrImpl
)
registerConfAdapter
()
{
mgr
.
init
=
true
mgr
.
adapters
[
IndexFaissIdmap
]
=
newBaseConfAdapter
()
mgr
.
adapters
[
IndexFaissIvfflat
]
=
newIVFConfAdapter
()
mgr
.
adapters
[
IndexFaissIvfpq
]
=
newIVFPQConfAdapter
()
mgr
.
adapters
[
IndexFaissIvfsq8
]
=
newIVFSQConfAdapter
()
mgr
.
adapters
[
IndexFaissIvfsq8h
]
=
newIVFSQConfAdapter
()
mgr
.
adapters
[
IndexFaissBinIdmap
]
=
newBinIDMAPConfAdapter
()
mgr
.
adapters
[
IndexFaissBinIvfflat
]
=
newBinIVFConfAdapter
()
mgr
.
adapters
[
IndexNsg
]
=
newNSGConfAdapter
()
mgr
.
adapters
[
IndexHnsw
]
=
newHNSWConfAdapter
()
mgr
.
adapters
[
IndexAnnoy
]
=
newANNOYConfAdapter
()
mgr
.
adapters
[
IndexRhnswflat
]
=
newRHNSWFlatConfAdapter
()
mgr
.
adapters
[
IndexRhnswpq
]
=
newRHNSWPQConfAdapter
()
mgr
.
adapters
[
IndexRhnswsq
]
=
newRHNSWSQConfAdapter
()
mgr
.
adapters
[
IndexNgtpanng
]
=
newNGTPANNGConfAdapter
()
mgr
.
adapters
[
IndexNgtonng
]
=
newNGTONNGConfAdapter
()
}
func
newConfAdapterMgrImpl
()
*
ConfAdapterMgrImpl
{
return
&
ConfAdapterMgrImpl
{}
}
var
confAdapterMgr
ConfAdapterMgr
var
getConfAdapterMgrOnce
sync
.
Once
func
GetConfAdapterMgrInstance
()
ConfAdapterMgr
{
getConfAdapterMgrOnce
.
Do
(
func
()
{
confAdapterMgr
=
newConfAdapterMgrImpl
()
})
return
confAdapterMgr
}
internal/proxynode/index_type.go
0 → 100644
浏览文件 @
dd20ab44
package
proxynode
const
(
IndexFaissIdmap
=
"FLAT"
IndexFaissIvfflat
=
"IVF_FLAT"
IndexFaissIvfpq
=
"IVF_PQ"
IndexFaissIvfsq8
=
"IVF_SQ8"
IndexFaissIvfsq8h
=
"IVF_SQ8_HYBRID"
IndexFaissBinIdmap
=
"BIN_FLAT"
IndexFaissBinIvfflat
=
"BIN_IVF_FLAT"
IndexNsg
=
"NSG"
IndexHnsw
=
"HNSW"
IndexRhnswflat
=
"RHNSW_FLAT"
IndexRhnswpq
=
"RHNSW_PQ"
IndexRhnswsq
=
"RHNSW_SQ"
IndexAnnoy
=
"ANNOY"
IndexNgtpanng
=
"NGT_PANNG"
IndexNgtonng
=
"NGT_ONNG"
)
internal/proxynode/insert_channels.go
浏览文件 @
dd20ab44
...
...
@@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"reflect"
"sort"
"sync"
...
...
@@ -13,61 +12,6 @@ import (
"go.uber.org/zap"
)
func
SliceContain
(
s
interface
{},
item
interface
{})
bool
{
ss
:=
reflect
.
ValueOf
(
s
)
if
ss
.
Kind
()
!=
reflect
.
Slice
{
panic
(
"SliceContain expect a slice"
)
}
for
i
:=
0
;
i
<
ss
.
Len
();
i
++
{
if
ss
.
Index
(
i
)
.
Interface
()
==
item
{
return
true
}
}
return
false
}
func
SliceSetEqual
(
s1
interface
{},
s2
interface
{})
bool
{
ss1
:=
reflect
.
ValueOf
(
s1
)
ss2
:=
reflect
.
ValueOf
(
s2
)
if
ss1
.
Kind
()
!=
reflect
.
Slice
{
panic
(
"expect a slice"
)
}
if
ss2
.
Kind
()
!=
reflect
.
Slice
{
panic
(
"expect a slice"
)
}
if
ss1
.
Len
()
!=
ss2
.
Len
()
{
return
false
}
for
i
:=
0
;
i
<
ss1
.
Len
();
i
++
{
if
!
SliceContain
(
s2
,
ss1
.
Index
(
i
)
.
Interface
())
{
return
false
}
}
return
true
}
func
SortedSliceEqual
(
s1
interface
{},
s2
interface
{})
bool
{
ss1
:=
reflect
.
ValueOf
(
s1
)
ss2
:=
reflect
.
ValueOf
(
s2
)
if
ss1
.
Kind
()
!=
reflect
.
Slice
{
panic
(
"expect a slice"
)
}
if
ss2
.
Kind
()
!=
reflect
.
Slice
{
panic
(
"expect a slice"
)
}
if
ss1
.
Len
()
!=
ss2
.
Len
()
{
return
false
}
for
i
:=
0
;
i
<
ss1
.
Len
();
i
++
{
if
ss2
.
Index
(
i
)
.
Interface
()
!=
ss1
.
Index
(
i
)
.
Interface
()
{
return
false
}
}
return
true
}
type
InsertChannelsMap
struct
{
collectionID2InsertChannels
map
[
UniqueID
]
int
// the value of map is the location of insertChannels & insertMsgStreams
insertChannels
[][]
string
// it's a little confusing to use []string as the key of map
...
...
internal/proxynode/util.go
浏览文件 @
dd20ab44
...
...
@@ -4,6 +4,7 @@ import (
"encoding/json"
"io/ioutil"
"net/http"
"reflect"
"time"
"go.uber.org/zap"
...
...
@@ -41,3 +42,58 @@ func GetPulsarConfig(protocol, ip, port, url string) (map[string]interface{}, er
return
ret
,
nil
}
func
SliceContain
(
s
interface
{},
item
interface
{})
bool
{
ss
:=
reflect
.
ValueOf
(
s
)
if
ss
.
Kind
()
!=
reflect
.
Slice
{
panic
(
"SliceContain expect a slice"
)
}
for
i
:=
0
;
i
<
ss
.
Len
();
i
++
{
if
ss
.
Index
(
i
)
.
Interface
()
==
item
{
return
true
}
}
return
false
}
func
SliceSetEqual
(
s1
interface
{},
s2
interface
{})
bool
{
ss1
:=
reflect
.
ValueOf
(
s1
)
ss2
:=
reflect
.
ValueOf
(
s2
)
if
ss1
.
Kind
()
!=
reflect
.
Slice
{
panic
(
"expect a slice"
)
}
if
ss2
.
Kind
()
!=
reflect
.
Slice
{
panic
(
"expect a slice"
)
}
if
ss1
.
Len
()
!=
ss2
.
Len
()
{
return
false
}
for
i
:=
0
;
i
<
ss1
.
Len
();
i
++
{
if
!
SliceContain
(
s2
,
ss1
.
Index
(
i
)
.
Interface
())
{
return
false
}
}
return
true
}
func
SortedSliceEqual
(
s1
interface
{},
s2
interface
{})
bool
{
ss1
:=
reflect
.
ValueOf
(
s1
)
ss2
:=
reflect
.
ValueOf
(
s2
)
if
ss1
.
Kind
()
!=
reflect
.
Slice
{
panic
(
"expect a slice"
)
}
if
ss2
.
Kind
()
!=
reflect
.
Slice
{
panic
(
"expect a slice"
)
}
if
ss1
.
Len
()
!=
ss2
.
Len
()
{
return
false
}
for
i
:=
0
;
i
<
ss1
.
Len
();
i
++
{
if
ss2
.
Index
(
i
)
.
Interface
()
!=
ss1
.
Index
(
i
)
.
Interface
()
{
return
false
}
}
return
true
}
internal/proxynode/util_test.go
浏览文件 @
dd20ab44
...
...
@@ -3,6 +3,7 @@ package proxynode
import
(
"fmt"
"net/http"
"sort"
"strconv"
"testing"
...
...
@@ -36,3 +37,99 @@ func TestGetPulsarConfig(t *testing.T) {
assert
.
Equal
(
t
,
fmt
.
Sprintf
(
"%v"
,
value
),
fmt
.
Sprintf
(
"%v"
,
runtimeConfig
[
key
]))
}
}
func
TestSliceContain
(
t
*
testing
.
T
)
{
strSlice
:=
[]
string
{
"test"
,
"for"
,
"SliceContain"
}
intSlice
:=
[]
int
{
1
,
2
,
3
}
cases
:=
[]
struct
{
s
interface
{}
item
interface
{}
want
bool
}{
{
strSlice
,
"test"
,
true
},
{
strSlice
,
"for"
,
true
},
{
strSlice
,
"SliceContain"
,
true
},
{
strSlice
,
"tests"
,
false
},
{
intSlice
,
1
,
true
},
{
intSlice
,
2
,
true
},
{
intSlice
,
3
,
true
},
{
intSlice
,
4
,
false
},
}
for
_
,
test
:=
range
cases
{
if
got
:=
SliceContain
(
test
.
s
,
test
.
item
);
got
!=
test
.
want
{
t
.
Errorf
(
"SliceContain(%v, %v) = %v"
,
test
.
s
,
test
.
item
,
test
.
want
)
}
}
}
func
TestSliceSetEqual
(
t
*
testing
.
T
)
{
cases
:=
[]
struct
{
s1
interface
{}
s2
interface
{}
want
bool
}{
{[]
int
{},
[]
int
{},
true
},
{[]
string
{},
[]
string
{},
true
},
{[]
int
{
1
,
2
,
3
},
[]
int
{
3
,
2
,
1
},
true
},
{[]
int
{
1
,
2
,
3
},
[]
int
{
1
,
2
,
3
},
true
},
{[]
int
{
1
,
2
,
3
},
[]
int
{},
false
},
{[]
int
{
1
,
2
,
3
},
[]
int
{
1
,
2
},
false
},
{[]
int
{
1
,
2
,
3
},
[]
int
{
4
,
5
,
6
},
false
},
{[]
string
{
"test"
,
"for"
,
"SliceSetEqual"
},
[]
string
{
"SliceSetEqual"
,
"test"
,
"for"
},
true
},
{[]
string
{
"test"
,
"for"
,
"SliceSetEqual"
},
[]
string
{
"test"
,
"for"
,
"SliceSetEqual"
},
true
},
{[]
string
{
"test"
,
"for"
,
"SliceSetEqual"
},
[]
string
{
"test"
,
"for"
},
false
},
{[]
string
{
"test"
,
"for"
,
"SliceSetEqual"
},
[]
string
{},
false
},
{[]
string
{
"test"
,
"for"
,
"SliceSetEqual"
},
[]
string
{
"test"
,
"for"
,
"SliceContain"
},
false
},
}
for
_
,
test
:=
range
cases
{
if
got
:=
SliceSetEqual
(
test
.
s1
,
test
.
s2
);
got
!=
test
.
want
{
t
.
Errorf
(
"SliceSetEqual(%v, %v) = %v"
,
test
.
s1
,
test
.
s2
,
test
.
want
)
}
}
}
func
TestSortedSliceEqual
(
t
*
testing
.
T
)
{
sortSlice
:=
func
(
slice
interface
{},
less
func
(
i
,
j
int
)
bool
)
{
sort
.
Slice
(
slice
,
less
)
}
intSliceAfterSort
:=
func
(
slice
[]
int
)
[]
int
{
sortSlice
(
slice
,
func
(
i
,
j
int
)
bool
{
return
slice
[
i
]
<=
slice
[
j
]
})
return
slice
}
stringSliceAfterSort
:=
func
(
slice
[]
string
)
[]
string
{
sortSlice
(
slice
,
func
(
i
,
j
int
)
bool
{
return
slice
[
i
]
<=
slice
[
j
]
})
return
slice
}
cases
:=
[]
struct
{
s1
interface
{}
s2
interface
{}
want
bool
}{
{
intSliceAfterSort
([]
int
{}),
intSliceAfterSort
([]
int
{}),
true
},
{
stringSliceAfterSort
([]
string
{}),
stringSliceAfterSort
([]
string
{}),
true
},
{
intSliceAfterSort
([]
int
{
1
,
2
,
3
}),
intSliceAfterSort
([]
int
{
3
,
2
,
1
}),
true
},
{
intSliceAfterSort
([]
int
{
1
,
2
,
3
}),
intSliceAfterSort
([]
int
{
1
,
2
,
3
}),
true
},
{
intSliceAfterSort
([]
int
{
1
,
2
,
3
}),
intSliceAfterSort
([]
int
{}),
false
},
{
intSliceAfterSort
([]
int
{
1
,
2
,
3
}),
intSliceAfterSort
([]
int
{
1
,
2
}),
false
},
{
intSliceAfterSort
([]
int
{
1
,
2
,
3
}),
intSliceAfterSort
([]
int
{
4
,
5
,
6
}),
false
},
{
stringSliceAfterSort
([]
string
{
"test"
,
"for"
,
"SliceSetEqual"
}),
stringSliceAfterSort
([]
string
{
"SliceSetEqual"
,
"test"
,
"for"
}),
true
},
{
stringSliceAfterSort
([]
string
{
"test"
,
"for"
,
"SliceSetEqual"
}),
stringSliceAfterSort
([]
string
{
"test"
,
"for"
,
"SliceSetEqual"
}),
true
},
{
stringSliceAfterSort
([]
string
{
"test"
,
"for"
,
"SliceSetEqual"
}),
stringSliceAfterSort
([]
string
{
"test"
,
"for"
}),
false
},
{
stringSliceAfterSort
([]
string
{
"test"
,
"for"
,
"SliceSetEqual"
}),
stringSliceAfterSort
([]
string
{}),
false
},
{
stringSliceAfterSort
([]
string
{
"test"
,
"for"
,
"SliceSetEqual"
}),
stringSliceAfterSort
([]
string
{
"test"
,
"for"
,
"SliceContain"
}),
false
},
}
for
_
,
test
:=
range
cases
{
if
got
:=
SortedSliceEqual
(
test
.
s1
,
test
.
s2
);
got
!=
test
.
want
{
t
.
Errorf
(
"SliceSetEqual(%v, %v) = %v"
,
test
.
s1
,
test
.
s2
,
test
.
want
)
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录