完善本地质量门禁与资金链路测试

This commit is contained in:
yml2213
2026-09-02 13:50:19 +08:00
parent dd2b45bd2c
commit 208f12ddb4
80 changed files with 12245 additions and 11541 deletions
@@ -4,6 +4,8 @@ import (
"context"
"encoding/json"
"errors"
"strings"
"sync"
"testing"
"time"
@@ -694,6 +696,75 @@ func TestConfirmPaidRollsBackOrderWhenPaymentUpdateFails(t *testing.T) {
}
}
func TestConcurrentPaidNotificationsAreIdempotent(t *testing.T) {
db := database.NewTestDBWithName("payment-concurrent")
if err := database.MigrateRentalTransactionTestSchema(db); err != nil {
t.Fatalf("数据库迁移失败: %v", err)
}
sqlDB, err := db.DB()
if err != nil {
t.Fatalf("get sqlite db: %v", err)
}
sqlDB.SetMaxOpenConns(8)
orderRepo := ordermodule.NewRepository(db)
repo := NewRepository(db, nil, orderRepo)
fixture := createPayableOrderFixture(t, db, "CONCURRENT", true)
params := map[string]string{
"third_order_id": fixture.Payment.ThirdOrderID,
"status": "paid",
"amount": "1000",
"provider_order_id": "PROVIDER-CONCURRENT",
}
const callers = 8
results := make(chan error, callers)
var group sync.WaitGroup
for i := 0; i < callers; i++ {
group.Add(1)
go func() {
defer group.Done()
var callErr error
for attempt := 0; attempt < 50; attempt++ {
_, callErr = repo.HandleNotify(t.Context(), "mock", params, "status=paid", "application/x-www-form-urlencoded", "")
if callErr == nil || !strings.Contains(callErr.Error(), "locked") {
break
}
time.Sleep(5 * time.Millisecond)
}
results <- callErr
}()
}
group.Wait()
close(results)
for callErr := range results {
if callErr != nil {
t.Fatalf("concurrent HandleNotify() error = %v", callErr)
}
}
var latestPayment model.PaymentOrder
if err := db.First(&latestPayment, fixture.Payment.ID).Error; err != nil {
t.Fatalf("find payment: %v", err)
}
if latestPayment.Status != "paid" {
t.Fatalf("payment status = %q, want paid", latestPayment.Status)
}
var latestOrder model.RentalOrder
if err := db.First(&latestOrder, fixture.Order.ID).Error; err != nil {
t.Fatalf("find order: %v", err)
}
if latestOrder.Status != "pending_handoff" || latestOrder.HandoffStatus != "pending_owner" {
t.Fatalf("order status = %q/%q, want pending_handoff/pending_owner", latestOrder.Status, latestOrder.HandoffStatus)
}
var paidCount int64
if err := db.Model(&model.PaymentOrder{}).Where("id = ? AND status = 'paid'", fixture.Payment.ID).Count(&paidCount).Error; err != nil {
t.Fatalf("count paid payment: %v", err)
}
if paidCount != 1 {
t.Fatalf("paid payment rows = %d, want 1", paidCount)
}
}
// TestQueryClosedPaymentReturnsLocalStatus 验证关闭状态不再依赖渠道配置或继续轮询渠道。
func TestQueryClosedPaymentReturnsLocalStatus(t *testing.T) {
db := setupPaymentTestDB(t)