test: isolate repeated auto-match scan regressions (#359)
This commit is contained in:
@@ -18,6 +18,23 @@ import (
|
||||
const sizeScanSpecs = `[{"name":"尺码","role":"size","values":[{"name":"XL","source":"import"}]}]`
|
||||
const otherScanSpecs = `[{"name":"材质","role":"other","values":[{"name":"棉","source":"import"}]}]`
|
||||
|
||||
func openScanTestDB(t *testing.T) *gorm.DB {
|
||||
t.Helper()
|
||||
db := openTestDB(t)
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Closing the final connection releases the named in-memory database,
|
||||
// including when go test repeats the same t.Name via -count.
|
||||
t.Cleanup(func() {
|
||||
if err := sqlDB.Close(); err != nil {
|
||||
t.Errorf("close scan test database: %v", err)
|
||||
}
|
||||
})
|
||||
return db
|
||||
}
|
||||
|
||||
func seedScanProducts(t *testing.T, db *gorm.DB, pddID uint64, count int, specs string) []models.ShopeeProduct {
|
||||
t.Helper()
|
||||
products := make([]models.ShopeeProduct, count)
|
||||
@@ -62,7 +79,7 @@ func scanCheckpoint(t *testing.T, run *AutoMatchRunView, cursor uint64, reason s
|
||||
}
|
||||
|
||||
func TestAutoMatchScanPassesLongEmptyPrefix(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
pdd := seedPDDProduct(t, db, "active")
|
||||
seedScanProducts(t, db, pdd.ID, 1812, `[]`)
|
||||
seedScanProducts(t, db, pdd.ID, 1, sizeScanSpecs)
|
||||
@@ -74,7 +91,7 @@ func TestAutoMatchScanPassesLongEmptyPrefix(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAutoMatchScanRotatesAcrossServiceRestart(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
pdd := seedPDDProduct(t, db, "active")
|
||||
prefix := seedScanProducts(t, db, pdd.ID, 2001, otherScanSpecs)
|
||||
seedScanProducts(t, db, pdd.ID, 1, sizeScanSpecs)
|
||||
@@ -98,7 +115,7 @@ func TestAutoMatchScanRotatesAcrossServiceRestart(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAutoMatchScanBatchLimitKeepsLastExaminedOnShortPage(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
pdd := seedPDDProduct(t, db, "active")
|
||||
products := seedScanProducts(t, db, pdd.ID, 3, sizeScanSpecs)
|
||||
for i := 0; i < 3; i++ {
|
||||
@@ -115,7 +132,7 @@ func TestAutoMatchScanBatchLimitKeepsLastExaminedOnShortPage(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAutoMatchScanExactBudgetDoesNotAssumeEnd(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
pdd := seedPDDProduct(t, db, "active")
|
||||
products := seedScanProducts(t, db, pdd.ID, 2000, otherScanSpecs)
|
||||
first := runScan(t, NewService(db), 20)
|
||||
@@ -130,7 +147,7 @@ func TestAutoMatchScanExactBudgetDoesNotAssumeEnd(t *testing.T) {
|
||||
func TestAutoMatchEligibilityRejectsUnusableSpecsBeforePDDRead(t *testing.T) {
|
||||
for i, specs := range []string{"", `[]`, `null`, `""`, otherScanSpecs, `[{"role":"size","values":[]}]`, `[{"role":"color","values":[{"name":" "}]}]`} {
|
||||
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
missing := uint64(999)
|
||||
_, eligible, err := NewService(db).autoMatchEligibility(context.Background(), models.ShopeeProduct{PDDProductID: &missing, SpecsJSON: specs})
|
||||
if err != nil || eligible {
|
||||
@@ -141,7 +158,7 @@ func TestAutoMatchEligibilityRejectsUnusableSpecsBeforePDDRead(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAutoMatchScanEmptyRepresentationsAndSingleDimension(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
pdd := seedPDDProduct(t, db, "active")
|
||||
for _, specs := range []string{`[]`, `null`, `""`} {
|
||||
seedScanProducts(t, db, pdd.ID, 1, specs)
|
||||
@@ -157,7 +174,7 @@ func TestAutoMatchScanEmptyRepresentationsAndSingleDimension(t *testing.T) {
|
||||
func TestAutoMatchScanLatestCommittedZeroWinsAndNullIsIgnored(t *testing.T) {
|
||||
for _, latest := range []uint64{0, 2} {
|
||||
t.Run(fmt.Sprint(latest), func(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
pdd := seedPDDProduct(t, db, "active")
|
||||
products := seedScanProducts(t, db, pdd.ID, 3, otherScanSpecs)
|
||||
old := uint64(1)
|
||||
@@ -179,7 +196,7 @@ func TestAutoMatchScanLatestCommittedZeroWinsAndNullIsIgnored(t *testing.T) {
|
||||
func TestAutoMatchRenewAndFinishRejectLostLease(t *testing.T) {
|
||||
for _, change := range []string{"owner", "expired", "slot", "status"} {
|
||||
t.Run(change, func(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
s := NewService(db)
|
||||
run, _, err := s.StartAutoMatchRun(context.Background(), "manual", uuid.NewString(), nil, 20)
|
||||
if err != nil {
|
||||
@@ -218,7 +235,7 @@ func TestAutoMatchRenewAndFinishRejectLostLease(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAutoMatchScanDatabaseErrorDoesNotCommitCheckpoint(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
pdd := seedPDDProduct(t, db, "active")
|
||||
products := seedScanProducts(t, db, pdd.ID, 2, sizeScanSpecs)
|
||||
s := NewService(db)
|
||||
@@ -255,7 +272,7 @@ func TestAutoMatchScanDatabaseErrorDoesNotCommitCheckpoint(t *testing.T) {
|
||||
func TestAutoMatchClaimRejectsLostOrExpiredRun(t *testing.T) {
|
||||
for _, change := range []string{"owner", "expired", "slot", "status"} {
|
||||
t.Run(change, func(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
s := NewService(db)
|
||||
run, _, err := s.StartAutoMatchRun(context.Background(), "manual", uuid.NewString(), nil, 20)
|
||||
if err != nil {
|
||||
@@ -291,7 +308,7 @@ func TestAutoMatchClaimRejectsLostOrExpiredRun(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAutoMatchScanOwnerLossDuringProviderStopsNextCallAndSave(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
s := NewService(db)
|
||||
pdd := seedPDDProduct(t, db, "active")
|
||||
products := seedScanProducts(t, db, pdd.ID, 2, `[{"name":"颜色","role":"color","values":[{"name":"深黑","source":"import"}]},{"name":"尺码","role":"size","values":[{"name":"大号","source":"import"}]}]`)
|
||||
@@ -342,7 +359,7 @@ func TestAutoMatchScanOwnerLossDuringProviderStopsNextCallAndSave(t *testing.T)
|
||||
}
|
||||
|
||||
func TestAutoMatchScanDeadlineStopsProviderAndKeepsLastDecision(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
pdd := seedPDDProduct(t, db, "active")
|
||||
first := seedScanProducts(t, db, pdd.ID, 1, otherScanSpecs)[0]
|
||||
products := seedScanProducts(t, db, pdd.ID, 2, `[{"name":"颜色","role":"color","values":[{"name":"深黑","source":"import"}]}]`)
|
||||
@@ -394,7 +411,7 @@ func TestAutoMatchScanDeadlineStopsProviderAndKeepsLastDecision(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAutoMatchScanDeadlineBoundsDatabaseAndNoClaimAfterBudget(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
pdd := seedPDDProduct(t, db, "active")
|
||||
seedScanProducts(t, db, pdd.ID, 2, sizeScanSpecs)
|
||||
s := NewService(db)
|
||||
@@ -439,7 +456,7 @@ func TestAutoMatchScanDeadlineBoundsDatabaseAndNoClaimAfterBudget(t *testing.T)
|
||||
}
|
||||
|
||||
func TestAutoMatchScanRecoveryIgnoresExpiredCheckpoint(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
s := NewService(db)
|
||||
run, _, err := s.StartAutoMatchRun(context.Background(), "manual", uuid.NewString(), nil, 20)
|
||||
if err != nil {
|
||||
@@ -461,7 +478,7 @@ func TestAutoMatchScanRecoveryIgnoresExpiredCheckpoint(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAutoMatchScanExactPageBoundaryAndCandidateFilters(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
pdd := seedPDDProduct(t, db, "active")
|
||||
seedScanProducts(t, db, pdd.ID, 200, otherScanSpecs)
|
||||
seedScanProducts(t, db, pdd.ID, 1, sizeScanSpecs)
|
||||
@@ -485,7 +502,7 @@ func TestAutoMatchScanExactPageBoundaryAndCandidateFilters(t *testing.T) {
|
||||
func TestAutoMatchWorkRetryAndCooldownPreserved(t *testing.T) {
|
||||
for _, status := range []string{"completed", "unmatched", "max_retry", "cooldown", "occupied", "retryable"} {
|
||||
t.Run(status, func(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
s := NewService(db)
|
||||
run, _, err := s.StartAutoMatchRun(context.Background(), "manual", uuid.NewString(), nil, 20)
|
||||
if err != nil {
|
||||
@@ -534,7 +551,7 @@ func TestAutoMatchWorkRetryAndCooldownPreserved(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAutoMatchClaimDoesNotUseLeaseTimeBeforeLockWait(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
s := NewService(db)
|
||||
run, _, err := s.StartAutoMatchRun(context.Background(), "manual", uuid.NewString(), nil, 20)
|
||||
if err != nil {
|
||||
@@ -558,7 +575,7 @@ func TestAutoMatchClaimDoesNotUseLeaseTimeBeforeLockWait(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAutoMatchProviderGuardDatabaseErrorMustNotRetryOrCheckpoint(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
pdd := seedPDDProduct(t, db, "active")
|
||||
seedScanProducts(t, db, pdd.ID, 1, `[{"name":"颜色","role":"color","values":[{"name":"深黑","source":"import"}]}]`)
|
||||
var calls atomic.Int32
|
||||
@@ -603,7 +620,7 @@ func TestAutoMatchProviderGuardDatabaseErrorMustNotRetryOrCheckpoint(t *testing.
|
||||
}
|
||||
|
||||
func TestAutoMatchProviderSettingsDatabaseErrorMustNotRetryOrCheckpoint(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
pdd := seedPDDProduct(t, db, "active")
|
||||
seedScanProducts(t, db, pdd.ID, 1, `[{"name":"颜色","role":"color","values":[{"name":"深黑","source":"import"}]}]`)
|
||||
var calls atomic.Int32
|
||||
@@ -648,7 +665,7 @@ func TestAutoMatchProviderSettingsDatabaseErrorMustNotRetryOrCheckpoint(t *testi
|
||||
func TestAutoMatchRunDatabaseWriteFailuresAreReturned(t *testing.T) {
|
||||
for _, operation := range []string{"renew", "finish", "work"} {
|
||||
t.Run(operation, func(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
s := NewService(db)
|
||||
run, _, err := s.StartAutoMatchRun(context.Background(), "manual", uuid.NewString(), nil, 20)
|
||||
if err != nil {
|
||||
@@ -686,7 +703,7 @@ func TestAutoMatchRunDatabaseWriteFailuresAreReturned(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAutoMatchDeadlineDuringCheckpointReadCannotCommitFalseHead(t *testing.T) {
|
||||
db := openTestDB(t)
|
||||
db := openScanTestDB(t)
|
||||
s := NewService(db)
|
||||
checkpoint := uint64(1700)
|
||||
old := models.ShopeeSpecAutoMatchRun{RequestID: uuid.NewString(), Trigger: "manual", Status: "completed", ResumeAfterID: &checkpoint}
|
||||
|
||||
Reference in New Issue
Block a user