Overhaul physics test organization (#3684)

* Moved files

Signed-off-by: Garcia Ruiz <aljanru@amazon.co.uk>

* Fixes for moved files

Signed-off-by: Garcia Ruiz <aljanru@amazon.co.uk>

* Removed tmp file

Signed-off-by: Garcia Ruiz <aljanru@amazon.co.uk>

Co-authored-by: Garcia Ruiz <aljanru@amazon.co.uk>
This commit is contained in:
AMZN-AlexOteiza
2021-08-31 10:04:24 +01:00
committed by GitHub
parent d784ff8c57
commit 77e630085b
161 changed files with 316 additions and 1333 deletions
@@ -0,0 +1,103 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# Test case ID : C13895144
# Test Case Title : Run a level with multiple ragdolls and then switch levels
# fmt: off
class Tests():
enter_game_mode_with_ragdolls = ("Entered game mode With Ragdolls", "Failed to enter game mode With Ragdolls")
found_ragdolls = ("Found all ragdolls", "Did not find all ragdolls")
exit_game_mode_with_ragdolls = ("Exited game mode With Ragdolls", "Couldn't exit game mode With Ragdolls")
enter_game_mode_without_ragdolls = ("Entered game mode Without Ragdolls", "Failed to enter game mode Without Ragdolls")
exit_game_mode_without_ragdolls = ("Exited game mode Without Ragdolls", "Couldn't exit game mode Without Ragdolls")
# fmt: on
def C13895144_Ragdoll_ChangeLevel():
"""
Summary:
Runs an automated test to ensure that switching from a level with many ragdolls to a level with no ragdolls does not
crash the editor.
Level Description:
C13895144_Ragdoll_WithRagdoll:
10 Ragdoll entities are placed in a row. Each Entity has an Actor, Anim Graph and PhysX Ragdoll component.
C13895144_Ragdoll_NoRagdoll:
The same default level configuration as previous, but with no ragdoll entities. Essentially an empty level.
Expected Behavior:
C13895144_Ragdoll_WithRagdoll loads, all entities are found, then C13895144_Ragdoll_NoRagdoll loads correctly.
No crash should occur.
Test Steps:
1) Open level (with ragdolls)
2) Enter game mode
3) Find all of our ragdolls
4) Exit game mode
5) Open level (without ragdolls)
6) Enter game mode
7) Wait for no crash
8) Exit game mode
9) Close the editor
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import sys
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
import azlmbr.legacy.general as general
WAIT = 3.0
helper.init_idle()
# 1) Open level
helper.open_level("Physics", "C13895144_Ragdoll_WithRagdoll")
# 2) Enter game mode
helper.enter_game_mode(Tests.enter_game_mode_with_ragdolls)
# 3) Find all of our ragdolls
all_valid = True
for id in range(0, 10):
ragdoll_id = general.find_game_entity("Ragdoll_{}".format(id))
if not ragdoll_id.IsValid():
Report.info("Could not find Ragdoll_{}".format(id))
all_valid = False
Report.result(Tests.found_ragdolls, all_valid)
# 4) Exit game mode
helper.exit_game_mode(Tests.exit_game_mode_with_ragdolls)
# 5) Open level (without ragdolls)
helper.open_level("Physics", "C13895144_Ragdoll_NoRagdoll")
# 6) Enter game mode
helper.enter_game_mode(Tests.enter_game_mode_without_ragdolls)
# 7) Wait for no crash
general.idle_wait(WAIT)
# 8) Exit game mode
helper.exit_game_mode(Tests.exit_game_mode_without_ragdolls)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(C13895144_Ragdoll_ChangeLevel)
@@ -0,0 +1,128 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
"""
Test case ID : C14654882
Test Case Title : Loading level with old PhysX Ragdoll component serialization should not produce asset processor errors
"""
# fmt: off
class Tests:
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
exit_game_mode = ("Exited game mode", "Failed to exit game mode")
log_modified = ("The log has been modified from the test run", "The test run failed to modify the logs")
length_of_recorded_lines = ("Log lines were grabbed for checking", "There were no lines grabbed for checking")
error_line_not_found = ("Specified lines were not found in the AP_GUI log file", "One or more specified lines were found in the AP_GUI log file")
# fmt: on
class ExpectedLines:
# These lines are exported to the test runner code to be used via the test suite log monitor
lines = []
class UnexpectedLines:
# These lines are exported to the test runner code to be used via the test suite log monitor
lines = ["Assert", "RagdollComponent' is not registered with the serializer"]
def C14654882_Ragdoll_ragdollAPTest():
"""
Summary:
Opens level containing old PhysX Ragdoll component.
Level Description:
Ragdoll - (entity): PhysX Ragdoll:
Position iteration count: 16
Velocity iteration count: 8
Enable joint projection: checked
Joint projection linear tolerance: 0.001
Joint projection angular tolerance: 1.0 degrees
Expected Behavior:
The level should load and not produce any errors for the asset processor component
serialization of the old PhysX Ragdoll.
Test Steps
0) Get the latest modified time for the AP_GUI.log
1) Open the level
2) Enter game mode
3) Exit game mode
4) Close the editor (Logs will be read after closing editor)
5) Check the AP_GUI log file for the error
5.1) Opens the log file to record the lines
5.2) Check that recorded_lines size > 0
5.3) Search the recorded lines for an Unexpected Line
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
import os
import sys
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
helper.init_idle()
# 0) Get the latest modified time for the AP_GUI.log
AP_GUI_log_path = os.path.join(os.getcwd(), "Bin64vc141", "logs", "AP_GUI.log")
log_modified_time = None
if os.path.exists(AP_GUI_log_path):
log_modified_time = os.stat(AP_GUI_log_path).st_mtime
# 1) Open the level
helper.open_level("Physics", "C14654882_Ragdoll_ragdollAPTest")
# 2) Enter game mode
helper.enter_game_mode(Tests.enter_game_mode)
# 3) Exit game mode
helper.exit_game_mode(Tests.exit_game_mode)
# 5) Check the AP_GUI log file for the error
recorded_lines = []
if log_modified_time:
log_modified_time_final = os.stat(AP_GUI_log_path).st_mtime
Report.info("Log modified time: {}".format(log_modified_time))
Report.info("Log final modified time: {}".format(log_modified_time))
Report.critical_result(
Tests.log_modified, log_modified_time_final > log_modified_time, "The log has not updated since last run."
)
# 5.1) Opens the log file to read the lines
with open(AP_GUI_log_path) as log_file:
for line in log_file:
if "~none~" in line: # "~none~" in line with the message for starting a new AzFramework File Logging run
recorded_lines = [] # clear the recorded lines to look for the newer lines
else:
recorded_lines.append(line)
# The end of log file was reached which should produce the lines for the newest run
# 5.2) Check that recorded_lines size > 0
size = len(recorded_lines)
Report.result(Tests.length_of_recorded_lines, size > 0)
# 5.3) Search the recorded lines for an Unexpected Line
error_found = False
for line in recorded_lines:
if any(s in line for s in UnexpectedLines.lines):
error_found = True
Report.info("Unexpected line was found:")
Report.info(line)
Report.result(Tests.error_line_not_found, not error_found)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(C14654882_Ragdoll_ragdollAPTest)
@@ -0,0 +1,92 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
Test case ID : C17411467
Test Case Title : Check that Physx Ragdoll component can be added without errors/warnings
"""
# fmt: off
class Tests():
create_test_entity = ("Entity created successfully", "Failed to create Entity")
add_actor_component = ("Actor component added", "Failed to add Actor component")
add_animgraph = ("AnimGraph component added", "Failed to add AnimGraph component")
add_physx_ragdoll = ("PhysX Ragdoll added", "Failed to add PhysX Ragdoll")
no_warnings_errors = ("Tracer found no errors or warnings", "Tracer found errors or warnings")
# fmt: on
def C17411467_AddPhysxRagdollComponent():
"""
Summary:
Load level with Entity having Actor, AnimGraph and PhysX Ragdoll components.
Verify that editor remains stable.
Expected Behavior:
Physx Ragdoll component can be added without any errors.
Test Steps:
1) Load the level
2) Create test entity
3) Add Actor and AnimGraph components
4) Start the Tracer to catch any warnings while adding the PhysX Ragdoll component
5) Add PhysX Ragdoll component
6) Verify there are no errors/warnings in the entity outliner
Note:
- This test file must be called from the Open 3D Engine Editor command terminal
- Any passed and failed tests are written to the Editor.log file.
Parsing the file or running a log_monitor are required to observe the test results.
:return: None
"""
from editor_python_test_tools.utils import Report
from editor_python_test_tools.editor_entity_utils import EditorEntity
from editor_python_test_tools.utils import TestHelper as helper
from editor_python_test_tools.utils import Tracer
helper.init_idle()
# 1) Load the level
helper.open_level("Physics", "Base")
# 2) Create test entity
test_entity = EditorEntity.create_editor_entity("TestEntity")
Report.result(Tests.create_test_entity, test_entity.id.IsValid())
# 3) Add Actor and AnimGraph components
test_entity.add_component("Actor")
Report.result(Tests.add_actor_component, test_entity.has_component("Actor"))
test_entity.add_component("Anim Graph")
Report.result(Tests.add_animgraph, test_entity.has_component("Anim Graph"))
# 4) Start the Tracer to catch any errors while adding the PhysX Ragdoll component
with Tracer() as section_tracer:
# 5) Add the PhysX Ragdoll component
ragdoll_component = test_entity.add_component("PhysX Ragdoll")
success_check = (
ragdoll_component.id.get_entity_id() == test_entity.id
and ragdoll_component.get_component_name() == "PhysX Ragdoll"
)
# Using this alternate way to check if PhysX Ragdoll is added to entity since there is an issue with the
# usual method in case of this component. Returned False for test_entity.has_component("PhysX Ragdoll")
Report.result(Tests.add_physx_ragdoll, success_check)
# 6) Verify there are no errors in the entity outliner
success_condition = not (section_tracer.has_errors or section_tracer.has_warnings)
Report.result(Tests.no_warnings_errors, success_condition)
if not success_condition:
if section_tracer.has_warnings:
Report.info(f"Warnings found: {section_tracer.warnings}")
if section_tracer.has_errors:
Report.info(f"Errors found: {section_tracer.errors}")
Report.failure(Tests.no_warnings_found)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(C17411467_AddPhysxRagdollComponent)
@@ -0,0 +1,115 @@
"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
# Test case ID : C28978033
# Test Case Title : Check that WorldRequestBus works with PhysX ragdoll
# fmt: off
class Tests():
enter_game_mode = ("Entered game mode", "Failed to enter game mode")
find_ragdoll = ("Ragdoll found", "Ragdoll not found")
aabb_correct = ("Ragdoll AABB is correct", "Ragdoll AABB is incorrect")
raycast_ref_found = ("Raycast reference entities found", "Raycast reference entities not found")
raycast_hit = ("Raycast hit the ragdoll", "Raycast didn't hit the ragdoll")
exit_game_mode = ("Exited game mode", "Failed to exit game mode")
# fmt: on
def C28978033_Ragdoll_WorldBodyBusTests():
r"""
Summary:
Runs a test to make sure that a WorldBodyBus works property for ragdolls
Level Description:
- TestRagdoll: ragdoll entity in the position(500, 500, 50)
- RayStart: entity that points where to start the raycast_correct
- RayEnd: entity that points where to end the raycast_correct
| ( ) |
o - - - | | | - - > o
RayStart | / \ | RayEnd
TestRagdoll
Expected Outcome:
Once game mode is entered, the gravity is disabled, ragdoll AABB is checked and
Raycast is done from RayStart to RayEnd. It should it hit the ragdoll.
:return:
"""
import os
import sys
import azlmbr.legacy.general as general
import azlmbr.bus
from editor_python_test_tools.utils import Report
from editor_python_test_tools.utils import TestHelper as helper
from editor_python_test_tools.utils import vector3_str, aabb_str
# Global time out
TIME_OUT = 1.0
EXPECTED_AABB = azlmbr.math.Aabb_CreateFromMinMax(azlmbr.math.Vector3(499.413513, 499.843201, 49.9907875),
azlmbr.math.Vector3(500.586487, 500.178009, 51.7091103)) # By observation
AABB_THRESHOLD = 0.2 # Big threshold, even if we waited a single frame only, it can vary a lot in the simulation
# 1) Open level / Enter game mode
helper.init_idle()
helper.open_level("Physics", "C28978033_Ragdoll_WorldBodyBusTests")
# Needs better solution
general.idle_wait(6) # wait a little bit for ragdoll data to load
helper.enter_game_mode(Tests.enter_game_mode)
general.idle_wait_frames(1)
gravity = azlmbr.math.Vector3(0.0, 0.0, 0.0)
azlmbr.physics.WorldRequestBus(azlmbr.bus.Broadcast, "SetGravity", gravity)
# 2) Retrieve entities and positions
ragdoll_id = general.find_game_entity("TestRagdoll")
Report.critical_result(Tests.find_ragdoll, ragdoll_id.IsValid())
aabb = azlmbr.physics.WorldBodyRequestBus(azlmbr.bus.Event, "GetAabb", ragdoll_id)
Report.info("Ragdoll AABB:" + aabb_str(aabb))
Report.info("Target Ragdoll AABB:" + aabb_str(EXPECTED_AABB))
is_expected_aabb_size = aabb.min.IsClose(EXPECTED_AABB.min, AABB_THRESHOLD) and aabb.max.IsClose(EXPECTED_AABB.max, AABB_THRESHOLD)
Report.result(Tests.aabb_correct, is_expected_aabb_size)
raystart_id = general.find_game_entity("RayStart")
rayend_id = general.find_game_entity("RayEnd")
Report.critical_result(Tests.raycast_ref_found, raystart_id.IsValid(), rayend_id.IsValid())
raystart_pos = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTM", raystart_id).GetPosition()
rayend_pos = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTM", rayend_id).GetPosition()
raycast_request = azlmbr.physics.RayCastRequest()
raycast_request.Start = raystart_pos
raycast_request.Distance = (rayend_pos.Subtract(raystart_pos)).GetLength()
raycast_request.Direction = (rayend_pos.Subtract(raystart_pos)).GetNormalized()
result = azlmbr.physics.WorldBodyRequestBus(azlmbr.bus.Event, "RayCast", ragdoll_id, raycast_request)
# Following line crashes due to a hydra bug, use distance for now
# has_hit_ragdoll = ragdoll_id.Equal(result.EntityId)
has_hit_ragdoll = result.Distance > 0.1
Report.result(Tests.raycast_hit, has_hit_ragdoll)
# 4) Exit game mode
helper.exit_game_mode(Tests.exit_game_mode)
if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(C28978033_Ragdoll_WorldBodyBusTests)