github.com/weaviate/weaviate@v1.24.6/test/acceptance/grpc/grpc_test.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 test
    13  
    14  import (
    15  	"context"
    16  	"math/big"
    17  	"strings"
    18  	"testing"
    19  
    20  	"github.com/stretchr/testify/assert"
    21  	"github.com/stretchr/testify/require"
    22  	pb "github.com/weaviate/weaviate/grpc/generated/protocol/v1"
    23  	"github.com/weaviate/weaviate/test/helper"
    24  	"github.com/weaviate/weaviate/test/helper/sample-schema/books"
    25  	"google.golang.org/grpc"
    26  	"google.golang.org/grpc/health/grpc_health_v1"
    27  )
    28  
    29  func idByte(id string) []byte {
    30  	hexInteger, _ := new(big.Int).SetString(strings.Replace(id, "-", "", -1), 16)
    31  	return hexInteger.Bytes()
    32  }
    33  
    34  func TestGRPC(t *testing.T) {
    35  	grpcClient, conn := newClient(t)
    36  
    37  	// delete if exists and then re-create Books class
    38  	booksClass := books.ClassContextionaryVectorizer()
    39  	helper.DeleteClass(t, booksClass.Class)
    40  	helper.CreateClass(t, booksClass)
    41  	defer helper.DeleteClass(t, booksClass.Class)
    42  
    43  	t.Run("Health Check", func(t *testing.T) {
    44  		client := grpc_health_v1.NewHealthClient(conn)
    45  		check, err := client.Check(context.TODO(), &grpc_health_v1.HealthCheckRequest{})
    46  		require.NoError(t, err)
    47  		require.NotNil(t, check)
    48  		assert.Equal(t, grpc_health_v1.HealthCheckResponse_SERVING.Enum().Number(), check.Status.Number())
    49  	})
    50  
    51  	t.Run("Batch import", func(t *testing.T) {
    52  		resp, err := grpcClient.BatchObjects(context.TODO(), &pb.BatchObjectsRequest{
    53  			Objects: books.BatchObjects(),
    54  		})
    55  		require.NoError(t, err)
    56  		require.NotNil(t, resp)
    57  	})
    58  
    59  	tests := []struct {
    60  		name string
    61  		req  *pb.SearchRequest
    62  	}{
    63  		{
    64  			name: "Search with props",
    65  			req: &pb.SearchRequest{
    66  				Collection: booksClass.Class,
    67  				Properties: &pb.PropertiesRequest{
    68  					NonRefProperties: []string{"title"},
    69  					ObjectProperties: []*pb.ObjectPropertiesRequest{
    70  						{
    71  							PropName:            "meta",
    72  							PrimitiveProperties: []string{"isbn"},
    73  							ObjectProperties: []*pb.ObjectPropertiesRequest{
    74  								{
    75  									PropName:            "obj",
    76  									PrimitiveProperties: []string{"text"},
    77  								},
    78  								{
    79  									PropName:            "objs",
    80  									PrimitiveProperties: []string{"text"},
    81  								},
    82  							},
    83  						},
    84  						{PropName: "reviews", PrimitiveProperties: []string{"tags"}},
    85  					},
    86  				},
    87  				Metadata: &pb.MetadataRequest{
    88  					Uuid: true,
    89  				},
    90  				Uses_123Api: true,
    91  			},
    92  		},
    93  		{
    94  			name: "Search without props",
    95  			req: &pb.SearchRequest{
    96  				Collection: booksClass.Class,
    97  				Metadata: &pb.MetadataRequest{
    98  					Uuid: true,
    99  				},
   100  				Uses_123Api: true,
   101  			},
   102  		},
   103  	}
   104  	for _, tt := range tests {
   105  		t.Run(tt.name, func(t *testing.T) {
   106  			scifi := "sci-fi"
   107  			resp, err := grpcClient.Search(context.TODO(), tt.req)
   108  			require.NoError(t, err)
   109  			require.NotNil(t, resp)
   110  			require.NotNil(t, resp.Results)
   111  			assert.Equal(t, len(books.BatchObjects()), len(resp.Results))
   112  			for i := range resp.Results {
   113  				res := resp.Results[i]
   114  				id := res.Metadata.Id
   115  
   116  				assert.True(t, id == books.Dune.String() || id == books.ProjectHailMary.String() || id == books.TheLordOfTheIceGarden.String())
   117  				titleRaw := res.Properties.NonRefProps.Fields["title"]
   118  				require.NotNil(t, titleRaw)
   119  				title := titleRaw.GetStringValue()
   120  				require.NotNil(t, title)
   121  
   122  				metaRaw := res.Properties.NonRefProps.Fields["meta"]
   123  				require.NotNil(t, metaRaw)
   124  				meta := metaRaw.GetObjectValue()
   125  				require.NotNil(t, meta)
   126  				isbnRaw := meta.GetFields()["isbn"]
   127  				require.NotNil(t, isbnRaw)
   128  				isbn := isbnRaw.GetStringValue()
   129  				require.NotNil(t, isbn)
   130  
   131  				objRaw := meta.GetFields()["obj"]
   132  				require.NotNil(t, objRaw)
   133  				obj := objRaw.GetObjectValue()
   134  				require.NotNil(t, obj)
   135  
   136  				objsRaw := meta.GetFields()["objs"]
   137  				require.NotNil(t, objsRaw)
   138  				objs := objsRaw.GetListValue()
   139  				require.NotNil(t, objs)
   140  
   141  				objEntryRaw := objs.Values[0]
   142  				require.NotNil(t, objEntryRaw)
   143  				objEntry := objEntryRaw.GetObjectValue()
   144  				require.NotNil(t, objEntry)
   145  
   146  				reviewsRaw := res.Properties.NonRefProps.Fields["reviews"]
   147  				require.NotNil(t, reviewsRaw)
   148  				reviews := reviewsRaw.GetListValue()
   149  				require.NotNil(t, reviews)
   150  				require.Len(t, reviews.Values, 1)
   151  
   152  				review := reviews.Values[0].GetObjectValue()
   153  				require.NotNil(t, review)
   154  
   155  				tags := review.Fields["tags"].GetListValue()
   156  				require.NotNil(t, tags)
   157  
   158  				strTags := make([]string, len(tags.Values))
   159  				for i, tag := range tags.Values {
   160  					strTags[i] = tag.GetStringValue()
   161  				}
   162  
   163  				expectedTitle := ""
   164  				expectedIsbn := ""
   165  				expectedTags := []string{}
   166  				if id == books.Dune.String() {
   167  					expectedTitle = "Dune"
   168  					expectedIsbn = "978-0593099322"
   169  					expectedTags = []string{scifi, "epic"}
   170  				}
   171  				if id == books.ProjectHailMary.String() {
   172  					expectedTitle = "Project Hail Mary"
   173  					expectedIsbn = "978-0593135204"
   174  					expectedTags = []string{scifi}
   175  				}
   176  				if id == books.TheLordOfTheIceGarden.String() {
   177  					expectedTitle = "The Lord of the Ice Garden"
   178  					expectedIsbn = "978-8374812962"
   179  					expectedTags = []string{scifi, "fantasy"}
   180  				}
   181  				assert.Equal(t, expectedTitle, title)
   182  				assert.Equal(t, expectedIsbn, isbn)
   183  				assert.Equal(t, expectedTags, strTags)
   184  
   185  				expectedObj := &pb.Properties{
   186  					Fields: map[string]*pb.Value{
   187  						"text": {Kind: &pb.Value_StringValue{StringValue: "some text"}},
   188  					},
   189  				}
   190  				assert.Equal(t, expectedObj, obj)
   191  				assert.Equal(t, expectedObj, objEntry)
   192  			}
   193  		})
   194  	}
   195  
   196  	t.Run("Batch delete", func(t *testing.T) {
   197  		resp, err := grpcClient.BatchDelete(context.TODO(), &pb.BatchDeleteRequest{
   198  			Collection: "Books",
   199  			Filters:    &pb.Filters{Operator: pb.Filters_OPERATOR_EQUAL, TestValue: &pb.Filters_ValueText{ValueText: "Dune"}, Target: &pb.FilterTarget{Target: &pb.FilterTarget_Property{Property: "title"}}},
   200  			DryRun:     true,
   201  			Verbose:    true,
   202  		})
   203  		require.NoError(t, err)
   204  		require.NotNil(t, resp)
   205  		require.Equal(t, resp.Matches, int64(1))
   206  		require.Equal(t, resp.Successful, int64(1))
   207  		require.Equal(t, resp.Failed, int64(0))
   208  		require.Equal(t, resp.Objects[0].Uuid, idByte(books.Dune.String()))
   209  	})
   210  
   211  	t.Run("gRPC Search removed", func(t *testing.T) {
   212  		_, err := grpcClient.Search(context.TODO(), &pb.SearchRequest{})
   213  		require.NotNil(t, err)
   214  	})
   215  }
   216  
   217  func newClient(t *testing.T) (pb.WeaviateClient, *grpc.ClientConn) {
   218  	conn, err := helper.CreateGrpcConnectionClient(":50051")
   219  	require.NoError(t, err)
   220  	require.NotNil(t, conn)
   221  	grpcClient := helper.CreateGrpcWeaviateClient(conn)
   222  	require.NotNil(t, grpcClient)
   223  	return grpcClient, conn
   224  }