Просмотр исходного кода

test(user-migration): cover rescan and batch status regressions

master
fengsilin 1 неделю назад
Родитель
Сommit
36b47379f7
3 измененных файлов: 153 добавлений и 0 удалений
  1. +44
    -0
      controller/user_migration_test.go
  2. +31
    -0
      model/user_migration_test.go
  3. +78
    -0
      service/user_migration/service_test.go

+ 44
- 0
controller/user_migration_test.go Просмотреть файл

@@ -135,3 +135,47 @@ func TestResolveUserMigrationItem_InvalidStrategy(t *testing.T) {


require.Equal(t, http.StatusBadRequest, w.Code) require.Equal(t, http.StatusBadRequest, w.Code)
} }

func TestResolveUserMigrationItem_RefreshesBatchStatusToReady(t *testing.T) {
gin.SetMode(gin.TestMode)
router := gin.New()
router.Use(testRootAuthMiddleware())
router.POST("/api/user-migrations/items/:id/resolve", ResolveUserMigrationItem)

db := setupUserMigrationControllerDB(t)
orig := model.DB
model.DB = db
defer func() {
model.DB = orig
}()

batch := &model.UserMigrationBatch{
Name: "resolve-ready",
SourceRegion: "ov",
TargetRegion: "cn",
OperatorId: 1,
Status: model.UserMigrationBatchStatusScanned,
}
require.NoError(t, model.CreateUserMigrationBatch(batch))
require.NoError(t, db.Create(&model.UserMigrationItem{
BatchId: batch.Id,
SourceUserId: 1001,
SourceUsername: "ov-u1",
Status: model.UserMigrationItemStatusConflict,
}).Error)

req := httptest.NewRequest(
http.MethodPost,
"/api/user-migrations/items/1/resolve",
bytes.NewBufferString(`{"resolution_strategy":"create_new"}`),
)
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)

require.Equal(t, http.StatusOK, w.Code)

var refreshed model.UserMigrationBatch
require.NoError(t, db.First(&refreshed, batch.Id).Error)
require.Equal(t, model.UserMigrationBatchStatusReady, refreshed.Status)
}

+ 31
- 0
model/user_migration_test.go Просмотреть файл

@@ -148,3 +148,34 @@ func TestAtomicGrantQuotaIfNotExists_Idempotent(t *testing.T) {
require.NoError(t, db.First(&user, 1).Error) require.NoError(t, db.First(&user, 1).Error)
require.Equal(t, 700, user.Quota) require.Equal(t, 700, user.Quota)
} }

func TestRefreshBatchStats_ReadyOnlyWhenNoPendingScan(t *testing.T) {
db := setupUserMigrationTestDB(t)
orig := DB
DB = db
defer func() {
DB = orig
}()

batch := &UserMigrationBatch{Name: "stats-test", SourceRegion: "ov", TargetRegion: "cn", OperatorId: 1}
require.NoError(t, CreateUserMigrationBatch(batch))

require.NoError(t, DB.Create(&UserMigrationItem{
BatchId: batch.Id,
SourceUserId: 1,
SourceUsername: "u1",
Status: UserMigrationItemStatusReady,
}).Error)
require.NoError(t, DB.Create(&UserMigrationItem{
BatchId: batch.Id,
SourceUserId: 2,
SourceUsername: "u2",
Status: UserMigrationItemStatusPendingScan,
}).Error)

require.NoError(t, RefreshUserMigrationBatchStats(batch.Id))

var refreshed UserMigrationBatch
require.NoError(t, DB.First(&refreshed, batch.Id).Error)
require.Equal(t, UserMigrationBatchStatusScanned, refreshed.Status)
}

+ 78
- 0
service/user_migration/service_test.go Просмотреть файл

@@ -247,6 +247,43 @@ func TestScanBatch_Paginated(t *testing.T) {
require.Len(t, items, scanPageSize+1) require.Len(t, items, scanPageSize+1)
} }


func TestScanBatch_Rescan_PreservesHumanStrategy(t *testing.T) {
db := setupMigrationServiceDB(t)
orig := model.DB
model.DB = db
defer func() {
model.DB = orig
}()

batch := &model.UserMigrationBatch{Name: "wave-rescan", SourceRegion: "ov", TargetRegion: "cn", OperatorId: 1}
require.NoError(t, model.CreateUserMigrationBatch(batch))

client := &fakeClient{
listPages: map[int][]RemoteUserSnapshot{
0: {{
Id: 10000001,
Username: "ov-dave",
Email: "dave@example.com",
Quota: 100,
AffCode: "OVD1",
}},
},
hasCopyResult: false,
}
svc := &Service{client: client}
require.NoError(t, svc.ScanBatch(batch.Id))

require.NoError(t, db.Model(&model.UserMigrationItem{}).Where("batch_id = ?", batch.Id).
Update("resolution_strategy", model.UserMigrationStrategySkip).Error)

require.NoError(t, svc.ScanBatch(batch.Id))

items, err := model.ListUserMigrationItemsByBatch(batch.Id)
require.NoError(t, err)
require.Len(t, items, 1)
require.Equal(t, model.UserMigrationStrategySkip, items[0].ResolutionStrategy)
}

func TestExecuteBatch_CreateNew_CreatesUserAndConvertsRemote(t *testing.T) { func TestExecuteBatch_CreateNew_CreatesUserAndConvertsRemote(t *testing.T) {
db := setupMigrationServiceDB(t) db := setupMigrationServiceDB(t)
orig := model.DB orig := model.DB
@@ -435,6 +472,47 @@ func TestExecuteBatch_MergeExisting_IdempotentQuota(t *testing.T) {
require.Len(t, client.convertCalls, 1) require.Len(t, client.convertCalls, 1)
} }


func TestExecuteBatch_SkipItem_DoesNotConvert(t *testing.T) {
db := setupMigrationServiceDB(t)
orig := model.DB
model.DB = db
defer func() {
model.DB = orig
}()

batch := &model.UserMigrationBatch{
Name: "skip-test",
SourceRegion: "ov",
TargetRegion: "cn",
OperatorId: 1,
Status: model.UserMigrationBatchStatusReady,
}
require.NoError(t, model.CreateUserMigrationBatch(batch))
require.NoError(t, model.UpsertUserMigrationItem(&model.UserMigrationItem{
BatchId: batch.Id,
SourceUserId: 10000099,
SourceUsername: "skip-user",
SourceQuota: 50,
ResolutionStrategy: model.UserMigrationStrategySkip,
Status: model.UserMigrationItemStatusReady,
MigrationToken: "batch-1-user-10000099",
}))

client := &fakeClient{}
svc := &Service{client: client}

locked, err := model.TryLockBatchForExecution(batch.Id)
require.NoError(t, err)
require.True(t, locked)
require.NoError(t, svc.ExecuteBatch(batch.Id))

require.Len(t, client.convertCalls, 0)
items, err := model.ListUserMigrationItemsByBatch(batch.Id)
require.NoError(t, err)
require.Len(t, items, 1)
require.Equal(t, model.UserMigrationItemStatusSkipped, items[0].Status)
}

func TestVerifyItem_CorrectlyChecksRemoteConverted(t *testing.T) { func TestVerifyItem_CorrectlyChecksRemoteConverted(t *testing.T) {
db := setupMigrationServiceDB(t) db := setupMigrationServiceDB(t)
orig := model.DB orig := model.DB


Загрузка…
Отмена
Сохранить