mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 15:43:49 +01:00
GetRewardPool now requires entries to have items (EXISTS clause from
2365b63), but the ordering test created entries without items.
380 lines
10 KiB
Go
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))
|
|
}
|
|
}
|