SemanticSearchPOC / adapters /handlers /grpc /v1 /batch_parse_request_test.go
KevinStephenson
Adding in weaviate code
b110593
raw
history blame
10.5 kB
// _ _
// __ _____ __ ___ ___ __ _| |_ ___
// \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
// \ V V / __/ (_| |\ V /| | (_| | || __/
// \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
//
// Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
//
// CONTACT: [email protected]
//
package v1
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/weaviate/weaviate/entities/models"
"github.com/weaviate/weaviate/entities/schema"
pb "github.com/weaviate/weaviate/grpc/generated/protocol/v1"
)
const (
UUID3 = "a4de3ca0-6975-464f-b23b-adddd83630d7"
UUID4 = "7e10ec81-a26d-4ac7-8264-3e3e05397ddc"
)
func TestGRPCBatchRequest(t *testing.T) {
collection := "TestClass"
refClass1 := "OtherClass"
refClass2 := "AnotherClass"
scheme := schema.Schema{
Objects: &models.Schema{
Classes: []*models.Class{
{
Class: collection,
Properties: []*models.Property{
{Name: "name", DataType: schema.DataTypeText.PropString()},
{Name: "number", DataType: []string{"int"}},
{Name: "ref", DataType: []string{refClass1}},
{Name: "multiRef", DataType: []string{refClass1, refClass2}},
},
},
{
Class: refClass1,
Properties: []*models.Property{
{Name: "something", DataType: schema.DataTypeText.PropString()},
{Name: "ref2", DataType: []string{refClass2}},
},
},
{
Class: refClass2,
Properties: []*models.Property{
{Name: "else", DataType: schema.DataTypeText.PropString()},
{Name: "ref3", DataType: []string{refClass2}},
},
},
},
},
}
var nilMap map[string]interface{}
tests := []struct {
name string
req []*pb.BatchObject
out []*models.Object
outError []int
origIndex map[int]int
}{
{
name: "empty object",
req: []*pb.BatchObject{{Collection: collection, Uuid: UUID4}},
out: []*models.Object{{Class: collection, Properties: nilMap, ID: UUID4}},
},
{
name: "no UUID",
req: []*pb.BatchObject{{Collection: collection}},
out: []*models.Object{},
outError: []int{0},
},
{
name: "only normal props",
req: []*pb.BatchObject{{Collection: collection, Uuid: UUID4, Properties: &pb.BatchObject_Properties{
NonRefProperties: newStruct(t, map[string]interface{}{
"name": "something",
"age": 45,
}),
}}},
out: []*models.Object{{Class: collection, ID: UUID4, Properties: map[string]interface{}{
"name": "something",
"age": float64(45),
}}},
},
{
name: "only single refs",
req: []*pb.BatchObject{{Collection: collection, Uuid: UUID4, Properties: &pb.BatchObject_Properties{
SingleTargetRefProps: []*pb.BatchObject_SingleTargetRefProps{
{PropName: "ref", Uuids: []string{UUID3, UUID4}},
},
}}},
out: []*models.Object{{Class: collection, ID: UUID4, Properties: map[string]interface{}{
"ref": []interface{}{
map[string]interface{}{"beacon": BEACON_START + refClass1 + "/" + UUID3},
map[string]interface{}{"beacon": BEACON_START + refClass1 + "/" + UUID4},
},
}}},
},
{
name: "only mult ref",
req: []*pb.BatchObject{{Collection: collection, Uuid: UUID4, Properties: &pb.BatchObject_Properties{
MultiTargetRefProps: []*pb.BatchObject_MultiTargetRefProps{
{PropName: "multiRef", Uuids: []string{UUID3, UUID4}, TargetCollection: refClass2},
},
}}},
out: []*models.Object{{Class: collection, ID: UUID4, Properties: map[string]interface{}{
"multiRef": []interface{}{
map[string]interface{}{"beacon": BEACON_START + refClass2 + "/" + UUID3},
map[string]interface{}{"beacon": BEACON_START + refClass2 + "/" + UUID4},
},
}}},
},
{
name: "all property types",
req: []*pb.BatchObject{{Collection: collection, Uuid: UUID4, Properties: &pb.BatchObject_Properties{
MultiTargetRefProps: []*pb.BatchObject_MultiTargetRefProps{
{PropName: "multiRef", Uuids: []string{UUID4, UUID3}, TargetCollection: refClass2},
},
SingleTargetRefProps: []*pb.BatchObject_SingleTargetRefProps{
{PropName: "ref", Uuids: []string{UUID4, UUID3}},
},
NonRefProperties: newStruct(t, map[string]interface{}{
"name": "else",
"age": 46,
}),
}}},
out: []*models.Object{{Class: collection, ID: UUID4, Properties: map[string]interface{}{
"multiRef": []interface{}{
map[string]interface{}{"beacon": BEACON_START + refClass2 + "/" + UUID4},
map[string]interface{}{"beacon": BEACON_START + refClass2 + "/" + UUID3},
},
"ref": []interface{}{
map[string]interface{}{"beacon": BEACON_START + refClass1 + "/" + UUID4},
map[string]interface{}{"beacon": BEACON_START + refClass1 + "/" + UUID3},
},
"name": "else",
"age": float64(46),
}}},
},
{
name: "mult ref to single target",
req: []*pb.BatchObject{{Collection: collection, Uuid: UUID4, Properties: &pb.BatchObject_Properties{
MultiTargetRefProps: []*pb.BatchObject_MultiTargetRefProps{
{PropName: "ref", Uuids: []string{UUID3, UUID4}, TargetCollection: refClass2},
},
}}},
out: []*models.Object{},
outError: []int{0},
},
{
name: "single ref to multi target",
req: []*pb.BatchObject{{Collection: collection, Uuid: UUID4, Properties: &pb.BatchObject_Properties{
SingleTargetRefProps: []*pb.BatchObject_SingleTargetRefProps{
{PropName: "multiRef", Uuids: []string{UUID3, UUID4}},
},
}}},
out: []*models.Object{},
outError: []int{0},
},
{
name: "slice props",
req: []*pb.BatchObject{{Collection: collection, Uuid: UUID4, Properties: &pb.BatchObject_Properties{
NonRefProperties: newStruct(t, map[string]interface{}{"name": "something"}),
BooleanArrayProperties: []*pb.BooleanArrayProperties{
{PropName: "boolArray1", Values: []bool{true, true}},
{PropName: "boolArray2", Values: []bool{false, true}},
},
IntArrayProperties: []*pb.IntArrayProperties{
{PropName: "int1", Values: []int64{2, 3, 4}}, {PropName: "int2", Values: []int64{7, 8}},
},
NumberArrayProperties: []*pb.NumberArrayProperties{
{PropName: "float1", Values: []float64{1, 2, 3}}, {PropName: "float2", Values: []float64{4, 5}},
},
TextArrayProperties: []*pb.TextArrayProperties{
{PropName: "text1", Values: []string{"first", "second"}}, {PropName: "text2", Values: []string{"third"}},
},
}}},
out: []*models.Object{{Class: collection, ID: UUID4, Properties: map[string]interface{}{
"name": "something",
"boolArray1": []interface{}{true, true},
"boolArray2": []interface{}{false, true},
"int1": []interface{}{int64(2), int64(3), int64(4)},
"int2": []interface{}{int64(7), int64(8)},
"float1": []interface{}{1., 2., 3.},
"float2": []interface{}{4., 5.},
"text1": []interface{}{"first", "second"},
"text2": []interface{}{"third"},
}}},
},
{
name: "object props",
req: []*pb.BatchObject{{Collection: collection, Uuid: UUID4, Properties: &pb.BatchObject_Properties{
ObjectProperties: []*pb.ObjectProperties{
{
PropName: "simpleObj", Value: &pb.ObjectPropertiesValue{
NonRefProperties: newStruct(t, map[string]interface{}{"name": "something"}),
},
},
{
PropName: "nestedObj", Value: &pb.ObjectPropertiesValue{
ObjectProperties: []*pb.ObjectProperties{{
PropName: "obj", Value: &pb.ObjectPropertiesValue{
NonRefProperties: newStruct(t, map[string]interface{}{"name": "something"}),
},
}},
},
},
},
}}},
out: []*models.Object{{Class: collection, ID: UUID4, Properties: map[string]interface{}{
"simpleObj": map[string]interface{}{"name": "something"},
"nestedObj": map[string]interface{}{
"obj": map[string]interface{}{"name": "something"},
},
}}},
},
{
name: "object array props",
req: []*pb.BatchObject{{Collection: collection, Uuid: UUID4, Properties: &pb.BatchObject_Properties{
ObjectArrayProperties: []*pb.ObjectArrayProperties{
{
PropName: "simpleObjs", Values: []*pb.ObjectPropertiesValue{
{
NonRefProperties: newStruct(t, map[string]interface{}{"name": "something"}),
},
{
NonRefProperties: newStruct(t, map[string]interface{}{"name": "something else"}),
},
},
},
{
PropName: "nestedObjs", Values: []*pb.ObjectPropertiesValue{
{
ObjectProperties: []*pb.ObjectProperties{{
PropName: "obj", Value: &pb.ObjectPropertiesValue{
NonRefProperties: newStruct(t, map[string]interface{}{"name": "something"}),
},
}},
},
{
ObjectProperties: []*pb.ObjectProperties{{
PropName: "obj", Value: &pb.ObjectPropertiesValue{
NonRefProperties: newStruct(t, map[string]interface{}{"name": "something else"}),
},
}},
},
},
},
},
}}},
out: []*models.Object{{Class: collection, ID: UUID4, Properties: map[string]interface{}{
"simpleObjs": []interface{}{map[string]interface{}{"name": "something"}, map[string]interface{}{"name": "something else"}},
"nestedObjs": []interface{}{
map[string]interface{}{"obj": map[string]interface{}{"name": "something"}},
map[string]interface{}{"obj": map[string]interface{}{"name": "something else"}},
},
}}},
},
{
name: "mix of errors and no errors",
req: []*pb.BatchObject{{Collection: collection, Uuid: UUID4}, {Collection: collection}, {Collection: collection}, {Collection: collection, Uuid: UUID3}},
out: []*models.Object{{Class: collection, Properties: nilMap, ID: UUID4}, {Class: collection, Properties: nilMap, ID: UUID3}},
outError: []int{1, 2},
origIndex: map[int]int{0: 0, 1: 3},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out, origIndex, batchErrors := batchFromProto(&pb.BatchObjectsRequest{Objects: tt.req}, scheme)
if len(tt.outError) > 0 {
require.NotNil(t, batchErrors)
if len(tt.out) > 0 {
require.Equal(t, tt.out, out)
require.Equal(t, tt.origIndex, origIndex)
}
} else {
require.Len(t, batchErrors, 0)
require.Equal(t, tt.out, out)
}
})
}
}