github.com/weaviate/weaviate@v1.24.6/entities/schema/data_types_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 "fmt" 16 "testing" 17 18 "github.com/stretchr/testify/assert" 19 "github.com/stretchr/testify/require" 20 "github.com/weaviate/weaviate/entities/models" 21 ) 22 23 func TestDetectPrimitiveTypes(t *testing.T) { 24 s := Empty() 25 26 for _, dt := range append(PrimitiveDataTypes, DeprecatedPrimitiveDataTypes...) { 27 pdt, err := s.FindPropertyDataType(dt.PropString()) 28 29 assert.Nil(t, err) 30 assert.True(t, pdt.IsPrimitive()) 31 assert.Equal(t, dt, pdt.AsPrimitive()) 32 33 assert.False(t, pdt.IsNested()) 34 assert.False(t, pdt.IsReference()) 35 } 36 } 37 38 func TestDetectNestedTypes(t *testing.T) { 39 s := Empty() 40 41 for _, dt := range NestedDataTypes { 42 ndt, err := s.FindPropertyDataType(dt.PropString()) 43 44 assert.Nil(t, err) 45 assert.True(t, ndt.IsNested()) 46 assert.Equal(t, dt, ndt.AsNested()) 47 48 assert.False(t, ndt.IsPrimitive()) 49 assert.False(t, ndt.IsReference()) 50 } 51 } 52 53 func TestExistingClassSingleRef(t *testing.T) { 54 className := "ExistingClass" 55 s := Empty() 56 s.Objects.Classes = []*models.Class{{Class: className}} 57 58 pdt, err := s.FindPropertyDataType([]string{className}) 59 60 assert.Nil(t, err) 61 assert.True(t, pdt.IsReference()) 62 assert.True(t, pdt.ContainsClass(ClassName(className))) 63 } 64 65 func TestNonExistingClassSingleRef(t *testing.T) { 66 className := "NonExistingClass" 67 s := Empty() 68 69 pdt, err := s.FindPropertyDataType([]string{className}) 70 71 assert.EqualError(t, err, ErrRefToNonexistentClass.Error()) 72 assert.Nil(t, pdt) 73 } 74 75 func TestNonExistingClassRelaxedCrossValidation(t *testing.T) { 76 className := "NonExistingClass" 77 s := Empty() 78 79 pdt, err := s.FindPropertyDataTypeWithRefs([]string{className}, true, ClassName("AnotherNonExistingClass")) 80 81 assert.Nil(t, err) 82 assert.True(t, pdt.IsReference()) 83 assert.True(t, pdt.ContainsClass(ClassName(className))) 84 } 85 86 func TestNonExistingClassPropertyBelongsTo(t *testing.T) { 87 className := "NonExistingClass" 88 s := Empty() 89 90 pdt, err := s.FindPropertyDataTypeWithRefs([]string{className}, false, ClassName(className)) 91 92 assert.Nil(t, err) 93 assert.True(t, pdt.IsReference()) 94 assert.True(t, pdt.ContainsClass(ClassName(className))) 95 } 96 97 func TestGetPropertyDataType(t *testing.T) { 98 class := &models.Class{Class: "TestClass"} 99 dataTypes := []string{ 100 "string", "text", "int", "number", "boolean", 101 "date", "geoCoordinates", "phoneNumber", "blob", "Ref", "invalid", 102 "string[]", "text[]", "int[]", "number[]", "boolean[]", "date[]", 103 "uuid", "uuid[]", 104 105 "object", "object[]", 106 } 107 class.Properties = make([]*models.Property, len(dataTypes)) 108 for i, dtString := range dataTypes { 109 class.Properties[i] = &models.Property{ 110 Name: dtString + "Prop", 111 DataType: []string{dtString}, 112 } 113 } 114 115 type test struct { 116 propName string 117 expectedDataType *DataType 118 expectedErr error 119 } 120 121 tests := []test{ 122 { 123 propName: "stringProp", 124 expectedDataType: ptDataType(DataTypeString), 125 }, 126 { 127 propName: "textProp", 128 expectedDataType: ptDataType(DataTypeText), 129 }, 130 { 131 propName: "numberProp", 132 expectedDataType: ptDataType(DataTypeNumber), 133 }, 134 { 135 propName: "intProp", 136 expectedDataType: ptDataType(DataTypeInt), 137 }, 138 { 139 propName: "booleanProp", 140 expectedDataType: ptDataType(DataTypeBoolean), 141 }, 142 { 143 propName: "dateProp", 144 expectedDataType: ptDataType(DataTypeDate), 145 }, 146 { 147 propName: "phoneNumberProp", 148 expectedDataType: ptDataType(DataTypePhoneNumber), 149 }, 150 { 151 propName: "geoCoordinatesProp", 152 expectedDataType: ptDataType(DataTypeGeoCoordinates), 153 }, 154 { 155 propName: "blobProp", 156 expectedDataType: ptDataType(DataTypeBlob), 157 }, 158 { 159 propName: "string[]Prop", 160 expectedDataType: ptDataType(DataTypeStringArray), 161 }, 162 { 163 propName: "text[]Prop", 164 expectedDataType: ptDataType(DataTypeTextArray), 165 }, 166 { 167 propName: "int[]Prop", 168 expectedDataType: ptDataType(DataTypeIntArray), 169 }, 170 { 171 propName: "number[]Prop", 172 expectedDataType: ptDataType(DataTypeNumberArray), 173 }, 174 { 175 propName: "boolean[]Prop", 176 expectedDataType: ptDataType(DataTypeBooleanArray), 177 }, 178 { 179 propName: "date[]Prop", 180 expectedDataType: ptDataType(DataTypeDateArray), 181 }, 182 { 183 propName: "uuidProp", 184 expectedDataType: ptDataType(DataTypeUUID), 185 }, 186 { 187 propName: "uuid[]Prop", 188 expectedDataType: ptDataType(DataTypeUUIDArray), 189 }, 190 { 191 propName: "objectProp", 192 expectedDataType: ptDataType(DataTypeObject), 193 }, 194 { 195 propName: "object[]Prop", 196 expectedDataType: ptDataType(DataTypeObjectArray), 197 }, 198 { 199 propName: "RefProp", 200 expectedDataType: ptDataType(DataTypeCRef), 201 }, 202 { 203 propName: "wrongProp", 204 expectedDataType: nil, 205 expectedErr: fmt.Errorf("no such prop with name 'wrongProp' found in class 'TestClass' in the schema. Check your schema files for which properties in this class are available"), 206 }, 207 { 208 propName: "invalidProp", 209 expectedDataType: nil, 210 expectedErr: fmt.Errorf("given value-DataType does not exist."), 211 }, 212 } 213 214 for _, test := range tests { 215 t.Run(test.propName, func(t *testing.T) { 216 dt, err := GetPropertyDataType(class, test.propName) 217 require.Equal(t, test.expectedErr, err) 218 assert.Equal(t, test.expectedDataType, dt) 219 }) 220 } 221 } 222 223 func Test_DataType_AsPrimitive(t *testing.T) { 224 type testCase struct { 225 name string 226 inputDataType []string 227 expectedDataType DataType 228 expectedIsPrimitive bool 229 } 230 231 runTestCases := func(t *testing.T, testCases []testCase) { 232 for _, tc := range testCases { 233 t.Run(tc.name, func(t *testing.T) { 234 dataType, ok := AsPrimitive(tc.inputDataType) 235 assert.Equal(t, tc.expectedDataType, dataType) 236 assert.Equal(t, tc.expectedIsPrimitive, ok) 237 }) 238 } 239 } 240 241 t.Run("is primitive data type", func(t *testing.T) { 242 testCases := []testCase{} 243 for _, dt := range append(PrimitiveDataTypes, DeprecatedPrimitiveDataTypes...) { 244 inputDataType := dt.PropString() 245 testCases = append(testCases, testCase{ 246 name: fmt.Sprintf("%v", inputDataType), 247 inputDataType: inputDataType, 248 expectedDataType: dt, 249 expectedIsPrimitive: true, 250 }) 251 } 252 253 runTestCases(t, testCases) 254 }) 255 256 t.Run("is empty data type", func(t *testing.T) { 257 testCases := []testCase{} 258 for _, dtStr := range []string{""} { 259 inputDataType := []string{dtStr} 260 testCases = append(testCases, testCase{ 261 name: fmt.Sprintf("%v", inputDataType), 262 inputDataType: inputDataType, 263 expectedDataType: "", 264 expectedIsPrimitive: true, 265 }) 266 } 267 268 runTestCases(t, testCases) 269 }) 270 271 t.Run("is non existent data type", func(t *testing.T) { 272 testCases := []testCase{} 273 for _, dtStr := range []string{"non-existent"} { 274 inputDataType := []string{dtStr} 275 testCases = append(testCases, testCase{ 276 name: fmt.Sprintf("%v", inputDataType), 277 inputDataType: inputDataType, 278 expectedDataType: "", 279 expectedIsPrimitive: false, 280 }) 281 } 282 283 runTestCases(t, testCases) 284 }) 285 286 t.Run("is nested data type", func(t *testing.T) { 287 testCases := []testCase{} 288 for _, dt := range NestedDataTypes { 289 inputDataType := dt.PropString() 290 testCases = append(testCases, testCase{ 291 name: fmt.Sprintf("%v", inputDataType), 292 inputDataType: inputDataType, 293 expectedDataType: "", 294 expectedIsPrimitive: false, 295 }) 296 } 297 298 runTestCases(t, testCases) 299 }) 300 301 t.Run("is reference data type", func(t *testing.T) { 302 testCases := []testCase{} 303 for _, inputDataType := range [][]string{ 304 {"SomeClass"}, 305 {"SomeOtherClass", "AndAnotherOne"}, 306 } { 307 testCases = append(testCases, testCase{ 308 name: fmt.Sprintf("%v", inputDataType), 309 inputDataType: inputDataType, 310 expectedDataType: "", 311 expectedIsPrimitive: false, 312 }) 313 } 314 315 runTestCases(t, testCases) 316 }) 317 } 318 319 func Test_DataType_AsNested(t *testing.T) { 320 type testCase struct { 321 name string 322 inputDataType []string 323 expectedDataType DataType 324 expectedIsNested bool 325 } 326 327 runTestCases := func(t *testing.T, testCases []testCase) { 328 for _, tc := range testCases { 329 t.Run(tc.name, func(t *testing.T) { 330 dataType, ok := AsNested(tc.inputDataType) 331 assert.Equal(t, tc.expectedDataType, dataType) 332 assert.Equal(t, tc.expectedIsNested, ok) 333 }) 334 } 335 } 336 337 t.Run("is nested data type", func(t *testing.T) { 338 testCases := []testCase{} 339 for _, dt := range NestedDataTypes { 340 inputDataType := dt.PropString() 341 testCases = append(testCases, testCase{ 342 name: fmt.Sprintf("%v", inputDataType), 343 inputDataType: inputDataType, 344 expectedDataType: dt, 345 expectedIsNested: true, 346 }) 347 } 348 349 runTestCases(t, testCases) 350 }) 351 352 t.Run("is empty data type", func(t *testing.T) { 353 testCases := []testCase{} 354 for _, dtStr := range []string{""} { 355 inputDataType := []string{dtStr} 356 testCases = append(testCases, testCase{ 357 name: fmt.Sprintf("%v", inputDataType), 358 inputDataType: inputDataType, 359 expectedDataType: "", 360 expectedIsNested: false, 361 }) 362 } 363 364 runTestCases(t, testCases) 365 }) 366 367 t.Run("is non existent data type", func(t *testing.T) { 368 testCases := []testCase{} 369 for _, dtStr := range []string{"non-existent"} { 370 inputDataType := []string{dtStr} 371 testCases = append(testCases, testCase{ 372 name: fmt.Sprintf("%v", inputDataType), 373 inputDataType: inputDataType, 374 expectedDataType: "", 375 expectedIsNested: false, 376 }) 377 } 378 379 runTestCases(t, testCases) 380 }) 381 382 t.Run("is primitive data type", func(t *testing.T) { 383 testCases := []testCase{} 384 for _, dt := range append(PrimitiveDataTypes, DeprecatedPrimitiveDataTypes...) { 385 inputDataType := dt.PropString() 386 testCases = append(testCases, testCase{ 387 name: fmt.Sprintf("%v", inputDataType), 388 inputDataType: inputDataType, 389 expectedDataType: "", 390 expectedIsNested: false, 391 }) 392 } 393 394 runTestCases(t, testCases) 395 }) 396 397 t.Run("is reference data type", func(t *testing.T) { 398 testCases := []testCase{} 399 for _, inputDataType := range [][]string{ 400 {"SomeClass"}, 401 {"SomeOtherClass", "AndAnotherOne"}, 402 } { 403 testCases = append(testCases, testCase{ 404 name: fmt.Sprintf("%v", inputDataType), 405 inputDataType: inputDataType, 406 expectedDataType: "", 407 expectedIsNested: false, 408 }) 409 } 410 411 runTestCases(t, testCases) 412 }) 413 } 414 415 func ptDataType(dt DataType) *DataType { 416 return &dt 417 }