Skip to content

Commit ca73a09

Browse files
committed
Refactor stringify, add tests for it, and use it to simplify exports.
1 parent 11337ed commit ca73a09

10 files changed

Lines changed: 2265 additions & 2017 deletions

File tree

spec/System/TestUtils_spec.lua

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
describe("Utils.stringify", function()
2+
local utils = require("Modules/Utils")
3+
4+
-- Parses stringify output back into a Lua value
5+
local function serializeAndLoad(value, allowNewlines)
6+
local str = utils.stringify(value, allowNewlines)
7+
local chunk, err = loadstring("return "..str)
8+
assert.is_truthy(chunk)
9+
return chunk(), str
10+
end
11+
12+
describe("scalars", function()
13+
it("stringifies strings with quotes", function()
14+
assert.equal('"hello"', utils.stringify("hello"))
15+
end)
16+
17+
it("strips newlines from strings by default", function()
18+
assert.equal('"a b"', utils.stringify("a\nb"))
19+
end)
20+
21+
it("preserves newlines as long strings when allowed", function()
22+
assert.equal("[[a\nb]]", utils.stringify("a\nb", true))
23+
end)
24+
25+
it("does not use long string form for newline-free strings", function()
26+
assert.equal('"ab"', utils.stringify("ab", true))
27+
end)
28+
29+
it("stringifies numbers", function()
30+
assert.equal("42", utils.stringify(42))
31+
assert.equal("-3.5", utils.stringify(-3.5))
32+
end)
33+
34+
it("stringifies booleans", function()
35+
assert.equal("true", utils.stringify(true))
36+
assert.equal("false", utils.stringify(false))
37+
end)
38+
39+
it("stringifies nil", function()
40+
assert.equal("nil", utils.stringify(nil))
41+
end)
42+
43+
-- supposedly these are valid table keys, but like come on
44+
it("errors on disallowed types", function()
45+
assert.has_error(function() utils.stringify(function() end) end)
46+
assert.has_error(function() utils.stringify({[ function() end ] = "hello"}) end)
47+
end)
48+
end)
49+
50+
describe("tables", function()
51+
it("serializes and loads an empty table", function()
52+
local out = serializeAndLoad({})
53+
assert.same({}, out)
54+
end)
55+
56+
it("serializes and loads an array using array syntax", function()
57+
local input = { 1, 2, 3 }
58+
local out, str = serializeAndLoad(input)
59+
assert.same(input, out)
60+
-- array entries should not include explicit keys
61+
assert.is_nil(str:find("%[1%]"))
62+
end)
63+
64+
it("serializes and loads a string-keyed map", function()
65+
local input = { foo = "bar", baz = 1 }
66+
local out = serializeAndLoad(input)
67+
assert.same(input, out)
68+
end)
69+
70+
it("serializes and loads nested tables (no mixed array/map levels)", function()
71+
local input = { a = { b = { c = { deep = true, value = 3 } } }, list = { "x", "y" } }
72+
local out = serializeAndLoad(input)
73+
assert.same(input, out)
74+
end)
75+
76+
it("sorts map keys deterministically", function()
77+
local str = utils.stringify({ c = 1, a = 1, b = 1 })
78+
local posA = str:find('%["a"%]')
79+
local posB = str:find('%["b"%]')
80+
local posC = str:find('%["c"%]')
81+
assert.is_truthy(posA < posB and posB < posC)
82+
end)
83+
84+
it("serializes and loads numeric (non-sequential) keys", function()
85+
local input = { [5] = "five", [10] = "ten" }
86+
local out = serializeAndLoad(input)
87+
assert.same(input, out)
88+
end)
89+
90+
it("serializes and loads multiline string values when allowed", function()
91+
local input = { text = "line1\nline2" }
92+
local out = serializeAndLoad(input, true)
93+
assert.same(input, out)
94+
end)
95+
96+
it("serializes and loads mixed tables", function()
97+
local input = {"one", "two", six = 7, 3, 4, five = "six"}
98+
local str = utils.stringify(input, false, 1)
99+
assert.equal([[{
100+
"one",
101+
"two",
102+
3,
103+
4,
104+
["five"] = "six",
105+
["six"] = 7,
106+
}]], str)
107+
local out = serializeAndLoad(input)
108+
assert.same(input, out)
109+
end)
110+
end)
111+
end)

src/Classes/TradeQueryGenerator.lua

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ local m_max = math.max
1010
local s_format = string.format
1111
local t_insert = table.insert
1212
local tradeHelpers = LoadModule("Classes/TradeHelpers")
13+
local utils = LoadModule("Modules/Utils")
1314

1415
-- string are an any type while tables require all fields to be matched with type and subType require both to be matched exactly. [1] type, [2] subType, subType is optional and must be nil if not present.
1516
local tradeCategoryNames = {
@@ -395,11 +396,6 @@ function TradeQueryGeneratorClass:InitMods()
395396
error("Error received from api/trade2/data/stats: "..body.error.message)
396397
end
397398

398-
local f = io.open("./Data/TradeSiteStats.lua", "w")
399-
if not f then
400-
error("Could not open file for writing trade stat data")
401-
end
402-
403399
for catIdx, _ in ipairs(body.result) do
404400
table.sort(body.result[catIdx].entries, function(a, b)
405401
if a.text == b.text then
@@ -409,14 +405,8 @@ function TradeQueryGeneratorClass:InitMods()
409405
end)
410406
end
411407

412-
local template = [[-- This file is automatically downloaded, do not edit!
413-
-- Trade site stat data (c) Grinding Gear Games
414-
-- https://www.pathofexile.com/api/trade2/data/stats
415-
-- spell-checker: disable
416-
return %s
417-
-- spell-checker: enable]]
418-
f:write(s_format(template, stringify(body.result)))
419-
f:close()
408+
local description = "This file contains the trade site data from https://www.pathofexile.com/api/trade2/data/stats"
409+
utils.saveTableToFile("./Data/TradeSiteStats.lua", body.result, description)
420410

421411
self.modData = {
422412
["Explicit"] = { },
@@ -636,19 +626,12 @@ return %s
636626
end
637627
end
638628

639-
local queryModsFile = io.open(queryModFilePath, 'w')
640-
queryModsFile:write([[-- This file is automatically generated, do not edit!
641-
-- Stat data (c) Grinding Gear Games
642-
643-
-- This file contains categories of stats, mapped from trade hash to details
644-
-- relevant for generating search weights Note that the trade site requires a
645-
-- prefix of e.g. explicit.stat_{hash}. See
646-
-- https://www.pathofexile.com/api/trade2/data/stats for a list of all trade
647-
-- site stats.
648-
649-
]])
650-
queryModsFile:write("return " .. stringify(self.modData))
651-
queryModsFile:close()
629+
local qmDescription = [[This file contains categories of stats, mapped from trade hash to details
630+
relevant for generating search weights Note that the trade site requires a
631+
prefix of e.g. explicit.stat_{hash}. See
632+
TradeSiteStats.lua for a list of all trade
633+
site stats.]]
634+
utils.saveTableToFile(queryModFilePath, self.modData, qmDescription)
652635
end
653636

654637
function TradeQueryGeneratorClass:GenerateModWeights(modsToTest)

src/Classes/TradeQueryRequests.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
--
66

77
local dkjson = require "dkjson"
8+
local utils = LoadModule("Modules/Utils")
89

910
---@class TradeQueryRequests
1011
local TradeQueryRequestsClass = newClass("TradeQueryRequests", function(self, rateLimiter)
@@ -219,7 +220,7 @@ function TradeQueryRequestsClass:PerformSearch(realm, league, query, callback)
219220
if response.error then
220221
if not (response.error.code and response.error.message) then
221222
errMsg = "Encountered unknown error, check console for details."
222-
ConPrintf("Unknown error: %s", stringify(response.error))
223+
ConPrintf("Unknown error: %s", utils.stringify(response.error))
223224
callback(response, errMsg)
224225
end
225226
if response.error.message:find("Logging in will increase this limit") then

0 commit comments

Comments
 (0)