Implement hunting AP and progress, event tasks, exchanges, games, stories and actions; connect battle and reward handling. Add CashShop plugin and installation, server purchases and entitlements, recharge rules and plugin version metadata. Distribute binary calendars independently; cache GameData in memory and fix single-connection query deadlocks. Improve automatic login and recovery diagnostics; document configuration and release flows.
163 lines
6.0 KiB
Go
163 lines
6.0 KiB
Go
package plugin
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestInstallRequiresBepInExWithoutCopyingPlugin(t *testing.T) {
|
|
for _, spec := range []Spec{LocalIdentity, LoginUI, CashShop} {
|
|
t.Run(spec.FileName(), func(t *testing.T) {
|
|
gameDir := t.TempDir()
|
|
for path, data := range map[string][]byte{
|
|
filepath.Join(gameDir, "BrownDust II.exe"): []byte("game"),
|
|
filepath.Join(gameDir, "BrownDust II_Data", "resources.assets"): []byte("assets"),
|
|
} {
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(path, data, 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
source := filepath.Join(t.TempDir(), spec.FileName())
|
|
if err := os.WriteFile(filepath.Join(filepath.Dir(source), GameNames.FileName()), []byte("names-v1"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(source, []byte("plugin"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, err := Install(spec, gameDir, source)
|
|
if err == nil || !strings.Contains(err.Error(), BepInExReleasesURL) {
|
|
t.Fatalf("missing BepInEx error=%v", err)
|
|
}
|
|
if _, statErr := os.Stat(filepath.Join(gameDir, "BepInEx", "plugins", spec.FileName())); !os.IsNotExist(statErr) {
|
|
t.Fatalf("plugin was copied without BepInEx: %v", statErr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInstallCopiesUpdatesAndSkipsIdenticalPlugin(t *testing.T) {
|
|
for _, spec := range []Spec{LocalIdentity, LoginUI, CashShop} {
|
|
t.Run(spec.FileName(), func(t *testing.T) {
|
|
gameDir := t.TempDir()
|
|
for path, data := range map[string][]byte{
|
|
filepath.Join(gameDir, "BrownDust II.exe"): []byte("game"),
|
|
filepath.Join(gameDir, "BrownDust II_Data", "resources.assets"): []byte("assets"),
|
|
filepath.Join(gameDir, "BepInEx", "core", "BepInEx.dll"): []byte("bepinex"),
|
|
} {
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(path, data, 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
source := filepath.Join(t.TempDir(), spec.FileName())
|
|
if err := os.WriteFile(filepath.Join(filepath.Dir(source), GameNames.FileName()), []byte("names-v1"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(source, []byte("v1"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
first, err := Install(spec, gameDir, source)
|
|
if err != nil || !first.Changed {
|
|
t.Fatalf("first install=%+v err=%v", first, err)
|
|
}
|
|
second, err := Install(spec, gameDir, source)
|
|
if err != nil || second.Changed {
|
|
t.Fatalf("idempotent install=%+v err=%v", second, err)
|
|
}
|
|
runtimeSource := filepath.Join(filepath.Dir(source), GameNames.FileName())
|
|
if err := os.WriteFile(runtimeSource, []byte("names-v2"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
runtimeUpdate, err := Install(spec, gameDir, source)
|
|
if err != nil || !runtimeUpdate.Changed {
|
|
t.Fatalf("runtime-only update=%+v err=%v", runtimeUpdate, err)
|
|
}
|
|
installedRuntime, err := os.ReadFile(filepath.Join(gameDir, "BepInEx", "plugins", GameNames.FileName()))
|
|
if err != nil || string(installedRuntime) != "names-v2" {
|
|
t.Fatalf("installed runtime=%q err=%v", installedRuntime, err)
|
|
}
|
|
if err := os.WriteFile(source, []byte("v2"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
third, err := Install(spec, gameDir, source)
|
|
if err != nil || !third.Changed {
|
|
t.Fatalf("update=%+v err=%v", third, err)
|
|
}
|
|
got, err := os.ReadFile(third.Destination)
|
|
if err != nil || string(got) != "v2" {
|
|
t.Fatalf("installed=%q err=%v", got, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInstallMissingSharedRuntimeDoesNotChangePlugin(t *testing.T) {
|
|
gameDir := t.TempDir()
|
|
for path, data := range map[string][]byte{
|
|
filepath.Join(gameDir, "BrownDust II.exe"): []byte("game"),
|
|
filepath.Join(gameDir, "BrownDust II_Data", "resources.assets"): []byte("assets"),
|
|
filepath.Join(gameDir, "BepInEx", "core", "BepInEx.dll"): []byte("bepinex"),
|
|
filepath.Join(gameDir, "BepInEx", "plugins", LocalIdentity.FileName()): []byte("old-plugin"),
|
|
} {
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(path, data, 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
source := filepath.Join(t.TempDir(), LocalIdentity.FileName())
|
|
if err := os.WriteFile(source, []byte("new-plugin"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := Install(LocalIdentity, gameDir, source); err == nil || !strings.Contains(err.Error(), GameNames.FileName()) {
|
|
t.Fatalf("missing runtime error=%v", err)
|
|
}
|
|
installed, err := os.ReadFile(filepath.Join(gameDir, "BepInEx", "plugins", LocalIdentity.FileName()))
|
|
if err != nil || string(installed) != "old-plugin" {
|
|
t.Fatalf("installed=%q err=%v", installed, err)
|
|
}
|
|
}
|
|
|
|
func TestInstallKeepsPluginsSeparate(t *testing.T) {
|
|
gameDir := t.TempDir()
|
|
for path, data := range map[string][]byte{
|
|
filepath.Join(gameDir, "BrownDust II.exe"): []byte("game"),
|
|
filepath.Join(gameDir, "BrownDust II_Data", "resources.assets"): []byte("assets"),
|
|
filepath.Join(gameDir, "BepInEx", "core", "BepInEx.dll"): []byte("bepinex"),
|
|
} {
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(path, data, 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
for _, spec := range []Spec{LocalIdentity, LoginUI, CashShop} {
|
|
source := filepath.Join(t.TempDir(), spec.FileName())
|
|
if err := os.WriteFile(filepath.Join(filepath.Dir(source), GameNames.FileName()), []byte("names-v1"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(source, []byte(spec.FileName()), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := Install(spec, gameDir, source); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
for _, spec := range []Spec{LocalIdentity, LoginUI, CashShop} {
|
|
path := filepath.Join(gameDir, "BepInEx", "plugins", spec.FileName())
|
|
data, err := os.ReadFile(path)
|
|
if err != nil || string(data) != spec.FileName() {
|
|
t.Fatalf("%s=%q err=%v", spec.FileName(), data, err)
|
|
}
|
|
}
|
|
}
|