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  }