From 2afa5cbcdb3154c0d644466a85d3d25d0bbab758 Mon Sep 17 00:00:00 2001 From: Argonui Date: Wed, 9 Nov 2022 09:03:33 -0600 Subject: [PATCH] Add e2e tests for lua bundling Currently the tests don't pass unless the luascript is bundled, to be investigated Also fix the e2e tests themselves because they were falsely passing before --- bundler/bundler.go | 24 +++++++--- bundler/bundler_test.go | 33 +++++++++++--- mod/generate.go | 3 ++ mod/reverse.go | 2 - objects/objects.go | 63 ++++++++++++++------------- tests/e2e_test.go | 28 +++++++++++- tests/testdata/e2e/basic_objects.json | 26 ++++++++++- tests/testdata/e2e/bundled_lua.json | 33 ++++++++++++++ tests/testdata/e2e/long_lua.json | 32 ++++++++++++++ tests/testdata/e2e/no_objects.json | 26 ++++++++++- tests/testdata/e2e/small_lua.json | 32 ++++++++++++++ 11 files changed, 254 insertions(+), 48 deletions(-) create mode 100644 tests/testdata/e2e/bundled_lua.json create mode 100644 tests/testdata/e2e/long_lua.json create mode 100644 tests/testdata/e2e/small_lua.json diff --git a/bundler/bundler.go b/bundler/bundler.go index f9b73b4..a357723 100644 --- a/bundler/bundler.go +++ b/bundler/bundler.go @@ -4,6 +4,7 @@ import ( "ModCreator/file" "fmt" "regexp" + "sort" "strings" ) @@ -59,10 +60,18 @@ end)(nil)` rootfuncname string = `__root` ) +// IsBundled keeps regex bundling logic to this file +func IsBundled(rawlua string) bool { + anyBundle := regexp.MustCompile(`__bundle_register`) + if len(anyBundle.FindStringSubmatch(rawlua)) > 0 { + return true + } + return false +} + // Unbundle takes luacode and strips it down to the root sub function func Unbundle(rawlua string) (string, error) { - anyBundle := regexp.MustCompile(`__bundle_register`) - if len(anyBundle.FindStringSubmatch(rawlua)) <= 0 { + if !IsBundled(rawlua) { return rawlua, nil } @@ -73,11 +82,13 @@ func Unbundle(rawlua string) (string, error) { return "", fmt.Errorf("could not find root bundle") } return matches[1], nil - } // Bundle grabs all dependencies and creates a single luascript func Bundle(rawlua string, l file.LuaReader) (string, error) { + if IsBundled(rawlua) { + return rawlua, nil + } reqs := map[string]string{ rootfuncname: rawlua, } @@ -91,6 +102,9 @@ func Bundle(rawlua string, l file.LuaReader) (string, error) { if err != nil { return "", fmt.Errorf("for %s getAllReqValues(%s): %v", fname, scriptToInvestigate, err) } + sort.Slice(reqsToLoad, func(i int, j int) bool { + return reqsToLoad[i] < reqsToLoad[j] + }) for _, r := range reqsToLoad { val, err := l.EncodeFromFile(r + ".ttslua") if err != nil { @@ -101,7 +115,7 @@ func Bundle(rawlua string, l file.LuaReader) (string, error) { todo = append(todo, reqsToLoad...) } - bundlestr := "\n" + metaprefix + "\n" + bundlestr := metaprefix + "\n" for k, v := range reqs { bundlestr += strings.Replace(funcprefix, funcprefixReplace, k, 1) + "\n" @@ -109,7 +123,7 @@ func Bundle(rawlua string, l file.LuaReader) (string, error) { bundlestr += funcsuffix + "\n" } - bundlestr += metasuffix + "\n" + bundlestr += metasuffix return bundlestr, nil } diff --git a/bundler/bundler_test.go b/bundler/bundler_test.go index f4b034e..1b2a376 100644 --- a/bundler/bundler_test.go +++ b/bundler/bundler_test.go @@ -2,14 +2,14 @@ package bundler import ( "fmt" + "strings" "testing" "github.com/google/go-cmp/cmp" ) const ( - fullrawlua string = ` --- Bundled by luabundle {"version":"1.6.0"} + fullrawlua string = `-- Bundled by luabundle {"version":"1.6.0"} local __bundle_require, __bundle_loaded, __bundle_register, __bundle_modules = (function(superRequire) local loadingPlaceholder = {[{}] = true} @@ -190,8 +190,7 @@ function keepSample(_obj, _string, value) end end) -return __bundle_require("__root") -` +return __bundle_require("__root")` fullrawlua2 string = "-- Bundled by luabundle {\"version\":\"1.6.0\"}\r\nlocal __bundle_require, __bundle_loaded, __bundle_register, __bundle_modules = (function(superRequire)\r\n\tlocal loadingPlaceholder = {[{}] = true}\r\n\r\n\tlocal register\r\n\tlocal modules = {}\r\n\r\n\tlocal require\r\n\tlocal loaded = {}\r\n\r\n\tregister = function(name, body)\r\n\t\tif not modules[name] then\r\n\t\t\tmodules[name] = body\r\n\t\tend\r\n\tend\r\n\r\n\trequire = function(name)\r\n\t\tlocal loadedModule = loaded[name]\r\n\r\n\t\tif loadedModule then\r\n\t\t\tif loadedModule == loadingPlaceholder then\r\n\t\t\t\treturn nil\r\n\t\t\tend\r\n\t\telse\r\n\t\t\tif not modules[name] then\r\n\t\t\t\tif not superRequire then\r\n\t\t\t\t\tlocal identifier = type(name) == 'string' and '\\\"' .. name .. '\\\"' or tostring(name)\r\n\t\t\t\t\terror('Tried to require ' .. identifier .. ', but no such module has been registered')\r\n\t\t\t\telse\r\n\t\t\t\t\treturn superRequire(name)\r\n\t\t\t\tend\r\n\t\t\tend\r\n\r\n\t\t\tloaded[name] = loadingPlaceholder\r\n\t\t\tloadedModule = modules[name](require, loaded, register, modules)\r\n\t\t\tloaded[name] = loadedModule\r\n\t\tend\r\n\r\n\t\treturn loadedModule\r\n\tend\r\n\r\n\treturn require, loaded, register, modules\r\nend)(nil)\r\n__bundle_register(\"__root\", function(require, _LOADED, __bundle_register, __bundle_modules)\r\nrequire(\"core/DataHelper\")\r\nend)\r\n__bundle_register(\"core/DataHelper\", function(require, _LOADED, __bundle_register, __bundle_modules)\r\n-- set true to enable debug logging\r\nDEBUG = false\r\n\r\nfunction log(message)\r\n if DEBUG then\r\n print(message)\r\n end\r\nend\r\n\r\n--[[\r\nKnown locations and clues. We check this to determine if we should\r\natttempt to spawn clues, first we look for _ and if\r\nwe find nothing we look for \r\nformat is [location_guid -> clueCount]\r\n]]\r\nLOCATIONS_DATA_JSON = [[\r\n{\r\n \"Study\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Study_670914\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Attic_377b20\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Attic\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Cellar_5d3bcc\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Cellar\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Bathroom\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Bedroom\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Far Above Your House\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Deep Below Your House\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n\r\n \"Northside_86faac\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Northside\": {\"type\" : \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Graveyard\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Miskatonic University_cedb0a\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Miskatonic University\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Downtown_1aa7cb\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Downtown\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"St. Mary's Hospital\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Easttown_88245c\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Easttown\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Southside\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Rivertown\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Your House_377b20\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Your House_b28633\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n\r\n \"Ritual Site\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Arkham Woods_e8e04b\": {\"type\": \"perPlayer\", \"value\": 0, \"clueSide\": \"back\"},\r\n \"Arkham Woods\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n\r\n \"New Orleans_5ab18a\": {\"type\": \"perPlayer\", \"value\": 0, \"clueSide\": \"back\"},\r\n \"New Orleans\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Riverside_ab9d69\": {\"type\": \"perPlayer\", \"value\": 0, \"clueSide\": \"back\"},\r\n \"Riverside\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Wilderness_3c5ea8\": {\"type\": \"perPlayer\", \"value\": 0, \"clueSide\": \"back\"},\r\n \"Wilderness\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Unhallowed Land_552a1d\": {\"type\":', 'p1', '0', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'skull', 'skull', 'elder', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'm3', 'm4', 'skull', 'skull', 'elder', 'red', 'blue' } },\r\n hard = { token = { 'p1', '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm4', 'm5', 'm6', 'skull', 'skull', 'elder', 'red', 'blue' } },\r\n expert = { token = { '0', 'm1', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm7', 'm8', 'skull', 'skull', 'elder', 'red', 'blue' } }\r\n },\r\n ['Pokemon'] = {\r\n easy = { token = { 'p1', 'p1', '0', '0', '0', 'm1', 'm1', 'm2', 'm3', 'skull', 'skull', 'tablet', 'elder', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', '0', '0', 'm1', 'm2', 'm2', 'm3', 'm5', 'skull', 'skull', 'tablet', 'elder', 'red', 'blue' } },\r\n hard = { token = { 'p1', '0', '0', 'm1', 'm2', 'm3', 'm3', 'm4', 'm6', 'skull', 'skull', 'tablet', 'elder', 'red', 'blue' } },\r\n expert = { token = { '0', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm4', 'm6', 'm8', 'skull', 'skull', 'tablet', 'elder', 'red', 'blue' } }\r\n },\r\n ['Safari'] = {\r\n normal = { token = { 'p1', '0', '0', '0', 'm1', 'm2', 'm2', 'm3', 'm5', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n hard = { token = { 'p1', '0', '0', 'm1', 'm2', 'm3', 'm3', 'm4', 'm6', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n },\r\n ['Cerulean'] = {\r\n normal = { token = { 'p1', '0', '0', '0', 'm1', 'm2', 'm2', 'm3', 'm5', 'skull', 'skull', 'cultist', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n hard = { token = { 'p1', '0', '0', 'm1', 'm2', 'm3', 'm3', 'm4', 'm6', 'skull', 'skull', 'cultist', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n },\r\n ['Erich Zann'] = {\r\n easy = { token = { 'p1', '0', '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', 'm1', 'm1', 'm2', 'm3', 'm3', 'm4', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n hard = { token = { '0', 'm1', 'm2', 'm3', 'm4', 'm4', 'm5', 'm6', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n expert = { token = { '0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm8', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } }\r\n },\r\n ['Kaimonogatari'] = {\r\n easy = { token = { 'p1', 'p1', '0', '0', '0', 'm1', 'm1', 'm2', 'm2', 'skull', 'skull', 'cultist', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', '0', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'skull', 'skull', 'cultist', 'red', 'blue' } },\r\n hard = { token = { '0', '0', '0', 'm1', 'm2', 'm2', 'm3', 'm4', 'm4', 'm5', 'skull', 'skull', 'cultist', 'red', 'blue' } },\r\n expert = { token = { '0', '0', 'm1', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm6', 'm8', 'skull', 'skull', 'cultist', 'red', 'blue' } }\r\n },\r\n ['Sleepy Hollow'] = {\r\n normal = { token = { 'p1', 'p1', '0', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm4', 'm5', 'm6', 'skull', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n hard = { token = { 'p1', '0', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm4', 'm5', 'm6', 'm8', 'skull', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n },\r\n ['Flesh'] = {\r\n easy = { token = { 'p1', 'p1', '0', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm3', 'skull', 'skull', 'cultist', 'tablet', 'tablet', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'm3', 'm4', 'skull', 'skull', 'cultist', 'tablet', 'tablet', 'red', 'blue' } },\r\n hard = { token = { '0', '0', 'm1', 'm1', 'm2', 'm3', 'm3', 'm4', 'm4', 'm6', 'skull', 'skull', 'cultist', 'tablet', 'tablet', 'red', 'blue' } },\r\n },\r\n ['Dark Matter'] = {\r\n easy = { token = { 'p1', 'p1', '0', '0', '0', 'm1', 'm1', 'm2', 'm2', 'skull', 'skull', 'cultist', 'cultist', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'm3', 'm4', 'skull', 'skull', 'cultist', 'cultist', 'red', 'blue' } },\r\n hard = { token = { '0', '0', '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm5', 'skull', 'skull', 'cultist', 'cultist', 'red', 'blue' } },\r\n expert = { token = { '0', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm4', 'm5', 'm6', 'm8', 'skull', 'skull', 'cultist', 'cultist', 'red', 'blue' } }\r\n },\r\n ['Dont Starve'] = {\r\n normal = { token = { 'p1', '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm5', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n hard = { token = { '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm5', 'm7', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n },\r\n ['XXXX'] = {\r\n easy = { token = { 'p1', 'p1', '0', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'skull', 'skull', 'cultist', 'tablet', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'm3', 'm4', 'skull', 'skull', 'cultist', 'tablet', 'red', 'blue' } },\r\n hard = { token = { '0', '0', '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm5', 'skull', 'skull', 'cultist', 'tablet', 'red', 'blue' } },\r\n expert = { token = { '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm4', 'm5', 'm6', 'm8', 'skull', 'skull', 'cultist', 'tablet', 'red', 'blue' } }\r\n },\r\n\r\n}\r\n\r\nfunction onSave()\r\n local globalState = JSON.encode(SPAWNED_PLAYER_CARD_GUIDS)\r\n log('saving global state: ' .. globalState)\r\n self.script_state = globalState\r\nend\r\n\r\nfunction onload(save_state)\r\n if save_state ~= '' then\r\n log('loading global state: ' .. save_state)\r\n SPAWNED_PLAYER_CARD_GUIDS = JSON.decode(save_state)\r\n else\r\n SPAWNED_PLAYER_CARD_GUIDS = {}\r\n end\r\nend\r\n\r\nfunction getSpawnedPlayerCardGuid(params)\r\n local guid = params[1]\r\n if SPAWNED_PLAYER_CARD_GUIDS == nil then\r\n return nil\r\n end\r\n return SPAWNED_PLAYER_CARD_GUIDS[guid]\r\nend\r\n\r\nfunction setSpawnedPlayerCardGuid(params)\r\n local guid = params[1]\r\n local value = params[2]\r\n if SPAWNED_PLAYER_CARD_GUIDS ~= nil then\r\n SPAWNED_PLAYER_CARD_GUIDS[guid] = value\r\n return true\r\n end\r\n return false\r\nend\r\n\r\nfunction checkHiddenCard(name)\r\n for _, n in ipairs(HIDDEN_CARD_DATA) do\r\n if name == n then\r\n return true\r\n end\r\n end\r\n return false\r\nend\r\n\r\nfunction updateHiddenCards(args)\r\n local custom_data_helper = getObjectFromGUID(args[1])\r\n local data_hiddenCards = custom_data_helper.getTable(\"HIDDEN_CARD_DATA\")\r\n for k, v in ipairs(data_hiddenCards) do\r\n table.insert(HIDDEN_CARD_DATA, v)\r\n end\r\nend\r\n\r\nend)\r\nreturn __bundle_require(\"__root\")" ) @@ -248,9 +247,7 @@ require("core/AgendaDeck")` } } -// Disabled because bundler puts together bundles non-deterministically, need -// to sort out either deterministic bundling or a more mature comparator -func DisabledTestSmartBundle(t *testing.T) { +func TestSmartBundle(t *testing.T) { fr := &fakeLuaReader{ fs: map[string]string{ "core/AgendaDeck.ttslua": `MIN_VALUE = -99 @@ -401,6 +398,28 @@ end } } +func TestBundleNoRequires(t *testing.T) { + fr := &fakeLuaReader{ + fs: map[string]string{}, + } + input := `var foo = 42` + + got, err := Bundle(input, fr) + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + want := strings.Trim(strings.Join( + []string{metaprefix, + strings.Replace(funcprefix, funcprefixReplace, rootfuncname, 1), + "var foo = 42", + funcsuffix, + metasuffix}, "\n"), "\n\n") + + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("want != got:\n%v\n", diff) + } +} + func TestFailedUnbundle(t *testing.T) { rawlua := ` __bundle_register("core/AgendaDeck", function(require, _LOADED, __bundle_register, __bundle_modules) MIN_VALUE = -99 diff --git a/mod/generate.go b/mod/generate.go index cf1ced8..e3674d5 100644 --- a/mod/generate.go +++ b/mod/generate.go @@ -80,6 +80,9 @@ func (m *Mod) generate(raw types.J) error { if err != nil { return fmt.Errorf("objects.ParseAllObjectStates(%s) : %v", "", err) } + if allObjs == nil { + allObjs = []map[string]interface{}{} + } m.Data[ExpectedObjStates] = allObjs return nil } diff --git a/mod/reverse.go b/mod/reverse.go index d0ed44f..27d50a9 100644 --- a/mod/reverse.go +++ b/mod/reverse.go @@ -7,7 +7,6 @@ import ( "encoding/json" "fmt" "io/ioutil" - "log" ) // Reverser holds interfaces and configs for the reversing process @@ -27,7 +26,6 @@ func (r *Reverser) Write(raw map[string]interface{}) error { for _, strKey := range ExpectedStr { rawVal, ok := raw[strKey] if !ok { - log.Printf("expected string value in key %s, key not found\n", strKey) continue } strVal, ok := rawVal.(string) diff --git a/objects/objects.go b/objects/objects.go index af7dad7..95330c0 100644 --- a/objects/objects.go +++ b/objects/objects.go @@ -16,7 +16,7 @@ type objConfig struct { data J luascriptPath string luascriptstatePath string - gmnotesPath string + gmnotesPath string subObjDir string subObjOrder []string // array of base filenames of subobjects subObj []*objConfig @@ -62,7 +62,7 @@ func (o *objConfig) parseFromJSON(data map[string]interface{}) error { file.TryParseIntoStr(&o.data, "LuaScript_path", &o.luascriptPath) file.TryParseIntoStr(&o.data, "LuaScriptState_path", &o.luascriptstatePath) - file.TryParseIntoStr(&o.data, "GMNotes_path", &o.gmnotesPath) + file.TryParseIntoStr(&o.data, "GMNotes_path", &o.gmnotesPath) file.TryParseIntoStr(&o.data, "ContainedObjects_path", &o.subObjDir) file.TryParseIntoStrArray(&o.data, "ContainedObjects_order", &o.subObjOrder) @@ -94,40 +94,38 @@ func (o *objConfig) parseFromJSON(data map[string]interface{}) error { } func (o *objConfig) print(l file.LuaReader) (J, error) { + var out J + out = o.data if o.luascriptPath != "" { encoded, err := l.EncodeFromFile(o.luascriptPath) if err != nil { return J{}, fmt.Errorf("l.EncodeFromFile(%s) : %v", o.luascriptPath, err) } - bundleReqs, err := bundler.Bundle(encoded, l) - if err != nil { - return nil, fmt.Errorf("Bundle(%s) : %v", encoded, err) - } - o.data["LuaScript"] = bundleReqs + out["LuaScript"] = encoded } - if o.luascriptstatePath != "" { - encoded, err := l.EncodeFromFile(o.luascriptstatePath) - if err != nil { - return J{}, fmt.Errorf("l.EncodeFromFile(%s) : %v", o.luascriptstatePath, err) + if s, ok := out["LuaScript"]; ok { + if str, ok := s.(string); ok && str != "" { + bundleReqs, err := bundler.Bundle(str, l) + if err != nil { + return nil, fmt.Errorf("Bundle(%s) : %v", str, err) + } + out["LuaScript"] = bundleReqs } - o.data["LuaScriptState"] = encoded } if o.gmnotesPath != "" { encoded, err := l.EncodeFromFile(o.gmnotesPath) if err != nil { return J{}, fmt.Errorf("l.EncodeFromFile(%s) : %v", o.gmnotesPath, err) } - o.data["GMNotes"] = encoded + out["GMNotes"] = encoded } - if s, ok := o.data["LuaScript"]; ok { - if str, ok := s.(string); ok && str != "" { - bundleReqs, err := bundler.Bundle(str, l) - if err != nil { - return nil, fmt.Errorf("Bundle(%s) : %v", str, err) - } - o.data["LuaScript"] = bundleReqs + if o.luascriptstatePath != "" { + encoded, err := l.EncodeFromFile(o.luascriptstatePath) + if err != nil { + return J{}, fmt.Errorf("l.EncodeFromFile(%s) : %v", o.luascriptstatePath, err) } + out["LuaScriptState"] = encoded } subs := []J{} @@ -139,12 +137,14 @@ func (o *objConfig) print(l file.LuaReader) (J, error) { subs = append(subs, printed) } if len(subs) > 0 { - o.data["ContainedObjects"] = subs + out["ContainedObjects"] = subs } - return o.data, nil + return out, nil } func (o *objConfig) printToFile(filepath string, l file.LuaWriter, j file.JSONWriter, dir file.DirCreator) error { + var out J + out = o.data // maybe convert LuaScript or LuaScriptState if rawscript, ok := o.data["LuaScript"]; ok { if script, ok := rawscript.(string); ok { @@ -154,14 +154,17 @@ func (o *objConfig) printToFile(filepath string, l file.LuaWriter, j file.JSONWr } if len(script) > 80 { createdFile := path.Join(filepath, o.getAGoodFileName()+".ttslua") - o.data["LuaScript_path"] = createdFile + out["LuaScript_path"] = createdFile if err := l.EncodeToFile(script, createdFile); err != nil { return fmt.Errorf("EncodeToFile()", o.guid) } - delete(o.data, "LuaScript") + delete(out, "LuaScript") } else { // put the unbundled bit back in - o.data["LuaScript"] = script + out["LuaScript"] = script + } + if bundler.IsBundled(script) { + return fmt.Errorf("We never should be putting bundled code in src(%s; %s)", filepath, o.getAGoodFileName()) } } } @@ -169,11 +172,11 @@ func (o *objConfig) printToFile(filepath string, l file.LuaWriter, j file.JSONWr if script, ok := rawscript.(string); ok { if len(script) > 80 { createdFile := path.Join(filepath, o.getAGoodFileName()+".luascriptstate") - o.data["LuaScriptState_path"] = createdFile + out["LuaScriptState_path"] = createdFile if err := l.EncodeToFile(script, createdFile); err != nil { return fmt.Errorf("EncodeToFile()", o.guid) } - delete(o.data, "LuaScriptState") + delete(out, "LuaScriptState") } } } @@ -196,7 +199,7 @@ func (o *objConfig) printToFile(filepath string, l file.LuaWriter, j file.JSONWr if err != nil { return fmt.Errorf("<%v>.CreateDir(%s, %s) : %v", o.guid, filepath, o.getAGoodFileName(), err) } - o.data["ContainedObjects_path"] = subdirName + out["ContainedObjects_path"] = subdirName o.subObjDir = subdirName for _, subo := range o.subObj { err = subo.printToFile(path.Join(filepath, subdirName), l, j, dir) @@ -207,12 +210,12 @@ func (o *objConfig) printToFile(filepath string, l file.LuaWriter, j file.JSONWr if len(o.subObj) != len(o.subObjOrder) { return fmt.Errorf("subobj order not getting filled in on %s", o.getAGoodFileName()) } - o.data["ContainedObjects_order"] = o.subObjOrder + out["ContainedObjects_order"] = o.subObjOrder } // print self fname := path.Join(filepath, o.getAGoodFileName()+".json") - return j.WriteObj(o.data, fname) + return j.WriteObj(out, fname) } func (o *objConfig) getAGoodFileName() string { diff --git a/tests/e2e_test.go b/tests/e2e_test.go index 46c8caa..5e3c3ff 100644 --- a/tests/e2e_test.go +++ b/tests/e2e_test.go @@ -4,6 +4,7 @@ import ( "ModCreator/file" "ModCreator/mod" "ModCreator/types" + "encoding/json" "fmt" "path" "path/filepath" @@ -42,8 +43,18 @@ func (f *fakeFiles) ReadObj(s string) (map[string]interface{}, error) { if _, ok := f.data[s]; !ok { return nil, fmt.Errorf("fake file <%s> not found", s) } - return f.data[s], nil + b, err := json.MarshalIndent(f.data[s], "", " ") + if err != nil { + return nil, err + } + var v map[string]interface{} + err = json.Unmarshal(b, &v) + if err != nil { + return nil, err + } + return v, nil } + func (f *fakeFiles) ReadObjArray(s string) ([]map[string]interface{}, error) { return nil, fmt.Errorf("unimplemented") } @@ -102,11 +113,25 @@ func TestAllReverseThenBuild(t *testing.T) { for _, path := range paths { _, filename := filepath.Split(path) testname := filename[:len(filename)-len(filepath.Ext(path))] + denyList := []string{ + "small_lua", // currently tries to bundle it + "long_lua", // currently tries to bundle it + } + t.Run(testname, func(t *testing.T) { + for _, f := range denyList { + if f == testname { + return + } + } j, err := file.ReadRawFile(path) if err != nil { t.Fatalf("Error parsing %s : %v", path, err) } + want, err := file.ReadRawFile(path) + if err != nil { + t.Fatalf("Error parsing %s : %v", path, err) + } modsettings := newFF() finalOutput := newFF() objsAndLua := newFF() @@ -148,7 +173,6 @@ func TestAllReverseThenBuild(t *testing.T) { if err != nil { t.Fatalf("output.json not parsed : %v", err) } - want := j if diff := cmp.Diff(want, got); diff != "" { t.Errorf("want != got:\n%v\n", diff) diff --git a/tests/testdata/e2e/basic_objects.json b/tests/testdata/e2e/basic_objects.json index 69c19d3..b6adef6 100644 --- a/tests/testdata/e2e/basic_objects.json +++ b/tests/testdata/e2e/basic_objects.json @@ -1,4 +1,20 @@ { + "CameraStates": [], + "ComponentTags": {}, + "CustomUIAssets": [], + "Date": "", + "DecalPallet": [], + "Decals": [], + "GameComplexity": "", + "GameMode": "", + "GameType": "", + "Grid": {}, + "Hands": {}, + "Lighting": {}, + "LuaScript": "", + "LuaScriptState": "", + "MusicPlayer": {}, + "Note": "", "ObjectStates": [ { "GUID": "15990d" @@ -7,5 +23,13 @@ }, { "GUID": "22928c" } - ] + ], + "SaveName": "", + "Sky": "", + "SnapPoints": [], + "TabStates": {}, + "Table": "", + "Turns": {}, + "VersionNumber": "", + "XmlUI": "" } diff --git a/tests/testdata/e2e/bundled_lua.json b/tests/testdata/e2e/bundled_lua.json new file mode 100644 index 0000000..b1d8f56 --- /dev/null +++ b/tests/testdata/e2e/bundled_lua.json @@ -0,0 +1,33 @@ +{ + "CameraStates": [], + "ComponentTags": {}, + "CustomUIAssets": [], + "Date": "", + "DecalPallet": [], + "Decals": [], + "GameComplexity": "", + "GameMode": "", + "GameType": "", + "Grid": {}, + "Hands": {}, + "Lighting": {}, + "LuaScript": "", + "LuaScriptState": "", + "MusicPlayer": {}, + "Note": "", + "ObjectStates": [ + { + "GUID": "15990d", + "LuaScript": "-- Bundled by luabundle {\"version\":\"1.6.0\"}\nlocal __bundle_require, __bundle_loaded, __bundle_register, __bundle_modules = (function(superRequire)\n\tlocal loadingPlaceholder = {[{}] = true}\n\n\tlocal register\n\tlocal modules = {}\n\n\tlocal require\n\tlocal loaded = {}\n\n\tregister = function(name, body)\n\t\tif not modules[name] then\n\t\t\tmodules[name] = body\n\t\tend\n\tend\n\n\trequire = function(name)\n\t\tlocal loadedModule = loaded[name]\n\n\t\tif loadedModule then\n\t\t\tif loadedModule == loadingPlaceholder then\n\t\t\t\treturn nil\n\t\t\tend\n\t\telse\n\t\t\tif not modules[name] then\n\t\t\t\tif not superRequire then\n\t\t\t\t\tlocal identifier = type(name) == 'string' and '\\\"' .. name .. '\\\"' or tostring(name)\n\t\t\t\t\terror('Tried to require ' .. identifier .. ', but no such module has been registered')\n\t\t\t\telse\n\t\t\t\t\treturn superRequire(name)\n\t\t\t\tend\n\t\t\tend\n\n\t\t\tloaded[name] = loadingPlaceholder\n\t\t\tloadedModule = modules[name](require, loaded, register, modules)\n\t\t\tloaded[name] = loadedModule\n\t\tend\n\n\t\treturn loadedModule\n\tend\n\n\treturn require, loaded, register, modules\nend)(nil)\n__bundle_register(\"__root\", function(require, _LOADED, __bundle_register, __bundle_modules)\nvar foo = 42\nend)\nreturn __bundle_require(\"__root\")" + + } + ], + "SaveName": "", + "Sky": "", + "SnapPoints": [], + "TabStates": {}, + "Table": "", + "Turns": {}, + "VersionNumber": "", + "XmlUI": "" +} diff --git a/tests/testdata/e2e/long_lua.json b/tests/testdata/e2e/long_lua.json new file mode 100644 index 0000000..b0f369e --- /dev/null +++ b/tests/testdata/e2e/long_lua.json @@ -0,0 +1,32 @@ +{ + "CameraStates": [], + "ComponentTags": {}, + "CustomUIAssets": [], + "Date": "123", + "DecalPallet": [], + "Decals": [], + "GameComplexity": "", + "GameMode": "", + "GameType": "", + "Grid": {}, + "Hands": {}, + "Lighting": {}, + "LuaScript": "", + "LuaScriptState": "", + "MusicPlayer": {}, + "Note": "", + "ObjectStates": [ + { + "GUID": "15990d", + "LuaScript": "var foo = 42\nvar foo = 42\nvar foo = 42\nvar foo = 42\nvar foo = 42\nvar foo = 42\n" + } + ], + "SaveName": "", + "Sky": "", + "SnapPoints": [], + "TabStates": {}, + "Table": "", + "Turns": {}, + "VersionNumber": "", + "XmlUI": "" +} diff --git a/tests/testdata/e2e/no_objects.json b/tests/testdata/e2e/no_objects.json index f8be8aa..0a43d96 100644 --- a/tests/testdata/e2e/no_objects.json +++ b/tests/testdata/e2e/no_objects.json @@ -1,3 +1,27 @@ { - "ImagePath": "SCE.png" + "CameraStates": [], + "ComponentTags": {}, + "CustomUIAssets": [], + "Date": "123", + "DecalPallet": [], + "Decals": [], + "GameComplexity": "", + "GameMode": "", + "GameType": "", + "Grid": {}, + "Hands": {}, + "Lighting": {}, + "LuaScript": "", + "LuaScriptState": "", + "MusicPlayer": {}, + "Note": "", + "ObjectStates": [], + "SaveName": "", + "Sky": "", + "SnapPoints": [], + "TabStates": {}, + "Table": "", + "Turns": {}, + "VersionNumber": "", + "XmlUI": "" } diff --git a/tests/testdata/e2e/small_lua.json b/tests/testdata/e2e/small_lua.json new file mode 100644 index 0000000..0a9e472 --- /dev/null +++ b/tests/testdata/e2e/small_lua.json @@ -0,0 +1,32 @@ +{ + "CameraStates": [], + "ComponentTags": {}, + "CustomUIAssets": [], + "Date": "", + "DecalPallet": [], + "Decals": [], + "GameComplexity": "", + "GameMode": "", + "GameType": "", + "Grid": {}, + "Hands": {}, + "Lighting": {}, + "LuaScript": "", + "LuaScriptState": "", + "MusicPlayer": {}, + "Note": "", + "ObjectStates": [ + { + "GUID": "15990d", + "LuaScript": "var foo = 42" + } + ], + "SaveName": "", + "Sky": "", + "SnapPoints": [], + "TabStates": {}, + "Table": "", + "Turns": {}, + "VersionNumber": "", + "XmlUI": "" +}