216 lines
6.9 KiB
Go
216 lines
6.9 KiB
Go
package catalog_test
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
catalogdata "git.zaynet.fr/DoGaMa/DoGaMa-serv/catalog"
|
|
"git.zaynet.fr/DoGaMa/DoGaMa-serv/internal/catalog"
|
|
)
|
|
|
|
func TestInitializeOfficialAndScanDirPreservesLocalFiles(t *testing.T) {
|
|
root := t.TempDir()
|
|
if err := catalog.InitializeOfficial(root, catalogdata.Files); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
first, err := catalog.ScanDir(root)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(first.Valid) == 0 || first.Found != len(first.Valid) || len(first.Errors) != 0 {
|
|
t.Fatalf("initial catalog scan = %#v", first)
|
|
}
|
|
|
|
path := filepath.Join(root, first.Valid[0].AssetRoot, "template.yaml")
|
|
if err := os.WriteFile(path, []byte("local customization"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := catalog.InitializeOfficial(root, catalogdata.Files); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
body, err := os.ReadFile(path)
|
|
if err != nil || string(body) != "local customization" {
|
|
t.Fatalf("local template was overwritten: %q, %v", body, err)
|
|
}
|
|
}
|
|
|
|
func TestScanDirKeepsValidTemplatesWhenOneIsInvalid(t *testing.T) {
|
|
root := t.TempDir()
|
|
if err := catalog.InitializeOfficial(root, catalogdata.Files); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
initial, err := catalog.ScanDir(root)
|
|
if err != nil || len(initial.Valid) == 0 {
|
|
t.Fatalf("initial scan = %#v, %v", initial, err)
|
|
}
|
|
|
|
broken := strings.Replace(initial.Valid[0].CanonicalYAML, `"image": "`+initial.Valid[0].Template.Game.Artwork.Image+`"`, `"image": "../invalid.jpg"`, 1)
|
|
if err := os.Mkdir(filepath.Join(root, "broken"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(root, "broken", "template.yaml"), []byte(broken), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
result, err := catalog.ScanDir(root)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if result.Found != initial.Found+1 || len(result.Valid) != len(initial.Valid) || len(result.Errors) != 1 {
|
|
t.Fatalf("scan with invalid template = %#v", result)
|
|
}
|
|
if result.Errors[0].Template != "broken" || !strings.Contains(result.Errors[0].Message, "/game/artwork/image") {
|
|
t.Fatalf("error = %#v", result.Errors)
|
|
}
|
|
}
|
|
|
|
func TestScanDirAcceptsLocallyModifiedReferencedAsset(t *testing.T) {
|
|
root := t.TempDir()
|
|
if err := catalog.InitializeOfficial(root, catalogdata.Files); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
before, err := catalog.ScanDir(root)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, snapshot := range before.Valid {
|
|
if len(snapshot.Template.Container.Assets) == 0 {
|
|
continue
|
|
}
|
|
asset := snapshot.Template.Container.Assets[0]
|
|
assetPath := filepath.Join(root, filepath.FromSlash(snapshot.AssetRoot), filepath.FromSlash(asset.Source))
|
|
if err := os.WriteFile(assetPath, []byte("locally maintained asset\n"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
templatePath := filepath.Join(root, filepath.FromSlash(snapshot.AssetRoot), "template.yaml")
|
|
body, err := os.ReadFile(templatePath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
legacy := strings.Replace(string(body), " destination: "+asset.Destination+"\n", " destination: "+asset.Destination+"\n sha256: obsolete-checksum\n", 1)
|
|
if err := os.WriteFile(templatePath, []byte(legacy), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
after, scanErr := catalog.ScanDir(root)
|
|
if scanErr != nil || len(after.Errors) != 0 || len(after.Valid) != len(before.Valid) {
|
|
t.Fatalf("scan after modifying asset %q = %#v, %v", assetPath, after, scanErr)
|
|
}
|
|
return
|
|
}
|
|
t.Skip("embedded catalog has no container assets")
|
|
}
|
|
|
|
func TestScanDirLoadsTemplateLocalModuleAndAcceptsChanges(t *testing.T) {
|
|
root := t.TempDir()
|
|
if err := catalog.InitializeOfficial(root, catalogdata.Files); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
first, err := catalog.ScanDir(root)
|
|
if err != nil || len(first.Valid) == 0 {
|
|
t.Fatalf("initial scan = %#v, %v", first, err)
|
|
}
|
|
var snapshot catalog.Snapshot
|
|
for _, candidate := range first.Valid {
|
|
if candidate.Template.Module != nil {
|
|
snapshot = candidate
|
|
break
|
|
}
|
|
}
|
|
if snapshot.Template.Module == nil || len(snapshot.ModuleFiles) == 0 {
|
|
t.Fatal("template-local module was not discovered")
|
|
}
|
|
wasmPath := filepath.Join(root, snapshot.AssetRoot, "module", "module.wasm")
|
|
body, err := os.ReadFile(wasmPath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(wasmPath, append(body, 0), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
second, err := catalog.ScanDir(root)
|
|
if err != nil || len(second.Errors) != 0 {
|
|
t.Fatalf("modified local module scan = %#v, %v", second, err)
|
|
}
|
|
var updated catalog.Snapshot
|
|
for _, candidate := range second.Valid {
|
|
if candidate.Template.ID == snapshot.Template.ID {
|
|
updated = candidate
|
|
break
|
|
}
|
|
}
|
|
if updated.Digest == snapshot.Digest {
|
|
t.Fatal("module change did not affect template snapshot digest")
|
|
}
|
|
}
|
|
|
|
func TestScanDirAcceptsLocalTemplateWithoutModule(t *testing.T) {
|
|
root := t.TempDir()
|
|
if err := catalog.InitializeOfficial(root, catalogdata.Files); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
result, err := catalog.ScanDir(root)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, snapshot := range result.Valid {
|
|
if snapshot.Template.ID != "vrising-didstopia" {
|
|
continue
|
|
}
|
|
path := filepath.Join(root, snapshot.AssetRoot, "template.yaml")
|
|
body, readErr := os.ReadFile(path)
|
|
if readErr != nil {
|
|
t.Fatal(readErr)
|
|
}
|
|
withoutModule := strings.Replace(string(body), "module:\n path: module/manifest.yaml\n\n", "", 1)
|
|
withoutModule = strings.Replace(withoutModule, "integration:\n module_id: vrising-rcon\n version_range: \">=1.0.0 <2.0.0\"\n port_id: rcon\n required: false\n\n", "", 1)
|
|
if err := os.WriteFile(path, []byte(withoutModule), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
rescanned, scanErr := catalog.ScanDir(root)
|
|
if scanErr != nil {
|
|
t.Fatal(scanErr)
|
|
}
|
|
for _, candidate := range rescanned.Valid {
|
|
if candidate.Template.ID == "vrising-didstopia" && candidate.Template.Module == nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
t.Fatal("a template without an optional module was not accepted")
|
|
}
|
|
|
|
func TestScanDirRejectsMissingAndEscapingLocalModule(t *testing.T) {
|
|
for _, modulePath := range []string{"module/missing.yaml", "../outside.wasm", "/outside.wasm"} {
|
|
t.Run(modulePath, func(t *testing.T) {
|
|
root := t.TempDir()
|
|
if err := catalog.InitializeOfficial(root, catalogdata.Files); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
initial, err := catalog.ScanDir(root)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var snapshot catalog.Snapshot
|
|
for _, candidate := range initial.Valid {
|
|
if candidate.Template.Module != nil {
|
|
snapshot = candidate
|
|
break
|
|
}
|
|
}
|
|
path := filepath.Join(root, snapshot.AssetRoot, "template.yaml")
|
|
body, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(path, []byte(strings.Replace(string(body), snapshot.Template.Module.Path, modulePath, 1)), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
result, err := catalog.ScanDir(root)
|
|
if err != nil || len(result.Errors) != 1 || result.Errors[0].Template != snapshot.AssetRoot {
|
|
t.Fatalf("unsafe local module scan = %#v, %v", result, err)
|
|
}
|
|
})
|
|
}
|
|
}
|