github.com/weaviate/weaviate@v1.24.6/usecases/schema/cache_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 schema 13 14 import ( 15 "errors" 16 "testing" 17 18 "github.com/stretchr/testify/assert" 19 "github.com/stretchr/testify/require" 20 "github.com/weaviate/weaviate/entities/models" 21 "github.com/weaviate/weaviate/entities/schema" 22 "github.com/weaviate/weaviate/entities/schema/test_utils" 23 "github.com/weaviate/weaviate/usecases/sharding" 24 ) 25 26 func TestShardReplicas(t *testing.T) { 27 cache := schemaCache{ 28 State: State{ 29 ShardingState: map[string]*sharding.State{}, 30 }, 31 } 32 33 // class not found 34 _, err := cache.ShardReplicas("C", "S") 35 assert.ErrorContains(t, err, "class not found") 36 37 // shard not found 38 ss := &sharding.State{Physical: make(map[string]sharding.Physical)} 39 cache.State.ShardingState["C"] = ss 40 _, err = cache.ShardReplicas("C", "S") 41 assert.ErrorContains(t, err, "shard not found") 42 43 // two replicas found 44 nodes := []string{"A", "B"} 45 ss.Physical["S"] = sharding.Physical{BelongsToNodes: nodes} 46 res, err := cache.ShardReplicas("C", "S") 47 assert.Nil(t, err) 48 assert.Equal(t, nodes, res) 49 } 50 51 func TestUpdateClass(t *testing.T) { 52 class := "C" 53 cache := schemaCache{ 54 State: State{ 55 ShardingState: map[string]*sharding.State{}, 56 ObjectSchema: &models.Schema{ 57 Classes: []*models.Class{}, 58 }, 59 }, 60 } 61 62 if err := cache.updateClass(&models.Class{}, nil); !errors.Is(err, errClassNotFound) { 63 t.Fatalf("update_class: want %v got %v", errClassNotFound, err) 64 } 65 if _, err := cache.addProperty("?", nil); !errors.Is(err, errClassNotFound) { 66 t.Fatalf("add_property: want %v got %v", errClassNotFound, err) 67 } 68 c := models.Class{ 69 Class: class, 70 Properties: []*models.Property{}, 71 } 72 uc := models.Class{ 73 Class: class, 74 Properties: []*models.Property{ 75 {Description: "P1"}, 76 }, 77 } 78 // add class 79 ss := sharding.State{} 80 cache.addClass(&c, &ss) 81 82 if c, _ := cache.readOnlyClass(class); c == nil { 83 t.Fatalf("class not found") 84 } else if c == cache.unsafeFindClass(class) { 85 t.Fatalf("read_only_class doesn't return a shallow copy") 86 } 87 88 // update class 89 cache.updateClass(&uc, &sharding.State{IndexID: class}) 90 p := models.Property{Description: "P2"} 91 92 x, err := cache.addProperty(class, &p) 93 if err != nil { 94 t.Fatalf("class not found") 95 } 96 if n := len(x.Properties); n != 2 { 97 t.Fatalf("number of properties want: %v got: 2", n) 98 } 99 } 100 101 func TestCache_MergeObjectProperty(t *testing.T) { 102 vFalse := false 103 vTrue := true 104 105 className := "objectClass" 106 propertyName := "objectProperty" 107 108 objectProperty := &models.Property{ 109 Name: propertyName, 110 DataType: schema.DataTypeObject.PropString(), 111 IndexFilterable: &vTrue, 112 IndexSearchable: &vFalse, 113 Tokenization: "", 114 NestedProperties: []*models.NestedProperty{ 115 { 116 Name: "nested_int", 117 DataType: schema.DataTypeInt.PropString(), 118 IndexFilterable: &vTrue, 119 IndexSearchable: &vFalse, 120 Tokenization: "", 121 }, 122 { 123 Name: "nested_text", 124 DataType: schema.DataTypeText.PropString(), 125 IndexFilterable: &vTrue, 126 IndexSearchable: &vTrue, 127 Tokenization: models.PropertyTokenizationWord, 128 }, 129 { 130 Name: "nested_objects", 131 DataType: schema.DataTypeObjectArray.PropString(), 132 IndexFilterable: &vTrue, 133 IndexSearchable: &vFalse, 134 Tokenization: "", 135 NestedProperties: []*models.NestedProperty{ 136 { 137 Name: "nested_bool_lvl2", 138 DataType: schema.DataTypeBoolean.PropString(), 139 IndexFilterable: &vTrue, 140 IndexSearchable: &vFalse, 141 Tokenization: "", 142 }, 143 { 144 Name: "nested_numbers_lvl2", 145 DataType: schema.DataTypeNumberArray.PropString(), 146 IndexFilterable: &vTrue, 147 IndexSearchable: &vFalse, 148 Tokenization: "", 149 }, 150 }, 151 }, 152 }, 153 } 154 updatedObjectProperty := &models.Property{ 155 Name: propertyName, 156 DataType: schema.DataTypeObject.PropString(), 157 IndexFilterable: &vFalse, // different setting than existing class/prop 158 IndexSearchable: &vFalse, 159 Tokenization: "", 160 NestedProperties: []*models.NestedProperty{ 161 { 162 Name: "nested_number", 163 DataType: schema.DataTypeNumber.PropString(), 164 IndexFilterable: &vTrue, 165 IndexSearchable: &vFalse, 166 Tokenization: "", 167 }, 168 { 169 Name: "nested_text", 170 DataType: schema.DataTypeText.PropString(), 171 IndexFilterable: &vTrue, 172 IndexSearchable: &vTrue, 173 Tokenization: models.PropertyTokenizationField, // different setting than existing class/prop 174 }, 175 { 176 Name: "nested_objects", 177 DataType: schema.DataTypeObjectArray.PropString(), 178 IndexFilterable: &vTrue, 179 IndexSearchable: &vFalse, 180 Tokenization: "", 181 NestedProperties: []*models.NestedProperty{ 182 { 183 Name: "nested_date_lvl2", 184 DataType: schema.DataTypeDate.PropString(), 185 IndexFilterable: &vTrue, 186 IndexSearchable: &vFalse, 187 Tokenization: "", 188 }, 189 { 190 Name: "nested_numbers_lvl2", 191 DataType: schema.DataTypeNumberArray.PropString(), 192 IndexFilterable: &vFalse, // different setting than existing class/prop 193 IndexSearchable: &vFalse, 194 Tokenization: "", 195 }, 196 }, 197 }, 198 }, 199 } 200 expectedObjectProperty := &models.Property{ 201 Name: propertyName, 202 DataType: schema.DataTypeObject.PropString(), 203 IndexFilterable: &vTrue, 204 IndexSearchable: &vFalse, 205 Tokenization: "", 206 NestedProperties: []*models.NestedProperty{ 207 { 208 Name: "nested_int", 209 DataType: schema.DataTypeInt.PropString(), 210 IndexFilterable: &vTrue, 211 IndexSearchable: &vFalse, 212 Tokenization: "", 213 }, 214 { 215 Name: "nested_number", 216 DataType: schema.DataTypeNumber.PropString(), 217 IndexFilterable: &vTrue, 218 IndexSearchable: &vFalse, 219 Tokenization: "", 220 }, 221 { 222 Name: "nested_text", 223 DataType: schema.DataTypeText.PropString(), 224 IndexFilterable: &vTrue, 225 IndexSearchable: &vTrue, 226 Tokenization: models.PropertyTokenizationWord, // from existing class/prop 227 }, 228 { 229 Name: "nested_objects", 230 DataType: schema.DataTypeObjectArray.PropString(), 231 IndexFilterable: &vTrue, 232 IndexSearchable: &vFalse, 233 Tokenization: "", 234 NestedProperties: []*models.NestedProperty{ 235 { 236 Name: "nested_bool_lvl2", 237 DataType: schema.DataTypeBoolean.PropString(), 238 IndexFilterable: &vTrue, 239 IndexSearchable: &vFalse, 240 Tokenization: "", 241 }, 242 { 243 Name: "nested_date_lvl2", 244 DataType: schema.DataTypeDate.PropString(), 245 IndexFilterable: &vTrue, 246 IndexSearchable: &vFalse, 247 Tokenization: "", 248 }, 249 { 250 Name: "nested_numbers_lvl2", 251 DataType: schema.DataTypeNumberArray.PropString(), 252 IndexFilterable: &vTrue, // from existing class/prop 253 IndexSearchable: &vFalse, 254 Tokenization: "", 255 }, 256 }, 257 }, 258 }, 259 } 260 261 cache := schemaCache{ 262 State: State{ 263 ShardingState: map[string]*sharding.State{}, 264 ObjectSchema: &models.Schema{ 265 Classes: []*models.Class{ 266 { 267 Class: className, 268 Properties: []*models.Property{objectProperty}, 269 }, 270 }, 271 }, 272 }, 273 } 274 275 updatedClass, err := cache.mergeObjectProperty(className, updatedObjectProperty) 276 require.NoError(t, err) 277 require.NotNil(t, updatedClass) 278 require.Len(t, updatedClass.Properties, 1) 279 280 mergedProperty := updatedClass.Properties[0] 281 require.NotNil(t, mergedProperty) 282 assert.Equal(t, expectedObjectProperty.DataType, mergedProperty.DataType) 283 assert.Equal(t, expectedObjectProperty.IndexFilterable, mergedProperty.IndexFilterable) 284 assert.Equal(t, expectedObjectProperty.IndexSearchable, mergedProperty.IndexSearchable) 285 assert.Equal(t, expectedObjectProperty.Tokenization, mergedProperty.Tokenization) 286 287 test_utils.AssertNestedPropsMatch(t, expectedObjectProperty.NestedProperties, mergedProperty.NestedProperties) 288 }