github.com/angryronald/go-kit@v0.0.0-20240505173814-ff2bd9c79dbf/generic/repository/generic.utils_test.go (about) 1 package repository 2 3 import ( 4 reflect "reflect" 5 "testing" 6 7 "github.com/google/uuid" 8 9 "github.com/angryronald/go-kit/cast" 10 ) 11 12 func TestIsValidOperations(t *testing.T) { 13 // Test case where conditions match and relational operations are 1 less 14 conditionalOps := []ConditionalOperation{"=", ">", "<"} 15 relationalOps := []RelationalOperation{"AND", "OR"} 16 params := map[string]interface{}{"field1": 1, "field2": 2, "field3": 3} 17 if !IsValidOperations(conditionalOps, relationalOps, params) { 18 t.Errorf("Expected IsValidOperations to return true, but got false") 19 } 20 21 // Test case where conditions do not match 22 conditionalOps = []ConditionalOperation{"=", ">", "<"} 23 relationalOps = []RelationalOperation{"AND", "OR"} 24 params = map[string]interface{}{"field1": 1, "field2": 2} 25 if IsValidOperations(conditionalOps, relationalOps, params) { 26 t.Errorf("Expected IsValidOperations to return false, but got true") 27 } 28 } 29 30 func TestToSnakeCase(t *testing.T) { 31 // Test with camel case string 32 input := "camelCaseString" 33 expected := "camel_case_string" 34 result := ToSnakeCase(input) 35 if result != expected { 36 t.Errorf("Expected ToSnakeCase(%s) to return %s, but got %s", input, expected, result) 37 } 38 39 // Test with already snake case string 40 input = "snake_case_string" 41 expected = "snake_case_string" 42 result = ToSnakeCase(input) 43 if result != expected { 44 t.Errorf("Expected ToSnakeCase(%s) to return %s, but got %s", input, expected, result) 45 } 46 } 47 48 func TestGetTableName(t *testing.T) { 49 // Test with a struct named User 50 type User struct{} 51 expected := "users" 52 result := GetTableName(&User{}) 53 if result != expected { 54 t.Errorf("Expected GetTableName(User{}) to return %s, but got %s", expected, result) 55 } 56 57 // Test with a struct named UserProfile 58 type UserProfile struct{} 59 expected = "user_profiles" 60 result = GetTableName(&UserProfile{}) 61 if result != expected { 62 t.Errorf("Expected GetTableName(UserProfile{}) to return %s, but got %s", expected, result) 63 } 64 65 type OTPModel struct{} 66 expected = "otp_models" 67 result = GetTableName(&OTPModel{}) 68 if result != expected { 69 t.Errorf("Expected GetTableName(OTPModel{}) to return %s, but got %s", expected, result) 70 } 71 } 72 73 func TestIsMapStringInterface(t *testing.T) { 74 tests := []struct { 75 name string 76 input interface{} 77 expect bool 78 }{ 79 { 80 name: "Valid map[string]interface{}", 81 input: map[string]interface{}{"key": "value"}, 82 expect: true, 83 }, 84 { 85 name: "Invalid non-map input", 86 input: "not a map", 87 expect: false, 88 }, 89 { 90 name: "Invalid map with non-string key", 91 input: map[int]interface{}{1: "value"}, 92 expect: false, 93 }, 94 { 95 name: "Invalid map with non-interface value", 96 input: map[string]int{"key": 42}, 97 expect: false, 98 }, 99 { 100 name: "Valid empty map", 101 input: map[string]interface{}{}, 102 expect: true, 103 }, 104 } 105 106 for _, test := range tests { 107 t.Run(test.name, func(t *testing.T) { 108 result := IsMapStringInterface(test.input) 109 if result != test.expect { 110 t.Errorf("Expected %v, but got %v for input %+v", test.expect, result, test.input) 111 } 112 }) 113 } 114 } 115 116 func TestGetStructPropertyAsString(t *testing.T) { 117 // Create an instance of the Person struct with a UUID field 118 type Person struct { 119 ID uuid.UUID 120 Name string 121 Age int 122 Email string 123 } 124 125 person := Person{ 126 ID: uuid.New(), 127 Name: "Alice", 128 Age: 30, 129 Email: "alice@example.com", 130 } 131 132 // Test getting a string property (Name) 133 name, err := GetStructPropertyAsString(&person, "NAME") 134 if err != nil { 135 t.Errorf("Error getting property 'Name': %v", err) 136 } 137 if name != "Alice" { 138 t.Errorf("Expected 'Name' to be 'Alice', but got '%s'", name) 139 } 140 141 // Test getting an integer property (Age) 142 age, err := GetStructPropertyAsString(&person, "AGE") 143 if err != nil { 144 t.Errorf("Error getting property 'Age': %v", err) 145 } 146 if age != "30" { 147 t.Errorf("Expected 'Age' to be '30', but got '%s'", age) 148 } 149 150 // Test getting a UUID property (ID) 151 id, err := GetStructPropertyAsString(&person, "ID") 152 if err != nil { 153 t.Errorf("Error getting property 'ID': %v", err) 154 } 155 // The actual UUID value is generated dynamically, so we can't predict the exact value. 156 // We'll just check that it's a non-empty string. 157 if id == "" { 158 t.Errorf("Expected a non-empty UUID string for 'ID', but got an empty string") 159 } 160 161 // Test getting a non-existent property 162 _, err = GetStructPropertyAsString(&person, "NonExistent") 163 if err == nil { 164 t.Errorf("Expected an error for getting a non-existent property") 165 } 166 167 // Test getting a property from a nil pointer (should return an error) 168 var nilPointer *Person 169 _, err = GetStructPropertyAsString(nilPointer, "NAME") 170 if err == nil { 171 t.Errorf("Expected an error for getting a property from a nil pointer") 172 } 173 } 174 175 func TestCopyObject(t *testing.T) { 176 type Person struct { 177 Name string 178 Age int 179 Address string 180 } 181 182 tests := []struct { 183 name string 184 src interface{} 185 }{ 186 { 187 name: "Copy Person Struct", 188 src: &Person{Name: "John", Age: 30, Address: "123 Main St"}, 189 }, 190 { 191 name: "Copy Empty Struct", 192 src: &struct{}{}, 193 }, 194 { 195 name: "Copy Struct with Different Field Types", 196 src: &struct { 197 Name string 198 Age int 199 Score float64 200 }{Name: "Alice", Age: 25, Score: 98.5}, 201 }, 202 } 203 204 for _, tt := range tests { 205 t.Run(tt.name, func(t *testing.T) { 206 dest, err := CopyObject(tt.src) 207 if err != nil { 208 t.Errorf("Error copying object: %v", err) 209 } 210 211 // Check if the source and destination objects have the same type. 212 if reflect.TypeOf(tt.src) != reflect.TypeOf(dest) { 213 t.Errorf("Expected source and destination types to be the same, but got different types.") 214 } 215 216 // Check if the source and destination objects have the same field values. 217 srcValue := reflect.ValueOf(tt.src).Elem() 218 destValue := reflect.ValueOf(dest).Elem() 219 220 for i := 0; i < srcValue.NumField(); i++ { 221 srcField := srcValue.Field(i) 222 destField := destValue.Field(i) 223 224 if !reflect.DeepEqual(srcField.Interface(), destField.Interface()) { 225 t.Errorf("Field %s mismatch between source and destination: expected %v, got %v", 226 srcValue.Type().Field(i).Name, srcField.Interface(), destField.Interface()) 227 } 228 } 229 }) 230 } 231 } 232 233 func TestCopySliceOfPointers(t *testing.T) { 234 // Define a sample struct type. 235 type SampleStruct struct { 236 ID int 237 Name string 238 } 239 240 // Create a sample slice of struct pointers. 241 sourceSlice := []*SampleStruct{ 242 &SampleStruct{1, "Alice"}, 243 &SampleStruct{2, "Bob"}, 244 &SampleStruct{3, "Charlie"}, 245 } 246 247 // Call the function to copy the slice. 248 result, err := CopySliceOfPointers(sourceSlice) 249 250 // Check for errors. 251 if err != nil { 252 t.Errorf("CopySliceOfPointers returned an error: %v", err) 253 } 254 255 // Check the type of the result. 256 resultValue := reflect.ValueOf(result) 257 if resultValue.Kind() != reflect.Slice { 258 t.Errorf("Result is not a slice") 259 } 260 261 // Check the length of the result slice. 262 if resultValue.Len() != len(sourceSlice) { 263 t.Errorf("Result slice has unexpected length") 264 } 265 266 // Check the type and content of each element in the result slice. 267 for i := 0; i < resultValue.Len(); i++ { 268 resultElem := resultValue.Index(i) 269 sourceElem := reflect.ValueOf(sourceSlice[i]) 270 271 // Check that the element is a pointer to a struct. 272 if resultElem.Kind() != reflect.Ptr || resultElem.Elem().Kind() != reflect.Struct { 273 t.Errorf("Element at index %d is not a struct pointer", i) 274 } 275 276 // Check that the element has the same type as the source element. 277 if resultElem.Elem().Type() != sourceElem.Elem().Type() { 278 t.Errorf("Element at index %d has a different type from the source", i) 279 } 280 281 // Check that the element's field values match the source element. 282 if !reflect.DeepEqual(resultElem.Elem().Interface(), sourceElem.Elem().Interface()) { 283 t.Errorf("Element at index %d does not match the source", i) 284 } 285 } 286 } 287 288 func TestCopySliceOfPointersWithIdentitySeparated(t *testing.T) { 289 type PersonStruct struct { 290 ID int 291 Name string 292 } 293 294 // Sample data 295 sourceSlice := []*PersonStruct{ 296 {ID: 1, Name: "One"}, 297 {ID: 2, Name: "Two"}, 298 {ID: 3, Name: "Three"}, 299 } 300 301 // Call the function 302 result, err := CopySliceOfPointersWithIdentitySeparated(sourceSlice, cast.StructPointerArrayToInterfacePointerArray(sourceSlice)) 303 if err != nil { 304 t.Fatalf("Unexpected error: %v", err) 305 } 306 307 // Check if the result is a slice 308 resultValue := reflect.ValueOf(result) 309 if resultValue.Kind() != reflect.Slice { 310 t.Errorf("Expected result to be a slice, got %v", resultValue.Kind()) 311 } 312 313 // Check if the length of the result is the same as the sourceSlice 314 if resultValue.Len() != len(sourceSlice) { 315 t.Errorf("Expected result length %d, got %d", len(sourceSlice), resultValue.Len()) 316 } 317 318 // Check if the elements in the result have the same identity as the sourceSlice 319 for i := 0; i < resultValue.Len(); i++ { 320 resultElement := resultValue.Index(i).Interface().(*PersonStruct) 321 sourceElement := sourceSlice[i] 322 323 // Compare fields or use a custom equality check based on your requirements 324 if !reflect.DeepEqual(resultElement, sourceElement) { 325 t.Errorf("Expected element %v, got %v", sourceElement, resultElement) 326 } 327 } 328 } 329 330 func TestAreAllNumbers(t *testing.T) { 331 tests := []struct { 332 name string 333 input []interface{} 334 expected bool 335 }{ 336 {"AllNumbers", []interface{}{1, 2, 3, 4}, true}, 337 {"MixedTypes", []interface{}{1, 2, "hello", 4}, false}, 338 {"EmptySlice", []interface{}{}, true}, // Empty slice is considered valid 339 } 340 341 for _, tt := range tests { 342 t.Run(tt.name, func(t *testing.T) { 343 got := AreAllNumbers(tt.input) 344 if got != tt.expected { 345 t.Errorf("AreAllNumbers(%v) = %v; want %v", tt.input, got, tt.expected) 346 } 347 }) 348 } 349 } 350 351 func TestStringJoin(t *testing.T) { 352 tests := []struct { 353 name string 354 inputArr []interface{} 355 encapsulation string 356 expected string 357 }{ 358 {"JoinStrings", []interface{}{"hello", "world"}, "'", "'hello','world'"}, 359 {"JoinNumbers", []interface{}{1, 2, 3}, "", "1,2,3"}, 360 {"JoinMixedTypes", []interface{}{"hello", 2, "world"}, "\"", "\"hello\",\"2\",\"world\""}, 361 } 362 363 for _, tt := range tests { 364 t.Run(tt.name, func(t *testing.T) { 365 got := StringJoin(tt.inputArr, tt.encapsulation) 366 if got != tt.expected { 367 t.Errorf("StringJoin(%v, %q) = %q; want %q", tt.inputArr, tt.encapsulation, got, tt.expected) 368 } 369 }) 370 } 371 } 372 373 func TestUpdatePropertyValue(t *testing.T) { 374 // Define a struct for testing 375 type TestStruct struct { 376 ID int 377 Name string 378 } 379 380 // Create an instance of TestStruct 381 obj := &TestStruct{ID: 1, Name: "John"} 382 383 // Define the property name and the new value 384 propertyName := "ID" 385 newValue := 2 386 387 // Call the function to update the property 388 err := UpdatePropertyValue(obj, propertyName, newValue) 389 if err != nil { 390 t.Errorf("UpdateIDProperty returned an error: %v", err) 391 } 392 393 // Check if the ID property was updated correctly 394 if obj.ID != newValue { 395 t.Errorf("ID property was not updated to the expected value. Expected: %d, Got: %d", newValue, obj.ID) 396 } 397 398 // Check if the Name property remains unchanged 399 expectedName := "John" 400 if obj.Name != expectedName { 401 t.Errorf("Name property was unexpectedly changed. Expected: %s, Got: %s", expectedName, obj.Name) 402 } 403 404 // Test with an invalid property name 405 invalidPropertyName := "Age" 406 invalidValue := 30 407 err = UpdatePropertyValue(obj, invalidPropertyName, invalidValue) 408 if err == nil { 409 t.Errorf("UpdateIDProperty did not return an error for an invalid property name") 410 } else { 411 // expectedErrorMessage := fmt.Sprintf("struct does not have an '%s' field", invalidPropertyName) 412 if err.Error() != ErrPropertyNotFound.Error() { 413 t.Errorf("UpdateIDProperty returned an unexpected error message. Expected: %s, Got: %s", ErrPropertyNotFound.Error(), err.Error()) 414 } 415 } 416 417 // Test with a newValue of a different type 418 invalidNewValue := "Invalid" 419 err = UpdatePropertyValue(obj, propertyName, invalidNewValue) 420 if err == nil { 421 t.Errorf("UpdateIDProperty did not return an error for an invalid newValue type") 422 } else { 423 // expectedErrorMessage := fmt.Sprintf("newValue must have the same type as the '%s' field", propertyName) 424 if err.Error() != ErrPropertyTypeNotMatch.Error() { 425 t.Errorf("UpdateIDProperty returned an unexpected error message. Expected: %s, Got: %s", ErrPropertyTypeNotMatch.Error(), err.Error()) 426 } 427 } 428 } 429 430 func TestAreAllUUIDs(t *testing.T) { 431 tests := []struct { 432 name string 433 input []interface{} 434 expected bool 435 }{ 436 {"AllUUIDs", []interface{}{uuid.New(), uuid.New(), uuid.New(), uuid.New()}, true}, 437 {"MixedTypes", []interface{}{1, 2, "hello", uuid.New()}, false}, 438 {"EmptySlice", []interface{}{}, true}, // Empty slice is considered valid 439 } 440 441 for _, tt := range tests { 442 t.Run(tt.name, func(t *testing.T) { 443 got := AreAllUUIDs(tt.input) 444 if got != tt.expected { 445 t.Errorf("AreAllUUIDs(%v) = %v; want %v", tt.input, got, tt.expected) 446 } 447 }) 448 } 449 }