github.com/angryronald/go-kit@v0.0.0-20240505173814-ff2bd9c79dbf/generic/repository/nosql/repositorytest/generic.repository_test.go (about)

     1  package repositorytest
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"strings"
     8  	"sync"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/google/uuid"
    13  
    14  	"github.com/angryronald/go-kit/cast"
    15  	"github.com/angryronald/go-kit/generic/repository"
    16  	"github.com/angryronald/go-kit/generic/repository/nosql"
    17  )
    18  
    19  var TEST_ID = uuid.MustParse("25ebc2e2-7fd2-47a0-bd2f-a8ec6e4d0163")
    20  
    21  var sample *TestModel
    22  var mutex sync.Mutex
    23  var isDone bool
    24  var keySpace string
    25  
    26  func init() {
    27  	keySpace = "example"
    28  	isDone = false
    29  	sample = &TestModel{
    30  		ID:        TEST_ID,
    31  		Text:      "text",
    32  		CreatedAt: time.Now().UTC(),
    33  		CreatedBy: uuid.Nil,
    34  		UpdatedAt: time.Now().UTC(),
    35  		UpdatedBy: uuid.Nil,
    36  	}
    37  }
    38  
    39  func preSeeding() {
    40  	mutex.Lock()
    41  	if !isDone {
    42  		// tableName := repository.GetTableName(sample)
    43  		// query := fmt.Sprintf("INSERT INTO %s ?", tableName)
    44  		// if err := db.Query(query, sample).Exec(); err != nil {
    45  		// 	log.Fatalf("failed to inject data: %v", err)
    46  		// }
    47  		tableName := repository.GetTableName(sample)
    48  		columns, values, err := nosql.GetPropertyNamesAndValues(sample)
    49  		if err != nil {
    50  			log.Fatalf("failed to inject data: %v", err)
    51  		}
    52  		paramString := ""
    53  		for i := 0; i < len(values); i++ {
    54  			paramString += "?,"
    55  		}
    56  
    57  		if len(paramString) > 0 {
    58  			paramString = paramString[:len(paramString)-1]
    59  		}
    60  
    61  		query := fmt.Sprintf("INSERT INTO %s.%s (%s) VALUES (%s)", keySpace, tableName, strings.Join(columns, ","), paramString)
    62  		if err = db.Query(query, values...).Exec(); err != nil {
    63  			log.Fatalf("failed to inject data: %v", err)
    64  		}
    65  		isDone = true
    66  	}
    67  	mutex.Unlock()
    68  }
    69  
    70  func insert(data *TestModel) {
    71  	tableName := repository.GetTableName(data)
    72  	columns, values, err := nosql.GetPropertyNamesAndValues(data)
    73  	if err != nil {
    74  		log.Fatalf("failed to inject data: %v", err)
    75  	}
    76  	paramString := ""
    77  	for i := 0; i < len(values); i++ {
    78  		paramString += "?,"
    79  	}
    80  
    81  	if len(paramString) > 0 {
    82  		paramString = paramString[:len(paramString)-1]
    83  	}
    84  
    85  	query := fmt.Sprintf("INSERT INTO %s.%s (%s) VALUES (%s)", keySpace, tableName, strings.Join(columns, ","), paramString)
    86  	if err = db.Query(query, values...).Exec(); err != nil {
    87  		log.Fatalf("failed to inject data: %v", err)
    88  	}
    89  }
    90  
    91  // func removePreseeding() {
    92  // 	mutex.Lock()
    93  // 	if isDone {
    94  // 		if err := db.Delete(sample).Error; err != nil {
    95  // 			logrus.Debugf("failed to remove seed data: %v", err)
    96  // 		}
    97  // 		isDone = false
    98  // 	}
    99  // 	mutex.Unlock()
   100  // }
   101  
   102  func TestGenericRepository_FindAll(t *testing.T) {
   103  	repo := nosql.NewRepository(db, keySpace)
   104  
   105  	ctx := context.Background()
   106  	params := map[string]interface{}{"text": "text"}
   107  	conditionalOperations := []repository.ConditionalOperation{repository.EQUAL_WITH}
   108  	page := 1
   109  	limit := 10
   110  
   111  	preSeeding()
   112  	// defer removePreseeding()
   113  
   114  	resultsRaw, err := repo.FindAll(ctx, params, conditionalOperations, nil, page, limit, []*TestModel{})
   115  	if err != nil {
   116  		t.Fatalf("Error in FindAll: %v", err)
   117  	}
   118  
   119  	/*
   120  		alternative casting:
   121  		results := []*TestModel{}
   122  		cast.TransformObject(resultsRaw, &results)
   123  	*/
   124  	// results := resultsRaw.([]*TestModel)
   125  	results := []*TestModel{}
   126  	cast.TransformObject(resultsRaw, &results)
   127  	if len(results) == 0 {
   128  		t.Fatalf("Expected not 0 result, but got %d", len(results))
   129  	}
   130  }
   131  
   132  func TestGenericRepository_FindAll_WithComplexQuery(t *testing.T) {
   133  	repo := nosql.NewRepository(db, keySpace)
   134  	ctx := context.Background()
   135  
   136  	preSeeding()
   137  	// // defer removePreseeding()
   138  
   139  	testCases := []struct {
   140  		name                  string
   141  		params                map[string]interface{}
   142  		conditionalOperations []repository.ConditionalOperation
   143  		page                  int
   144  		limit                 int
   145  		expectedResultCount   int
   146  		expectedError         error
   147  	}{
   148  		{
   149  			name:                  "FindAll with IN Query",
   150  			params:                map[string]interface{}{"id": []interface{}{TEST_ID}},
   151  			conditionalOperations: []repository.ConditionalOperation{repository.IN},
   152  			page:                  1,
   153  			limit:                 10,
   154  			expectedResultCount:   1,
   155  			expectedError:         nil,
   156  		},
   157  		{
   158  			name:                  "FindAll with ILIKE Query",
   159  			params:                map[string]interface{}{"text": "ex"},
   160  			conditionalOperations: []repository.ConditionalOperation{repository.ILIKE},
   161  			page:                  1,
   162  			limit:                 10,
   163  			expectedResultCount:   0,
   164  			expectedError:         repository.ErrNotImplement,
   165  		},
   166  	}
   167  
   168  	for _, test := range testCases {
   169  		t.Run(test.name, func(t *testing.T) {
   170  			resultsRaw, err := repo.FindAll(ctx, test.params, test.conditionalOperations, nil, test.page, test.limit, []*TestModel{})
   171  			if err != test.expectedError {
   172  				t.Fatalf("Expected %v, but got %v", test.expectedError, err)
   173  			}
   174  
   175  			/*
   176  				alternative casting:
   177  				results := []*TestModel{}
   178  				cast.TransformObject(resultsRaw, &results)
   179  			*/
   180  			// results := resultsRaw.([]*TestModel)
   181  			results := []*TestModel{}
   182  			cast.TransformObject(resultsRaw, &results)
   183  			if len(results) != test.expectedResultCount {
   184  				t.Fatalf("Expected %d result, but got %d", test.expectedResultCount, len(results))
   185  			}
   186  		})
   187  	}
   188  }
   189  
   190  func TestGenericRepository_FindAll_WithRelationalOperation(t *testing.T) {
   191  	repo := nosql.NewRepository(db, keySpace)
   192  
   193  	ctx := context.Background()
   194  	params := map[string]interface{}{
   195  		"text": "text",
   196  		"id":   TEST_ID.String(),
   197  	}
   198  	conditionalOperations := []repository.ConditionalOperation{repository.EQUAL_WITH, repository.EQUAL_WITH}
   199  	relationalOperations := []repository.RelationalOperation{repository.AND}
   200  	page := 1
   201  	limit := 10
   202  
   203  	preSeeding()
   204  	// defer removePreseeding()
   205  
   206  	resultsRaw, err := repo.FindAll(ctx, params, conditionalOperations, relationalOperations, page, limit, []*TestModel{})
   207  	if err != nil {
   208  		t.Fatalf("Error in FindAll: %v", err)
   209  	}
   210  
   211  	/*
   212  		alternative casting:
   213  		results := []*TestModel{}
   214  		cast.TransformObject(resultsRaw, &results)
   215  	*/
   216  	// results := resultsRaw.([]*TestModel)
   217  	results := []*TestModel{}
   218  	cast.TransformObject(resultsRaw, &results)
   219  	if len(results) != 1 {
   220  		t.Fatalf("Expected 1 result, but got %d", len(results))
   221  	}
   222  }
   223  
   224  func TestGenericRepository_FindOne(t *testing.T) {
   225  	repo := nosql.NewRepository(db, keySpace)
   226  
   227  	ctx := context.Background()
   228  	key := "text"
   229  	value := "unique text4"
   230  
   231  	id, _ := uuid.NewRandom()
   232  	data := &TestModel{
   233  		ID:        id,
   234  		Text:      "unique text4",
   235  		CreatedAt: time.Now().UTC(),
   236  		CreatedBy: uuid.Nil,
   237  		UpdatedAt: time.Now().UTC(),
   238  		UpdatedBy: uuid.Nil,
   239  	}
   240  
   241  	insert(data)
   242  
   243  	result := &TestModel{}
   244  	_, err := repo.FindOne(ctx, key, value, result)
   245  	if err != nil {
   246  		t.Fatalf("Error in FindOne: %v", err)
   247  	}
   248  
   249  	if result.ID != data.ID || result.Text != data.Text {
   250  		t.Fatalf("Unexpected result: %+v", result)
   251  	}
   252  }
   253  
   254  func TestGenericRepository_FindByID(t *testing.T) {
   255  	repo := nosql.NewRepository(db, keySpace)
   256  
   257  	id := uuid.New()
   258  	data := sample
   259  	data.ID = id
   260  	data.Text = "test"
   261  
   262  	insert(data)
   263  	// defer removePreseeding()
   264  
   265  	ctx := context.Background()
   266  	result := &TestModel{}
   267  	_, err := repo.FindByID(ctx, id, result)
   268  	if err != nil {
   269  		t.Fatalf("Error in FindByID: %v", err)
   270  	}
   271  
   272  	if result.ID != id || result.Text != sample.Text {
   273  		t.Fatalf("Unexpected result: %+v", result)
   274  	}
   275  }
   276  
   277  func TestGenericRepository_Insert(t *testing.T) {
   278  	repo := nosql.NewRepository(db, keySpace)
   279  
   280  	ctx := context.Background()
   281  	id, _ := uuid.NewRandom()
   282  	data := &TestModel{
   283  		ID:        id,
   284  		Text:      "test insert",
   285  		CreatedAt: time.Now().UTC(),
   286  		CreatedBy: uuid.Nil,
   287  		UpdatedAt: time.Now().UTC(),
   288  		UpdatedBy: uuid.Nil,
   289  	}
   290  
   291  	result, err := repo.Insert(ctx, data)
   292  	if err != nil {
   293  		t.Fatalf("Error in Insert: %v", err)
   294  	}
   295  
   296  	if result.(*TestModel) == nil {
   297  		t.Fatalf("Unexpected result: %+v", result)
   298  	}
   299  }
   300  
   301  func TestGenericRepository_Update(t *testing.T) {
   302  	repo := nosql.NewRepository(db, keySpace)
   303  
   304  	ctx := context.Background()
   305  
   306  	preSeeding()
   307  	// defer removePreseeding()
   308  
   309  	data := sample
   310  	data.Text = "updated text"
   311  
   312  	result, err := repo.Update(ctx, data)
   313  	if err != nil {
   314  		t.Fatalf("Error in Update: %v", err)
   315  	}
   316  
   317  	if result.(*TestModel).ID != TEST_ID {
   318  		t.Fatalf("Unexpected result: %+v", result)
   319  	}
   320  }
   321  
   322  func TestGenericRepository_Update_DataDeleted_ErrNotFound(t *testing.T) {
   323  	repo := nosql.NewRepository(db, keySpace)
   324  
   325  	ctx := context.Background()
   326  
   327  	data := sample
   328  	data.ID = uuid.New()
   329  	data.Text = "updated text"
   330  
   331  	_, err := repo.Update(ctx, data)
   332  	if err != repository.ErrNotFound {
   333  		t.Fatalf("expected %v, got %v", repository.ErrNotFound, err)
   334  	}
   335  }
   336  
   337  func TestGenericRepository_Delete(t *testing.T) {
   338  	repo := nosql.NewRepository(db, keySpace)
   339  
   340  	ctx := context.Background()
   341  
   342  	id, _ := uuid.NewRandom()
   343  	data := &TestModel{
   344  		ID:        id,
   345  		Text:      "test insert",
   346  		CreatedAt: time.Now().UTC(),
   347  		CreatedBy: uuid.Nil,
   348  		UpdatedAt: time.Now().UTC(),
   349  		UpdatedBy: uuid.Nil,
   350  	}
   351  
   352  	insert(data)
   353  
   354  	_, err := repo.Delete(ctx, data)
   355  	if err != nil {
   356  		t.Fatalf("Error in Delete: %v", err)
   357  	}
   358  }
   359  
   360  func TestGenericRepository_Upsert(t *testing.T) {
   361  	repo := nosql.NewRepository(db, keySpace)
   362  
   363  	ctx := context.Background()
   364  	data := sample
   365  
   366  	result, err := repo.Upsert(ctx, data)
   367  
   368  	if result != nil {
   369  		t.Errorf("expected %v, got %v", nil, result)
   370  	}
   371  	if err != repository.ErrNotImplement {
   372  		t.Errorf("expected %v, got %v", repository.ErrNotImplement, err)
   373  	}
   374  }
   375  
   376  func TestGenericRepository_BulkInsert(t *testing.T) {
   377  	id, _ := uuid.NewRandom()
   378  	secondId, _ := uuid.NewRandom()
   379  	sample.ID = secondId
   380  	data := []*TestModel{
   381  		sample,
   382  		&TestModel{
   383  			ID:        id,
   384  			Text:      "test bulk insert",
   385  			CreatedAt: time.Now().UTC(),
   386  			CreatedBy: uuid.Nil,
   387  			UpdatedAt: time.Now().UTC(),
   388  			UpdatedBy: uuid.Nil,
   389  		},
   390  	}
   391  
   392  	repo := nosql.NewRepository(db, keySpace)
   393  
   394  	ctx := context.Background()
   395  
   396  	resultsRaw, err := repo.BulkInsert(ctx, data)
   397  
   398  	if resultsRaw != nil {
   399  		t.Errorf("expected %v, got %v", nil, resultsRaw)
   400  	}
   401  	if err != repository.ErrNotImplement {
   402  		t.Errorf("expected %v, got %v", repository.ErrNotImplement, err)
   403  	}
   404  }
   405  
   406  func TestGenericRepository_BulkUpsert(t *testing.T) {
   407  	repo := nosql.NewRepository(db, keySpace)
   408  
   409  	preSeeding()
   410  	// defer removePreseeding()
   411  
   412  	one := sample
   413  	one.Text = "updated text"
   414  	id, _ := uuid.NewRandom()
   415  	data := []*TestModel{
   416  		one,
   417  		&TestModel{
   418  			ID:        id,
   419  			Text:      "test bulk insert",
   420  			CreatedAt: time.Now().UTC(),
   421  			CreatedBy: uuid.Nil,
   422  			UpdatedAt: time.Now().UTC(),
   423  			UpdatedBy: uuid.Nil,
   424  		},
   425  	}
   426  
   427  	ctx := context.Background()
   428  
   429  	resultsRaw, err := repo.BulkUpsert(ctx, data)
   430  
   431  	if resultsRaw != nil {
   432  		t.Errorf("expected %v, got %v", nil, resultsRaw)
   433  	}
   434  	if err != repository.ErrNotImplement {
   435  		t.Errorf("expected %v, got %v", repository.ErrNotImplement, err)
   436  	}
   437  }
   438  
   439  func TestGenericRepository_Query(t *testing.T) {
   440  	repo := nosql.NewRepository(db, keySpace)
   441  
   442  	ctx := context.Background()
   443  	id, _ := uuid.NewRandom()
   444  	params := []interface{}{
   445  		"text",
   446  		id.String(),
   447  	}
   448  
   449  	data := &TestModel{
   450  		ID:        id,
   451  		Text:      "text",
   452  		CreatedAt: time.Now().UTC(),
   453  		CreatedBy: uuid.Nil,
   454  		UpdatedAt: time.Now().UTC(),
   455  		UpdatedBy: uuid.Nil,
   456  	}
   457  
   458  	insert(data)
   459  
   460  	result := []*TestModel{}
   461  	resultsRaw, err := repo.Query(
   462  		ctx,
   463  		fmt.Sprintf(`SELECT * FROM %s.%s WHERE text = ? AND id = ? ALLOW FILTERING;`, keySpace, repository.GetTableName(&TestModel{})),
   464  		params,
   465  		result,
   466  	)
   467  	if err != nil {
   468  		t.Fatalf("Error in Query: %v", err)
   469  	}
   470  
   471  	/*
   472  		alternative casting:
   473  		results := []*TestModel{}
   474  		cast.TransformObject(resultsRaw, &results)
   475  	*/
   476  	// results := resultsRaw.([]*TestModel)
   477  
   478  	results := []*TestModel{}
   479  	cast.TransformObject(resultsRaw, &results)
   480  	if len(results) != 1 {
   481  		t.Fatalf("Expected 1 result, but got %d", len(results))
   482  	}
   483  }
   484  
   485  func TestGenericRepository_Query_DELETE(t *testing.T) {
   486  	repo := nosql.NewRepository(db, keySpace)
   487  
   488  	ctx := context.Background()
   489  	id, _ := uuid.NewRandom()
   490  	params := []interface{}{
   491  		time.Now().UTC(),
   492  	}
   493  
   494  	data := &TestModel{
   495  		ID:        id,
   496  		Text:      "test insert",
   497  		CreatedAt: time.Now().UTC(),
   498  		CreatedBy: uuid.Nil,
   499  		UpdatedAt: time.Now().UTC(),
   500  		UpdatedBy: uuid.Nil,
   501  	}
   502  
   503  	insert(data)
   504  
   505  	result := []*TestModel{}
   506  	if _, err := repo.Query(
   507  		ctx,
   508  		fmt.Sprintf(`DELETE FROM %s WHERE createdat < ? ALLOW FILTERING;`, repository.GetTableName(&TestModel{})),
   509  		params,
   510  		result,
   511  	); err != nil {
   512  		t.Fatalf("Error in Query: %v", err)
   513  	}
   514  
   515  	if _, err := repo.FindByID(ctx, id, result); err != nil && err != repository.ErrNotFound {
   516  		t.Fatalf("expected %v, got %v", repository.ErrNotFound, err)
   517  	}
   518  }