Native Workflow Support
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package pipeline
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"gitea.westgate.pw/ShadowsOverWestgate/sow-tools/internal/erf"
|
||||
"gitea.westgate.pw/ShadowsOverWestgate/sow-tools/internal/gff"
|
||||
"gitea.westgate.pw/ShadowsOverWestgate/sow-tools/internal/project"
|
||||
)
|
||||
|
||||
@@ -32,7 +34,7 @@ func TestBuildThenExtract(t *testing.T) {
|
||||
`)
|
||||
|
||||
mustMkdir(t, filepath.Join(root, "src", "module"))
|
||||
mustWriteFile(t, filepath.Join(root, "src", "module", "module.ifo.json"), `{
|
||||
mustWriteFile(t, filepath.Join(root, "src", "module", "module.ifo.json"), `{
|
||||
"file_type": "IFO ",
|
||||
"file_version": "V3.2",
|
||||
"root": {
|
||||
@@ -427,6 +429,259 @@ printf 'compiled:%s\n' "$(basename "$src")" > "$out"
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildModuleBuildsTopPackageAndInjectsHAKList(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
mustMkdir(t, filepath.Join(root, "src", "module"))
|
||||
mustMkdir(t, filepath.Join(root, "assets"))
|
||||
mustMkdir(t, filepath.Join(root, "build"))
|
||||
mustMkdir(t, filepath.Join(root, "topdata", "data", "repadjust"))
|
||||
mustMkdir(t, filepath.Join(root, "topdata", "assets", "gui"))
|
||||
|
||||
mustWriteFile(t, filepath.Join(root, "nwn-tool.json"), `{
|
||||
"module": {
|
||||
"name": "Test Module",
|
||||
"resref": "testmod",
|
||||
"hak_order": ["sow_top"]
|
||||
},
|
||||
"paths": {
|
||||
"source": "src",
|
||||
"assets": "assets",
|
||||
"build": "build"
|
||||
},
|
||||
"topdata": {
|
||||
"source": "topdata",
|
||||
"build": "build/topdata"
|
||||
}
|
||||
}
|
||||
`)
|
||||
mustWriteFile(t, filepath.Join(root, "src", "module", "module.ifo.json"), `{
|
||||
"file_type": "IFO ",
|
||||
"file_version": "V3.2",
|
||||
"root": {
|
||||
"struct_type": 0,
|
||||
"fields": [
|
||||
{"label": "Mod_Name", "type": "CExoString", "value": "Test Module"},
|
||||
{"label": "Mod_CustomTlk", "type": "CExoString", "value": "sow_tlk"}
|
||||
]
|
||||
}
|
||||
}
|
||||
`)
|
||||
mustWriteFile(t, filepath.Join(root, "topdata", "base_dialog.json"), "{}\n")
|
||||
mustWriteFile(t, filepath.Join(root, "topdata", "data", "repadjust", "base.json"), `{
|
||||
"output": "repadjust.2da",
|
||||
"columns": ["Label"],
|
||||
"rows": [{"id": 0, "Label": "TEST_LABEL"}]
|
||||
}
|
||||
`)
|
||||
mustWriteFile(t, filepath.Join(root, "topdata", "assets", "gui", "testicon.tga"), "icon-data")
|
||||
|
||||
p, err := project.Load(root)
|
||||
if err != nil {
|
||||
t.Fatalf("load project: %v", err)
|
||||
}
|
||||
if err := p.ValidateLayout(); err != nil {
|
||||
t.Fatalf("validate layout: %v", err)
|
||||
}
|
||||
if err := p.Scan(); err != nil {
|
||||
t.Fatalf("scan: %v", err)
|
||||
}
|
||||
|
||||
result, err := BuildModule(p)
|
||||
if err != nil {
|
||||
t.Fatalf("build module: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(root, "build", "sow_top.hak")); err != nil {
|
||||
t.Fatalf("expected sow_top.hak: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(root, "build", "sow_tlk.tlk")); err != nil {
|
||||
t.Fatalf("expected sow_tlk.tlk: %v", err)
|
||||
}
|
||||
if result.TopPackageHAK == "" || result.TopPackageTLK == "" {
|
||||
t.Fatalf("expected top package paths in build result: %#v", result)
|
||||
}
|
||||
|
||||
input, err := os.Open(result.ModulePath)
|
||||
if err != nil {
|
||||
t.Fatalf("open module: %v", err)
|
||||
}
|
||||
defer input.Close()
|
||||
archive, err := erf.Read(input)
|
||||
if err != nil {
|
||||
t.Fatalf("read module archive: %v", err)
|
||||
}
|
||||
var ifoData []byte
|
||||
for _, resource := range archive.Resources {
|
||||
ext, _ := erf.ExtensionForResourceType(resource.Type)
|
||||
if strings.ToLower(resource.Name)+"."+ext == "module.ifo" {
|
||||
ifoData = resource.Data
|
||||
break
|
||||
}
|
||||
}
|
||||
if ifoData == nil {
|
||||
t.Fatalf("expected module.ifo in built archive")
|
||||
}
|
||||
document, err := gff.Read(bytes.NewReader(ifoData))
|
||||
if err != nil {
|
||||
t.Fatalf("decode module.ifo: %v", err)
|
||||
}
|
||||
foundHak := false
|
||||
for _, field := range document.Root.Fields {
|
||||
if field.Label != "Mod_HakList" {
|
||||
continue
|
||||
}
|
||||
list, ok := field.Value.(gff.ListValue)
|
||||
if !ok {
|
||||
t.Fatalf("expected Mod_HakList list, got %T", field.Value)
|
||||
}
|
||||
for _, item := range list {
|
||||
for _, nested := range item.Fields {
|
||||
if nested.Label == "Mod_Hak" && nested.Value == gff.StringValue("sow_top") {
|
||||
foundHak = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !foundHak {
|
||||
t.Fatalf("expected built module to reference sow_top")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareFailsWhenTopPackageIsStale(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
mustMkdir(t, filepath.Join(root, "src", "module"))
|
||||
mustMkdir(t, filepath.Join(root, "assets"))
|
||||
mustMkdir(t, filepath.Join(root, "build"))
|
||||
mustMkdir(t, filepath.Join(root, "topdata", "data", "repadjust"))
|
||||
|
||||
mustWriteFile(t, filepath.Join(root, "nwn-tool.json"), `{
|
||||
"module": {
|
||||
"name": "Test Module",
|
||||
"resref": "testmod",
|
||||
"hak_order": ["sow_top"]
|
||||
},
|
||||
"paths": {
|
||||
"source": "src",
|
||||
"assets": "assets",
|
||||
"build": "build"
|
||||
},
|
||||
"topdata": {
|
||||
"source": "topdata",
|
||||
"build": "build/topdata"
|
||||
}
|
||||
}
|
||||
`)
|
||||
mustWriteFile(t, filepath.Join(root, "src", "module", "module.ifo.json"), `{
|
||||
"file_type": "IFO ",
|
||||
"file_version": "V3.2",
|
||||
"root": {
|
||||
"struct_type": 0,
|
||||
"fields": [
|
||||
{"label": "Mod_Name", "type": "CExoString", "value": "Test Module"},
|
||||
{"label": "Mod_CustomTlk", "type": "CExoString", "value": "sow_tlk"}
|
||||
]
|
||||
}
|
||||
}
|
||||
`)
|
||||
mustWriteFile(t, filepath.Join(root, "topdata", "base_dialog.json"), "{}\n")
|
||||
topdataBase := filepath.Join(root, "topdata", "data", "repadjust", "base.json")
|
||||
mustWriteFile(t, topdataBase, `{
|
||||
"output": "repadjust.2da",
|
||||
"columns": ["Label"],
|
||||
"rows": [{"id": 0, "Label": "TEST_LABEL"}]
|
||||
}
|
||||
`)
|
||||
|
||||
p, err := project.Load(root)
|
||||
if err != nil {
|
||||
t.Fatalf("load project: %v", err)
|
||||
}
|
||||
if err := p.ValidateLayout(); err != nil {
|
||||
t.Fatalf("validate layout: %v", err)
|
||||
}
|
||||
if err := p.Scan(); err != nil {
|
||||
t.Fatalf("scan: %v", err)
|
||||
}
|
||||
|
||||
if _, err := BuildModule(p); err != nil {
|
||||
t.Fatalf("build module: %v", err)
|
||||
}
|
||||
newTime := time.Now().Add(2 * time.Second)
|
||||
if err := os.Chtimes(topdataBase, newTime, newTime); err != nil {
|
||||
t.Fatalf("touch topdata source: %v", err)
|
||||
}
|
||||
if _, err := Compare(p); err == nil {
|
||||
t.Fatalf("expected compare to fail when top package is stale")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareNormalizesModuleHakListFromConfig(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
mustMkdir(t, filepath.Join(root, "src", "module"))
|
||||
mustMkdir(t, filepath.Join(root, "assets"))
|
||||
mustMkdir(t, filepath.Join(root, "build"))
|
||||
|
||||
mustWriteFile(t, filepath.Join(root, "nwn-tool.json"), `{
|
||||
"module": {
|
||||
"name": "Test Module",
|
||||
"resref": "testmod",
|
||||
"hak_order": ["manual_top"]
|
||||
},
|
||||
"paths": {
|
||||
"source": "src",
|
||||
"assets": "assets",
|
||||
"build": "build"
|
||||
}
|
||||
}`)
|
||||
mustWriteFile(t, filepath.Join(root, "src", "module", "module.ifo.json"), `{
|
||||
"file_type": "IFO ",
|
||||
"file_version": "V3.2",
|
||||
"root": {
|
||||
"struct_type": 0,
|
||||
"fields": [
|
||||
{
|
||||
"label": "Mod_Name",
|
||||
"type": "CExoString",
|
||||
"value": "Test Module"
|
||||
},
|
||||
{
|
||||
"label": "Mod_HakList",
|
||||
"type": "List",
|
||||
"value": [
|
||||
{
|
||||
"struct_type": 8,
|
||||
"fields": [
|
||||
{
|
||||
"label": "Mod_Hak",
|
||||
"type": "CExoString",
|
||||
"value": "stale_old_hak"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
p, err := project.Load(root)
|
||||
if err != nil {
|
||||
t.Fatalf("load project: %v", err)
|
||||
}
|
||||
if err := p.ValidateLayout(); err != nil {
|
||||
t.Fatalf("validate layout: %v", err)
|
||||
}
|
||||
if err := p.Scan(); err != nil {
|
||||
t.Fatalf("scan: %v", err)
|
||||
}
|
||||
|
||||
if _, err := BuildModule(p); err != nil {
|
||||
t.Fatalf("build module: %v", err)
|
||||
}
|
||||
if _, err := Compare(p); err != nil {
|
||||
t.Fatalf("compare project: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildOrdersMultipleHAKGroups(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
mustMkdir(t, filepath.Join(root, "src"))
|
||||
|
||||
Reference in New Issue
Block a user