diff --git a/internal/util/funcutil/func_test.go b/internal/util/funcutil/func_test.go index 48cca5d30b..92a3263cad 100644 --- a/internal/util/funcutil/func_test.go +++ b/internal/util/funcutil/func_test.go @@ -12,13 +12,90 @@ package funcutil import ( + "context" "encoding/json" + "errors" "strconv" "testing" + "time" + "github.com/milvus-io/milvus/internal/proto/commonpb" + "github.com/milvus-io/milvus/internal/proto/internalpb" + "github.com/milvus-io/milvus/internal/proto/milvuspb" "github.com/stretchr/testify/assert" ) +type MockComponent struct { + compState *internalpb.ComponentStates + strResp *milvuspb.StringResponse + compErr error +} + +func (mc *MockComponent) SetCompState(state *internalpb.ComponentStates) { + mc.compState = state +} + +func (mc *MockComponent) SetStrResp(resp *milvuspb.StringResponse) { + mc.strResp = resp +} + +func (mc *MockComponent) Init() error { + return nil +} + +func (mc *MockComponent) Start() error { + return nil +} + +func (mc *MockComponent) Stop() error { + return nil +} + +func (mc *MockComponent) GetComponentStates(ctx context.Context) (*internalpb.ComponentStates, error) { + return mc.compState, mc.compErr +} + +func (mc *MockComponent) GetStatisticsChannel(ctx context.Context) (*milvuspb.StringResponse, error) { + return mc.strResp, nil +} + +func (mc *MockComponent) Register() error { + return nil +} + +func buildMockComponent(code internalpb.StateCode) *MockComponent { + mc := &MockComponent{ + compState: &internalpb.ComponentStates{ + State: &internalpb.ComponentInfo{ + NodeID: 0, + Role: "role", + StateCode: code, + }, + SubcomponentStates: nil, + Status: &commonpb.Status{ErrorCode: commonpb.ErrorCode_Success}, + }, + strResp: nil, + compErr: nil, + } + + return mc +} + +func TestCheckGrpcReady(t *testing.T) { + errChan := make(chan error) + + // test errChan can receive nil after interval + go CheckGrpcReady(context.TODO(), errChan) + + err := <-errChan + assert.Nil(t, err) + + // test CheckGrpcReady can finish after context done + ctx, cancel := context.WithTimeout(context.TODO(), 10*time.Millisecond) + CheckGrpcReady(ctx, errChan) + cancel() +} + func TestCheckPortAvailable(t *testing.T) { num := 10 @@ -28,6 +105,74 @@ func TestCheckPortAvailable(t *testing.T) { } } +func TestGetLocalIP(t *testing.T) { + ip := GetLocalIP() + assert.NotNil(t, ip) + assert.NotZero(t, len(ip)) +} + +func TestWaitForComponentInitOrHealthy(t *testing.T) { + mc := &MockComponent{ + compState: nil, + strResp: nil, + compErr: errors.New("error"), + } + err := WaitForComponentInitOrHealthy(context.TODO(), mc, "mockService", 1, 10*time.Millisecond) + assert.NotNil(t, err) + + mc = &MockComponent{ + compState: &internalpb.ComponentStates{ + State: nil, + SubcomponentStates: nil, + Status: &commonpb.Status{ErrorCode: commonpb.ErrorCode_UnexpectedError}, + }, + strResp: nil, + compErr: nil, + } + err = WaitForComponentInitOrHealthy(context.TODO(), mc, "mockService", 1, 10*time.Millisecond) + assert.NotNil(t, err) + + validCodes := []internalpb.StateCode{internalpb.StateCode_Initializing, internalpb.StateCode_Healthy} + testCodes := []internalpb.StateCode{internalpb.StateCode_Initializing, internalpb.StateCode_Healthy, internalpb.StateCode_Abnormal} + for _, code := range testCodes { + mc := buildMockComponent(code) + err := WaitForComponentInitOrHealthy(context.TODO(), mc, "mockService", 1, 10*time.Millisecond) + if SliceContain(validCodes, code) { + assert.Nil(t, err) + } else { + assert.NotNil(t, err) + } + } +} + +func TestWaitForComponentInit(t *testing.T) { + validCodes := []internalpb.StateCode{internalpb.StateCode_Initializing} + testCodes := []internalpb.StateCode{internalpb.StateCode_Initializing, internalpb.StateCode_Healthy, internalpb.StateCode_Abnormal} + for _, code := range testCodes { + mc := buildMockComponent(code) + err := WaitForComponentInit(context.TODO(), mc, "mockService", 1, 10*time.Millisecond) + if SliceContain(validCodes, code) { + assert.Nil(t, err) + } else { + assert.NotNil(t, err) + } + } +} + +func TestWaitForComponentHealthy(t *testing.T) { + validCodes := []internalpb.StateCode{internalpb.StateCode_Healthy} + testCodes := []internalpb.StateCode{internalpb.StateCode_Initializing, internalpb.StateCode_Healthy, internalpb.StateCode_Abnormal} + for _, code := range testCodes { + mc := buildMockComponent(code) + err := WaitForComponentHealthy(context.TODO(), mc, "mockService", 1, 10*time.Millisecond) + if SliceContain(validCodes, code) { + assert.Nil(t, err) + } else { + assert.NotNil(t, err) + } + } +} + func TestParseIndexParamsMap(t *testing.T) { num := 10 keys := make([]string, 0) diff --git a/internal/util/funcutil/parallel_test.go b/internal/util/funcutil/parallel_test.go index d31c389a0e..4e49215d53 100644 --- a/internal/util/funcutil/parallel_test.go +++ b/internal/util/funcutil/parallel_test.go @@ -16,11 +16,20 @@ import ( "math/rand" "runtime" "strconv" + "strings" "testing" "github.com/stretchr/testify/assert" ) +func dummyFunc() { +} + +func TestGetFunctionName(t *testing.T) { + name := GetFunctionName(dummyFunc) + assert.True(t, strings.Contains(name, "dummyFunc")) +} + func TestProcessFuncParallel(t *testing.T) { total := 64 s := make([]int, total) @@ -37,6 +46,12 @@ func TestProcessFuncParallel(t *testing.T) { var err error + err = ProcessFuncParallel(total, 0, naiveF, "naiveF") // maxParallel = 0 + assert.Equal(t, err, nil) + + err = ProcessFuncParallel(0, 1, naiveF, "naiveF") // total = 0 + assert.Equal(t, err, nil) + err = ProcessFuncParallel(total, 1, naiveF, "naiveF") // serial assert.Equal(t, err, nil, "process function serially must be right") assert.Equal(t, s, expectedS, "process function serially must be right") diff --git a/internal/util/funcutil/random_test.go b/internal/util/funcutil/random_test.go new file mode 100644 index 0000000000..7675470608 --- /dev/null +++ b/internal/util/funcutil/random_test.go @@ -0,0 +1,24 @@ +// Copyright (C) 2019-2020 Zilliz. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software distributed under the License +// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and limitations under the License. + +package funcutil + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRandomString(t *testing.T) { + length := 10 + str := RandomString(length) + assert.Equal(t, len(str), length) +} diff --git a/internal/util/funcutil/slice_test.go b/internal/util/funcutil/slice_test.go index 58c0c006ce..df39ec5d80 100644 --- a/internal/util/funcutil/slice_test.go +++ b/internal/util/funcutil/slice_test.go @@ -14,9 +14,14 @@ package funcutil import ( "sort" "testing" + + "github.com/stretchr/testify/assert" ) func TestSliceContain(t *testing.T) { + invalid := "invalid" + assert.Panics(t, func() { SliceContain(invalid, 1) }) + strSlice := []string{"test", "for", "SliceContain"} intSlice := []int{1, 2, 3} @@ -43,6 +48,11 @@ func TestSliceContain(t *testing.T) { } func TestSliceSetEqual(t *testing.T) { + invalid := "invalid" + assert.Panics(t, func() { SliceSetEqual(invalid, 1) }) + temp := []int{1, 2, 3} + assert.Panics(t, func() { SliceSetEqual(temp, invalid) }) + cases := []struct { s1 interface{} s2 interface{} @@ -70,6 +80,11 @@ func TestSliceSetEqual(t *testing.T) { } func TestSortedSliceEqual(t *testing.T) { + invalid := "invalid" + assert.Panics(t, func() { SortedSliceEqual(invalid, 1) }) + temp := []int{1, 2, 3} + assert.Panics(t, func() { SortedSliceEqual(temp, invalid) }) + sortSlice := func(slice interface{}, less func(i, j int) bool) { sort.Slice(slice, less) }