diff --git a/pkg/duplicatechecker/in_memory_duplicate_checker_test.go b/pkg/duplicatechecker/in_memory_duplicate_checker_test.go new file mode 100644 index 00000000..41767947 --- /dev/null +++ b/pkg/duplicatechecker/in_memory_duplicate_checker_test.go @@ -0,0 +1,157 @@ +package duplicatechecker + +import ( + "fmt" + "sync" + "sync/atomic" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/mayswind/ezbookkeeping/pkg/settings" + "github.com/mayswind/ezbookkeeping/pkg/utils" +) + +func TestSetAndGetSubmissionRemark(t *testing.T) { + checker, _ := NewInMemoryDuplicateChecker(&settings.Config{ + DuplicateSubmissionsIntervalDuration: 100 * time.Second, + InMemoryDuplicateCheckerCleanupIntervalDuration: 100 * time.Second, + }) + + uid := int64(1234567890) + id := "2345678901" + expectedRemark := "0123456789" + + checker.SetSubmissionRemark(DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, uid, id, expectedRemark) + found, actualRemark := checker.GetSubmissionRemark(DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, uid, id) + assert.Equal(t, true, found) + assert.Equal(t, expectedRemark, actualRemark) +} + +func TestSetAndGetNotExistedSubmissionRemark(t *testing.T) { + checker, _ := NewInMemoryDuplicateChecker(&settings.Config{ + DuplicateSubmissionsIntervalDuration: 100 * time.Second, + InMemoryDuplicateCheckerCleanupIntervalDuration: 100 * time.Second, + }) + + uid := int64(1234567890) + id := "2345678901" + expectedRemark := "0123456789" + + checker.SetSubmissionRemark(DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, uid, id, expectedRemark) + found, actualRemark := checker.GetSubmissionRemark(DUPLICATE_CHECKER_TYPE_NEW_ACCOUNT, uid, id) + assert.Equal(t, false, found) + assert.Equal(t, "", actualRemark) + + found, actualRemark = checker.GetSubmissionRemark(DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, uid, "") + assert.Equal(t, false, found) + assert.Equal(t, "", actualRemark) + + found, actualRemark = checker.GetSubmissionRemark(DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, uid, "2345678900") + assert.Equal(t, false, found) + assert.Equal(t, "", actualRemark) + + found, actualRemark = checker.GetSubmissionRemark(DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, int64(123456791), "") + assert.Equal(t, false, found) + assert.Equal(t, "", actualRemark) +} + +func TestSetAndGetExpiredSubmissionRemark(t *testing.T) { + checker, _ := NewInMemoryDuplicateChecker(&settings.Config{ + DuplicateSubmissionsIntervalDuration: time.Second, + InMemoryDuplicateCheckerCleanupIntervalDuration: time.Second, + }) + + uid := int64(1234567890) + id := "2345678901" + expectedRemark := "0123456789" + + checker.SetSubmissionRemark(DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, uid, id, expectedRemark) + time.Sleep(time.Second * 2) + + found, actualRemark := checker.GetSubmissionRemark(DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION, uid, id) + assert.Equal(t, false, found) + assert.Equal(t, "", actualRemark) +} + +func TestGetOrSetCronJobRunningInfo(t *testing.T) { + checker, _ := NewInMemoryDuplicateChecker(&settings.Config{ + DuplicateSubmissionsIntervalDuration: time.Second, + InMemoryDuplicateCheckerCleanupIntervalDuration: time.Second, + }) + + jobName := "foo" + expectedRunningInfo := "bar" + + found, actualRunningInfo := checker.GetOrSetCronJobRunningInfo(jobName, expectedRunningInfo, 100*time.Second) + assert.Equal(t, false, found) + assert.Equal(t, "", actualRunningInfo) + + found, actualRunningInfo = checker.GetOrSetCronJobRunningInfo(jobName, expectedRunningInfo, 100*time.Second) + assert.Equal(t, true, found) + assert.Equal(t, expectedRunningInfo, actualRunningInfo) + + checker.RemoveCronJobRunningInfo(jobName) + + found, actualRunningInfo = checker.GetOrSetCronJobRunningInfo(jobName, expectedRunningInfo, 100*time.Second) + assert.Equal(t, false, found) + assert.Equal(t, "", actualRunningInfo) +} + +func TestGetNotExistedRunningInfo(t *testing.T) { + checker, _ := NewInMemoryDuplicateChecker(&settings.Config{ + DuplicateSubmissionsIntervalDuration: time.Second, + InMemoryDuplicateCheckerCleanupIntervalDuration: time.Second, + }) + + jobName := "foo" + expectedRunningInfo := "bar" + + found, actualRunningInfo := checker.GetOrSetCronJobRunningInfo(jobName, expectedRunningInfo, 100*time.Second) + assert.Equal(t, false, found) + assert.Equal(t, "", actualRunningInfo) + + found, actualRunningInfo = checker.GetOrSetCronJobRunningInfo("bar", expectedRunningInfo, 100*time.Second) + assert.Equal(t, false, found) + assert.Equal(t, "", actualRunningInfo) +} + +func TestGetOrSetRunningInfoConcurrent(t *testing.T) { + checker, _ := NewInMemoryDuplicateChecker(&settings.Config{ + DuplicateSubmissionsIntervalDuration: time.Second, + InMemoryDuplicateCheckerCleanupIntervalDuration: time.Second, + }) + + jobName := "foo" + + concurrentCount := 10 + var setRunningInfoCount atomic.Uint32 + var waitGroup sync.WaitGroup + + for routineIndex := 0; routineIndex < concurrentCount; routineIndex++ { + waitGroup.Add(1) + + go func(currentRoutineIndex int) { + randomNumber, _ := utils.GetRandomInteger(10) + time.Sleep(time.Duration(int64(randomNumber) * int64(time.Millisecond))) + + for cycle := 0; cycle < 100; cycle++ { + expectedRunningInfo := fmt.Sprintf("%d-%d", currentRoutineIndex, cycle) + found, _ := checker.GetOrSetCronJobRunningInfo(jobName, expectedRunningInfo, 100*time.Second) + + if found { + setRunningInfoCount.Add(1) + } else { + fmt.Printf("routine#%d set cron job running info %s\n", currentRoutineIndex, expectedRunningInfo) + } + } + + waitGroup.Done() + }(routineIndex) + } + + waitGroup.Wait() + + assert.Equal(t, uint32(999), setRunningInfoCount.Load()) +} diff --git a/pkg/errs/error_test.go b/pkg/errs/error_test.go new file mode 100644 index 00000000..c145fb39 --- /dev/null +++ b/pkg/errs/error_test.go @@ -0,0 +1,26 @@ +package errs + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMultiError(t *testing.T) { + err1 := errors.New("error1 message") + err2 := errors.New("error2 message") + err := NewMultiErrorOrNil(err1, err2) + assert.Equal(t, "multi errors: error1 message, error2 message", err.Error()) +} + +func TestNewMultiErrorOrNilWithOnlyOneParamerter(t *testing.T) { + err1 := errors.New("error1 message") + err := NewMultiErrorOrNil(err1) + assert.Equal(t, err1, err) +} + +func TestNewMultiErrorOrNilWithoutOneParamerter(t *testing.T) { + err := NewMultiErrorOrNil() + assert.Nil(t, err) +} diff --git a/pkg/validators/amount_filter_test.go b/pkg/validators/amount_filter_test.go new file mode 100644 index 00000000..e701200d --- /dev/null +++ b/pkg/validators/amount_filter_test.go @@ -0,0 +1,151 @@ +package validators + +import ( + "testing" + + "github.com/go-playground/validator/v10" + "github.com/stretchr/testify/assert" +) + +func TestEmptyAmount(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("validAmountFilter", ValidAmountFilter) + assert.Nil(t, err) + + err = validate.Var("", "validAmountFilter") + assert.Nil(t, err) +} + +func TestValidOneParameterAmount(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("validAmountFilter", ValidAmountFilter) + assert.Nil(t, err) + + for _, filterType := range []string{"gt", "lt", "eq", "ne"} { + err = validate.Var(filterType+":0", "validAmountFilter") + assert.Nil(t, err) + + err = validate.Var(filterType+":1", "validAmountFilter") + assert.Nil(t, err) + + err = validate.Var(filterType+":-1", "validAmountFilter") + assert.Nil(t, err) + + err = validate.Var(filterType+":1073741824", "validAmountFilter") + assert.Nil(t, err) + + err = validate.Var(filterType+":-2147483648", "validAmountFilter") + assert.Nil(t, err) + } +} + +func TestInvalidOneParameterAmount(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("validAmountFilter", ValidAmountFilter) + assert.Nil(t, err) + + for _, filterType := range []string{"gt", "lt", "eq", "ne"} { + err = validate.Var(filterType, "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+": ", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":-", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":a", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":-a", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":1.1", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":-1.1", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":1:2", "validAmountFilter") + assert.NotNil(t, err) + } +} + +func TestValidTwoParameterAmount(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("validAmountFilter", ValidAmountFilter) + assert.Nil(t, err) + + for _, filterType := range []string{"bt", "nb"} { + err = validate.Var(filterType+":0:0", "validAmountFilter") + assert.Nil(t, err) + + err = validate.Var(filterType+":1:1", "validAmountFilter") + assert.Nil(t, err) + + err = validate.Var(filterType+":0:1", "validAmountFilter") + assert.Nil(t, err) + + err = validate.Var(filterType+":-1:-1", "validAmountFilter") + assert.Nil(t, err) + + err = validate.Var(filterType+":-1:0", "validAmountFilter") + assert.Nil(t, err) + + err = validate.Var(filterType+":-2147483648:1073741824", "validAmountFilter") + assert.Nil(t, err) + } +} + +func TestInvalidTwoParameterAmount(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("validAmountFilter", ValidAmountFilter) + assert.Nil(t, err) + + for _, filterType := range []string{"bt", "nb"} { + err = validate.Var(filterType+":", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+"::", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":1", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":1:", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+"::1", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":-:-", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":a:b", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":-a:-b", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":1.1:1.2", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":-1.2:-1.1", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":1:0", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":0:-1", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":1073741824:-2147483648", "validAmountFilter") + assert.NotNil(t, err) + + err = validate.Var(filterType+":1:2:3", "validAmountFilter") + assert.NotNil(t, err) + } +} diff --git a/pkg/validators/currency_test.go b/pkg/validators/currency_test.go new file mode 100644 index 00000000..2d9981f1 --- /dev/null +++ b/pkg/validators/currency_test.go @@ -0,0 +1,41 @@ +package validators + +import ( + "testing" + + "github.com/go-playground/validator/v10" + "github.com/stretchr/testify/assert" +) + +func TestValidCurrency(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("validCurrency", ValidCurrency) + assert.Nil(t, err) + + err = validate.Var("CNY", "validCurrency") + assert.Nil(t, err) + + err = validate.Var("USD", "validCurrency") + assert.Nil(t, err) + + err = validate.Var("---", "validCurrency") + assert.Nil(t, err) +} + +func TestInvalidCurrency(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("validCurrency", ValidCurrency) + assert.Nil(t, err) + + err = validate.Var("XXX", "validCurrency") + assert.NotNil(t, err) + + err = validate.Var("RMB", "validCurrency") + assert.NotNil(t, err) + + err = validate.Var("", "validCurrency") + assert.NotNil(t, err) + + err = validate.Var("-", "validCurrency") + assert.NotNil(t, err) +} diff --git a/pkg/validators/email_test.go b/pkg/validators/email_test.go new file mode 100644 index 00000000..e0cebee8 --- /dev/null +++ b/pkg/validators/email_test.go @@ -0,0 +1,48 @@ +package validators + +import ( + "testing" + + "github.com/go-playground/validator/v10" + "github.com/stretchr/testify/assert" +) + +func TestValidEmail(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("validEmail", ValidEmail) + assert.Nil(t, err) + + email := "foo@bar.com" + err = validate.Var(email, "validEmail") + assert.Nil(t, err) + + email = "foo@1.2.3.4" + err = validate.Var(email, "validEmail") + assert.Nil(t, err) + + email = "foo_bar@foo.bar" + err = validate.Var(email, "validEmail") + assert.Nil(t, err) +} + +func TestInvalidEmail(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("validEmail", ValidEmail) + assert.Nil(t, err) + + email := "foo" + err = validate.Var(email, "validEmail") + assert.NotNil(t, err) + + email = "@bar" + err = validate.Var(email, "validEmail") + assert.NotNil(t, err) + + email = "foo@bar" + err = validate.Var(email, "validEmail") + assert.NotNil(t, err) + + email = "foo@bar." + err = validate.Var(email, "validEmail") + assert.NotNil(t, err) +} diff --git a/pkg/validators/hex_rgb_color_test.go b/pkg/validators/hex_rgb_color_test.go new file mode 100644 index 00000000..2903fb3a --- /dev/null +++ b/pkg/validators/hex_rgb_color_test.go @@ -0,0 +1,56 @@ +package validators + +import ( + "testing" + + "github.com/go-playground/validator/v10" + "github.com/stretchr/testify/assert" +) + +func TestValidHexRGBColor(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("validHexRGBColor", ValidHexRGBColor) + assert.Nil(t, err) + + color := "000000" + err = validate.Var(color, "validHexRGBColor") + assert.Nil(t, err) + + color = "000" + err = validate.Var(color, "validHexRGBColor") + assert.Nil(t, err) + + color = "e0e0e0" + err = validate.Var(color, "validHexRGBColor") + assert.Nil(t, err) + + color = "ffffff" + err = validate.Var(color, "validHexRGBColor") + assert.Nil(t, err) + + color = "FFFFFF" + err = validate.Var(color, "validHexRGBColor") + assert.Nil(t, err) +} + +func TestInvalidHexRGBColor(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("validHexRGBColor", ValidHexRGBColor) + assert.Nil(t, err) + + color := "f" + err = validate.Var(color, "validHexRGBColor") + assert.NotNil(t, err) + + color = "fffffff" + err = validate.Var(color, "validHexRGBColor") + assert.NotNil(t, err) + + color = "gggggg" + err = validate.Var(color, "validHexRGBColor") + assert.NotNil(t, err) + + color = "#ffffff" + err = validate.Var(color, "validHexRGBColor") + assert.NotNil(t, err) +} diff --git a/pkg/validators/not_blank_test.go b/pkg/validators/not_blank_test.go new file mode 100644 index 00000000..5df43498 --- /dev/null +++ b/pkg/validators/not_blank_test.go @@ -0,0 +1,32 @@ +package validators + +import ( + "testing" + + "github.com/go-playground/validator/v10" + "github.com/stretchr/testify/assert" +) + +func TestValidNotBlank(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("notBlank", NotBlank) + assert.Nil(t, err) + + err = validate.Var("1", "notBlank") + assert.Nil(t, err) + + err = validate.Var(" 1 ", "notBlank") + assert.Nil(t, err) +} + +func TestInvalidNotBlank(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("notBlank", NotBlank) + assert.Nil(t, err) + + err = validate.Var("", "notBlank") + assert.NotNil(t, err) + + err = validate.Var(" ", "notBlank") + assert.NotNil(t, err) +} diff --git a/pkg/validators/username_test.go b/pkg/validators/username_test.go new file mode 100644 index 00000000..b5d1acf2 --- /dev/null +++ b/pkg/validators/username_test.go @@ -0,0 +1,32 @@ +package validators + +import ( + "testing" + + "github.com/go-playground/validator/v10" + "github.com/stretchr/testify/assert" +) + +func TestValidUsername(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("validUsername", ValidUsername) + assert.Nil(t, err) + + username := "foobar" + err = validate.Var(username, "validUsername") + assert.Nil(t, err) + + username = "--foo_bar--" + err = validate.Var(username, "validUsername") + assert.Nil(t, err) +} + +func TestInvalidUsername(t *testing.T) { + validate := validator.New() + err := validate.RegisterValidation("validUsername", ValidUsername) + assert.Nil(t, err) + + username := "foo~bar~" + err = validate.Var(username, "validUsername") + assert.NotNil(t, err) +}