github.com/weaviate/weaviate@v1.24.6/test/acceptance/replication/crud_ops.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package replication 13 14 import ( 15 "encoding/json" 16 "fmt" 17 "strings" 18 "testing" 19 20 "github.com/go-openapi/strfmt" 21 "github.com/stretchr/testify/assert" 22 "github.com/stretchr/testify/require" 23 "github.com/weaviate/weaviate/client/nodes" 24 "github.com/weaviate/weaviate/client/objects" 25 "github.com/weaviate/weaviate/entities/filters" 26 "github.com/weaviate/weaviate/entities/models" 27 "github.com/weaviate/weaviate/entities/verbosity" 28 "github.com/weaviate/weaviate/test/helper" 29 graphqlhelper "github.com/weaviate/weaviate/test/helper/graphql" 30 "github.com/weaviate/weaviate/usecases/replica" 31 ) 32 33 func getClass(t *testing.T, host, class string) *models.Class { 34 helper.SetupClient(host) 35 return helper.GetClass(t, class) 36 } 37 38 func updateClass(t *testing.T, host string, class *models.Class) { 39 helper.SetupClient(host) 40 helper.UpdateClass(t, class) 41 } 42 43 func createObject(t *testing.T, host string, obj *models.Object) { 44 helper.SetupClient(host) 45 helper.CreateObject(t, obj) 46 } 47 48 func createObjectCL(t *testing.T, host string, obj *models.Object, cl replica.ConsistencyLevel) { 49 helper.SetupClient(host) 50 helper.CreateObjectCL(t, obj, cl) 51 } 52 53 func createTenantObject(t *testing.T, host string, obj *models.Object) { 54 helper.SetupClient(host) 55 helper.CreateObject(t, obj) 56 } 57 58 func createObjects(t *testing.T, host string, batch []*models.Object) { 59 helper.SetupClient(host) 60 helper.CreateObjectsBatch(t, batch) 61 } 62 63 func createTenantObjects(t *testing.T, host string, batch []*models.Object) { 64 helper.SetupClient(host) 65 helper.CreateObjectsBatch(t, batch) 66 } 67 68 func getObject(t *testing.T, host, class string, id strfmt.UUID, withVec bool) (*models.Object, error) { 69 helper.SetupClient(host) 70 var include string 71 if withVec { 72 include = "vector" 73 } 74 return helper.GetObject(t, class, id, include) 75 } 76 77 func getTenantObject(t *testing.T, host, class string, id strfmt.UUID, tenant string) (*models.Object, error) { 78 helper.SetupClient(host) 79 return helper.TenantObject(t, class, id, tenant) 80 } 81 82 func objectExistsCL(t *testing.T, host, class string, id strfmt.UUID, cl replica.ConsistencyLevel) (bool, error) { 83 helper.SetupClient(host) 84 return helper.ObjectExistsCL(t, class, id, cl) 85 } 86 87 func getObjectCL(t *testing.T, host, class string, id strfmt.UUID, cl replica.ConsistencyLevel) (*models.Object, error) { 88 helper.SetupClient(host) 89 return helper.GetObjectCL(t, class, id, cl) 90 } 91 92 func getObjectFromNode(t *testing.T, host, class string, id strfmt.UUID, nodename string) (*models.Object, error) { 93 helper.SetupClient(host) 94 return helper.GetObjectFromNode(t, class, id, nodename) 95 } 96 97 func getTenantObjectFromNode(t *testing.T, host, class string, id strfmt.UUID, nodename, tenant string) (*models.Object, error) { 98 helper.SetupClient(host) 99 return helper.GetTenantObjectFromNode(t, class, id, nodename, tenant) 100 } 101 102 func patchObject(t *testing.T, host string, patch *models.Object) { 103 helper.SetupClient(host) 104 helper.PatchObject(t, patch) 105 } 106 107 func patchTenantObject(t *testing.T, host string, patch *models.Object) { 108 helper.SetupClient(host) 109 helper.PatchObject(t, patch) 110 } 111 112 func updateObjectCL(t *testing.T, host string, obj *models.Object, cl replica.ConsistencyLevel) { 113 helper.SetupClient(host) 114 helper.UpdateObjectCL(t, obj, cl) 115 } 116 117 func addReferences(t *testing.T, host string, refs []*models.BatchReference) { 118 helper.SetupClient(host) 119 resp, err := helper.AddReferences(t, refs) 120 helper.CheckReferencesBatchResponse(t, resp, err) 121 } 122 123 func addTenantReferences(t *testing.T, host string, refs []*models.BatchReference) { 124 helper.SetupClient(host) 125 resp, err := helper.AddReferences(t, refs) 126 helper.CheckReferencesBatchResponse(t, resp, err) 127 } 128 129 func deleteObject(t *testing.T, host, class string, id strfmt.UUID) { 130 helper.SetupClient(host) 131 132 toDelete, err := helper.GetObject(t, class, id) 133 require.Nil(t, err) 134 135 helper.DeleteObject(t, toDelete) 136 137 _, err = helper.GetObject(t, class, id) 138 assert.Equal(t, &objects.ObjectsClassGetNotFound{}, err) 139 } 140 141 func deleteTenantObject(t *testing.T, host, class string, id strfmt.UUID, tenant string) { 142 helper.SetupClient(host) 143 helper.DeleteTenantObject(t, class, id, tenant) 144 145 _, err := helper.TenantObject(t, class, id, tenant) 146 assert.Equal(t, &objects.ObjectsClassGetNotFound{}, err) 147 } 148 149 func deleteObjects(t *testing.T, host, class string, path []string, valueText string) { 150 helper.SetupClient(host) 151 152 batchDelete := &models.BatchDelete{ 153 Match: &models.BatchDeleteMatch{ 154 Class: class, 155 Where: &models.WhereFilter{ 156 Operator: filters.OperatorLike.Name(), 157 Path: path, 158 ValueText: &valueText, 159 }, 160 }, 161 } 162 helper.DeleteObjectsBatch(t, batchDelete) 163 164 resp := gqlGet(t, host, class, replica.All) 165 assert.Empty(t, resp) 166 } 167 168 func deleteTenantObjects(t *testing.T, host, class string, path []string, valueText, tenant string) { 169 helper.SetupClient(host) 170 171 batchDelete := &models.BatchDelete{ 172 Match: &models.BatchDeleteMatch{ 173 Class: class, 174 Where: &models.WhereFilter{ 175 Operator: filters.OperatorLike.Name(), 176 Path: path, 177 ValueText: &valueText, 178 }, 179 }, 180 } 181 resp, err := helper.DeleteTenantObjectsBatch(t, batchDelete, tenant) 182 helper.AssertRequestOk(t, resp, err, nil) 183 184 deleted := gqlTenantGet(t, host, class, replica.All, tenant) 185 assert.Empty(t, deleted) 186 } 187 188 func gqlGet(t *testing.T, host, class string, cl replica.ConsistencyLevel, fields ...string) []interface{} { 189 helper.SetupClient(host) 190 191 if cl == "" { 192 cl = replica.Quorum 193 } 194 195 q := fmt.Sprintf("{Get {%s (consistencyLevel: %s)", class, cl) + " {%s}}}" 196 if len(fields) == 0 { 197 fields = []string{"_additional{id isConsistent vector}"} 198 } 199 q = fmt.Sprintf(q, strings.Join(fields, " ")) 200 201 return gqlDo(t, class, q) 202 } 203 204 func gqlGetNearVec(t *testing.T, host, class string, vec []interface{}, cl replica.ConsistencyLevel, fields ...string) []interface{} { 205 helper.SetupClient(host) 206 207 if cl == "" { 208 cl = replica.Quorum 209 } 210 211 q := fmt.Sprintf("{Get {%s (consistencyLevel: %s, nearVector: {vector: %s, certainty: 0.8})", 212 class, cl, vec2String(vec)) + " {%s}}}" 213 if len(fields) == 0 { 214 fields = []string{"_additional{id isConsistent}"} 215 } 216 q = fmt.Sprintf(q, strings.Join(fields, " ")) 217 218 return gqlDo(t, class, q) 219 } 220 221 func gqlDo(t *testing.T, class, query string) []interface{} { 222 resp := graphqlhelper.AssertGraphQL(t, helper.RootAuth, query) 223 224 result := resp.Get("Get").Get(class) 225 return result.Result.([]interface{}) 226 } 227 228 func gqlTenantGet(t *testing.T, host, class string, cl replica.ConsistencyLevel, 229 tenant string, fields ...string, 230 ) []interface{} { 231 helper.SetupClient(host) 232 233 if cl == "" { 234 cl = replica.Quorum 235 } 236 237 q := fmt.Sprintf("{Get {%s (tenant: %q, consistencyLevel: %s)", class, tenant, cl) + " {%s}}}" 238 if len(fields) == 0 { 239 fields = []string{"_additional{id isConsistent}"} 240 } 241 q = fmt.Sprintf(q, strings.Join(fields, " ")) 242 243 resp := graphqlhelper.AssertGraphQL(t, helper.RootAuth, q) 244 245 result := resp.Get("Get").Get(class) 246 return result.Result.([]interface{}) 247 } 248 249 func countTenantObjects(t *testing.T, host, class string, 250 tenant string, 251 ) int64 { 252 helper.SetupClient(host) 253 254 q := fmt.Sprintf(`{Aggregate{%s(tenant: %q){meta{count}}}}`, class, tenant) 255 256 resp := graphqlhelper.AssertGraphQL(t, helper.RootAuth, q) 257 258 result := resp.Get("Aggregate").Get(class).AsSlice() 259 require.Len(t, result, 1) 260 meta := result[0].(map[string]interface{})["meta"].(map[string]interface{}) 261 count, err := meta["count"].(json.Number).Int64() 262 require.Nil(t, err) 263 return count 264 } 265 266 func getNodes(t *testing.T, host string) *models.NodesStatusResponse { 267 helper.SetupClient(host) 268 verbose := verbosity.OutputVerbose 269 params := nodes.NewNodesGetParams().WithOutput(&verbose) 270 resp, err := helper.Client(t).Nodes.NodesGet(params, nil) 271 helper.AssertRequestOk(t, resp, err, nil) 272 return resp.Payload 273 } 274 275 func vec2String(v []interface{}) (s string) { 276 for _, n := range v { 277 x := n.(json.Number) 278 s = fmt.Sprintf("%s, %s", s, x.String()) 279 } 280 s = strings.TrimLeft(s, ", ") 281 return fmt.Sprintf("[%s]", s) 282 }