1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-06-20 06:41:33 +00:00

Register global tests to run them

This commit is contained in:
elsid 2025-02-26 23:12:17 +01:00
parent 8b62f02523
commit 981ca957c1
No known key found for this signature in database
GPG key ID: B845CB9FEE18AB40
6 changed files with 181 additions and 224 deletions

View file

@ -7,7 +7,7 @@ local vfs = require('openmw.vfs')
local world = require('openmw.world') local world = require('openmw.world')
local I = require('openmw.interfaces') local I = require('openmw.interfaces')
local function testTimers() testing.registerGlobalTest('testTimers', function()
testing.expectAlmostEqual(core.getGameTimeScale(), 30, 'incorrect getGameTimeScale() result') testing.expectAlmostEqual(core.getGameTimeScale(), 30, 'incorrect getGameTimeScale() result')
testing.expectAlmostEqual(core.getSimulationTimeScale(), 1, 'incorrect getSimulationTimeScale result') testing.expectAlmostEqual(core.getSimulationTimeScale(), 1, 'incorrect getSimulationTimeScale result')
@ -39,9 +39,9 @@ local function testTimers()
testing.expectGreaterOrEqual(ts1, 0.5, 'async:newSimulationTimer failed') testing.expectGreaterOrEqual(ts1, 0.5, 'async:newSimulationTimer failed')
testing.expectGreaterOrEqual(th2, 72, 'async:newUnsavableGameTimer failed') testing.expectGreaterOrEqual(th2, 72, 'async:newUnsavableGameTimer failed')
testing.expectGreaterOrEqual(ts2, 1, 'async:newUnsavableSimulationTimer failed') testing.expectGreaterOrEqual(ts2, 1, 'async:newUnsavableSimulationTimer failed')
end end)
local function testTeleport() testing.registerGlobalTest('testTeleport', function()
local player = world.players[1] local player = world.players[1]
player:teleport('', util.vector3(100, 50, 500), util.transform.rotateZ(math.rad(90))) player:teleport('', util.vector3(100, 50, 500), util.transform.rotateZ(math.rad(90)))
coroutine.yield() coroutine.yield()
@ -72,16 +72,16 @@ local function testTeleport()
testing.expectEqualWithDelta(player.position.x, 50, 1, 'incorrect position after teleporting') testing.expectEqualWithDelta(player.position.x, 50, 1, 'incorrect position after teleporting')
testing.expectEqualWithDelta(player.position.y, -100, 1, 'incorrect position after teleporting') testing.expectEqualWithDelta(player.position.y, -100, 1, 'incorrect position after teleporting')
testing.expectEqualWithDelta(player.rotation:getYaw(), math.rad(-90), 0.05, 'teleporting changes rotation') testing.expectEqualWithDelta(player.rotation:getYaw(), math.rad(-90), 0.05, 'teleporting changes rotation')
end end)
local function testGetGMST() testing.registerGlobalTest('testGetGMST', function()
testing.expectEqual(core.getGMST('non-existed gmst'), nil) testing.expectEqual(core.getGMST('non-existed gmst'), nil)
testing.expectEqual(core.getGMST('Water_RippleFrameCount'), 4) testing.expectEqual(core.getGMST('Water_RippleFrameCount'), 4)
testing.expectEqual(core.getGMST('Inventory_DirectionalDiffuseR'), 0.5) testing.expectEqual(core.getGMST('Inventory_DirectionalDiffuseR'), 0.5)
testing.expectEqual(core.getGMST('Level_Up_Level2'), 'something') testing.expectEqual(core.getGMST('Level_Up_Level2'), 'something')
end end)
local function testMWScript() testing.registerGlobalTest('testMWScript', function()
local variableStoreCount = 18 local variableStoreCount = 18
local variableStore = world.mwscript.getGlobalVariables(player) local variableStore = world.mwscript.getGlobalVariables(player)
testing.expectEqual(variableStoreCount, #variableStore) testing.expectEqual(variableStoreCount, #variableStore)
@ -101,7 +101,7 @@ local function testMWScript()
indexCheck = indexCheck + 1 indexCheck = indexCheck + 1
end end
testing.expectEqual(variableStoreCount, indexCheck) testing.expectEqual(variableStoreCount, indexCheck)
end end)
local function testRecordStore(store, storeName, skipPairs) local function testRecordStore(store, storeName, skipPairs)
testing.expect(store.records) testing.expect(store.records)
@ -122,7 +122,7 @@ local function testRecordStore(store, storeName, skipPairs)
testing.expectEqual(status, true, storeName) testing.expectEqual(status, true, storeName)
end end
local function testRecordStores() testing.registerGlobalTest('testRecordStores', function()
for key, type in pairs(types) do for key, type in pairs(types) do
if type.records then if type.records then
testRecordStore(type, key) testRecordStore(type, key)
@ -141,9 +141,9 @@ local function testRecordStores()
testRecordStore(types.NPC.classes, "classes") testRecordStore(types.NPC.classes, "classes")
testRecordStore(types.NPC.races, "races") testRecordStore(types.NPC.races, "races")
testRecordStore(types.Player.birthSigns, "birthSigns") testRecordStore(types.Player.birthSigns, "birthSigns")
end end)
local function testRecordCreation() testing.registerGlobalTest('testRecordCreation', function()
local newLight = { local newLight = {
isCarriable = true, isCarriable = true,
isDynamic = true, isDynamic = true,
@ -166,9 +166,9 @@ local function testRecordCreation()
for key, value in pairs(newLight) do for key, value in pairs(newLight) do
testing.expectEqual(record[key], value) testing.expectEqual(record[key], value)
end end
end end)
local function testUTF8Chars() testing.registerGlobalTest('testUTF8Chars', function()
testing.expectEqual(utf8.codepoint("😀"), 0x1F600) testing.expectEqual(utf8.codepoint("😀"), 0x1F600)
local chars = {} local chars = {}
@ -193,9 +193,9 @@ local function testUTF8Chars()
testing.expectEqual(utf8.codepoint(char), codepoint) testing.expectEqual(utf8.codepoint(char), codepoint)
testing.expectEqual(utf8.len(char), 1) testing.expectEqual(utf8.len(char), 1)
end end
end end)
local function testUTF8Strings() testing.registerGlobalTest('testUTF8Strings', function()
local utf8str = "Hello, 你好, 🌎!" local utf8str = "Hello, 你好, 🌎!"
local str = "" local str = ""
@ -206,9 +206,9 @@ local function testUTF8Strings()
testing.expectEqual(utf8.len(utf8str), 13) testing.expectEqual(utf8.len(utf8str), 13)
testing.expectEqual(utf8.offset(utf8str, 9), 11) testing.expectEqual(utf8.offset(utf8str, 9), 11)
end end)
local function testMemoryLimit() testing.registerGlobalTest('testMemoryLimit', function()
local ok, err = pcall(function() local ok, err = pcall(function()
local t = {} local t = {}
local n = 1 local n = 1
@ -219,7 +219,7 @@ local function testMemoryLimit()
end) end)
testing.expectEqual(ok, false, 'Script reaching memory limit should fail') testing.expectEqual(ok, false, 'Script reaching memory limit should fail')
testing.expectEqual(err, 'not enough memory') testing.expectEqual(err, 'not enough memory')
end end)
local function initPlayer() local function initPlayer()
local player = world.players[1] local player = world.players[1]
@ -228,7 +228,7 @@ local function initPlayer()
return player return player
end end
local function testVFS() testing.registerGlobalTest('testVFS', function()
local file = 'test_vfs_dir/lines.txt' local file = 'test_vfs_dir/lines.txt'
local nosuchfile = 'test_vfs_dir/nosuchfile' local nosuchfile = 'test_vfs_dir/nosuchfile'
testing.expectEqual(vfs.fileExists(file), true, 'lines.txt should exist') testing.expectEqual(vfs.fileExists(file), true, 'lines.txt should exist')
@ -272,9 +272,9 @@ local function testVFS()
for _,v in pairs(expectedLines) do for _,v in pairs(expectedLines) do
testing.expectEqual(getLine(), v) testing.expectEqual(getLine(), v)
end end
end end)
local function testCommitCrime() testing.registerGlobalTest('testCommitCrime', function()
local player = initPlayer() local player = initPlayer()
testing.expectEqual(player == nil, false, 'A viable player reference should exist to run `testCommitCrime`') testing.expectEqual(player == nil, false, 'A viable player reference should exist to run `testCommitCrime`')
testing.expectEqual(I.Crimes == nil, false, 'Crimes interface should be available in global contexts') testing.expectEqual(I.Crimes == nil, false, 'Crimes interface should be available in global contexts')
@ -294,80 +294,41 @@ local function testCommitCrime()
types.Player.setCrimeLevel(player, 0) types.Player.setCrimeLevel(player, 0)
testing.expectEqual(I.Crimes.commitCrime(player, { victim = victim, type = types.Player.OFFENSE_TYPE.Theft, arg = 50 }).wasCrimeSeen, true, "Running a crime with a valid victim should notify them when the player is not sneaking, even if it's not explicitly passed in") testing.expectEqual(I.Crimes.commitCrime(player, { victim = victim, type = types.Player.OFFENSE_TYPE.Theft, arg = 50 }).wasCrimeSeen, true, "Running a crime with a valid victim should notify them when the player is not sneaking, even if it's not explicitly passed in")
testing.expectEqual(types.Player.getCrimeLevel(player), 0, "Crime level should not change if the victim's alarm value is low and there's no other witnesses") testing.expectEqual(types.Player.getCrimeLevel(player), 0, "Crime level should not change if the victim's alarm value is low and there's no other witnesses")
end end)
local function testRecordModelProperty() testing.registerGlobalTest('testRecordModelProperty', function()
local player = initPlayer() local player = initPlayer()
testing.expectEqual(types.NPC.record(player).model, 'meshes/basicplayer.dae') testing.expectEqual(types.NPC.record(player).model, 'meshes/basicplayer.dae')
end)
local function registerPlayerTest(name)
testing.registerGlobalTest(name, function()
local player = initPlayer()
testing.runLocalTest(player, name)
end)
end end
tests = { registerPlayerTest('playerYawRotation')
{'timers', testTimers}, registerPlayerTest('playerPitchRotation')
{'rotating player with controls.yawChange should change rotation', function() registerPlayerTest('playerPitchAndYawRotation')
local player = initPlayer() registerPlayerTest('playerRotation')
testing.runLocalTest(player, 'playerYawRotation') registerPlayerTest('playerForwardRunning')
end}, registerPlayerTest('playerDiagonalWalking')
{'rotating player with controls.pitchChange should change rotation', function() registerPlayerTest('findPath')
local player = initPlayer() registerPlayerTest('findRandomPointAroundCircle')
testing.runLocalTest(player, 'playerPitchRotation') registerPlayerTest('castNavigationRay')
end}, registerPlayerTest('findNearestNavMeshPosition')
{'rotating player with controls.pitchChange and controls.yawChange should change rotation', function() registerPlayerTest('playerMemoryLimit')
local player = initPlayer()
testing.runLocalTest(player, 'playerPitchAndYawRotation') testing.registerGlobalTest('playerWeaponAttack', function()
end}, local player = initPlayer()
{'rotating player should not lead to nan rotation', function() world.createObject('basic_dagger1h', 1):moveInto(player)
local player = initPlayer() testing.runLocalTest(player, 'playerWeaponAttack')
testing.runLocalTest(player, 'playerRotation') end)
end},
{'playerForwardRunning', function()
local player = initPlayer()
testing.runLocalTest(player, 'playerForwardRunning')
end},
{'playerDiagonalWalking', function()
local player = initPlayer()
testing.runLocalTest(player, 'playerDiagonalWalking')
end},
{'findPath', function()
local player = initPlayer()
testing.runLocalTest(player, 'findPath')
end},
{'findRandomPointAroundCircle', function()
local player = initPlayer()
testing.runLocalTest(player, 'findRandomPointAroundCircle')
end},
{'castNavigationRay', function()
local player = initPlayer()
testing.runLocalTest(player, 'castNavigationRay')
end},
{'findNearestNavMeshPosition', function()
local player = initPlayer()
testing.runLocalTest(player, 'findNearestNavMeshPosition')
end},
{'teleport', testTeleport},
{'getGMST', testGetGMST},
{'recordStores', testRecordStores},
{'recordCreation', testRecordCreation},
{'utf8Chars', testUTF8Chars},
{'utf8Strings', testUTF8Strings},
{'mwscript', testMWScript},
{'testMemoryLimit', testMemoryLimit},
{'playerMemoryLimit', function()
local player = initPlayer()
testing.runLocalTest(player, 'playerMemoryLimit')
end},
{'player with equipped weapon on attack should damage health of other actors', function()
local player = initPlayer()
world.createObject('basic_dagger1h', 1):moveInto(player)
testing.runLocalTest(player, 'playerWeaponAttack')
end},
{'vfs', testVFS},
{'testCommitCrime', testCommitCrime},
{'recordModelProperty', testRecordModelProperty},
}
return { return {
engineHandlers = { engineHandlers = {
onUpdate = testing.testRunner(tests), onUpdate = testing.makeUpdateGlobal(),
}, },
eventHandlers = testing.eventHandlers, eventHandlers = testing.eventHandlers,
} }

View file

@ -2,12 +2,19 @@ local core = require('openmw.core')
local util = require('openmw.util') local util = require('openmw.util')
local M = {} local M = {}
local globalTestsOrder = {}
local globalTests = {}
local globalTestRunner = nil
local localTests = {}
local localTestRunner = nil
local currentLocalTest = nil local currentLocalTest = nil
local currentLocalTestError = nil local currentLocalTestError = nil
function M.testRunner(tests) function M.makeUpdateGlobal()
local fn = function() local fn = function()
for i, test in ipairs(tests) do for i, test in ipairs(globalTestsOrder) do
local name, fn = unpack(test) local name, fn = unpack(test)
print('TEST_START', i, name) print('TEST_START', i, name)
local status, err = pcall(fn) local status, err = pcall(fn)
@ -27,6 +34,11 @@ function M.testRunner(tests)
end end
end end
function M.registerGlobalTest(name, fn)
globalTests[name] = fn
table.insert(globalTestsOrder, {name, fn})
end
function M.runLocalTest(obj, name) function M.runLocalTest(obj, name)
currentLocalTest = name currentLocalTest = name
currentLocalTestError = nil currentLocalTestError = nil
@ -39,7 +51,21 @@ function M.runLocalTest(obj, name)
end end
end end
function M.expect(cond, delta, msg) function M.registerLocalTest(name, fn)
localTests[name] = fn
end
function M.updateLocal()
if localTestRunner and coroutine.status(localTestRunner) ~= 'dead' then
if not core.isWorldPaused() then
coroutine.resume(localTestRunner)
end
else
localTestRunner = nil
end
end
function M.expect(cond, msg)
if not cond then if not cond then
error(msg or '"true" expected', 2) error(msg or '"true" expected', 2)
end end
@ -182,28 +208,11 @@ function M.formatActualExpected(actual, expected)
return string.format('actual: %s, expected: %s', actual, expected) return string.format('actual: %s, expected: %s', actual, expected)
end end
local localTests = {}
local localTestRunner = nil
function M.registerLocalTest(name, fn)
localTests[name] = fn
end
function M.updateLocal()
if localTestRunner and coroutine.status(localTestRunner) ~= 'dead' then
if not core.isWorldPaused() then
coroutine.resume(localTestRunner)
end
else
localTestRunner = nil
end
end
M.eventHandlers = { M.eventHandlers = {
runLocalTest = function(name) -- used only in local scripts runLocalTest = function(name) -- used only in local scripts
fn = localTests[name] fn = localTests[name]
if not fn then if not fn then
core.sendGlobalEvent('localTestFinished', {name=name, errMsg='Test not found'}) core.sendGlobalEvent('localTestFinished', {name=name, errMsg='Local test is not found'})
return return
end end
localTestRunner = coroutine.create(function() localTestRunner = coroutine.create(function()

View file

@ -8,28 +8,13 @@ if not core.contentFiles.has('Morrowind.esm') then
error('This test requires Morrowind.esm') error('This test requires Morrowind.esm')
end end
function makeTests(modules) require('global_issues')
local tests = {} require('global_dialogues')
require('global_mwscript')
for _, moduleName in ipairs(modules) do
local module = require(moduleName)
for _, v in ipairs(module) do
table.insert(tests, {string.format('[%s] %s', moduleName, v[1]), v[2]})
end
end
return tests
end
local testModules = {
'global_issues',
'global_dialogues',
'global_mwscript',
}
return { return {
engineHandlers = { engineHandlers = {
onUpdate = testing.testRunner(makeTests(testModules)), onUpdate = testing.makeUpdateGlobal(),
}, },
eventHandlers = testing.eventHandlers, eventHandlers = testing.eventHandlers,
} }

View file

@ -13,35 +13,37 @@ function iterateOverRecords(records)
return firstRecordId, lastRecordId, count return firstRecordId, lastRecordId, count
end end
return { testing.registerGlobalTest('[dialogues] Should support iteration over journal dialogues', function()
{'Should support iteration over journal dialogues', function() local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.journal.records)
local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.journal.records) testing.expectEqual(firstRecordId, '11111 test journal')
testing.expectEqual(firstRecordId, '11111 test journal') testing.expectEqual(lastRecordId, 'va_vamprich')
testing.expectEqual(lastRecordId, 'va_vamprich') testing.expectEqual(count, 632)
testing.expectEqual(count, 632) end)
end},
{'Should support iteration over topic dialogues', function() testing.registerGlobalTest('[dialogues] Should support iteration over topic dialogues', function()
local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.topic.records) local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.topic.records)
testing.expectEqual(firstRecordId, '1000-drake pledge') testing.expectEqual(firstRecordId, '1000-drake pledge')
testing.expectEqual(lastRecordId, 'zenithar') testing.expectEqual(lastRecordId, 'zenithar')
testing.expectEqual(count, 1698) testing.expectEqual(count, 1698)
end}, end)
{'Should support iteration over greeting dialogues', function()
local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.greeting.records) testing.registerGlobalTest('[dialogues] Should support iteration over greeting dialogues', function()
testing.expectEqual(firstRecordId, 'greeting 0') local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.greeting.records)
testing.expectEqual(lastRecordId, 'greeting 9') testing.expectEqual(firstRecordId, 'greeting 0')
testing.expectEqual(count, 10) testing.expectEqual(lastRecordId, 'greeting 9')
end}, testing.expectEqual(count, 10)
{'Should support iteration over persuasion dialogues', function() end)
local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.persuasion.records)
testing.expectEqual(firstRecordId, 'admire fail') testing.registerGlobalTest('[dialogues] Should support iteration over persuasion dialogues', function()
testing.expectEqual(lastRecordId, 'taunt success') local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.persuasion.records)
testing.expectEqual(count, 10) testing.expectEqual(firstRecordId, 'admire fail')
end}, testing.expectEqual(lastRecordId, 'taunt success')
{'Should support iteration over voice dialogues', function() testing.expectEqual(count, 10)
local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.voice.records) end)
testing.expectEqual(firstRecordId, 'alarm')
testing.expectEqual(lastRecordId, 'thief') testing.registerGlobalTest('[dialogues] Should support iteration over voice dialogues', function()
testing.expectEqual(count, 8) local firstRecordId, lastRecordId, count = iterateOverRecords(core.dialogue.voice.records)
end}, testing.expectEqual(firstRecordId, 'alarm')
} testing.expectEqual(lastRecordId, 'thief')
testing.expectEqual(count, 8)
end)

View file

@ -4,37 +4,37 @@ local world = require('openmw.world')
local core = require('openmw.core') local core = require('openmw.core')
local types = require('openmw.types') local types = require('openmw.types')
return { testing.registerGlobalTest('[issues] Player should be able to walk up stairs in Ebonheart docks (#4247)', function()
{'Player should be able to walk up stairs in Ebonheart docks (#4247)', function() world.players[1]:teleport('', util.vector3(19867, -102180, -79), util.transform.rotateZ(math.rad(91)))
world.players[1]:teleport('', util.vector3(19867, -102180, -79), util.transform.rotateZ(math.rad(91))) coroutine.yield()
coroutine.yield() testing.runLocalTest(world.players[1], 'Player should be able to walk up stairs in Ebonheart docks (#4247)')
testing.runLocalTest(world.players[1], 'Player should be able to walk up stairs in Ebonheart docks (#4247)') end)
end},
{'Guard in Imperial Prison Ship should find path (#7241)', function() testing.registerGlobalTest('[issues] Guard in Imperial Prison Ship should find path (#7241)', function()
world.players[1]:teleport('Imperial Prison Ship', util.vector3(61, -135, -105), util.transform.rotateZ(math.rad(-20))) world.players[1]:teleport('Imperial Prison Ship', util.vector3(61, -135, -105), util.transform.rotateZ(math.rad(-20)))
coroutine.yield() coroutine.yield()
testing.runLocalTest(world.players[1], 'Guard in Imperial Prison Ship should find path (#7241)') testing.runLocalTest(world.players[1], 'Guard in Imperial Prison Ship should find path (#7241)')
end}, end)
{'Should keep reference to an object moved into container (#7663)', function()
world.players[1]:teleport('ToddTest', util.vector3(2176, 3648, -191), util.transform.rotateZ(math.rad(0))) testing.registerGlobalTest('[issues] Should keep reference to an object moved into container (#7663)', function()
coroutine.yield() world.players[1]:teleport('ToddTest', util.vector3(2176, 3648, -191), util.transform.rotateZ(math.rad(0)))
local barrel = world.createObject('barrel_01', 1) coroutine.yield()
local fargothRing = world.createObject('ring_keley', 1) local barrel = world.createObject('barrel_01', 1)
coroutine.yield() local fargothRing = world.createObject('ring_keley', 1)
testing.expectEqual(types.Container.inventory(barrel):find('ring_keley'), nil) coroutine.yield()
fargothRing:moveInto(types.Container.inventory(barrel)) testing.expectEqual(types.Container.inventory(barrel):find('ring_keley'), nil)
coroutine.yield() fargothRing:moveInto(types.Container.inventory(barrel))
testing.expectEqual(fargothRing.recordId, 'ring_keley') coroutine.yield()
local isFargothRing = function(actual) testing.expectEqual(fargothRing.recordId, 'ring_keley')
if actual == nil then local isFargothRing = function(actual)
return 'ring_keley is not found' if actual == nil then
end return 'ring_keley is not found'
if actual.id ~= fargothRing.id then
return 'found ring_keley id does not match expected: actual=' .. tostring(actual.id)
.. ', expected=' .. tostring(fargothRing.id)
end
return ''
end end
testing.expectThat(types.Container.inventory(barrel):find('ring_keley'), isFargothRing) if actual.id ~= fargothRing.id then
end}, return 'found ring_keley id does not match expected: actual=' .. tostring(actual.id)
} .. ', expected=' .. tostring(fargothRing.id)
end
return ''
end
testing.expectThat(types.Container.inventory(barrel):find('ring_keley'), isFargothRing)
end)

View file

@ -14,38 +14,38 @@ function iterateOverVariables(variables)
return first, last, count return first, last, count
end end
return { testing.registerGlobalTest('[mwscript] Should support iteration over an empty set of script variables', function()
{'Should support iteration over an empty set of script variables', function() local mainVars = world.mwscript.getGlobalScript('main').variables
local mainVars = world.mwscript.getGlobalScript('main').variables local first, last, count = iterateOverVariables(mainVars)
local first, last, count = iterateOverVariables(mainVars) testing.expectEqual(first, nil)
testing.expectEqual(first, nil) testing.expectEqual(last, nil)
testing.expectEqual(last, nil) testing.expectEqual(count, 0)
testing.expectEqual(count, 0) testing.expectEqual(count, #mainVars)
testing.expectEqual(count, #mainVars) end)
end},
{'Should support iteration of script variables', function()
local jiub = world.getObjectByFormId(core.getFormId('Morrowind.esm', 172867))
local jiubVars = world.mwscript.getLocalScript(jiub).variables
local first, last, count = iterateOverVariables(jiubVars)
testing.expectEqual(first, 'state') testing.registerGlobalTest('[mwscript] Should support iteration of script variables', function()
testing.expectEqual(last, 'timer') local jiub = world.getObjectByFormId(core.getFormId('Morrowind.esm', 172867))
testing.expectEqual(count, 3) local jiubVars = world.mwscript.getLocalScript(jiub).variables
testing.expectEqual(count, #jiubVars) local first, last, count = iterateOverVariables(jiubVars)
end},
{'Should support numeric and string indices for getting and setting', function()
local jiub = world.getObjectByFormId(core.getFormId('Morrowind.esm', 172867))
local jiubVars = world.mwscript.getLocalScript(jiub).variables
testing.expectEqual(jiubVars[1], jiubVars.state) testing.expectEqual(first, 'state')
testing.expectEqual(jiubVars[2], jiubVars.wandering) testing.expectEqual(last, 'timer')
testing.expectEqual(jiubVars[3], jiubVars.timer) testing.expectEqual(count, 3)
testing.expectEqual(count, #jiubVars)
end)
jiubVars[1] = 123; testing.registerGlobalTest('[mwscript] Should support numeric and string indices for getting and setting', function()
testing.expectEqual(jiubVars.state, 123) local jiub = world.getObjectByFormId(core.getFormId('Morrowind.esm', 172867))
jiubVars.wandering = 42; local jiubVars = world.mwscript.getLocalScript(jiub).variables
testing.expectEqual(jiubVars[2], 42)
jiubVars[3] = 1.25; testing.expectEqual(jiubVars[1], jiubVars.state)
testing.expectEqual(jiubVars.timer, 1.25) testing.expectEqual(jiubVars[2], jiubVars.wandering)
end}, testing.expectEqual(jiubVars[3], jiubVars.timer)
}
jiubVars[1] = 123;
testing.expectEqual(jiubVars.state, 123)
jiubVars.wandering = 42;
testing.expectEqual(jiubVars[2], 42)
jiubVars[3] = 1.25;
testing.expectEqual(jiubVars.timer, 1.25)
end)