package roomrocket import ( "errors" "testing" ) func TestNormalizeConfigDefaultsAndSortsLevels(t *testing.T) { config, err := normalizeConfig(RoomRocketConfig{ AppCode: "lalu", LaunchDelayMS: defaultLaunchDelayMS, Levels: []RoomRocketLevelConfig{ {Level: 2, FuelThreshold: 300}, {Level: 1, FuelThreshold: 100}, {Level: 3, FuelThreshold: 600}, {Level: 4, FuelThreshold: 1_000}, {Level: 5, FuelThreshold: 1_500}, {Level: 6, FuelThreshold: 2_100}, {Level: 7, FuelThreshold: 2_800}, }, }) if err != nil { t.Fatalf("normalizeConfig failed: %v", err) } if config.FuelSource != defaultFuelSource || config.LaunchDelayMS != defaultLaunchDelayMS || config.BroadcastScope != defaultBroadcastScope { t.Fatalf("default fields mismatch: %+v", config) } if config.Levels[0].Level != 1 || config.Levels[6].Level != 7 { t.Fatalf("levels should be sorted by level: %+v", config.Levels) } } func TestDefaultConfigKeepsOperationalDefaults(t *testing.T) { config, err := normalizeConfig(defaultConfig("lalu")) if err != nil { t.Fatalf("normalizeConfig(defaultConfig) failed: %v", err) } if !config.BroadcastEnabled || config.LaunchDelayMS != defaultLaunchDelayMS || len(config.Levels) != roomRocketLevelCount { t.Fatalf("default config mismatch: %+v", config) } } func TestNormalizeConfigRejectsInvalidLevels(t *testing.T) { tests := []struct { name string config RoomRocketConfig }{ {name: "missing_level", config: RoomRocketConfig{AppCode: "lalu", Levels: []RoomRocketLevelConfig{{Level: 1, FuelThreshold: 1}}}}, {name: "duplicate", config: RoomRocketConfig{AppCode: "lalu", Levels: []RoomRocketLevelConfig{ {Level: 1, FuelThreshold: 1}, {Level: 1, FuelThreshold: 2}, {Level: 3, FuelThreshold: 3}, {Level: 4, FuelThreshold: 4}, {Level: 5, FuelThreshold: 5}, {Level: 6, FuelThreshold: 6}, {Level: 7, FuelThreshold: 7}, }}}, {name: "zero_threshold", config: RoomRocketConfig{AppCode: "lalu", Levels: []RoomRocketLevelConfig{ {Level: 1, FuelThreshold: 0}, {Level: 2, FuelThreshold: 2}, {Level: 3, FuelThreshold: 3}, {Level: 4, FuelThreshold: 4}, {Level: 5, FuelThreshold: 5}, {Level: 6, FuelThreshold: 6}, {Level: 7, FuelThreshold: 7}, }}}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { _, err := normalizeConfig(test.config) if !errors.Is(err, ErrInvalidArgument) { t.Fatalf("normalizeConfig should reject %s with ErrInvalidArgument, got %v", test.name, err) } }) } } func TestNormalizeConfigRejectsIncompleteRewardAndFuelRule(t *testing.T) { config := defaultConfig("lalu") config.Levels[0].InRoomRewards = []RoomRocketRewardItem{{ResourceGroupID: 0, Weight: 100}} if _, err := normalizeConfig(config); !errors.Is(err, ErrInvalidArgument) { t.Fatalf("reward without resource group should be invalid, got %v", err) } config = defaultConfig("lalu") config.GiftFuelRules = []GiftFuelRuleConfig{{GiftID: "gift-1"}} if _, err := normalizeConfig(config); !errors.Is(err, ErrInvalidArgument) { t.Fatalf("energy rule without multiplier or fixed energy should be invalid, got %v", err) } }