Files
Erupe/server/channelserver/repo_gacha_test.go
Houmgaor 1ae7dffe7b fix(gacha): add items to reward pool test entries
GetRewardPool now requires entries to have items (EXISTS clause from
2365b63), but the ordering test created entries without items.
2026-03-16 00:07:46 +01:00

380 lines
10 KiB
Go

package channelserver
import (
"database/sql"
"errors"
"testing"
"github.com/jmoiron/sqlx"
)
func setupGachaRepo(t *testing.T) (*GachaRepository, *sqlx.DB, uint32) {
t.Helper()
db := SetupTestDB(t)
userID := CreateTestUser(t, db, "gacha_test_user")
charID := CreateTestCharacter(t, db, userID, "GachaChar")
repo := NewGachaRepository(db)
t.Cleanup(func() { TeardownTestDB(t, db) })
return repo, db, charID
}
func TestRepoGachaListShopEmpty(t *testing.T) {
repo, _, _ := setupGachaRepo(t)
shops, err := repo.ListShop()
if err != nil {
t.Fatalf("ListShop failed: %v", err)
}
if len(shops) != 0 {
t.Errorf("Expected empty shop list, got: %d", len(shops))
}
}
func TestRepoGachaListShop(t *testing.T) {
repo, db, _ := setupGachaRepo(t)
CreateTestGachaShop(t, db, "Test Gacha", 1)
CreateTestGachaShop(t, db, "Premium Gacha", 2)
shops, err := repo.ListShop()
if err != nil {
t.Fatalf("ListShop failed: %v", err)
}
if len(shops) != 2 {
t.Fatalf("Expected 2 shops, got: %d", len(shops))
}
}
func TestRepoGachaGetShopType(t *testing.T) {
repo, db, _ := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "Type Test", 3)
gachaType, err := repo.GetShopType(shopID)
if err != nil {
t.Fatalf("GetShopType failed: %v", err)
}
if gachaType != 3 {
t.Errorf("Expected gacha_type=3, got: %d", gachaType)
}
}
func TestRepoGachaGetEntryForTransaction(t *testing.T) {
repo, db, _ := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "Entry Test", 1)
_, err := db.Exec(
`INSERT INTO gacha_entries (gacha_id, entry_type, weight, rarity, item_type, item_number, item_quantity, rolls, frontier_points, daily_limit)
VALUES ($1, 5, 100, 1, 7, 500, 10, 3, 0, 0)`, shopID,
)
if err != nil {
t.Fatalf("Setup failed: %v", err)
}
itemType, itemNumber, rolls, err := repo.GetEntryForTransaction(shopID, 5)
if err != nil {
t.Fatalf("GetEntryForTransaction failed: %v", err)
}
if itemType != 7 {
t.Errorf("Expected itemType=7, got: %d", itemType)
}
if itemNumber != 500 {
t.Errorf("Expected itemNumber=500, got: %d", itemNumber)
}
if rolls != 3 {
t.Errorf("Expected rolls=3, got: %d", rolls)
}
}
func TestRepoGachaGetRewardPoolEmpty(t *testing.T) {
repo, db, _ := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "Empty Pool", 1)
entries, err := repo.GetRewardPool(shopID)
if err != nil {
t.Fatalf("GetRewardPool failed: %v", err)
}
if len(entries) != 0 {
t.Errorf("Expected empty reward pool, got: %d", len(entries))
}
}
func TestRepoGachaGetRewardPoolOrdering(t *testing.T) {
repo, db, _ := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "Pool Test", 1)
// entry_type=100 is the reward pool; each entry needs at least one item
e1 := CreateTestGachaEntry(t, db, shopID, 100, 50)
CreateTestGachaItem(t, db, e1, 1, 100, 1)
e2 := CreateTestGachaEntry(t, db, shopID, 100, 200)
CreateTestGachaItem(t, db, e2, 1, 101, 1)
e3 := CreateTestGachaEntry(t, db, shopID, 100, 100)
CreateTestGachaItem(t, db, e3, 1, 102, 1)
// entry_type=5 should NOT appear in reward pool
e4 := CreateTestGachaEntry(t, db, shopID, 5, 999)
CreateTestGachaItem(t, db, e4, 1, 103, 1)
entries, err := repo.GetRewardPool(shopID)
if err != nil {
t.Fatalf("GetRewardPool failed: %v", err)
}
if len(entries) != 3 {
t.Fatalf("Expected 3 reward entries, got: %d", len(entries))
}
// Should be ordered by weight DESC
if entries[0].Weight < entries[1].Weight || entries[1].Weight < entries[2].Weight {
t.Errorf("Expected descending weight order, got: %v, %v, %v", entries[0].Weight, entries[1].Weight, entries[2].Weight)
}
}
func TestRepoGachaGetItemsForEntry(t *testing.T) {
repo, db, _ := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "Items Test", 1)
entryID := CreateTestGachaEntry(t, db, shopID, 100, 100)
CreateTestGachaItem(t, db, entryID, 1, 100, 5)
CreateTestGachaItem(t, db, entryID, 2, 200, 10)
items, err := repo.GetItemsForEntry(entryID)
if err != nil {
t.Fatalf("GetItemsForEntry failed: %v", err)
}
if len(items) != 2 {
t.Fatalf("Expected 2 items, got: %d", len(items))
}
}
func TestRepoGachaGetGuaranteedItems(t *testing.T) {
repo, db, _ := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "Guaranteed Test", 1)
entryID := CreateTestGachaEntry(t, db, shopID, 10, 0)
CreateTestGachaItem(t, db, entryID, 3, 300, 1)
items, err := repo.GetGuaranteedItems(10, shopID)
if err != nil {
t.Fatalf("GetGuaranteedItems failed: %v", err)
}
if len(items) != 1 {
t.Fatalf("Expected 1 guaranteed item, got: %d", len(items))
}
if items[0].ItemID != 300 {
t.Errorf("Expected item_id=300, got: %d", items[0].ItemID)
}
}
func TestRepoGachaGetAllEntries(t *testing.T) {
repo, db, _ := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "All Entries", 1)
CreateTestGachaEntry(t, db, shopID, 100, 50)
CreateTestGachaEntry(t, db, shopID, 5, 200)
entries, err := repo.GetAllEntries(shopID)
if err != nil {
t.Fatalf("GetAllEntries failed: %v", err)
}
if len(entries) != 2 {
t.Fatalf("Expected 2 entries, got: %d", len(entries))
}
}
func TestRepoGachaGetWeightDivisorZero(t *testing.T) {
repo, db, _ := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "Zero Weight", 1)
divisor, err := repo.GetWeightDivisor(shopID)
if err != nil {
t.Fatalf("GetWeightDivisor failed: %v", err)
}
if divisor != 0 {
t.Errorf("Expected divisor=0 for empty, got: %f", divisor)
}
}
func TestRepoGachaGetWeightDivisor(t *testing.T) {
repo, db, _ := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "Weight Test", 1)
CreateTestGachaEntry(t, db, shopID, 100, 50000)
CreateTestGachaEntry(t, db, shopID, 100, 50000)
divisor, err := repo.GetWeightDivisor(shopID)
if err != nil {
t.Fatalf("GetWeightDivisor failed: %v", err)
}
// (50000 + 50000) / 100000 = 1.0
if divisor != 1.0 {
t.Errorf("Expected divisor=1.0, got: %f", divisor)
}
}
func TestRepoGachaHasEntryTypeTrue(t *testing.T) {
repo, db, _ := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "HasType Test", 1)
CreateTestGachaEntry(t, db, shopID, 100, 50)
has, err := repo.HasEntryType(shopID, 100)
if err != nil {
t.Fatalf("HasEntryType failed: %v", err)
}
if !has {
t.Error("Expected HasEntryType=true for entry_type=100")
}
}
func TestRepoGachaHasEntryTypeFalse(t *testing.T) {
repo, db, _ := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "HasType False", 1)
has, err := repo.HasEntryType(shopID, 100)
if err != nil {
t.Fatalf("HasEntryType failed: %v", err)
}
if has {
t.Error("Expected HasEntryType=false for empty gacha")
}
}
// Stepup tests
func TestRepoGachaStepupLifecycle(t *testing.T) {
repo, db, charID := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "Stepup Test", 1)
// Insert stepup
if err := repo.InsertStepup(shopID, 1, charID); err != nil {
t.Fatalf("InsertStepup failed: %v", err)
}
// Get step
step, err := repo.GetStepupStep(shopID, charID)
if err != nil {
t.Fatalf("GetStepupStep failed: %v", err)
}
if step != 1 {
t.Errorf("Expected step=1, got: %d", step)
}
// Delete stepup
if err := repo.DeleteStepup(shopID, charID); err != nil {
t.Fatalf("DeleteStepup failed: %v", err)
}
// Get step should fail
_, err = repo.GetStepupStep(shopID, charID)
if err == nil {
t.Fatal("Expected error after DeleteStepup, got nil")
}
}
func TestRepoGachaGetStepupWithTime(t *testing.T) {
repo, db, charID := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "Stepup Time", 1)
if err := repo.InsertStepup(shopID, 2, charID); err != nil {
t.Fatalf("InsertStepup failed: %v", err)
}
step, createdAt, err := repo.GetStepupWithTime(shopID, charID)
if err != nil {
t.Fatalf("GetStepupWithTime failed: %v", err)
}
if step != 2 {
t.Errorf("Expected step=2, got: %d", step)
}
if createdAt.IsZero() {
t.Error("Expected non-zero created_at")
}
}
func TestRepoGachaGetStepupWithTimeNotFound(t *testing.T) {
repo, db, charID := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "Stepup NF", 1)
_, _, err := repo.GetStepupWithTime(shopID, charID)
if !errors.Is(err, sql.ErrNoRows) {
t.Fatalf("Expected sql.ErrNoRows, got: %v", err)
}
}
// Box gacha tests
func TestRepoGachaBoxLifecycle(t *testing.T) {
repo, db, charID := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "Box Test", 1)
entryID1 := CreateTestGachaEntry(t, db, shopID, 100, 50)
entryID2 := CreateTestGachaEntry(t, db, shopID, 100, 100)
// Initially empty
ids, err := repo.GetBoxEntryIDs(shopID, charID)
if err != nil {
t.Fatalf("GetBoxEntryIDs failed: %v", err)
}
if len(ids) != 0 {
t.Errorf("Expected empty box, got: %d entries", len(ids))
}
// Insert drawn entries
if err := repo.InsertBoxEntry(shopID, entryID1, charID); err != nil {
t.Fatalf("InsertBoxEntry failed: %v", err)
}
if err := repo.InsertBoxEntry(shopID, entryID2, charID); err != nil {
t.Fatalf("InsertBoxEntry failed: %v", err)
}
ids, err = repo.GetBoxEntryIDs(shopID, charID)
if err != nil {
t.Fatalf("GetBoxEntryIDs failed: %v", err)
}
if len(ids) != 2 {
t.Errorf("Expected 2 box entries, got: %d", len(ids))
}
// Delete all box entries (reset)
if err := repo.DeleteBoxEntries(shopID, charID); err != nil {
t.Fatalf("DeleteBoxEntries failed: %v", err)
}
ids, err = repo.GetBoxEntryIDs(shopID, charID)
if err != nil {
t.Fatalf("GetBoxEntryIDs after delete failed: %v", err)
}
if len(ids) != 0 {
t.Errorf("Expected empty box after delete, got: %d", len(ids))
}
}
func TestRepoGachaBoxIsolation(t *testing.T) {
repo, db, charID := setupGachaRepo(t)
shopID := CreateTestGachaShop(t, db, "Box Iso", 1)
entryID := CreateTestGachaEntry(t, db, shopID, 100, 50)
// Create another character
userID2 := CreateTestUser(t, db, "gacha_other_user")
charID2 := CreateTestCharacter(t, db, userID2, "GachaChar2")
// Char1 draws
if err := repo.InsertBoxEntry(shopID, entryID, charID); err != nil {
t.Fatalf("InsertBoxEntry failed: %v", err)
}
// Char2 should have empty box
ids, err := repo.GetBoxEntryIDs(shopID, charID2)
if err != nil {
t.Fatalf("GetBoxEntryIDs for char2 failed: %v", err)
}
if len(ids) != 0 {
t.Errorf("Expected empty box for char2, got: %d entries", len(ids))
}
}