|
- package model
-
- import (
- "sync"
- "testing"
-
- "github.com/glebarez/sqlite"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "gorm.io/gorm"
- "gorm.io/gorm/logger"
- )
-
- func setupUserAssetChannelDB(t *testing.T) *gorm.DB {
- t.Helper()
-
- db, err := gorm.Open(sqlite.Open("file:user_asset_channels?mode=memory&cache=shared"), &gorm.Config{
- Logger: logger.Default.LogMode(logger.Silent),
- })
- require.NoError(t, err)
-
- sqlDB, err := db.DB()
- require.NoError(t, err)
- sqlDB.SetMaxOpenConns(1)
-
- origDB := DB
- origGroupCol := commonGroupCol
- DB = db
- commonGroupCol = "`group`"
-
- require.NoError(t, db.AutoMigrate(&UserAssetChannel{}))
-
- t.Cleanup(func() {
- DB = origDB
- commonGroupCol = origGroupCol
- require.NoError(t, sqlDB.Close())
- })
-
- return db
- }
-
- func TestGetUserAssetChannel_NotFound(t *testing.T) {
- setupUserAssetChannelDB(t)
-
- binding, err := GetUserAssetChannel(1, 2, "default")
- require.NoError(t, err)
- assert.Nil(t, binding)
- }
-
- func TestBindUserAssetChannel_CreateAndUpdate(t *testing.T) {
- db := setupUserAssetChannelDB(t)
-
- require.NoError(t, BindUserAssetChannel(1, 2, "default", 100))
-
- binding, err := GetUserAssetChannel(1, 2, "default")
- require.NoError(t, err)
- require.NotNil(t, binding)
- assert.Equal(t, 100, binding.ChannelId)
- assert.NotZero(t, binding.CreatedAt)
- assert.NotZero(t, binding.UpdatedAt)
-
- require.NoError(t, BindUserAssetChannel(1, 2, "default", 200))
-
- binding, err = GetUserAssetChannel(1, 2, "default")
- require.NoError(t, err)
- require.NotNil(t, binding)
- assert.Equal(t, 200, binding.ChannelId)
-
- var count int64
- require.NoError(t, db.Model(&UserAssetChannel{}).Count(&count).Error)
- assert.Equal(t, int64(1), count)
- }
-
- func TestGetUserAssetChannelsByTypesSortsLatestFirst(t *testing.T) {
- db := setupUserAssetChannelDB(t)
- require.NoError(t, BindUserAssetChannel(1, 2, "default", 100))
- require.NoError(t, BindUserAssetChannel(1, 3, "default", 200))
- require.NoError(t, BindUserAssetChannel(1, 4, "default", 300))
- require.NoError(t, db.Model(&UserAssetChannel{}).
- Where("user_id = ? AND channel_type = ?", 1, 2).
- Update("updated_at", int64(100)).Error)
- require.NoError(t, db.Model(&UserAssetChannel{}).
- Where("user_id = ? AND channel_type = ?", 1, 3).
- Update("updated_at", int64(200)).Error)
-
- bindings, err := GetUserAssetChannelsByTypes(1, []int{2, 3}, "default")
-
- require.NoError(t, err)
- require.Len(t, bindings, 2)
- assert.Equal(t, 3, bindings[0].ChannelType)
- assert.Equal(t, 200, bindings[0].ChannelId)
- assert.Equal(t, 2, bindings[1].ChannelType)
- }
-
- func TestBindUserAssetChannelWithTxUpserts(t *testing.T) {
- db := setupUserAssetChannelDB(t)
-
- require.NoError(t, BindUserAssetChannel(1, 2, "default", 100))
- require.NoError(t, BindUserAssetChannel(1, 2, "default", 200))
-
- binding, err := GetUserAssetChannel(1, 2, "default")
- require.NoError(t, err)
- require.NotNil(t, binding)
- assert.Equal(t, 200, binding.ChannelId)
-
- var count int64
- require.NoError(t, db.Model(&UserAssetChannel{}).Count(&count).Error)
- assert.Equal(t, int64(1), count)
- }
-
- func TestDeleteUserAssetChannelsByTypesWithTxDeletesOnlyRequestedRows(t *testing.T) {
- db := setupUserAssetChannelDB(t)
- require.NoError(t, BindUserAssetChannel(1, 2, "default", 100))
- require.NoError(t, BindUserAssetChannel(1, 3, "default", 200))
- require.NoError(t, BindUserAssetChannel(1, 4, "default", 300))
- require.NoError(t, BindUserAssetChannel(1, 2, "vip", 400))
- require.NoError(t, BindUserAssetChannel(2, 2, "default", 500))
-
- require.NoError(t, db.Transaction(func(tx *gorm.DB) error {
- return DeleteUserAssetChannelsByTypesWithTx(tx, 1, []int{2, 3}, "default")
- }))
-
- binding, err := GetUserAssetChannel(1, 2, "default")
- require.NoError(t, err)
- assert.Nil(t, binding)
- binding, err = GetUserAssetChannel(1, 3, "default")
- require.NoError(t, err)
- assert.Nil(t, binding)
- binding, err = GetUserAssetChannel(1, 4, "default")
- require.NoError(t, err)
- require.NotNil(t, binding)
- assert.Equal(t, 300, binding.ChannelId)
- binding, err = GetUserAssetChannel(1, 2, "vip")
- require.NoError(t, err)
- require.NotNil(t, binding)
- assert.Equal(t, 400, binding.ChannelId)
- binding, err = GetUserAssetChannel(2, 2, "default")
- require.NoError(t, err)
- require.NotNil(t, binding)
- assert.Equal(t, 500, binding.ChannelId)
- }
-
- func TestBindUserAssetChannel_IsolatesUserTypeGroup(t *testing.T) {
- setupUserAssetChannelDB(t)
-
- require.NoError(t, BindUserAssetChannel(1, 2, "default", 100))
- require.NoError(t, BindUserAssetChannel(2, 2, "default", 200))
- require.NoError(t, BindUserAssetChannel(1, 3, "default", 300))
- require.NoError(t, BindUserAssetChannel(1, 2, "vip", 400))
-
- cases := []struct {
- userId int
- channelType int
- group string
- channelId int
- }{
- {1, 2, "default", 100},
- {2, 2, "default", 200},
- {1, 3, "default", 300},
- {1, 2, "vip", 400},
- }
-
- for _, tc := range cases {
- binding, err := GetUserAssetChannel(tc.userId, tc.channelType, tc.group)
- require.NoError(t, err)
- require.NotNil(t, binding)
- assert.Equal(t, tc.channelId, binding.ChannelId)
- }
- }
-
- func TestBindUserAssetChannel_ConcurrentUpsert(t *testing.T) {
- db := setupUserAssetChannelDB(t)
-
- const workers = 20
- var wg sync.WaitGroup
- errCh := make(chan error, workers)
- expected := make(map[int]bool, workers)
-
- for i := 0; i < workers; i++ {
- channelId := 1000 + i
- expected[channelId] = true
- wg.Add(1)
- go func() {
- defer wg.Done()
- errCh <- BindUserAssetChannel(1, 2, "default", channelId)
- }()
- }
-
- wg.Wait()
- close(errCh)
- for err := range errCh {
- require.NoError(t, err)
- }
-
- var count int64
- require.NoError(t, db.Model(&UserAssetChannel{}).Count(&count).Error)
- assert.Equal(t, int64(1), count)
-
- binding, err := GetUserAssetChannel(1, 2, "default")
- require.NoError(t, err)
- require.NotNil(t, binding)
- assert.True(t, expected[binding.ChannelId])
- }
-
- func TestUnbindUserAssetChannel(t *testing.T) {
- setupUserAssetChannelDB(t)
-
- require.NoError(t, BindUserAssetChannel(1, 2, "default", 100))
- require.NoError(t, BindUserAssetChannel(1, 2, "vip", 200))
-
- require.NoError(t, UnbindUserAssetChannel(1, 2, "default"))
-
- binding, err := GetUserAssetChannel(1, 2, "default")
- require.NoError(t, err)
- assert.Nil(t, binding)
-
- binding, err = GetUserAssetChannel(1, 2, "vip")
- require.NoError(t, err)
- require.NotNil(t, binding)
- assert.Equal(t, 200, binding.ChannelId)
- }
|