-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: cross server sync support for wow10 only
- Loading branch information
lantisnt
committed
Apr 9, 2023
1 parent
f7db118
commit ca7f267
Showing
7 changed files
with
285 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
local WoW10 = select(4, GetBuildInfo()) >= 100000 | ||
if not WoW10 then return end | ||
|
||
local LogEntry, _ = LibStub:NewLibrary("EventSourcing/LogEntry", 2) | ||
if not LogEntry then | ||
return | ||
end | ||
|
||
local Util = LibStub("EventSourcing/Util") | ||
local SortedList = LibStub("EventSourcing/SortedList") | ||
|
||
--[[ | ||
LogEntry models an entry in the event log | ||
We use short field names because the field names are serialized to disk. | ||
The assumption is that all field names are private to this file and other files will use functions to get what they need. | ||
Since functions are not serialized we do use descriptive names for the functions | ||
]]-- | ||
|
||
-- we use a random property name to guarantee people not accessing it. | ||
local privateStaticPrefix = Util.random(6) | ||
local privateStaticClass = privateStaticPrefix .. '_cls' | ||
|
||
--[[ | ||
These are property constants that we replace for more readability in our code | ||
CHANGING THESE WILL BREAK ALL EXISTING LEDGER ENTRIES | ||
THIS IS ALWAYS A MAJOR BREAKING CHANGE | ||
]]-- | ||
local privateCreator = '_a' | ||
local privateCounter = '_b' | ||
local privateTimestamp = '_c' | ||
local privateClass = '_d' | ||
local privateRealm = '_e' | ||
|
||
|
||
|
||
LogEntry.__index = LogEntry | ||
LogEntry[privateStaticClass] = 'LE' | ||
|
||
local counter = 0 | ||
local lastTimestamp = 0 | ||
|
||
-- private constructor | ||
local function constructor(self) | ||
local o = {} | ||
setmetatable(o, self) | ||
return o | ||
end | ||
|
||
function LogEntry:extend(identifier) | ||
local o = constructor(self) | ||
|
||
if (identifier == nil or type(identifier) ~= "string" or string.len(identifier) == 0) then | ||
error("Identifier must be a non-empty string") | ||
end | ||
o.__index = o | ||
|
||
-- static properties (won't appear on instances) | ||
o[privateStaticClass] = identifier | ||
return o | ||
end | ||
|
||
-- Check if the given table is an subclass of LogEntry | ||
function LogEntry.isSubClassType(child) | ||
return child ~= nil | ||
and type(child) == "table" | ||
and child[privateStaticClass] ~= nil | ||
end | ||
|
||
function LogEntry.staticClassName(metatable) | ||
if not LogEntry.isSubClassType(metatable) then | ||
error("Class is not a child of LogEntry") | ||
end | ||
return metatable[privateStaticClass] | ||
end | ||
|
||
|
||
function LogEntry:new(creator, realm) | ||
local o = constructor(self) | ||
o[privateClass] = LogEntry.staticClassName(self) | ||
|
||
o[privateTimestamp] = Util.time() | ||
if o[privateTimestamp] == lastTimestamp then | ||
counter = counter + 1 | ||
else | ||
lastTimestamp = o[privateTimestamp] | ||
counter = 0 | ||
end | ||
o[privateCounter] = counter | ||
if creator == nil then | ||
o[privateCreator], o[privateRealm] = Util.getIntegerGuid("player") | ||
elseif type(creator) == 'string' then | ||
o[privateCreator], o[privateRealm] = Util.getIntegerGuid(creator) | ||
if (o[privateCreator] == nil) or (o[privateRealm] == nil) then | ||
error(string.format("Failed to convert string `%s` into number", creator)) | ||
end | ||
else | ||
o[privateCreator], o[privateRealm] = creator, realm | ||
if type(o[privateCreator]) ~= 'number' or type(o[privateRealm]) ~= 'number'then | ||
error(string.format("Failed to fill data `creator [%s] -> %s | realm [%s] -> %s` ", | ||
tostring(creator), tostring(o[privateCreator]), | ||
tostring(realm), tostring(o[privateRealm]))) | ||
end | ||
end | ||
|
||
return o | ||
end | ||
|
||
function LogEntry:class() | ||
return self[privateClass] | ||
end | ||
|
||
function LogEntry:time() | ||
return self[privateTimestamp] | ||
end | ||
|
||
function LogEntry:setTime(value) | ||
self[privateTimestamp] = value | ||
end | ||
|
||
function LogEntry:setCounter(value) | ||
self[privateCounter] = value | ||
end | ||
|
||
function LogEntry:setClass(value) | ||
self[privateClass] = value | ||
end | ||
|
||
--[[ | ||
Returns the numbers to be used | ||
]]-- | ||
function LogEntry:numbersForHash() | ||
return {self[privateTimestamp], self[privateCounter], self[privateRealm], self[privateCreator]} | ||
end | ||
|
||
function LogEntry.fields() | ||
return {privateTimestamp, privateCounter, privateRealm, privateCreator} | ||
end | ||
|
||
function LogEntry:creator() | ||
return self[privateCreator] | ||
end | ||
|
||
function LogEntry:realm() | ||
return self[privateRealm] | ||
end | ||
|
||
function LogEntry:counter() | ||
return self[privateCounter] | ||
end | ||
|
||
-- return int the weeknumber of this entry | ||
function LogEntry:weekNumber() | ||
return Util.WeekNumber(self[privateTimestamp]) | ||
end | ||
|
||
-- Return a sorted list set up for log entries | ||
function LogEntry.sortedList(data) | ||
local r = SortedList:new(data or {}, Util.CreateMultiFieldSorter(unpack(LogEntry.fields())), true) | ||
if type(r.uniqueInsert) ~= 'function' then | ||
error("Error creating sorted list but doesn't have unique insert function") | ||
end | ||
return r | ||
end | ||
|
||
function LogEntry:uuid() | ||
return table.concat(self:numbersForHash(), '-') | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
require "tests/_wowstubs_wow10" | ||
|
||
local addonName = "DoesNotMatter" | ||
local addonTable = {} | ||
|
||
local function parseXml(xmlFile, prefix) | ||
prefix = prefix or '' | ||
for line in io.lines(xmlFile) do | ||
for file in string.gmatch(line, 'Script file="(.+\.lua)"') do | ||
local search = prefix .. file:gsub('\\', '/'); | ||
loadfile(search, "bt", {})(addonName, addonTable) | ||
end | ||
for file in string.gmatch(line, 'Include file="(.+\.xml)"') do | ||
local xmlFile = prefix .. file:gsub('\\', '/'); | ||
-- get the new prefix | ||
local newPrefix = string.match(xmlFile, "(.*/).*") | ||
print("new prefix", newPrefix) | ||
parseXml(xmlFile, newPrefix) | ||
end | ||
end | ||
end | ||
|
||
parseXml('LibEventSourcing.xml') | ||
math.randomseed(os.time()) | ||
|
||
local Util = LibStub("EventSourcing/Util") | ||
local assertionStatistics = { | ||
total = 0, | ||
passed = 0, | ||
failed = 0 | ||
} | ||
function assertTrue(param, message) | ||
assertionStatistics["total"] = assertionStatistics["total"] + 1 | ||
assert(param == true, "Assertion failed: " .. (message or '')) | ||
assertionStatistics["passed"] = assertionStatistics["passed"] + 1 | ||
end | ||
|
||
function assertFalse(param, message) | ||
assertionStatistics["total"] = assertionStatistics["total"] + 1 | ||
assert(param == false, message or "failed asserting that param is false") | ||
assertionStatistics["passed"] = assertionStatistics["passed"] + 1 | ||
end | ||
|
||
function assertSame(expected, value) | ||
assertionStatistics["total"] = assertionStatistics["total"] + 1 | ||
assert(expected == value, "failed assert that expected " .. (expected or 'NIL') .. " matches " .. (value or 'NIL')) | ||
assertionStatistics["passed"] = assertionStatistics["passed"] + 1 | ||
end | ||
|
||
function assertNotSame(expected, value) | ||
assertionStatistics["total"] = assertionStatistics["total"] + 1 | ||
assert(expected ~= value, "failed assert that expected " .. (expected or 'NIL') .. " does not match " .. (value or 'NIL')) | ||
assertionStatistics["passed"] = assertionStatistics["passed"] + 1 | ||
end | ||
|
||
function assertEmpty(table) | ||
assertCount(0, table) | ||
end | ||
|
||
function assertCount(expected, table) | ||
assertionStatistics["total"] = assertionStatistics["total"] + 1 | ||
assert(#table == expected, string.format("failed assert that table has length %d", expected)) | ||
assertionStatistics["passed"] = assertionStatistics["passed"] + 1 | ||
end | ||
function assertError(cb) | ||
assertionStatistics["total"] = assertionStatistics["total"] + 1 | ||
assert(pcall(cb) == false, "Assert failed: Expected error") | ||
assertionStatistics["passed"] = assertionStatistics["passed"] + 1 | ||
end | ||
|
||
local Util = LibStub("EventSourcing/Util") | ||
-- freeze time | ||
local ts = Util.time() | ||
Util.time = function() return ts end | ||
|
||
function printResultsAndExit() | ||
Util.DumpTable(assertionStatistics) | ||
if (assertionStatistics['failed'] > 0) then | ||
os.exit(1) | ||
else | ||
os.exit(0) | ||
end | ||
end | ||
|
||
function beginTests() | ||
print(string.format("Starting tests in file %s", arg[0])) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
-- Placeholders for WoW functions | ||
require "tests/_wowstubs" | ||
|
||
GetBuildInfo = function() | ||
return "10.0.5", "112233", "May 01 2023", 100005 | ||
end |