SimulationIterfaceAppTest.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "TestFixture.h"
  9. #include <SimulationInterfaces/SimulationEntityManagerRequestBus.h>
  10. namespace UnitTest
  11. {
  12. class SimulationInterfaceTestEnvironmentWithAssets : public SimulationInterfaceTestEnvironment
  13. {
  14. protected:
  15. void PostSystemEntityActivate();
  16. };
  17. void SimulationInterfaceTestEnvironmentWithAssets::PostSystemEntityActivate()
  18. {
  19. // Prepare the asset catalog and ensure that our test asset (testsimulationentity.spawnable) is loaded and
  20. // ready to be used in test scenarios.
  21. AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
  22. AZ::ComponentApplication* app = nullptr;
  23. AZ::ComponentApplicationBus::BroadcastResult(app, &AZ::ComponentApplicationBus::Events::GetApplication);
  24. AZ_Assert(app, "Failed to get application");
  25. auto products = AZ::Utils::GetProjectProductPathForPlatform().c_str();
  26. AZ::IO::Path assetCatalogPath = AZ::IO::Path(products) / "assetcatalog.xml";
  27. bool catalogExists = AZ::IO::FileIOBase::GetInstance()->Exists(assetCatalogPath.c_str());
  28. AZ_Assert(catalogExists, "Asset Catalog in %s does not exist", assetCatalogPath.c_str());
  29. AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, assetCatalogPath.c_str());
  30. const AZ::IO::Path TestSpawnable = "sampleasset/testsimulationentity.spawnable";
  31. const AZ::IO::Path TestSpawnableGlobalPath = AZ::IO::Path(products) / TestSpawnable;
  32. bool spawnableExists = AZ::IO::FileIOBase::GetInstance()->Exists(assetCatalogPath.c_str());
  33. AZ_Assert(spawnableExists, "%s does not exist", TestSpawnableGlobalPath.c_str());
  34. AZ::Data::AssetId assetId;
  35. AZ::Data::AssetCatalogRequestBus::BroadcastResult(
  36. assetId,
  37. &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
  38. TestSpawnable.c_str(),
  39. AZ::Data::s_invalidAssetType,
  40. false);
  41. AZ_Assert(assetId.IsValid(), "Failed to get asset id for %s", TestSpawnable.c_str());
  42. }
  43. TEST_F(SimulationInterfaceTestFixture, SpawnAppTest)
  44. {
  45. // This is an integration test that runs the test application with the SimulationInterfaces gem enabled.
  46. // It has prepared asset catalog, and we are able to spawn entities with the test asset.
  47. using namespace SimulationInterfaces;
  48. constexpr AZStd::string_view entityName = "MySuperDuperEntity";
  49. const AZ::Transform initialPose = AZ::Transform::CreateTranslation(AZ::Vector3(0.0f, 0.0f, 0.0f));
  50. constexpr AZStd::string_view uri = "product_asset:///sampleasset/testsimulationentity.spawnable";
  51. constexpr AZStd::string_view entityNamespace = "";
  52. AZStd::atomic_bool completed = false;
  53. SimulationEntityManagerRequests::SpawnCompletedCb completedCb = [&](const AZ::Outcome<AZStd::string, AZStd::string>& result)
  54. {
  55. EXPECT_TRUE(result.IsSuccess());
  56. completed = true;
  57. };
  58. SimulationEntityManagerRequestBus::Broadcast(
  59. &SimulationEntityManagerRequestBus::Events::SpawnEntity, entityName, uri, entityNamespace, initialPose, completedCb);
  60. // entities are spawned asynchronously, so we need to tick the app to let the entity be spawned
  61. TickApp(100);
  62. EXPECT_TRUE(completed);
  63. // list simulation entities
  64. AZStd::vector<AZStd::string> entities;
  65. SimulationEntityManagerRequestBus::BroadcastResult(entities, &SimulationEntityManagerRequestBus::Events::GetEntities, EntityFilters());
  66. EXPECT_EQ(entities.size(), 1);
  67. ASSERT_FALSE(entities.empty())<< "Simulated Entities Empty";
  68. const AZStd::string spawnedEntityName = entities.front();
  69. printf("Spawned entity name %s\n", spawnedEntityName.c_str());
  70. // run physics simulation
  71. StepPhysics(100);
  72. // Get entity state,
  73. AZStd::unordered_map<AZStd::string, EntityState> entityStates;
  74. SimulationEntityManagerRequestBus::BroadcastResult(
  75. entityStates, &SimulationEntityManagerRequestBus::Events::GetEntitiesStates, EntityFilters());
  76. auto entityState = entityStates.find(spawnedEntityName);
  77. ASSERT_NE(entityState, entityStates.end());
  78. EXPECT_EQ(entityState->first, spawnedEntityName);
  79. // check if the entity moved
  80. EXPECT_GE(entityState->second.m_pose.GetTranslation().GetDistance(initialPose.GetTranslation()), 1.0f);
  81. // set new entity state - move the entity to X=1000 meters
  82. const AZ::Vector3 newPosition = AZ::Vector3(1000.0f, 0.0f, 0.0f);
  83. const EntityState newState = { AZ::Transform::CreateTranslation(newPosition), AZ::Vector3::CreateZero(), AZ::Vector3::CreateZero() };
  84. SimulationEntityManagerRequestBus::Broadcast(&SimulationEntityManagerRequestBus::Events::SetEntityState, spawnedEntityName, newState);
  85. StepPhysics();
  86. // Check if entity was teleported by setting the new state, we use a filter to check if the entity is at the new position
  87. EntityFilters filter;
  88. filter.m_bounds_shape = AZStd::make_shared<Physics::SphereShapeConfiguration>(2.0f);
  89. filter.m_bounds_pose = AZ::Transform::CreateTranslation(AZ::Vector3(1000.0f, 0.0f, 0.0f));
  90. AZStd::vector<AZStd::string> entitiesFiltered;
  91. SimulationEntityManagerRequestBus::BroadcastResult(entitiesFiltered, &SimulationEntityManagerRequestBus::Events::GetEntities, filter);
  92. EXPECT_EQ(entitiesFiltered.size(), 1);
  93. // delete entity using its name
  94. SimulationEntityManagerRequestBus::Broadcast(&SimulationEntityManagerRequestBus::Events::DeleteEntity, entityName);
  95. TickApp(100);
  96. // list simulation entities after deletion, expect no simulation entities
  97. AZStd::vector<AZStd::string> entities2;
  98. SimulationEntityManagerRequestBus::BroadcastResult(entities2, &SimulationEntityManagerRequestBus::Events::GetEntities, EntityFilters());
  99. EXPECT_EQ(entities2.size(), 0);
  100. }
  101. } // namespace UnitTest
  102. // required to support running integration tests with Qt and PhysX
  103. AZTEST_EXPORT int AZ_UNIT_TEST_HOOK_NAME(int argc, char** argv)
  104. {
  105. ::testing::InitGoogleMock(&argc, argv);
  106. AzQtComponents::PrepareQtPaths();
  107. QApplication app(argc, argv);
  108. AZ::Test::printUnusedParametersWarning(argc, argv);
  109. AZ::Test::addTestEnvironments({ new UnitTest::SimulationInterfaceTestEnvironmentWithAssets() });
  110. int result = RUN_ALL_TESTS();
  111. return result;
  112. }
  113. IMPLEMENT_TEST_EXECUTABLE_MAIN();