package reader import ( "context" "encoding/binary" "fmt" "math" "testing" "github.com/stretchr/testify/assert" msgPb "github.com/zilliztech/milvus-distributed/internal/proto/message" ) func TestSegment_ConstructorAndDestructor(t *testing.T) { // 1. Construct node, collection, partition and segment ctx := context.Background() node := NewQueryNode(ctx, 0, 0) var collection = node.NewCollection(0, "collection0", "") var partition = collection.NewPartition("partition0") var segment = partition.NewSegment(0) node.SegmentsMap[int64(0)] = segment assert.Equal(t, collection.CollectionName, "collection0") assert.Equal(t, partition.PartitionName, "partition0") assert.Equal(t, segment.SegmentID, int64(0)) assert.Equal(t, len(node.SegmentsMap), 1) // 2. Destruct collection, partition and segment partition.DeleteSegment(node, segment) collection.DeletePartition(node, partition) node.DeleteCollection(collection) assert.Equal(t, len(node.Collections), 0) assert.Equal(t, len(node.SegmentsMap), 0) node.Close() } func TestSegment_SegmentInsert(t *testing.T) { // 1. Construct node, collection, partition and segment ctx := context.Background() node := NewQueryNode(ctx, 0, 0) var collection = node.NewCollection(0, "collection0", "") var partition = collection.NewPartition("partition0") var segment = partition.NewSegment(0) node.SegmentsMap[int64(0)] = segment assert.Equal(t, collection.CollectionName, "collection0") assert.Equal(t, partition.PartitionName, "partition0") assert.Equal(t, segment.SegmentID, int64(0)) assert.Equal(t, len(node.SegmentsMap), 1) // 2. Create ids and timestamps //ids := []int64{1, 2, 3} //timestamps := []uint64{0, 0, 0} // 3. Create records, use schema below: // schema_tmp->AddField("fakeVec", DataType::VECTOR_FLOAT, 16); // schema_tmp->AddField("age", DataType::INT32); const DIM = 16 const N = 3 var vec = [DIM]float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} var rawData []byte for _, ele := range vec { buf := make([]byte, 4) binary.LittleEndian.PutUint32(buf, math.Float32bits(ele)) rawData = append(rawData, buf...) } bs := make([]byte, 4) binary.LittleEndian.PutUint32(bs, 1) rawData = append(rawData, bs...) var records [][]byte for i := 0; i < N; i++ { records = append(records, rawData) } // 4. Do PreInsert var offset = segment.SegmentPreInsert(N) assert.GreaterOrEqual(t, offset, int64(0)) // 5. Do Insert //var err = segment.SegmentInsert(offset, &ids, ×tamps, &records) //assert.NoError(t, err) // 6. Destruct collection, partition and segment partition.DeleteSegment(node, segment) collection.DeletePartition(node, partition) node.DeleteCollection(collection) assert.Equal(t, len(node.Collections), 0) assert.Equal(t, len(node.SegmentsMap), 0) node.Close() } func TestSegment_SegmentDelete(t *testing.T) { ctx := context.Background() // 1. Construct node, collection, partition and segment node := NewQueryNode(ctx, 0, 0) var collection = node.NewCollection(0, "collection0", "") var partition = collection.NewPartition("partition0") var segment = partition.NewSegment(0) node.SegmentsMap[int64(0)] = segment assert.Equal(t, collection.CollectionName, "collection0") assert.Equal(t, partition.PartitionName, "partition0") assert.Equal(t, segment.SegmentID, int64(0)) assert.Equal(t, len(node.SegmentsMap), 1) // 2. Create ids and timestamps ids := []int64{1, 2, 3} timestamps := []uint64{0, 0, 0} // 3. Do PreDelete var offset = segment.SegmentPreDelete(10) assert.GreaterOrEqual(t, offset, int64(0)) // 4. Do Delete var err = segment.SegmentDelete(offset, &ids, ×tamps) assert.NoError(t, err) // 5. Destruct collection, partition and segment partition.DeleteSegment(node, segment) collection.DeletePartition(node, partition) node.DeleteCollection(collection) assert.Equal(t, len(node.Collections), 0) assert.Equal(t, len(node.SegmentsMap), 0) node.Close() } func TestSegment_SegmentSearch(t *testing.T) { ctx := context.Background() // 1. Construct node, collection, partition and segment node := NewQueryNode(ctx, 0, 0) var collection = node.NewCollection(0, "collection0", "") var partition = collection.NewPartition("partition0") var segment = partition.NewSegment(0) node.SegmentsMap[int64(0)] = segment assert.Equal(t, collection.CollectionName, "collection0") assert.Equal(t, partition.PartitionName, "partition0") assert.Equal(t, segment.SegmentID, int64(0)) assert.Equal(t, len(node.SegmentsMap), 1) // 2. Create ids and timestamps ids := make([]int64, 0) timestamps := make([]uint64, 0) // 3. Create records, use schema below: // schema_tmp->AddField("fakeVec", DataType::VECTOR_FLOAT, 16); // schema_tmp->AddField("age", DataType::INT32); const DIM = 16 const N = 100 var vec = [DIM]float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} var rawData []byte for _, ele := range vec { buf := make([]byte, 4) binary.LittleEndian.PutUint32(buf, math.Float32bits(ele)) rawData = append(rawData, buf...) } bs := make([]byte, 4) binary.LittleEndian.PutUint32(bs, 1) rawData = append(rawData, bs...) var records [][]byte for i := 0; i < N; i++ { ids = append(ids, int64(i)) timestamps = append(timestamps, uint64(i+1)) records = append(records, rawData) } // 4. Do PreInsert var offset = segment.SegmentPreInsert(N) assert.GreaterOrEqual(t, offset, int64(0)) // 5. Do Insert //var err = segment.SegmentInsert(offset, &ids, ×tamps, &records) //assert.NoError(t, err) // 6. Do search var queryJSON = "{\"field_name\":\"fakevec\",\"num_queries\":1,\"topK\":10}" var queryRawData = make([]float32, 0) for i := 0; i < 16; i++ { queryRawData = append(queryRawData, float32(i)) } var vectorRecord = msgPb.VectorRowRecord{ FloatData: queryRawData, } query := node.QueryJSON2Info(&queryJSON) var searchRes, searchErr = segment.SegmentSearch(query, timestamps[N/2], &vectorRecord) assert.NoError(t, searchErr) fmt.Println(searchRes) // 7. Destruct collection, partition and segment partition.DeleteSegment(node, segment) collection.DeletePartition(node, partition) node.DeleteCollection(collection) assert.Equal(t, len(node.Collections), 0) assert.Equal(t, len(node.SegmentsMap), 0) node.Close() } func TestSegment_SegmentPreInsert(t *testing.T) { ctx := context.Background() // 1. Construct node, collection, partition and segment node := NewQueryNode(ctx, 0, 0) var collection = node.NewCollection(0, "collection0", "") var partition = collection.NewPartition("partition0") var segment = partition.NewSegment(0) node.SegmentsMap[int64(0)] = segment assert.Equal(t, collection.CollectionName, "collection0") assert.Equal(t, partition.PartitionName, "partition0") assert.Equal(t, segment.SegmentID, int64(0)) assert.Equal(t, len(node.SegmentsMap), 1) // 2. Do PreInsert var offset = segment.SegmentPreInsert(10) assert.GreaterOrEqual(t, offset, int64(0)) // 3. Destruct collection, partition and segment partition.DeleteSegment(node, segment) collection.DeletePartition(node, partition) node.DeleteCollection(collection) assert.Equal(t, len(node.Collections), 0) assert.Equal(t, len(node.SegmentsMap), 0) node.Close() } func TestSegment_SegmentPreDelete(t *testing.T) { ctx := context.Background() // 1. Construct node, collection, partition and segment node := NewQueryNode(ctx, 0, 0) var collection = node.NewCollection(0, "collection0", "") var partition = collection.NewPartition("partition0") var segment = partition.NewSegment(0) node.SegmentsMap[int64(0)] = segment assert.Equal(t, collection.CollectionName, "collection0") assert.Equal(t, partition.PartitionName, "partition0") assert.Equal(t, segment.SegmentID, int64(0)) assert.Equal(t, len(node.SegmentsMap), 1) // 2. Do PreDelete var offset = segment.SegmentPreDelete(10) assert.GreaterOrEqual(t, offset, int64(0)) // 3. Destruct collection, partition and segment partition.DeleteSegment(node, segment) collection.DeletePartition(node, partition) node.DeleteCollection(collection) assert.Equal(t, len(node.Collections), 0) assert.Equal(t, len(node.SegmentsMap), 0) node.Close() } // Segment util functions test //////////////////////////////////////////////////////////////////////////// //func TestSegment_GetStatus(t *testing.T) { // ctx := context.Background() // // 1. Construct node, collection, partition and segment // node := NewQueryNode(ctx, 0, 0) // var collection = node.NewCollection(0, "collection0", "") // var partition = collection.NewPartition("partition0") // var segment = partition.NewSegment(0) // // // 2. Get segment status // var status = segment.GetStatus() // assert.Equal(t, status, SegmentOpened) // // // 3. Destruct collection, partition and segment // partition.DeleteSegment(segment) // collection.DeletePartition(partition) // node.DeleteCollection(collection) // // node.Close() //} //func TestSegment_Close(t *testing.T) { // ctx := context.Background() // // 1. Construct node, collection, partition and segment // node := NewQueryNode(ctx, 0, 0) // var collection = node.NewCollection(0, "collection0", "") // var partition = collection.NewPartition("partition0") // var segment = partition.NewSegment(0) // // // 2. Close segment // var err = segment.CloseSegment(collection) // assert.NoError(t, err) // // // 3. Destruct collection, partition and segment // partition.DeleteSegment(segment) // collection.DeletePartition(partition) // node.DeleteCollection(collection) // // node.Close() //} func TestSegment_GetRowCount(t *testing.T) { ctx := context.Background() // 1. Construct node, collection, partition and segment node := NewQueryNode(ctx, 0, 0) var collection = node.NewCollection(0, "collection0", "") var partition = collection.NewPartition("partition0") var segment = partition.NewSegment(0) node.SegmentsMap[int64(0)] = segment assert.Equal(t, collection.CollectionName, "collection0") assert.Equal(t, partition.PartitionName, "partition0") assert.Equal(t, segment.SegmentID, int64(0)) assert.Equal(t, len(node.SegmentsMap), 1) // 2. Create ids and timestamps ids := []int64{1, 2, 3} //timestamps := []uint64{0, 0, 0} // 3. Create records, use schema below: // schema_tmp->AddField("fakeVec", DataType::VECTOR_FLOAT, 16); // schema_tmp->AddField("age", DataType::INT32); const DIM = 16 const N = 3 var vec = [DIM]float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} var rawData []byte for _, ele := range vec { buf := make([]byte, 4) binary.LittleEndian.PutUint32(buf, math.Float32bits(ele)) rawData = append(rawData, buf...) } bs := make([]byte, 4) binary.LittleEndian.PutUint32(bs, 1) rawData = append(rawData, bs...) var records [][]byte for i := 0; i < N; i++ { records = append(records, rawData) } // 4. Do PreInsert var offset = segment.SegmentPreInsert(N) assert.GreaterOrEqual(t, offset, int64(0)) // 5. Do Insert //var err = segment.SegmentInsert(offset, &ids, ×tamps, &records) //assert.NoError(t, err) // 6. Get segment row count var rowCount = segment.GetRowCount() assert.Equal(t, rowCount, int64(len(ids))) // 7. Destruct collection, partition and segment partition.DeleteSegment(node, segment) collection.DeletePartition(node, partition) node.DeleteCollection(collection) assert.Equal(t, len(node.Collections), 0) assert.Equal(t, len(node.SegmentsMap), 0) node.Close() } func TestSegment_GetDeletedCount(t *testing.T) { ctx := context.Background() // 1. Construct node, collection, partition and segment node := NewQueryNode(ctx, 0, 0) var collection = node.NewCollection(0, "collection0", "") var partition = collection.NewPartition("partition0") var segment = partition.NewSegment(0) node.SegmentsMap[int64(0)] = segment assert.Equal(t, collection.CollectionName, "collection0") assert.Equal(t, partition.PartitionName, "partition0") assert.Equal(t, segment.SegmentID, int64(0)) assert.Equal(t, len(node.SegmentsMap), 1) // 2. Create ids and timestamps ids := []int64{1, 2, 3} timestamps := []uint64{0, 0, 0} // 3. Do PreDelete var offset = segment.SegmentPreDelete(10) assert.GreaterOrEqual(t, offset, int64(0)) // 4. Do Delete var err = segment.SegmentDelete(offset, &ids, ×tamps) assert.NoError(t, err) // 5. Get segment deleted count var deletedCount = segment.GetDeletedCount() // TODO: assert.Equal(t, deletedCount, len(ids)) assert.Equal(t, deletedCount, int64(0)) // 6. Destruct collection, partition and segment partition.DeleteSegment(node, segment) collection.DeletePartition(node, partition) node.DeleteCollection(collection) assert.Equal(t, len(node.Collections), 0) assert.Equal(t, len(node.SegmentsMap), 0) node.Close() } func TestSegment_GetMemSize(t *testing.T) { ctx := context.Background() // 1. Construct node, collection, partition and segment node := NewQueryNode(ctx, 0, 0) var collection = node.NewCollection(0, "collection0", "") var partition = collection.NewPartition("partition0") var segment = partition.NewSegment(0) node.SegmentsMap[int64(0)] = segment assert.Equal(t, collection.CollectionName, "collection0") assert.Equal(t, partition.PartitionName, "partition0") assert.Equal(t, segment.SegmentID, int64(0)) assert.Equal(t, len(node.SegmentsMap), 1) // 2. Create ids and timestamps //ids := []int64{1, 2, 3} //timestamps := []uint64{0, 0, 0} // 3. Create records, use schema below: // schema_tmp->AddField("fakeVec", DataType::VECTOR_FLOAT, 16); // schema_tmp->AddField("age", DataType::INT32); const DIM = 16 const N = 3 var vec = [DIM]float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} var rawData []byte for _, ele := range vec { buf := make([]byte, 4) binary.LittleEndian.PutUint32(buf, math.Float32bits(ele)) rawData = append(rawData, buf...) } bs := make([]byte, 4) binary.LittleEndian.PutUint32(bs, 1) rawData = append(rawData, bs...) var records [][]byte for i := 0; i < N; i++ { records = append(records, rawData) } // 4. Do PreInsert var offset = segment.SegmentPreInsert(N) assert.GreaterOrEqual(t, offset, int64(0)) // 5. Do Insert //var err = segment.SegmentInsert(offset, &ids, ×tamps, &records) //assert.NoError(t, err) // 6. Get memory usage in bytes var memSize = segment.GetMemSize() assert.Equal(t, memSize, uint64(2785280)) // 7. Destruct collection, partition and segment partition.DeleteSegment(node, segment) collection.DeletePartition(node, partition) node.DeleteCollection(collection) assert.Equal(t, len(node.Collections), 0) assert.Equal(t, len(node.SegmentsMap), 0) node.Close() } func TestSegment_RealSchemaTest(t *testing.T) { ctx := context.Background() // 1. Construct node, collection, partition and segment //var schemaString = "id: 6873737669791618215\nname: \"collection0\"\nschema: \u003c\n " + // "field_metas: \u003c\n field_name: \"age\"\n type: INT32\n dim: 1\n \u003e\n " + // "field_metas: \u003c\n field_name: \"field_1\"\n type: VECTOR_FLOAT\n dim: 16\n \u003e\n" + // "\u003e\ncreate_time: 1600416765\nsegment_ids: 6873737669791618215\npartition_tags: \"default\"\n" var schemaString = "id: 6875229265736357360\nname: \"collection0\"\nschema: \u003c\n " + "field_metas: \u003c\n field_name: \"field_3\"\n type: INT32\n dim: 1\n \u003e\n " + "field_metas: \u003c\n field_name: \"field_vec\"\n type: VECTOR_FLOAT\n dim: 16\n " + "\u003e\n\u003e\ncreate_time: 1600764055\nsegment_ids: 6875229265736357360\npartition_tags: \"default\"\n" node := NewQueryNode(ctx, 0, 0) var collection = node.NewCollection(0, "collection0", schemaString) var partition = collection.NewPartition("partition0") var segment = partition.NewSegment(0) node.SegmentsMap[int64(0)] = segment assert.Equal(t, collection.CollectionName, "collection0") assert.Equal(t, partition.PartitionName, "partition0") assert.Equal(t, segment.SegmentID, int64(0)) assert.Equal(t, len(node.SegmentsMap), 1) // 2. Create ids and timestamps //ids := []int64{1, 2, 3} //timestamps := []uint64{0, 0, 0} // 3. Create records, use schema below: // schema_tmp->AddField("fakeVec", DataType::VECTOR_FLOAT, 16); // schema_tmp->AddField("age", DataType::INT32); const DIM = 16 const N = 3 var vec = [DIM]float32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} var rawData []byte for _, ele := range vec { buf := make([]byte, 4) binary.LittleEndian.PutUint32(buf, math.Float32bits(ele)) rawData = append(rawData, buf...) } bs := make([]byte, 4) binary.LittleEndian.PutUint32(bs, 1) rawData = append(rawData, bs...) var records [][]byte for i := 0; i < N; i++ { records = append(records, rawData) } // 4. Do PreInsert var offset = segment.SegmentPreInsert(N) assert.GreaterOrEqual(t, offset, int64(0)) // 5. Do Insert //var err = segment.SegmentInsert(offset, &ids, ×tamps, &records) //assert.NoError(t, err) // 6. Destruct collection, partition and segment partition.DeleteSegment(node, segment) collection.DeletePartition(node, partition) node.DeleteCollection(collection) assert.Equal(t, len(node.Collections), 0) assert.Equal(t, len(node.SegmentsMap), 0) node.Close() }