139 lines
4.3 KiB
Go
139 lines
4.3 KiB
Go
// Package mysqltest provides real wallet-service MySQL repositories for tests.
|
|
package mysqltest
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"hyapp/internal/testutil/mysqlschema"
|
|
mysqlstorage "hyapp/services/wallet-service/internal/storage/mysql"
|
|
)
|
|
|
|
// Repository wraps the production MySQL wallet repository with test seed helpers.
|
|
type Repository struct {
|
|
*mysqlstorage.Repository
|
|
|
|
t testing.TB
|
|
schema *mysqlschema.Schema
|
|
}
|
|
|
|
// CountRows returns a simple count from a known wallet table for persistence assertions.
|
|
func (r *Repository) CountRows(table string, where string, args ...any) int {
|
|
r.t.Helper()
|
|
|
|
query := "SELECT COUNT(*) FROM " + validateTableName(table)
|
|
if where != "" {
|
|
query += " WHERE " + where
|
|
}
|
|
var count int
|
|
if err := r.schema.DB.QueryRowContext(context.Background(), query, args...).Scan(&count); err != nil {
|
|
r.t.Fatalf("count %s rows failed: %v\nquery=%s", table, err, query)
|
|
}
|
|
return count
|
|
}
|
|
|
|
// InsertRawGiftPrice allows tests to seed inactive or future prices without service helpers.
|
|
func (r *Repository) InsertRawGiftPrice(giftID string, priceVersion string, status string, effectiveAtMs int64) {
|
|
r.t.Helper()
|
|
|
|
nowMs := time.Now().UnixMilli()
|
|
_, err := r.schema.DB.ExecContext(context.Background(), `
|
|
INSERT INTO wallet_gift_prices (
|
|
gift_id, price_version, status, coin_price, gift_point_amount, heat_value,
|
|
effective_at_ms, created_at_ms, updated_at_ms
|
|
) VALUES (?, ?, ?, 1, 1, 1, ?, ?, ?)
|
|
`, giftID, priceVersion, status, effectiveAtMs, nowMs, nowMs)
|
|
if err != nil {
|
|
r.t.Fatalf("insert raw gift price failed: %v", err)
|
|
}
|
|
}
|
|
|
|
// NewRepository creates an isolated wallet schema and opens the production repository.
|
|
func NewRepository(t testing.TB) *Repository {
|
|
t.Helper()
|
|
|
|
schema := mysqlschema.New(t, mysqlschema.Config{
|
|
EnvVar: "WALLET_SERVICE_MYSQL_TEST_DSN",
|
|
InitDBPath: initDBPath(t),
|
|
DatabasePrefix: "hyapp_wallet_test",
|
|
})
|
|
repository, err := mysqlstorage.Open(context.Background(), schema.DSN)
|
|
if err != nil {
|
|
t.Fatalf("open wallet mysql repository failed: %v", err)
|
|
}
|
|
|
|
wrapped := &Repository{Repository: repository, t: t, schema: schema}
|
|
t.Cleanup(wrapped.Close)
|
|
return wrapped
|
|
}
|
|
|
|
// Close shuts down the repository; mysqlschema owns schema cleanup.
|
|
func (r *Repository) Close() {
|
|
r.t.Helper()
|
|
|
|
if r.Repository != nil {
|
|
_ = r.Repository.Close()
|
|
}
|
|
}
|
|
|
|
// SetBalance prepares a sender COIN account for debit tests.
|
|
func (r *Repository) SetBalance(userID int64, balance int64) {
|
|
r.t.Helper()
|
|
|
|
nowMs := time.Now().UnixMilli()
|
|
_, err := r.schema.DB.ExecContext(context.Background(), `
|
|
INSERT INTO wallet_accounts (user_id, asset_type, available_amount, frozen_amount, version, created_at_ms, updated_at_ms)
|
|
VALUES (?, 'COIN', ?, 0, 1, ?, ?)
|
|
ON DUPLICATE KEY UPDATE
|
|
available_amount = VALUES(available_amount),
|
|
frozen_amount = VALUES(frozen_amount),
|
|
version = version + 1,
|
|
updated_at_ms = VALUES(updated_at_ms)
|
|
`, userID, balance, nowMs, nowMs)
|
|
if err != nil {
|
|
r.t.Fatalf("seed wallet balance failed: %v", err)
|
|
}
|
|
}
|
|
|
|
// SetGiftPrice overrides or inserts a gift settlement price for server-side billing tests.
|
|
func (r *Repository) SetGiftPrice(giftID string, priceVersion string, coinPrice int64, giftPointAmount int64, heatValue int64) {
|
|
r.t.Helper()
|
|
|
|
nowMs := time.Now().UnixMilli()
|
|
_, err := r.schema.DB.ExecContext(context.Background(), `
|
|
INSERT INTO wallet_gift_prices (
|
|
gift_id, price_version, status, coin_price, gift_point_amount, heat_value,
|
|
effective_at_ms, created_at_ms, updated_at_ms
|
|
) VALUES (?, ?, 'active', ?, ?, ?, 0, ?, ?)
|
|
ON DUPLICATE KEY UPDATE
|
|
status = VALUES(status),
|
|
coin_price = VALUES(coin_price),
|
|
gift_point_amount = VALUES(gift_point_amount),
|
|
heat_value = VALUES(heat_value),
|
|
updated_at_ms = VALUES(updated_at_ms)
|
|
`, giftID, priceVersion, coinPrice, giftPointAmount, heatValue, nowMs, nowMs)
|
|
if err != nil {
|
|
r.t.Fatalf("seed wallet gift price failed: %v", err)
|
|
}
|
|
}
|
|
|
|
func initDBPath(t testing.TB) string {
|
|
t.Helper()
|
|
|
|
return mysqlschema.InitDBPath(t,
|
|
mysqlschema.CallerFile(t, 1),
|
|
"..", "..", "..", "deploy", "mysql", "initdb", "001_wallet_service.sql",
|
|
)
|
|
}
|
|
|
|
func validateTableName(table string) string {
|
|
switch table {
|
|
case "wallet_transactions", "wallet_entries", "wallet_outbox", "wallet_accounts":
|
|
return table
|
|
default:
|
|
panic(fmt.Sprintf("unsupported wallet test table %q", table))
|
|
}
|
|
}
|