mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
The config package used `package _config` with a leading underscore, which is unconventional in Go. Rename to `package config` (matching the directory name) and use `cfg` as the standard import alias across all 93 importing files.
410 lines
9.2 KiB
Go
410 lines
9.2 KiB
Go
package channelserver
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"erupe-ce/common/byteframe"
|
|
cfg "erupe-ce/config"
|
|
)
|
|
|
|
func TestWriteShopItems_Empty(t *testing.T) {
|
|
bf := byteframe.NewByteFrame()
|
|
items := []ShopItem{}
|
|
|
|
writeShopItems(bf, items, cfg.ZZ)
|
|
|
|
result := byteframe.NewByteFrameFromBytes(bf.Data())
|
|
count1 := result.ReadUint16()
|
|
count2 := result.ReadUint16()
|
|
|
|
if count1 != 0 {
|
|
t.Errorf("Expected first count 0, got %d", count1)
|
|
}
|
|
if count2 != 0 {
|
|
t.Errorf("Expected second count 0, got %d", count2)
|
|
}
|
|
}
|
|
|
|
func TestWriteShopItems_SingleItem(t *testing.T) {
|
|
bf := byteframe.NewByteFrame()
|
|
items := []ShopItem{
|
|
{
|
|
ID: 1,
|
|
ItemID: 100,
|
|
Cost: 500,
|
|
Quantity: 10,
|
|
MinHR: 1,
|
|
MinSR: 0,
|
|
MinGR: 0,
|
|
StoreLevel: 1,
|
|
MaxQuantity: 99,
|
|
UsedQuantity: 5,
|
|
RoadFloors: 0,
|
|
RoadFatalis: 0,
|
|
},
|
|
}
|
|
|
|
writeShopItems(bf, items, cfg.ZZ)
|
|
|
|
result := byteframe.NewByteFrameFromBytes(bf.Data())
|
|
count1 := result.ReadUint16()
|
|
count2 := result.ReadUint16()
|
|
|
|
if count1 != 1 {
|
|
t.Errorf("Expected first count 1, got %d", count1)
|
|
}
|
|
if count2 != 1 {
|
|
t.Errorf("Expected second count 1, got %d", count2)
|
|
}
|
|
|
|
// Read the item data
|
|
id := result.ReadUint32()
|
|
_ = result.ReadUint16() // padding
|
|
itemID := result.ReadUint16()
|
|
cost := result.ReadUint32()
|
|
quantity := result.ReadUint16()
|
|
minHR := result.ReadUint16()
|
|
minSR := result.ReadUint16()
|
|
minGR := result.ReadUint16()
|
|
storeLevel := result.ReadUint16()
|
|
maxQuantity := result.ReadUint16()
|
|
usedQuantity := result.ReadUint16()
|
|
roadFloors := result.ReadUint16()
|
|
roadFatalis := result.ReadUint16()
|
|
|
|
if id != 1 {
|
|
t.Errorf("Expected ID 1, got %d", id)
|
|
}
|
|
if itemID != 100 {
|
|
t.Errorf("Expected itemID 100, got %d", itemID)
|
|
}
|
|
if cost != 500 {
|
|
t.Errorf("Expected cost 500, got %d", cost)
|
|
}
|
|
if quantity != 10 {
|
|
t.Errorf("Expected quantity 10, got %d", quantity)
|
|
}
|
|
if minHR != 1 {
|
|
t.Errorf("Expected minHR 1, got %d", minHR)
|
|
}
|
|
if minSR != 0 {
|
|
t.Errorf("Expected minSR 0, got %d", minSR)
|
|
}
|
|
if minGR != 0 {
|
|
t.Errorf("Expected minGR 0, got %d", minGR)
|
|
}
|
|
if storeLevel != 1 {
|
|
t.Errorf("Expected storeLevel 1, got %d", storeLevel)
|
|
}
|
|
if maxQuantity != 99 {
|
|
t.Errorf("Expected maxQuantity 99, got %d", maxQuantity)
|
|
}
|
|
if usedQuantity != 5 {
|
|
t.Errorf("Expected usedQuantity 5, got %d", usedQuantity)
|
|
}
|
|
if roadFloors != 0 {
|
|
t.Errorf("Expected roadFloors 0, got %d", roadFloors)
|
|
}
|
|
if roadFatalis != 0 {
|
|
t.Errorf("Expected roadFatalis 0, got %d", roadFatalis)
|
|
}
|
|
}
|
|
|
|
func TestWriteShopItems_MultipleItems(t *testing.T) {
|
|
bf := byteframe.NewByteFrame()
|
|
items := []ShopItem{
|
|
{ID: 1, ItemID: 100, Cost: 500, Quantity: 10},
|
|
{ID: 2, ItemID: 200, Cost: 1000, Quantity: 5},
|
|
{ID: 3, ItemID: 300, Cost: 2000, Quantity: 1},
|
|
}
|
|
|
|
writeShopItems(bf, items, cfg.ZZ)
|
|
|
|
result := byteframe.NewByteFrameFromBytes(bf.Data())
|
|
count1 := result.ReadUint16()
|
|
count2 := result.ReadUint16()
|
|
|
|
if count1 != 3 {
|
|
t.Errorf("Expected first count 3, got %d", count1)
|
|
}
|
|
if count2 != 3 {
|
|
t.Errorf("Expected second count 3, got %d", count2)
|
|
}
|
|
}
|
|
|
|
// Test struct definitions
|
|
func TestShopItemStruct(t *testing.T) {
|
|
item := ShopItem{
|
|
ID: 42,
|
|
ItemID: 1234,
|
|
Cost: 9999,
|
|
Quantity: 50,
|
|
MinHR: 10,
|
|
MinSR: 5,
|
|
MinGR: 100,
|
|
StoreLevel: 3,
|
|
MaxQuantity: 99,
|
|
UsedQuantity: 10,
|
|
RoadFloors: 50,
|
|
RoadFatalis: 25,
|
|
}
|
|
|
|
if item.ID != 42 {
|
|
t.Errorf("ID = %d, want 42", item.ID)
|
|
}
|
|
if item.ItemID != 1234 {
|
|
t.Errorf("ItemID = %d, want 1234", item.ItemID)
|
|
}
|
|
if item.Cost != 9999 {
|
|
t.Errorf("Cost = %d, want 9999", item.Cost)
|
|
}
|
|
}
|
|
|
|
func TestGachaStruct(t *testing.T) {
|
|
gacha := Gacha{
|
|
ID: 1,
|
|
MinGR: 100,
|
|
MinHR: 999,
|
|
Name: "Test Gacha",
|
|
URLBanner: "http://example.com/banner.png",
|
|
URLFeature: "http://example.com/feature.png",
|
|
URLThumbnail: "http://example.com/thumb.png",
|
|
Wide: true,
|
|
Recommended: true,
|
|
GachaType: 2,
|
|
Hidden: false,
|
|
}
|
|
|
|
if gacha.ID != 1 {
|
|
t.Errorf("ID = %d, want 1", gacha.ID)
|
|
}
|
|
if gacha.Name != "Test Gacha" {
|
|
t.Errorf("Name = %s, want Test Gacha", gacha.Name)
|
|
}
|
|
if !gacha.Wide {
|
|
t.Error("Wide should be true")
|
|
}
|
|
if !gacha.Recommended {
|
|
t.Error("Recommended should be true")
|
|
}
|
|
}
|
|
|
|
func TestGachaEntryStruct(t *testing.T) {
|
|
entry := GachaEntry{
|
|
EntryType: 1,
|
|
ID: 100,
|
|
ItemType: 0,
|
|
ItemNumber: 1234,
|
|
ItemQuantity: 10,
|
|
Weight: 0.5,
|
|
Rarity: 3,
|
|
Rolls: 1,
|
|
FrontierPoints: 500,
|
|
DailyLimit: 5,
|
|
}
|
|
|
|
if entry.EntryType != 1 {
|
|
t.Errorf("EntryType = %d, want 1", entry.EntryType)
|
|
}
|
|
if entry.ID != 100 {
|
|
t.Errorf("ID = %d, want 100", entry.ID)
|
|
}
|
|
if entry.Weight != 0.5 {
|
|
t.Errorf("Weight = %f, want 0.5", entry.Weight)
|
|
}
|
|
}
|
|
|
|
func TestGachaItemStruct(t *testing.T) {
|
|
item := GachaItem{
|
|
ItemType: 0,
|
|
ItemID: 5678,
|
|
Quantity: 20,
|
|
}
|
|
|
|
if item.ItemType != 0 {
|
|
t.Errorf("ItemType = %d, want 0", item.ItemType)
|
|
}
|
|
if item.ItemID != 5678 {
|
|
t.Errorf("ItemID = %d, want 5678", item.ItemID)
|
|
}
|
|
if item.Quantity != 20 {
|
|
t.Errorf("Quantity = %d, want 20", item.Quantity)
|
|
}
|
|
}
|
|
|
|
func TestGetRandomEntries_ZeroRolls(t *testing.T) {
|
|
entries := []GachaEntry{
|
|
{ID: 1, Weight: 1.0},
|
|
}
|
|
result, err := getRandomEntries(entries, 0, false)
|
|
if err != nil {
|
|
t.Errorf("unexpected error: %v", err)
|
|
}
|
|
if len(result) != 0 {
|
|
t.Errorf("expected 0 results, got %d", len(result))
|
|
}
|
|
}
|
|
|
|
func TestGetRandomEntries_SingleEntryNonBox(t *testing.T) {
|
|
entries := []GachaEntry{
|
|
{ID: 1, Weight: 1.0, ItemNumber: 100},
|
|
}
|
|
result, err := getRandomEntries(entries, 3, false)
|
|
if err != nil {
|
|
t.Errorf("unexpected error: %v", err)
|
|
}
|
|
if len(result) != 3 {
|
|
t.Errorf("expected 3 results, got %d", len(result))
|
|
}
|
|
for i, r := range result {
|
|
if r.ID != 1 {
|
|
t.Errorf("result[%d].ID = %d, expected 1", i, r.ID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGetRandomEntries_NonBoxAllowsDuplicates(t *testing.T) {
|
|
entries := []GachaEntry{
|
|
{ID: 1, Weight: 1.0},
|
|
}
|
|
result, err := getRandomEntries(entries, 5, false)
|
|
if err != nil {
|
|
t.Errorf("unexpected error: %v", err)
|
|
}
|
|
if len(result) != 5 {
|
|
t.Errorf("expected 5 results, got %d", len(result))
|
|
}
|
|
// All should be the same since there's only one entry
|
|
for i, r := range result {
|
|
if r.ID != 1 {
|
|
t.Errorf("result[%d].ID = %d, expected 1", i, r.ID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGetRandomEntries_BoxModeRemovesSelected(t *testing.T) {
|
|
entries := []GachaEntry{
|
|
{ID: 1, Weight: 1.0},
|
|
{ID: 2, Weight: 1.0},
|
|
{ID: 3, Weight: 1.0},
|
|
}
|
|
result, err := getRandomEntries(entries, 3, true)
|
|
if err != nil {
|
|
t.Errorf("unexpected error: %v", err)
|
|
}
|
|
if len(result) != 3 {
|
|
t.Errorf("expected 3 results, got %d", len(result))
|
|
}
|
|
|
|
// In box mode, all entries should be unique
|
|
seen := make(map[uint32]bool)
|
|
for _, r := range result {
|
|
if seen[r.ID] {
|
|
t.Errorf("duplicate entry in box mode: ID=%d", r.ID)
|
|
}
|
|
seen[r.ID] = true
|
|
}
|
|
}
|
|
|
|
func TestGetRandomEntries_BoxModeMatchingCount(t *testing.T) {
|
|
entries := []GachaEntry{
|
|
{ID: 1, Weight: 1.0},
|
|
{ID: 2, Weight: 1.0},
|
|
}
|
|
result, err := getRandomEntries(entries, 2, true)
|
|
if err != nil {
|
|
t.Errorf("unexpected error: %v", err)
|
|
}
|
|
if len(result) != 2 {
|
|
t.Errorf("expected 2 results, got %d", len(result))
|
|
}
|
|
|
|
// Should contain both entries exactly once
|
|
seen := make(map[uint32]bool)
|
|
for _, r := range result {
|
|
seen[r.ID] = true
|
|
}
|
|
if !seen[1] || !seen[2] {
|
|
t.Errorf("box mode should return all entries when rolls == len(entries)")
|
|
}
|
|
}
|
|
|
|
func TestGetRandomEntries_WeightedSelectionBias(t *testing.T) {
|
|
// Test that weighted selection respects weights
|
|
entries := []GachaEntry{
|
|
{ID: 1, Weight: 100.0}, // Very high weight
|
|
{ID: 2, Weight: 0.001}, // Very low weight
|
|
}
|
|
|
|
// Run many iterations
|
|
counts := make(map[uint32]int)
|
|
for i := 0; i < 1000; i++ {
|
|
result, _ := getRandomEntries(entries, 1, false)
|
|
if len(result) > 0 {
|
|
counts[result[0].ID]++
|
|
}
|
|
}
|
|
|
|
// ID 1 should be selected much more often
|
|
if counts[1] <= counts[2] {
|
|
t.Errorf("weighted selection not working: high weight count=%d, low weight count=%d",
|
|
counts[1], counts[2])
|
|
}
|
|
}
|
|
|
|
func TestGetRandomEntries_MultipleEntriesMultipleRolls(t *testing.T) {
|
|
entries := []GachaEntry{
|
|
{ID: 1, Weight: 1.0},
|
|
{ID: 2, Weight: 1.0},
|
|
{ID: 3, Weight: 1.0},
|
|
}
|
|
result, err := getRandomEntries(entries, 10, false)
|
|
if err != nil {
|
|
t.Errorf("unexpected error: %v", err)
|
|
}
|
|
if len(result) != 10 {
|
|
t.Errorf("expected 10 results, got %d", len(result))
|
|
}
|
|
|
|
// All results should have valid IDs
|
|
for i, r := range result {
|
|
if r.ID < 1 || r.ID > 3 {
|
|
t.Errorf("result[%d].ID = %d, expected 1, 2, or 3", i, r.ID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGetRandomEntries_PreservesEntryData(t *testing.T) {
|
|
entries := []GachaEntry{
|
|
{
|
|
ID: 1,
|
|
Weight: 1.0,
|
|
ItemNumber: 100,
|
|
ItemQuantity: 5,
|
|
Rarity: 3,
|
|
FrontierPoints: 500,
|
|
},
|
|
}
|
|
result, err := getRandomEntries(entries, 1, false)
|
|
if err != nil {
|
|
t.Errorf("unexpected error: %v", err)
|
|
}
|
|
if len(result) != 1 {
|
|
t.Fatalf("expected 1 result, got %d", len(result))
|
|
}
|
|
|
|
r := result[0]
|
|
if r.ItemNumber != 100 {
|
|
t.Errorf("ItemNumber = %d, expected 100", r.ItemNumber)
|
|
}
|
|
if r.ItemQuantity != 5 {
|
|
t.Errorf("ItemQuantity = %d, expected 5", r.ItemQuantity)
|
|
}
|
|
if r.Rarity != 3 {
|
|
t.Errorf("Rarity = %d, expected 3", r.Rarity)
|
|
}
|
|
if r.FrontierPoints != 500 {
|
|
t.Errorf("FrontierPoints = %d, expected 500", r.FrontierPoints)
|
|
}
|
|
}
|