mirror of
https://gitee.com/milvus-io/milvus.git
synced 2026-01-07 19:31:51 +08:00
issue: https://github.com/milvus-io/milvus/issues/43931 --------- Signed-off-by: Buqian Zheng <zhengbuqian@gmail.com>
210 lines
7.2 KiB
C++
210 lines
7.2 KiB
C++
// 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
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <random>
|
|
#include <vector>
|
|
#include <string>
|
|
|
|
#include "common/VectorArray.h"
|
|
#include "pb/schema.pb.h"
|
|
#include "common/Schema.h"
|
|
|
|
using namespace milvus;
|
|
|
|
TEST(VectorArray, TestSchema) {
|
|
namespace pb = milvus::proto;
|
|
pb::schema::CollectionSchema proto;
|
|
proto.set_name("col");
|
|
proto.set_description("asdfhsalkgfhsadg");
|
|
auto dim = 16;
|
|
bool bool_default_value = true;
|
|
int32_t int_default_value = 20;
|
|
int64_t long_default_value = 20;
|
|
float float_default_value = 20;
|
|
double double_default_value = 20;
|
|
std::string varchar_dafualt_vlaue = "20";
|
|
|
|
{
|
|
auto field = proto.add_fields();
|
|
field->set_name("key");
|
|
field->set_nullable(false);
|
|
field->set_fieldid(100);
|
|
field->set_is_primary_key(true);
|
|
field->set_description("asdgfsagf");
|
|
field->set_data_type(pb::schema::DataType::Int64);
|
|
}
|
|
|
|
{
|
|
auto struct_field = proto.add_struct_array_fields();
|
|
struct_field->set_name("struct");
|
|
struct_field->set_fieldid(101);
|
|
|
|
auto field = struct_field->add_fields();
|
|
field->set_name("struct_key");
|
|
field->set_nullable(false);
|
|
field->set_fieldid(102);
|
|
field->set_data_type(pb::schema::DataType::Array);
|
|
field->set_element_type(pb::schema::DataType::Int64);
|
|
|
|
auto field2 = struct_field->add_fields();
|
|
field2->set_name("struct_float_vec");
|
|
field2->set_fieldid(103);
|
|
field2->set_data_type(pb::schema::DataType::ArrayOfVector);
|
|
field2->set_element_type(pb::schema::DataType::FloatVector);
|
|
auto param = field2->add_type_params();
|
|
param->set_key("dim");
|
|
param->set_value("16");
|
|
auto iparam = field2->add_index_params();
|
|
iparam->set_key("metric_type");
|
|
iparam->set_value("L2");
|
|
}
|
|
|
|
auto schema = Schema::ParseFrom(proto);
|
|
auto field = schema->operator[](FieldId(102));
|
|
ASSERT_EQ(field.get_data_type(), DataType::ARRAY);
|
|
ASSERT_EQ(field.get_element_type(), DataType::INT64);
|
|
|
|
auto field2 = schema->operator[](FieldId(103));
|
|
ASSERT_EQ(field2.get_data_type(), DataType::VECTOR_ARRAY);
|
|
ASSERT_EQ(field2.get_element_type(), DataType::VECTOR_FLOAT);
|
|
ASSERT_EQ(field2.get_dim(), 16);
|
|
}
|
|
|
|
std::vector<float>
|
|
generate_float_vector(int64_t seed, int64_t N, int64_t dim) {
|
|
std::vector<float> final(dim * N);
|
|
for (int n = 0; n < N; ++n) {
|
|
// generate random float vector
|
|
std::vector<float> data(dim);
|
|
std::default_random_engine er2(seed + n);
|
|
std::normal_distribution<> distr2(0, 1);
|
|
for (auto& x : data) {
|
|
x = distr2(er2);
|
|
}
|
|
|
|
std::copy(data.begin(), data.end(), final.begin() + dim * n);
|
|
}
|
|
return final;
|
|
};
|
|
|
|
TEST(VectorArray, TestConstructVectorArray) {
|
|
using namespace milvus;
|
|
|
|
int N = 10;
|
|
// 1. test float vector
|
|
int64_t dim = 128;
|
|
milvus::proto::schema::VectorField field_float_vector_array;
|
|
field_float_vector_array.set_dim(dim);
|
|
|
|
auto data = generate_float_vector(100, N, dim);
|
|
field_float_vector_array.mutable_float_vector()->mutable_data()->Add(
|
|
data.begin(), data.end());
|
|
|
|
auto float_vector_array = milvus::VectorArray(field_float_vector_array);
|
|
ASSERT_EQ(float_vector_array.length(), N);
|
|
ASSERT_EQ(float_vector_array.dim(), dim);
|
|
ASSERT_EQ(float_vector_array.get_element_type(), DataType::VECTOR_FLOAT);
|
|
ASSERT_EQ(float_vector_array.byte_size(), N * dim * sizeof(float));
|
|
|
|
ASSERT_TRUE(float_vector_array.is_same_array(field_float_vector_array));
|
|
|
|
auto float_vector_array_tmp = milvus::VectorArray(float_vector_array);
|
|
|
|
ASSERT_TRUE(float_vector_array_tmp.is_same_array(field_float_vector_array));
|
|
|
|
auto float_vector_array_view =
|
|
milvus::VectorArrayView(const_cast<char*>(float_vector_array.data()),
|
|
float_vector_array.length(),
|
|
float_vector_array.dim(),
|
|
float_vector_array.byte_size(),
|
|
float_vector_array.get_element_type());
|
|
|
|
ASSERT_TRUE(
|
|
float_vector_array_view.is_same_array(field_float_vector_array));
|
|
|
|
// todo: add other vector types
|
|
}
|
|
|
|
TEST(VectorArray, TestConstructorWithData) {
|
|
using namespace milvus;
|
|
|
|
int N = 10; // number of vectors
|
|
int64_t dim = 128;
|
|
|
|
// Generate test data
|
|
auto data = generate_float_vector(42, N, dim);
|
|
|
|
// Test 1: Direct construction from raw float data
|
|
{
|
|
milvus::VectorArray va(data.data(), N, dim, DataType::VECTOR_FLOAT);
|
|
|
|
ASSERT_EQ(va.length(), N);
|
|
ASSERT_EQ(va.dim(), dim);
|
|
ASSERT_EQ(va.get_element_type(), DataType::VECTOR_FLOAT);
|
|
ASSERT_EQ(va.byte_size(), N * dim * sizeof(float));
|
|
|
|
// Verify data integrity
|
|
for (int i = 0; i < N; ++i) {
|
|
auto vec_data = va.get_data<float>(i);
|
|
for (int j = 0; j < dim; ++j) {
|
|
ASSERT_FLOAT_EQ(vec_data[j], data[i * dim + j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test 2: Compare with protobuf-based constructor
|
|
{
|
|
// Create via protobuf
|
|
milvus::proto::schema::VectorField field_proto;
|
|
field_proto.set_dim(dim);
|
|
field_proto.mutable_float_vector()->mutable_data()->Add(data.begin(),
|
|
data.end());
|
|
milvus::VectorArray va_proto(field_proto);
|
|
|
|
// Create via data constructor
|
|
milvus::VectorArray va_direct(
|
|
data.data(), N, dim, DataType::VECTOR_FLOAT);
|
|
|
|
// Both should be equal
|
|
ASSERT_EQ(va_proto.length(), va_direct.length());
|
|
ASSERT_EQ(va_proto.dim(), va_direct.dim());
|
|
ASSERT_EQ(va_proto.byte_size(), va_direct.byte_size());
|
|
ASSERT_EQ(va_proto.get_element_type(), va_direct.get_element_type());
|
|
|
|
// Compare data
|
|
for (int i = 0; i < N; ++i) {
|
|
auto proto_vec = va_proto.get_data<float>(i);
|
|
auto direct_vec = va_direct.get_data<float>(i);
|
|
for (int j = 0; j < dim; ++j) {
|
|
ASSERT_FLOAT_EQ(proto_vec[j], direct_vec[j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test 3: Test with edge cases
|
|
{
|
|
// Single vector
|
|
milvus::VectorArray va_single(
|
|
data.data(), 1, dim, DataType::VECTOR_FLOAT);
|
|
ASSERT_EQ(va_single.length(), 1);
|
|
ASSERT_EQ(va_single.byte_size(), dim * sizeof(float));
|
|
|
|
// Small dimension
|
|
int64_t small_dim = 4;
|
|
auto small_data = generate_float_vector(123, 5, small_dim);
|
|
milvus::VectorArray va_small(
|
|
small_data.data(), 5, small_dim, DataType::VECTOR_FLOAT);
|
|
ASSERT_EQ(va_small.length(), 5);
|
|
ASSERT_EQ(va_small.dim(), small_dim);
|
|
}
|
|
}
|