Skip to content

Commit

Permalink
feat: Add e2e test cases for GoSDK
Browse files Browse the repository at this point in the history
Signed-off-by: ThreadDao <yufen.zong@zilliz.com>
  • Loading branch information
ThreadDao committed May 24, 2024
1 parent ed883b3 commit 815742b
Show file tree
Hide file tree
Showing 18 changed files with 3,884 additions and 0 deletions.
1 change: 1 addition & 0 deletions client/entity/sparse.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type SparseEmbedding interface {
Len() int // the actual items in this vector
Get(idx int) (pos uint32, value float32, ok bool)
Serialize() []byte
FieldType() FieldType
}

var (
Expand Down
266 changes: 266 additions & 0 deletions tests/go_client/base/milvus_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
package base

import (
"context"

"github.com/milvus-io/milvus/pkg/log"

"github.com/milvus-io/milvus/client/v2/entity"

"go.uber.org/zap"

"google.golang.org/grpc"

clientv2 "github.com/milvus-io/milvus/client/v2"
"github.com/milvus-io/milvus/client/v2/index"
)

func preRequest(funcName string, args ...interface{}) {
//log.Info("(ApiRequest): func [%s], args: %v\n", funcName, args)
log.Info("ApiRequest", zap.String("func", funcName), zap.Any("args", args))
}

func postResponse(funcName string, err error, res ...interface{}) {
if err != nil {
log.Info("ApiResponse", zap.String("func", funcName), zap.Any("results", res), zap.Error(err))
} else {
log.Info("ApiResponse", zap.String("func", funcName), zap.Any("results", res))
}
}

type MilvusClient struct {
mClient *clientv2.Client
}

func NewMilvusClient(ctx context.Context, cfg *clientv2.ClientConfig) (*MilvusClient, error) {
preRequest("NewClient", ctx, cfg)
mClient, err := clientv2.New(ctx, cfg)
postResponse("NewClient", err, mClient)
return &MilvusClient{
mClient,
}, err
}

func (mc *MilvusClient) Close(ctx context.Context) error {
preRequest("Close")
err := mc.mClient.Close(ctx)
postResponse("Close", err)
return err
}

// -- database --

// ListDatabases list all database in milvus cluster.
func (mc *MilvusClient) UsingDatabase(ctx context.Context, option clientv2.UsingDatabaseOption) error {
preRequest("UsingDatabase", ctx, option)
err := mc.mClient.UsingDatabase(ctx, option)
postResponse("UsingDatabase", err)
return err
}

// ListDatabases list all database in milvus cluster.
func (mc *MilvusClient) ListDatabases(ctx context.Context, option clientv2.ListDatabaseOption, callOptions ...grpc.CallOption) ([]string, error) {
preRequest("ListDatabases", ctx, option, callOptions)
databaseNames, err := mc.mClient.ListDatabase(ctx, option, callOptions...)
postResponse("ListDatabases", err, databaseNames)
return databaseNames, err
}

// CreateDatabase create database with the given name.
func (mc *MilvusClient) CreateDatabase(ctx context.Context, option clientv2.CreateDatabaseOption, callOptions ...grpc.CallOption) error {
preRequest("CreateDatabase", ctx, option, callOptions)
err := mc.mClient.CreateDatabase(ctx, option, callOptions...)
postResponse("CreateDatabase", err)
return err
}

// DropDatabase drop database with the given db name.
func (mc *MilvusClient) DropDatabase(ctx context.Context, option clientv2.DropDatabaseOption, callOptions ...grpc.CallOption) error {
preRequest("DropDatabase", ctx, option, callOptions)
err := mc.mClient.DropDatabase(ctx, option, callOptions...)
postResponse("DropDatabase", err)
return err
}

// -- collection --

// CreateCollection Create Collection
func (mc *MilvusClient) CreateCollection(ctx context.Context, option clientv2.CreateCollectionOption, callOptions ...grpc.CallOption) error {
preRequest("CreateCollection", ctx, option, callOptions)
err := mc.mClient.CreateCollection(ctx, option, callOptions...)
postResponse("CreateCollection", err)
return err
}

// ListCollections Create Collection
func (mc *MilvusClient) ListCollections(ctx context.Context, option clientv2.ListCollectionOption, callOptions ...grpc.CallOption) ([]string, error) {
preRequest("ListCollections", ctx, option, callOptions)
collectionNames, err := mc.mClient.ListCollections(ctx, option, callOptions...)
postResponse("ListCollections", err, collectionNames)
return collectionNames, err
}

//DescribeCollection Describe collection
func (mc *MilvusClient) DescribeCollection(ctx context.Context, option clientv2.DescribeCollectionOption, callOptions ...grpc.CallOption) (*entity.Collection, error) {
preRequest("DescribeCollection", ctx, option, callOptions)
collection, err := mc.mClient.DescribeCollection(ctx, option, callOptions...)
postResponse("DescribeCollection", err, collection)
return collection, err
}

// HasCollection Has collection
func (mc *MilvusClient) HasCollection(ctx context.Context, option clientv2.HasCollectionOption, callOptions ...grpc.CallOption) (bool, error) {
preRequest("HasCollection", ctx, option, callOptions)
has, err := mc.mClient.HasCollection(ctx, option, callOptions...)
postResponse("HasCollection", err, has)
return has, err
}

// DropCollection Drop Collection
func (mc *MilvusClient) DropCollection(ctx context.Context, option clientv2.DropCollectionOption, callOptions ...grpc.CallOption) error {
preRequest("DropCollection", ctx, option, callOptions)
err := mc.mClient.DropCollection(ctx, option, callOptions...)
postResponse("DropCollection", err)
return err
}

// -- partition --

// CreatePartition Create Partition
func (mc *MilvusClient) CreatePartition(ctx context.Context, option clientv2.CreatePartitionOption, callOptions ...grpc.CallOption) error {
preRequest("CreatePartition", option, callOptions)
err := mc.mClient.CreatePartition(ctx, option, callOptions...)
postResponse("CreatePartition", err)
return err
}

// DropPartition Drop Partition
func (mc *MilvusClient) DropPartition(ctx context.Context, option clientv2.DropPartitionOption, callOptions ...grpc.CallOption) error {
preRequest("DropPartition", ctx, option, callOptions)
err := mc.mClient.DropPartition(ctx, option, callOptions...)
postResponse("DropPartition", err)
return err
}

// HasPartition Has Partition
func (mc *MilvusClient) HasPartition(ctx context.Context, option clientv2.HasPartitionOption, callOptions ...grpc.CallOption) (bool, error) {
preRequest("HasPartition", ctx, option, callOptions)
has, err := mc.mClient.HasPartition(ctx, option, callOptions...)
postResponse("HasPartition", err, has)
return has, err
}

// ListPartitions List Partitions
func (mc *MilvusClient) ListPartitions(ctx context.Context, option clientv2.ListPartitionsOption, callOptions ...grpc.CallOption) ([]string, error) {
preRequest("ListPartitions", ctx, option, callOptions)
partitionNames, err := mc.mClient.ListPartitions(ctx, option, callOptions...)
postResponse("ListPartitions", err, partitionNames)
return partitionNames, err
}

// LoadPartitions Load Partitions into memory
func (mc *MilvusClient) LoadPartitions(ctx context.Context, option clientv2.LoadPartitionsOption, callOptions ...grpc.CallOption) (clientv2.LoadTask, error) {
preRequest("LoadPartitions", ctx, option, callOptions)
loadTask, err := mc.mClient.LoadPartitions(ctx, option, callOptions...)
postResponse("LoadPartitions", err, loadTask)
return loadTask, err
}

// -- index --

// CreateIndex Create Index
func (mc *MilvusClient) CreateIndex(ctx context.Context, option clientv2.CreateIndexOption, callOptions ...grpc.CallOption) (*clientv2.CreateIndexTask, error) {
preRequest("CreateIndex", ctx, option, callOptions)
createIndexTask, err := mc.mClient.CreateIndex(ctx, option, callOptions...)
postResponse("CreateIndex", err, createIndexTask)
return createIndexTask, err
}

// ListIndexes List Indexes
func (mc *MilvusClient) ListIndexes(ctx context.Context, option clientv2.ListIndexOption, callOptions ...grpc.CallOption) ([]string, error) {
preRequest("ListIndexes", ctx, option, callOptions)
indexes, err := mc.mClient.ListIndexes(ctx, option, callOptions...)
postResponse("ListIndexes", err, indexes)
return indexes, err
}

// DescribeIndex Describe Index
func (mc *MilvusClient) DescribeIndex(ctx context.Context, option clientv2.DescribeIndexOption, callOptions ...grpc.CallOption) (index.Index, error) {
preRequest("DescribeIndex", ctx, option, callOptions)
index, err := mc.mClient.DescribeIndex(ctx, option, callOptions...)
postResponse("DescribeIndex", err, index)
return index, err
}

// DropIndex Drop Index
func (mc *MilvusClient) DropIndex(ctx context.Context, option clientv2.DropIndexOption, callOptions ...grpc.CallOption) error {
preRequest("DropIndex", ctx, ctx, option, callOptions)
err := mc.mClient.DropIndex(ctx, option, callOptions...)
postResponse("DropIndex", err)
return err
}

// -- write --

// Insert insert data
func (mc *MilvusClient) Insert(ctx context.Context, option clientv2.InsertOption, callOptions ...grpc.CallOption) (clientv2.InsertResult, error) {
preRequest("Insert", ctx, option, callOptions)
insertRes, err := mc.mClient.Insert(ctx, option, callOptions...)
postResponse("Insert", err, insertRes)
return insertRes, err
}

// Flush flush data
func (mc *MilvusClient) Flush(ctx context.Context, option clientv2.FlushOption, callOptions ...grpc.CallOption) (*clientv2.FlushTask, error) {
preRequest("Flush", ctx, option, callOptions)
flushTask, err := mc.mClient.Flush(ctx, option, callOptions...)
postResponse("Flush", err, flushTask)
return flushTask, err
}

// Delete deletes data
func (mc *MilvusClient) Delete(ctx context.Context, option clientv2.DeleteOption, callOptions ...grpc.CallOption) (clientv2.DeleteResult, error) {
preRequest("Delete", ctx, option, callOptions)
deleteRes, err := mc.mClient.Delete(ctx, option, callOptions...)
postResponse("Delete", err, deleteRes)
return deleteRes, err
}

// Upsert upsert data
func (mc *MilvusClient) Upsert(ctx context.Context, option clientv2.UpsertOption, callOptions ...grpc.CallOption) (clientv2.UpsertResult, error) {
preRequest("Upsert", ctx, option, callOptions)
upsertRes, err := mc.mClient.Upsert(ctx, option, callOptions...)
postResponse("Upsert", err, upsertRes)
return upsertRes, err
}

// -- read --

// LoadCollection Load Collection
func (mc *MilvusClient) LoadCollection(ctx context.Context, option clientv2.LoadCollectionOption, callOptions ...grpc.CallOption) (clientv2.LoadTask, error) {
funcName := "LoadCollection"
preRequest(funcName, ctx, option, callOptions)
loadTask, err := mc.mClient.LoadCollection(ctx, option, callOptions...)
postResponse(funcName, err, loadTask)
return loadTask, err
}

// Search search from collection
func (mc *MilvusClient) Search(ctx context.Context, option clientv2.SearchOption, callOptions ...grpc.CallOption) ([]clientv2.ResultSet, error) {
funcName := "Search"
preRequest(funcName, ctx, option, callOptions)
resultSets, err := mc.mClient.Search(ctx, option, callOptions...)
postResponse(funcName, err, resultSets)
return resultSets, err
}

// Query query from collection
func (mc *MilvusClient) Query(ctx context.Context, option clientv2.QueryOption, callOptions ...grpc.CallOption) (clientv2.ResultSet, error) {
funcName := "Query"
preRequest(funcName, ctx, option, callOptions)
resultSet, err := mc.mClient.Query(ctx, option, callOptions...)
postResponse(funcName, err, resultSet)
return resultSet, err
}

///usr/local/go/bin/go tool test2json -t /tmp/___TestConnectClose_in_github_com_milvus_io_milvus_sdk_go_v2_test_testcases -test.v -test.run ^\QTestConnectClose\E$
67 changes: 67 additions & 0 deletions tests/go_client/common/consts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package common

// cost default field name
const (
DefaultInt8FieldName = "int8"
DefaultInt16FieldName = "int16"
DefaultInt32FieldName = "int32"
DefaultInt64FieldName = "int64"
DefaultBoolFieldName = "bool"
DefaultFloatFieldName = "float"
DefaultDoubleFieldName = "double"
DefaultVarcharFieldName = "varchar"
DefaultJSONFieldName = "json"
DefaultArrayFieldName = "array"
DefaultFloatVecFieldName = "floatVec"
DefaultBinaryVecFieldName = "binaryVec"
DefaultFloat16VecFieldName = "fp16Vec"
DefaultBFloat16VecFieldName = "bf16Vec"
DefaultSparseVecFieldName = "sparseVec"
DefaultDynamicNumberField = "dynamicNumber"
DefaultDynamicStringField = "dynamicString"
DefaultDynamicBoolField = "dynamicBool"
DefaultDynamicListField = "dynamicList"
DefaultBoolArrayField = "boolArray"
DefaultInt8ArrayField = "int8Array"
DefaultInt16ArrayField = "int16Array"
DefaultInt32ArrayField = "int32Array"
DefaultInt64ArrayField = "int64Array"
DefaultFloatArrayField = "floatArray"
DefaultDoubleArrayField = "doubleArray"
DefaultVarcharArrayField = "varcharArray"
)

// cost for test cases
const (
RowCount = "row_count"
DefaultTimeout = 120
DefaultDim = 128
DefaultShards = int32(2)
DefaultNb = 3000
DefaultNq = 5
DefaultLimit = 10
TestCapacity = 100 // default array field capacity
TestMaxLen = 100 // default varchar field max length
)

// const default value from milvus config
const (
MaxPartitionNum = 4096
DefaultDynamicFieldName = "$meta"
QueryCountFieldName = "count(*)"
DefaultPartition = "_default"
DefaultIndexName = "_default_idx_102"
DefaultIndexNameBinary = "_default_idx_100"
DefaultRgName = "__default_resource_group"
DefaultDb = "default"
MaxDim = 32768
MaxLength = int64(65535)
MaxCollectionNameLen = 255
DefaultRgCapacity = 1000000
RetentionDuration = 40 // common.retentionDuration
MaxCapacity = 4096 // max array capacity
DefaultPartitionNum = 16 // default num_partitions
MaxTopK = 16384
MaxVectorFieldNum = 4
MaxShardNum = 16
)
44 changes: 44 additions & 0 deletions tests/go_client/common/response_checker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package common

import (
"strings"
"testing"

"github.com/milvus-io/milvus/pkg/log"
"github.com/stretchr/testify/require"

clientv2 "github.com/milvus-io/milvus/client/v2"
)

func CheckErr(t *testing.T, actualErr error, expErrNil bool, expErrorMsg ...string) {
if expErrNil {
require.NoError(t, actualErr)
} else {
require.Error(t, actualErr)
switch len(expErrorMsg) {
case 0:
log.Fatal("expect error message should not be empty")
case 1:
require.ErrorContains(t, actualErr, expErrorMsg[0])
default:
contains := false
for i := 0; i < len(expErrorMsg); i++ {
if strings.Contains(actualErr.Error(), expErrorMsg[i]) {
contains = true
}
}
if !contains {
t.FailNow()
}
}
}
}

// CheckSearchResult check search result, check nq, topk, ids, score
func CheckSearchResult(t *testing.T, actualSearchResults []clientv2.ResultSet, expNq int, expTopK int) {
require.Equal(t, len(actualSearchResults), expNq)
require.Len(t, actualSearchResults, expNq)
for _, actualSearchResult := range actualSearchResults {
require.Equal(t, actualSearchResult.ResultCount, expTopK)
}
}
Loading

0 comments on commit 815742b

Please sign in to comment.