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  }