mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-06 07:15:36 +00:00
Add Morrowind specific tests
This commit is contained in:
parent
9bff292a29
commit
5a0ad8cdd7
8 changed files with 273 additions and 0 deletions
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
|
||||
#include <components/misc/color.hpp>
|
||||
|
@ -87,6 +89,7 @@ namespace LuaUtil
|
|||
};
|
||||
vectorType[sol::meta_function::to_string] = [](const T& v) {
|
||||
std::stringstream ss;
|
||||
ss << std::setprecision(std::numeric_limits<typename T::value_type>::max_exponent10);
|
||||
ss << "(" << v[0];
|
||||
for (int i = 1; i < T::num_components; ++i)
|
||||
ss << ", " << v[i];
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
local core = require('openmw.core')
|
||||
local util = require('openmw.util')
|
||||
|
||||
local M = {}
|
||||
local currentLocalTest = nil
|
||||
|
@ -76,6 +77,83 @@ function M.expectEqual(v1, v2, msg)
|
|||
end
|
||||
end
|
||||
|
||||
function M.closeToVector(expected, maxDistance)
|
||||
return function(actual)
|
||||
local distance = (expected - actual):length()
|
||||
if distance <= maxDistance then
|
||||
return ''
|
||||
end
|
||||
return string.format('%s is too far from expected %s: %s > %s', actual, expected, distance, maxDistance)
|
||||
end
|
||||
end
|
||||
|
||||
---
|
||||
-- Matcher verifying that given value is an array each element of which matches elements of expected.
|
||||
-- @function elementsAreArray
|
||||
-- @param expected#array of values or matcher functions.
|
||||
-- @usage
|
||||
-- local t = {42, 13}
|
||||
-- local matcher = function(actual)
|
||||
-- if actual ~= 42 then
|
||||
-- return string.format('%s is not 42', actual)
|
||||
-- end
|
||||
-- return ''
|
||||
-- end
|
||||
-- expectThat({42, 13}, elementsAreArray({matcher, 13}))
|
||||
function M.elementsAreArray(expected)
|
||||
local expected_matchers = {}
|
||||
for i, v in ipairs(expected) do
|
||||
if type(v) == 'function' then
|
||||
expected_matchers[i] = v
|
||||
else
|
||||
expected_matchers[i] = function (other)
|
||||
if expected[i].__eq(expected[i], other) then
|
||||
return ''
|
||||
end
|
||||
return string.format('%s element %s does no match expected: %s', i, other, expected[i])
|
||||
end
|
||||
end
|
||||
end
|
||||
return function(actual)
|
||||
if #actual < #expected_matchers then
|
||||
return string.format('number of elements is less than expected: %s < %s', #actual, #expected_matchers)
|
||||
end
|
||||
local message = ''
|
||||
for i, v in ipairs(actual) do
|
||||
if i > #expected_matchers then
|
||||
message = string.format('%s\n%s element is out of expected range: %s', message, i, #expected_matchers)
|
||||
break
|
||||
end
|
||||
local match_message = expected_matchers[i](v)
|
||||
if match_message ~= '' then
|
||||
message = string.format('%s\n%s', message, match_message)
|
||||
end
|
||||
end
|
||||
return message
|
||||
end
|
||||
end
|
||||
|
||||
---
|
||||
-- Verifies that given value matches provided matcher.
|
||||
-- @function expectThat
|
||||
-- @param value#any any value to match.
|
||||
-- @param matcher#function a function returing empty string in the case of success or a message explaining the mismatch.
|
||||
-- @param msg#string a message to prefix failure reason.
|
||||
-- @usage
|
||||
-- local matcher = function(actual)
|
||||
-- if actual == 42 then
|
||||
-- return ''
|
||||
-- end
|
||||
-- return string.format('%s is not 42', actual)
|
||||
-- end
|
||||
-- expectThat(42, matcher)
|
||||
function M.expectThat(value, matcher, msg)
|
||||
local message = matcher(value)
|
||||
if message ~= '' then
|
||||
error(string.format('%s: actual does not match expected: %s', msg or 'Failure', message), 2)
|
||||
end
|
||||
end
|
||||
|
||||
local localTests = {}
|
||||
local localTestRunner = nil
|
||||
|
||||
|
|
10
scripts/data/morrowind_tests/README.md
Normal file
10
scripts/data/morrowind_tests/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Morrowind integration tests
|
||||
|
||||
A set of scripts to provide integration tests based on Morrowind content.
|
||||
|
||||
Simple usage:
|
||||
```bash
|
||||
"${OPENMW_BINARY_DIR:?}/openmw" \
|
||||
--config "${OPENMW_SOURCE_DIR:?}/scripts/data/morrowind_tests" \
|
||||
--data "${MORROWIND_DATA_DIR:?}"
|
||||
```
|
1
scripts/data/morrowind_tests/builtin.omwscripts
Normal file
1
scripts/data/morrowind_tests/builtin.omwscripts
Normal file
|
@ -0,0 +1 @@
|
|||
# It is an empty file that overrides builtin.omwscripts and disables builtin scripts
|
11
scripts/data/morrowind_tests/openmw.cfg
Normal file
11
scripts/data/morrowind_tests/openmw.cfg
Normal file
|
@ -0,0 +1,11 @@
|
|||
skip-menu=1
|
||||
no-grab=1
|
||||
replace=config
|
||||
config=test_workdir
|
||||
user-data=test_workdir
|
||||
data-local=test_workdir
|
||||
data=../integration_tests/testing_util
|
||||
data=.
|
||||
content=Morrowind.esm
|
||||
content=test.omwscripts
|
||||
fallback-archive=Morrowind.bsa
|
140
scripts/data/morrowind_tests/player.lua
Normal file
140
scripts/data/morrowind_tests/player.lua
Normal file
|
@ -0,0 +1,140 @@
|
|||
local core = require('openmw.core')
|
||||
local input = require('openmw.input')
|
||||
local self = require('openmw.self')
|
||||
local testing = require('testing_util')
|
||||
local util = require('openmw.util')
|
||||
local types = require('openmw.types')
|
||||
local nearby = require('openmw.nearby')
|
||||
|
||||
input.setControlSwitch(input.CONTROL_SWITCH.Fighting, false)
|
||||
input.setControlSwitch(input.CONTROL_SWITCH.Jumping, false)
|
||||
input.setControlSwitch(input.CONTROL_SWITCH.Looking, false)
|
||||
input.setControlSwitch(input.CONTROL_SWITCH.Magic, false)
|
||||
input.setControlSwitch(input.CONTROL_SWITCH.VanityMode, false)
|
||||
input.setControlSwitch(input.CONTROL_SWITCH.ViewMode, false)
|
||||
|
||||
testing.registerLocalTest('Player should be able to walk up stairs in Ebonheart docks (#4247)',
|
||||
function()
|
||||
local startPos = self.position
|
||||
local dest = util.vector3(20296, -102194, 73)
|
||||
local endTime = core.getSimulationTime() + 3
|
||||
while (self.position.x <= dest.x or self.position.z <= dest.z) and core.getSimulationTime() < endTime do
|
||||
self.controls.jump = false
|
||||
self.controls.run = true
|
||||
self.controls.movement = 1
|
||||
self.controls.sideMovement = 0
|
||||
self.controls.yawChange = 0
|
||||
coroutine.yield()
|
||||
end
|
||||
testing.expectGreaterThan(self.position.x, dest.x, 'Final position, X')
|
||||
testing.expectEqualWithDelta(self.position.y, dest.y, 10, 'Final position, Y')
|
||||
testing.expectGreaterThan(self.position.z, dest.z, 'Final position, Z')
|
||||
end)
|
||||
|
||||
testing.registerLocalTest('Guard in Imperial Prison Ship should find path (#7241)',
|
||||
function()
|
||||
local src = util.vector3(34.297367095947265625, 806.3817138671875, 109.278961181640625)
|
||||
local dst = util.vector3(90, -90, -88)
|
||||
local agentBounds = types.Actor.getPathfindingAgentBounds(self)
|
||||
local options = {
|
||||
agentBounds = agentBounds,
|
||||
destinationTolerance = 0,
|
||||
}
|
||||
local status, path = nearby.findPath(src, dst, options)
|
||||
testing.expectEqual(status, nearby.FIND_PATH_STATUS.Success, 'Status')
|
||||
testing.expectLessOrEqual((util.vector2(path[path:size()].x, path[path:size()].y) - util.vector2(dst.x, dst.y)):length(), 1, 'Last path point x, y')
|
||||
testing.expectLessOrEqual(path[path:size()].z - dst.z, 20, 'Last path point z')
|
||||
if agentBounds.shapeType == nearby.COLLISION_SHAPE_TYPE.Aabb then
|
||||
testing.expectThat(path, testing.elementsAreArray({
|
||||
testing.closeToVector(util.vector3(34.29737091064453125, 806.3817138671875, 112.76610565185546875), 1e-1),
|
||||
testing.closeToVector(util.vector3(30.4828090667724609375, 864.81732177734375, 112.76610565185546875), 1e-1),
|
||||
testing.closeToVector(util.vector3(26.6682491302490234375, 923.25299072265625, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(22.85369110107421875, 981.6885986328125, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(19.03913116455078125, 1040.124267578125, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(15.22457122802734375, 1098.559814453125, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(15, 1102, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(15, 1102, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(15, 1102, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-67.99993896484375, 1108.4000244140625, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-112, 1110, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-112, 1110, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-112, 1110, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-115.59993743896484375, 1360.0001220703125, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-101.39704132080078125, 1416.811767578125, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-43.336151123046875, 1424.44091796875, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-3.460088253021240234375, 1381.5552978515625, 92.34075927734375), 1e-1),
|
||||
testing.closeToVector(util.vector3(3.82649898529052734375, 1323.4503173828125, 43.302886962890625), 1e-1),
|
||||
testing.closeToVector(util.vector3(11.11308765411376953125, 1265.345458984375, -7.3479709625244140625), 1e-1),
|
||||
testing.closeToVector(util.vector3(18.399677276611328125, 1207.240478515625, -54.67620849609375), 1e-1),
|
||||
testing.closeToVector(util.vector3(25.6862640380859375, 1149.135498046875, -91.845550537109375), 1e-1),
|
||||
testing.closeToVector(util.vector3(32.9728546142578125, 1091.030517578125, -97.08281707763671875), 1e-1),
|
||||
testing.closeToVector(util.vector3(40.2594451904296875, 1032.9256591796875, -98.50542449951171875), 1e-1),
|
||||
testing.closeToVector(util.vector3(47.546039581298828125, 974.82080078125, -98.50542449951171875), 1e-1),
|
||||
testing.closeToVector(util.vector3(54.832630157470703125, 916.71588134765625, -98.50542449951171875), 1e-1),
|
||||
testing.closeToVector(util.vector3(62.119220733642578125, 858.61102294921875, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(69.40581512451171875, 800.50616455078125, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(76.692413330078125, 742.4012451171875, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(79, 724, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(79, 724, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(79, 724, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(40.80001068115234375, 353.600006103515625, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(73.7038726806640625, 305.158203125, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(84, 290.000030517578125, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(84, 290.000030517578125, -104.58989715576171875), 1e-1),
|
||||
testing.closeToVector(util.vector3(136.0000152587890625, 81.60001373291015625, -104.58989715576171875), 1e-1),
|
||||
testing.closeToVector(util.vector3(89.15203094482421875, 46.464019775390625, -104.58989715576171875), 1e-1),
|
||||
testing.closeToVector(util.vector3(83.552001953125, 42.26399993896484375, -104.58989715576171875), 1e-1),
|
||||
testing.closeToVector(util.vector3(83.552001953125, 42.26399993896484375, -98.72841644287109375), 1e-1),
|
||||
testing.closeToVector(util.vector3(115.60001373291015625, -27.1999359130859375, -98.72841644287109375), 1e-1),
|
||||
testing.closeToVector(util.vector3(93.4945526123046875, -81.42742156982421875, -100.4057159423828125), 1e-1),
|
||||
testing.closeToVector(util.vector3(90, -90, -99.7056884765625), 1e-1),
|
||||
}))
|
||||
elseif agentBounds.shapeType == nearby.COLLISION_SHAPE_TYPE.Cylinder then
|
||||
testing.expectThat(path, testing.elementsAreArray({
|
||||
testing.closeToVector(util.vector3(34.29737091064453125, 806.3817138671875, 112.76610565185546875), 1e-1),
|
||||
testing.closeToVector(util.vector3(23.4630756378173828125, 863.9307861328125, 112.76610565185546875), 1e-1),
|
||||
testing.closeToVector(util.vector3(12.628780364990234375, 921.4798583984375, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(1.79448258876800537109375, 979.0289306640625, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-9.0398197174072265625, 1036.5780029296875, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-19.8741359710693359375, 1094.126953125, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-70.930450439453125, 1122.8067626953125, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-121.98685455322265625, 1151.486328125, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-121.020294189453125, 1210.038330078125, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-120.0537261962890625, 1268.59033203125, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-119.08716583251953125, 1327.142333984375, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-118.12059783935546875, 1385.6944580078125, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-118, 1393, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-118, 1393, 112.2945709228515625), 1e-1),
|
||||
testing.closeToVector(util.vector3(-118, 1393, 114.73973846435546875), 1e-1),
|
||||
testing.closeToVector(util.vector3(27.200008392333984375, 1380.4000244140625, 114.73973846435546875), 1e-1),
|
||||
testing.closeToVector(util.vector3(29.74369049072265625, 1321.8953857421875, 114.73973846435546875), 1e-1),
|
||||
testing.closeToVector(util.vector3(32.287372589111328125, 1263.3907470703125, 114.73973846435546875), 1e-1),
|
||||
testing.closeToVector(util.vector3(34.831058502197265625, 1204.885986328125, -57.1894378662109375), 1e-1),
|
||||
testing.closeToVector(util.vector3(40.18719482421875, 1146.571533203125, -90.156890869140625), 1e-1),
|
||||
testing.closeToVector(util.vector3(45.543331146240234375, 1088.2569580078125, -97.2764434814453125), 1e-1),
|
||||
testing.closeToVector(util.vector3(50.89946746826171875, 1029.9423828125, -98.50542449951171875), 1e-1),
|
||||
testing.closeToVector(util.vector3(56.255603790283203125, 971.62786865234375, -98.50542449951171875), 1e-1),
|
||||
testing.closeToVector(util.vector3(61.6117401123046875, 913.31329345703125, -98.50542449951171875), 1e-1),
|
||||
testing.closeToVector(util.vector3(66.9678802490234375, 854.998779296875, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(72.3240203857421875, 796.6842041015625, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(77.68015289306640625, 738.36968994140625, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(79, 724, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(79, 724, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(108.80001068115234375, 299.20001220703125, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(84, 290.000030517578125, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(84, 290.000030517578125, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(84, 290.000030517578125, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(108.80001068115234375, 54.4000091552734375, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(101.23966217041015625, -3.6698896884918212890625, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(93.6793060302734375, -61.7397918701171875, -104.83390045166015625), 1e-1),
|
||||
testing.closeToVector(util.vector3(90, -90, -104.83390045166015625), 1e-1),
|
||||
}))
|
||||
end
|
||||
end)
|
||||
|
||||
return {
|
||||
engineHandlers = {
|
||||
onUpdate = testing.updateLocal,
|
||||
},
|
||||
eventHandlers = testing.eventHandlers
|
||||
}
|
28
scripts/data/morrowind_tests/test.lua
Normal file
28
scripts/data/morrowind_tests/test.lua
Normal file
|
@ -0,0 +1,28 @@
|
|||
local testing = require('testing_util')
|
||||
local util = require('openmw.util')
|
||||
local world = require('openmw.world')
|
||||
local core = require('openmw.core')
|
||||
|
||||
if not core.contentFiles.has('Morrowind.esm') then
|
||||
error('This test requires Morrowind.esm')
|
||||
end
|
||||
|
||||
local tests = {
|
||||
{'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)))
|
||||
coroutine.yield()
|
||||
testing.runLocalTest(world.players[1], 'Player should be able to walk up stairs in Ebonheart docks (#4247)')
|
||||
end},
|
||||
{'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)))
|
||||
coroutine.yield()
|
||||
testing.runLocalTest(world.players[1], 'Guard in Imperial Prison Ship should find path (#7241)')
|
||||
end},
|
||||
}
|
||||
|
||||
return {
|
||||
engineHandlers = {
|
||||
onUpdate = testing.testRunner(tests),
|
||||
},
|
||||
eventHandlers = testing.eventHandlers,
|
||||
}
|
2
scripts/data/morrowind_tests/test.omwscripts
Normal file
2
scripts/data/morrowind_tests/test.omwscripts
Normal file
|
@ -0,0 +1,2 @@
|
|||
GLOBAL: test.lua
|
||||
PLAYER: player.lua
|
Loading…
Reference in a new issue