Apply Patch
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
-- Per-addon memory: the !!!!GentleGC_Memory companion measuring a simulated
|
||||
-- login, and Gentle GC reporting it.
|
||||
-- Run: lua5.0 tests/test_memory.lua GentleGC.lua "!!!!GentleGC_Memory/GentleGC_Memory.lua"
|
||||
local MAIN, COMPANION = arg[1], arg[2]
|
||||
format = string.format
|
||||
local now = 1000
|
||||
function GetTime() return now end
|
||||
function UnitAffectingCombat() return false end
|
||||
function UnitIsAFK() return false end
|
||||
function date() return "2026-10-21 12:00" end
|
||||
local log = {}
|
||||
DEFAULT_CHAT_FRAME = { AddMessage = function(_, m) table.insert(log, m); print(" " .. m) end }
|
||||
|
||||
local origCG = collectgarbage
|
||||
local ADDONS, LOADED
|
||||
|
||||
-- frames, with events dispatched in registration order like the client
|
||||
local FRAMES
|
||||
function CreateFrame()
|
||||
local f = { scripts = {}, events = {} }
|
||||
function f:RegisterEvent(e) self.events[e] = true end
|
||||
function f:UnregisterEvent(e) self.events[e] = nil end
|
||||
function f:UnregisterAllEvents() self.events = {} end
|
||||
function f:RegisterAllEvents() end
|
||||
function f:SetScript(k, fn) self.scripts[k] = fn end
|
||||
table.insert(FRAMES, f)
|
||||
return f
|
||||
end
|
||||
local function fire(e, a1)
|
||||
for _, f in ipairs(FRAMES) do
|
||||
if f.events[e] and f.scripts.OnEvent then event, arg1 = e, a1; this = f; f.scripts.OnEvent() end
|
||||
end
|
||||
end
|
||||
|
||||
function GetNumAddOns() return table.getn(ADDONS) end
|
||||
function GetAddOnInfo(i)
|
||||
local a = type(i) == "number" and ADDONS[i] or nil
|
||||
if not a then return nil end
|
||||
return a.name, a.name, "", a.enabled and 1 or nil
|
||||
end
|
||||
function IsAddOnLoaded(name) return LOADED[name] and 1 or nil end
|
||||
|
||||
local function count(pat) local n = 0; for _, m in ipairs(log) do if string.find(m, pat) then n = n + 1 end end; return n end
|
||||
local function lastMatch(pat) for i = table.getn(log), 1, -1 do if string.find(log[i], pat) then return log[i] end end; return "" end
|
||||
local function check(name, c) print((c and "PASS " or "FAIL ") .. name); if not c then FAILED = true end end
|
||||
|
||||
-- an addon's data: tables kept in a global, roughly `mb` megabytes
|
||||
KEEP = {}
|
||||
local function allocate(name, mb)
|
||||
local t = {}
|
||||
for i = 1, mb * 9000 do t[i] = { i } end
|
||||
KEEP[name] = t
|
||||
end
|
||||
|
||||
-- one full login: every enabled addon in order, then login and world events
|
||||
-- sizes: MB per addon; withCompanion: install the companion
|
||||
local function login(sizes, withCompanion)
|
||||
FRAMES, LOADED, KEEP = {}, {}, {}
|
||||
collectgarbage = origCG
|
||||
SlashCmdList = {}
|
||||
GentleGCMemory = nil
|
||||
origCG()
|
||||
for _, a in ipairs(ADDONS) do
|
||||
if a.enabled and (withCompanion or a.name ~= "!!!!GentleGC_Memory") then
|
||||
if a.name == "!!!!GentleGC_Memory" then
|
||||
dofile(COMPANION)
|
||||
elseif a.name == "GentleGC" then
|
||||
dofile(MAIN)
|
||||
else
|
||||
allocate(a.name, sizes[a.name] or 0)
|
||||
end
|
||||
LOADED[a.name] = true
|
||||
fire("ADDON_LOADED", a.name)
|
||||
end
|
||||
end
|
||||
allocate("variables", 0.5)
|
||||
fire("PLAYER_LOGIN")
|
||||
allocate("login setup", 3)
|
||||
fire("PLAYER_ENTERING_WORLD")
|
||||
end
|
||||
|
||||
local SIZES = { ["!!!ClassicAPI"] = 1, Atlas = 2, Bagshui = 5, pfQuest = 20, Wrekkit = 1 }
|
||||
ADDONS = {
|
||||
{ name = "!!!ClassicAPI", enabled = true },
|
||||
{ name = "!!!!GentleGC_Memory", enabled = true },
|
||||
{ name = "Atlas", enabled = true },
|
||||
{ name = "Bagshui", enabled = true },
|
||||
{ name = "GentleGC", enabled = true },
|
||||
{ name = "pfQuest", enabled = true },
|
||||
{ name = "Wrekkit", enabled = true },
|
||||
}
|
||||
-- (the client loads "!!!!" before "!!!", but the test puts ClassicAPI first to
|
||||
-- check the "loaded before" list)
|
||||
|
||||
local function rowMB(name)
|
||||
local m = GentleGCMemoryDB.measured
|
||||
for i = 1, table.getn(m.rows) do if m.rows[i][1] == name then return m.rows[i][2] / 1024 end end
|
||||
end
|
||||
local function near(v, want) return v and math.abs(v - want) <= math.max(0.35, want * 0.15) end
|
||||
|
||||
print("1. first login with the companion: measured")
|
||||
login(SIZES, true)
|
||||
local m = GentleGCMemoryDB and GentleGCMemoryDB.measured
|
||||
check("a measurement was saved", m ~= nil and table.getn(m.rows) >= 5)
|
||||
check("first login is the reason", m and m.reason == "first login")
|
||||
check("Atlas ~2 MB", near(rowMB("Atlas"), 2))
|
||||
check("Bagshui ~5 MB", near(rowMB("Bagshui"), 5))
|
||||
check("pfQuest ~20 MB", near(rowMB("pfQuest"), 20))
|
||||
check("Wrekkit ~1 MB", near(rowMB("Wrekkit"), 1))
|
||||
check("ClassicAPI listed as loaded before", m and m.before[1] == "!!!ClassicAPI")
|
||||
check("summary printed after loading", string.find(lastMatch("measured your addons"), "Biggest: pfQuest") ~= nil)
|
||||
check("companion stopped measuring", GentleGCMemory.measuring == false)
|
||||
|
||||
print("2. /ggc addons")
|
||||
local cmd = SlashCmdList.GENTLEGC
|
||||
cmd("addons")
|
||||
check("header line", count("addon memory at login on 2026%-10%-21") == 1)
|
||||
local first
|
||||
for i = 1, table.getn(log) do if string.find(log[i], "addon memory at login") then first = log[i + 1] end end
|
||||
check("biggest addon on the first row", first and string.find(first, "pfQuest") ~= nil)
|
||||
check("login stage shown", count("then addons setting up at login") == 1)
|
||||
check("loaded-before line", count("counted in the interface number: !!!ClassicAPI") == 1)
|
||||
cmd("")
|
||||
check("status names the biggest addons", string.find(lastMatch("biggest addons"), "pfQuest") ~= nil)
|
||||
check("measuring collections not counted as other addons'", count("by other addons") == 0)
|
||||
check("nor as automatic", string.find(lastMatch("session:"), "0 automatic") ~= nil)
|
||||
|
||||
print("3. next login, same addons: not measured again")
|
||||
local when = m
|
||||
login(SIZES, true)
|
||||
check("same measurement kept", GentleGCMemoryDB.measured == when)
|
||||
check("no summary this time", count("measured your addons") == 1)
|
||||
|
||||
print("4. an addon added: measured again")
|
||||
table.insert(ADDONS, { name = "ShaguTweaks", enabled = true })
|
||||
SIZES.ShaguTweaks = 3
|
||||
login(SIZES, true)
|
||||
check("new measurement", GentleGCMemoryDB.measured ~= when and GentleGCMemoryDB.measured.reason == "addons changed")
|
||||
check("ShaguTweaks ~3 MB", near(rowMB("ShaguTweaks"), 3))
|
||||
|
||||
print("5. /ggc addons measure: measured on the next reload")
|
||||
local before = GentleGCMemoryDB.measured
|
||||
SlashCmdList.GENTLEGC("addons measure")
|
||||
check("asks for a reload", count("type /reload to measure") == 1)
|
||||
login(SIZES, true)
|
||||
check("measured because it was requested", GentleGCMemoryDB.measured ~= before and GentleGCMemoryDB.measured.reason == "requested")
|
||||
|
||||
print("6. without the companion")
|
||||
GentleGCMemoryDB = nil
|
||||
login(SIZES, false)
|
||||
SlashCmdList.GENTLEGC("addons")
|
||||
check("explains the companion folder", count("needs the !!!!GentleGC_Memory folder") == 1)
|
||||
|
||||
print(FAILED and "SOME TESTS FAILED" or "ALL TESTS PASSED")
|
||||
Reference in New Issue
Block a user