220 lines
7.3 KiB
Go
220 lines
7.3 KiB
Go
package aiser
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"91porn-server/app/appg"
|
|
"91porn-server/common/laosiji_app"
|
|
"91porn-server/models/v/fundtransferlogmod"
|
|
"91porn-server/models/v/usermod"
|
|
"91porn-server/models/v/walletmod"
|
|
)
|
|
|
|
func TestGetAuthURLTransfersWalletAmount(t *testing.T) {
|
|
originalConfig := appg.Conf
|
|
appg.Conf = &appg.GlobalConfig{}
|
|
appg.Conf.Base.Env = "test"
|
|
t.Cleanup(func() { appg.Conf = originalConfig })
|
|
|
|
var (
|
|
gotAsset string
|
|
gotDebit int64
|
|
gotUser string
|
|
debitTime time.Time
|
|
)
|
|
now := time.Date(2026, 7, 27, 12, 0, 0, 0, time.UTC)
|
|
deps := transferDependencies{
|
|
findLatest: func(uint64, fundtransferlogmod.Category) (*fundtransferlogmod.FundTransferLog, error) {
|
|
return nil, nil
|
|
},
|
|
findLatestOut: func(uint64, fundtransferlogmod.Category) (*fundtransferlogmod.FundTransferLog, error) {
|
|
return &fundtransferlogmod.FundTransferLog{Remainder: 0.04}, nil
|
|
},
|
|
getWallet: func(uint64) (*walletmod.Wallet, error) {
|
|
return &walletmod.Wallet{Amount: 123}, nil
|
|
},
|
|
findUser: func(uint64) (*usermod.User, error) {
|
|
return &usermod.User{Name: "测试", Portrait: "avatar"}, nil
|
|
},
|
|
getAuthURL: func(_ context.Context, req laosiji_app.GetAiMateURLReq) (laosiji_app.GetAiMateURLResp, error) {
|
|
gotAsset = req.Asset
|
|
gotUser = req.Username
|
|
return laosiji_app.GetAiMateURLResp{AuthURL: "https://example.com/auth"}, nil
|
|
},
|
|
bringOut: func(context.Context, laosiji_app.AiMateBringOutReq) (laosiji_app.AiMateBringOutResp, error) {
|
|
t.Fatal("bringOut must not be called without pending transfer")
|
|
return laosiji_app.AiMateBringOutResp{}, nil
|
|
},
|
|
debitAndLog: func(_ uint64, amount int64, at time.Time) error {
|
|
gotDebit, debitTime = amount, at
|
|
return nil
|
|
},
|
|
creditAndLog: func(uint64, int64, float64, string, time.Time) error {
|
|
t.Fatal("creditAndLog must not be called")
|
|
return nil
|
|
},
|
|
now: func() time.Time { return now },
|
|
}
|
|
|
|
resp, err := getAuthURL(context.Background(), 99, deps)
|
|
if err != nil {
|
|
t.Fatalf("getAuthURL() error = %v", err)
|
|
}
|
|
if resp.URL != "https://example.com/auth" {
|
|
t.Fatalf("URL = %q", resp.URL)
|
|
}
|
|
if gotAsset != "12.34" {
|
|
t.Fatalf("asset = %q, want 12.34", gotAsset)
|
|
}
|
|
if gotUser != "TEST-204_99" {
|
|
t.Fatalf("username = %q", gotUser)
|
|
}
|
|
if gotDebit != 123 || !debitTime.Equal(now) {
|
|
t.Fatalf("debit = %d at %s", gotDebit, debitTime)
|
|
}
|
|
}
|
|
|
|
func TestGetAuthURLDoesNotDebitWhenThirdPartyFails(t *testing.T) {
|
|
originalConfig := appg.Conf
|
|
appg.Conf = &appg.GlobalConfig{}
|
|
t.Cleanup(func() { appg.Conf = originalConfig })
|
|
|
|
deps := transferDependencies{
|
|
findLatest: func(uint64, fundtransferlogmod.Category) (*fundtransferlogmod.FundTransferLog, error) {
|
|
return nil, nil
|
|
},
|
|
findLatestOut: func(uint64, fundtransferlogmod.Category) (*fundtransferlogmod.FundTransferLog, error) {
|
|
return nil, nil
|
|
},
|
|
getWallet: func(uint64) (*walletmod.Wallet, error) {
|
|
return &walletmod.Wallet{Amount: 100}, nil
|
|
},
|
|
findUser: func(uint64) (*usermod.User, error) { return nil, nil },
|
|
getAuthURL: func(context.Context, laosiji_app.GetAiMateURLReq) (laosiji_app.GetAiMateURLResp, error) {
|
|
return laosiji_app.GetAiMateURLResp{}, errors.New("remote failed")
|
|
},
|
|
debitAndLog: func(uint64, int64, time.Time) error {
|
|
t.Fatal("debitAndLog must not be called after remote failure")
|
|
return nil
|
|
},
|
|
now: time.Now,
|
|
}
|
|
if _, err := getAuthURL(context.Background(), 99, deps); err == nil {
|
|
t.Fatal("getAuthURL() error = nil")
|
|
}
|
|
}
|
|
|
|
func TestGetAuthURLSettlesPendingTransferBeforeNewTransfer(t *testing.T) {
|
|
originalConfig := appg.Conf
|
|
appg.Conf = &appg.GlobalConfig{}
|
|
appg.Conf.Base.Env = "test"
|
|
t.Cleanup(func() { appg.Conf = originalConfig })
|
|
|
|
steps := make([]string, 0, 5)
|
|
deps := transferDependencies{
|
|
findLatest: func(uint64, fundtransferlogmod.Category) (*fundtransferlogmod.FundTransferLog, error) {
|
|
steps = append(steps, "find-pending")
|
|
return &fundtransferlogmod.FundTransferLog{FundType: fundtransferlogmod.FundTypeIn}, nil
|
|
},
|
|
bringOut: func(context.Context, laosiji_app.AiMateBringOutReq) (laosiji_app.AiMateBringOutResp, error) {
|
|
steps = append(steps, "bring-out")
|
|
return laosiji_app.AiMateBringOutResp{Balance: "1.00"}, nil
|
|
},
|
|
creditAndLog: func(uint64, int64, float64, string, time.Time) error {
|
|
steps = append(steps, "credit")
|
|
return nil
|
|
},
|
|
getWallet: func(uint64) (*walletmod.Wallet, error) {
|
|
steps = append(steps, "wallet")
|
|
return &walletmod.Wallet{Amount: 20}, nil
|
|
},
|
|
findLatestOut: func(uint64, fundtransferlogmod.Category) (*fundtransferlogmod.FundTransferLog, error) {
|
|
return nil, nil
|
|
},
|
|
findUser: func(uint64) (*usermod.User, error) { return nil, nil },
|
|
getAuthURL: func(context.Context, laosiji_app.GetAiMateURLReq) (laosiji_app.GetAiMateURLResp, error) {
|
|
steps = append(steps, "auth")
|
|
return laosiji_app.GetAiMateURLResp{AuthURL: "https://example.com/auth"}, nil
|
|
},
|
|
debitAndLog: func(uint64, int64, time.Time) error { return nil },
|
|
now: time.Now,
|
|
}
|
|
|
|
if _, err := getAuthURL(context.Background(), 99, deps); err != nil {
|
|
t.Fatalf("getAuthURL() error = %v", err)
|
|
}
|
|
want := []string{"find-pending", "bring-out", "credit", "wallet", "auth"}
|
|
if len(steps) != len(want) {
|
|
t.Fatalf("steps = %v, want %v", steps, want)
|
|
}
|
|
for index := range want {
|
|
if steps[index] != want[index] {
|
|
t.Fatalf("steps = %v, want %v", steps, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSettleDownCreditsConvertedBalance(t *testing.T) {
|
|
originalConfig := appg.Conf
|
|
appg.Conf = &appg.GlobalConfig{}
|
|
appg.Conf.Base.Env = "prod"
|
|
t.Cleanup(func() { appg.Conf = originalConfig })
|
|
|
|
var (
|
|
gotAmount int64
|
|
gotRemainder float64
|
|
gotDesc string
|
|
gotUsername string
|
|
)
|
|
deps := transferDependencies{
|
|
findLatest: func(uint64, fundtransferlogmod.Category) (*fundtransferlogmod.FundTransferLog, error) {
|
|
return &fundtransferlogmod.FundTransferLog{FundType: fundtransferlogmod.FundTypeIn}, nil
|
|
},
|
|
bringOut: func(_ context.Context, req laosiji_app.AiMateBringOutReq) (laosiji_app.AiMateBringOutResp, error) {
|
|
gotUsername = req.Username
|
|
return laosiji_app.AiMateBringOutResp{Balance: "1.23"}, nil
|
|
},
|
|
creditAndLog: func(_ uint64, amount int64, remainder float64, desc string, _ time.Time) error {
|
|
gotAmount, gotRemainder, gotDesc = amount, remainder, desc
|
|
return nil
|
|
},
|
|
now: time.Now,
|
|
}
|
|
if err := settleDown(context.Background(), 88, deps); err != nil {
|
|
t.Fatalf("settleDown() error = %v", err)
|
|
}
|
|
if gotUsername != "JHA-204_88" {
|
|
t.Fatalf("username = %q", gotUsername)
|
|
}
|
|
if gotAmount != 12 || gotRemainder != 0.03 || gotDesc != "AI女友下分" {
|
|
t.Fatalf("credit amount=%d remainder=%v desc=%q", gotAmount, gotRemainder, gotDesc)
|
|
}
|
|
}
|
|
|
|
func TestBalanceToWallet(t *testing.T) {
|
|
tests := []struct {
|
|
balance string
|
|
amount int64
|
|
remainder float64
|
|
wantErr bool
|
|
}{
|
|
{balance: "0", amount: 0, remainder: 0},
|
|
{balance: "1.20", amount: 12, remainder: 0},
|
|
{balance: "1.29", amount: 12, remainder: 0.09},
|
|
{balance: "-1", wantErr: true},
|
|
{balance: "invalid", wantErr: true},
|
|
}
|
|
for _, test := range tests {
|
|
amount, remainder, err := balanceToWallet(test.balance)
|
|
if (err != nil) != test.wantErr {
|
|
t.Fatalf("balanceToWallet(%q) error = %v", test.balance, err)
|
|
}
|
|
if amount != test.amount || remainder != test.remainder {
|
|
t.Fatalf("balanceToWallet(%q) = (%d,%v), want (%d,%v)", test.balance, amount, remainder, test.amount, test.remainder)
|
|
}
|
|
}
|
|
}
|