package common import ( "encoding/json" "os" "path/filepath" "testing" ) func TestFeaturedGachaUsesCapturedBannerAndPreservesProgression(t *testing.T) { catalog, err := os.ReadFile(filepath.Join("..", "..", "resources", "PreviewGameplayCatalog.json")) if err != nil { t.Fatal(err) } policy, err := os.ReadFile(filepath.Join("..", "..", "resources", "GachaSandboxPolicy.json")) if err != nil { t.Fatal(err) } // This store test supplies its own asset verification; production must not // infer installed bundle availability from the captured flat table. var fixtureCatalog struct { Tables struct { Gacha []struct { Prefab string `json:"PrefabPath"` } `json:"gacha"` } `json:"tables"` } if err = json.Unmarshal(catalog, &fixtureCatalog); err != nil { t.Fatal(err) } var fixturePolicy GachaSandboxPolicy if err = json.Unmarshal(policy, &fixturePolicy); err != nil { t.Fatal(err) } for _, row := range fixtureCatalog.Tables.Gacha { fixturePolicy.VerifiedBannerPrefabs = append(fixturePolicy.VerifiedBannerPrefabs, row.Prefab) } policy, err = json.Marshal(fixturePolicy) if err != nil { t.Fatal(err) } t.Chdir(t.TempDir()) if err = os.Mkdir("resources", 0755); err != nil { t.Fatal(err) } if err = os.WriteFile(filepath.Join("resources", "PreviewGameplayCatalog.json"), catalog, 0644); err != nil { t.Fatal(err) } if err = os.WriteFile(filepath.Join("resources", "GachaSandboxPolicy.json"), policy, 0644); err != nil { t.Fatal(err) } banners, _, err := LoadFeaturedGachaBanners() if err != nil || len(banners) == 0 { t.Fatalf("catalog: %v", err) } avatar := banners[0].AvatarID initial := map[string]any{"avatars": map[uint32]any{avatar: map[string]any{"avatar_id": avatar, "data": map[string]any{"rank": 6, "skills": map[string]uint32{"preserve": 1}}, "ex_rank_unlocked": false}}, "materials": map[uint32]uint32{2: 73}, "unrelated": "preserve"} raw, err := json.Marshal(initial) if err != nil { t.Fatal(err) } if err = os.WriteFile("freesr-data.json", raw, 0644); err != nil { t.Fatal(err) } // Fixture material identity is a store key, not an invented production grant. const material = uint32(77) result, err := GrantGachaDuplicate(avatar, map[uint32]uint32{material: 10}, map[uint32]uint32{material: 6}) if err != nil || result[material] != 16 { t.Fatalf("generated baseline grant: %v %v", result, err) } result, err = GrantGachaDuplicate(avatar, map[uint32]uint32{material: 1}, map[uint32]uint32{material: 6}) if err != nil || result[material] != 17 { t.Fatalf("latest override grant: %v %v", result, err) } saved, err := os.ReadFile("freesr-data.json") if err != nil { t.Fatal(err) } var before, after map[string]json.RawMessage json.Unmarshal(raw, &before) json.Unmarshal(saved, &after) for _, key := range []string{"avatars", "unrelated"} { var a, b any json.Unmarshal(before[key], &a) json.Unmarshal(after[key], &b) x, _ := json.Marshal(a) y, _ := json.Marshal(b) if string(x) != string(y) { t.Fatalf("changed %s", key) } } if _, err = GrantGachaDuplicate(avatar, map[uint32]uint32{material: ^uint32(0)}, nil); err == nil { t.Fatal("accepted overflow") } current, _ := os.ReadFile("freesr-data.json") if string(current) != string(saved) { t.Fatal("failed grant changed import") } }