Spaces:
Running
Running
File size: 4,992 Bytes
b110593 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
// _ _
// __ _____ __ ___ ___ __ _| |_ ___
// \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
// \ V V / __/ (_| |\ V /| | (_| | || __/
// \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
//
// Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
//
// CONTACT: [email protected]
//
package test
import (
"fmt"
"strings"
"testing"
"time"
"github.com/go-openapi/strfmt"
"github.com/stretchr/testify/assert"
"github.com/weaviate/weaviate/client/objects"
clschema "github.com/weaviate/weaviate/client/schema"
"github.com/weaviate/weaviate/entities/models"
"github.com/weaviate/weaviate/entities/schema"
"github.com/weaviate/weaviate/test/helper"
)
// This aims to prevent a regression on
// https://github.com/weaviate/weaviate/issues/1016
// The issue was that rapid POST .../references/... request in succession would
// overwrite each other due to the eventual consistency nature of the used
// backend (esvector). This bug is considered fix if n items can be rapidly
// added and a subsequent GET request of the source resource contains all
// previously added references.
func Test_RapidlyAddingReferences(t *testing.T) {
sourceClass := "SequenceReferenceTestSource"
targetClass := "SequenceReferenceTestTarget"
sourceID := strfmt.UUID("96ce03ca-58ed-48e1-a0f1-51f63fa9aa12")
targetIDs := []strfmt.UUID{
"ce1a4756-b7ce-44fa-b079-45a7ec400882",
"e1edb4ff-570c-4f0b-a1a1-18af118369aa",
"25d22c70-3df0-4e5c-b8c1-a88d4d2771ef",
"6f2a0708-3e8e-4a68-9763-26c465d8bf83",
"c4dfae47-ebcf-4808-9122-1c67898ec140",
"754bd925-1900-4f93-9f5d-27631eb618bb",
"babba820-e3f5-4e8d-a354-76f2cb13fdba",
"270942da-1999-40cd-a580-a91aa144b6c0",
"a7a06618-6d50-4654-be75-2c9f639a6368",
"47ba1d2b-6b8c-4b3b-92a8-46574a069ae8",
}
t.Run("adding the required schema", func(t *testing.T) {
t.Run("target class", func(t *testing.T) {
params := clschema.NewSchemaObjectsCreateParams().WithObjectClass(
&models.Class{
Class: targetClass,
Properties: []*models.Property{
{
DataType: schema.DataTypeText.PropString(),
Tokenization: models.PropertyTokenizationWhitespace,
Name: "name",
},
},
},
)
resp, err := helper.Client(t).Schema.SchemaObjectsCreate(params, nil)
helper.AssertRequestOk(t, resp, err, nil)
})
t.Run("source class", func(t *testing.T) {
params := clschema.NewSchemaObjectsCreateParams().WithObjectClass(
&models.Class{
Class: sourceClass,
Properties: []*models.Property{
{
DataType: []string{targetClass},
Name: "toTarget",
},
{
DataType: schema.DataTypeText.PropString(),
Tokenization: models.PropertyTokenizationWhitespace,
Name: "name",
},
},
},
)
resp, err := helper.Client(t).Schema.SchemaObjectsCreate(params, nil)
helper.AssertRequestOk(t, resp, err, nil)
})
})
t.Run("adding all objects (without referencing)", func(t *testing.T) {
t.Run("source object", func(t *testing.T) {
assertCreateObjectWithID(t, sourceClass, "", sourceID, map[string]interface{}{
"name": "Source Object",
})
})
t.Run("target objects", func(t *testing.T) {
for i, id := range targetIDs {
assertCreateObjectWithID(t, targetClass, "", id, map[string]interface{}{
"name": fmt.Sprintf("target object %d", i),
})
}
})
})
t.Run("waiting for the last added object to be present", func(t *testing.T) {
assertGetObjectEventually(t, targetIDs[len(targetIDs)-1])
})
t.Run("placing all references in succession", func(t *testing.T) {
for _, id := range targetIDs {
params := objects.NewObjectsReferencesCreateParams().
WithID(sourceID).
WithPropertyName("toTarget").
WithBody(
&models.SingleRef{
Beacon: strfmt.URI(fmt.Sprintf("weaviate://localhost/%s", id)),
},
)
res, err := helper.Client(t).Objects.ObjectsReferencesCreate(params, nil)
helper.AssertRequestOk(t, res, err, nil)
}
})
// wait for index refresh
time.Sleep(2 * time.Second) // TODO: improve through polling
t.Run("checking which refs were set", func(t *testing.T) {
source := assertGetObject(t, sourceID)
var foundIDs []strfmt.UUID
// extract IDs
for _, ref := range source.Properties.(map[string]interface{})["toTarget"].([]interface{}) {
beacon := ref.(map[string]interface{})["beacon"].(string)
chunks := strings.Split(beacon, "/")
foundIDs = append(foundIDs, strfmt.UUID(chunks[len(chunks)-1]))
}
assert.ElementsMatch(t, targetIDs, foundIDs)
})
// cleanup
helper.Client(t).Schema.SchemaObjectsDelete(
clschema.NewSchemaObjectsDeleteParams().WithClassName(sourceClass), nil)
helper.Client(t).Schema.SchemaObjectsDelete(
clschema.NewSchemaObjectsDeleteParams().WithClassName(targetClass), nil)
}
|