Переглянути джерело

Moved component unit tests.

Daniel Buckmaster 11 роки тому
батько
коміт
21ecb6f50d

+ 1 - 48
Engine/source/component/moreAdvancedComponent.cpp

@@ -21,7 +21,6 @@
 //-----------------------------------------------------------------------------
 
 #include "component/moreAdvancedComponent.h"
-#include "unit/test.h"
 
 // unitTest_runTests("Component/MoreAdvancedComponent");
 
@@ -58,50 +57,4 @@ bool MoreAdvancedComponent::testDependentInterface()
       return false;
 
    return mSCInterface->isFortyTwo( 42 );
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-using namespace UnitTesting;
-
-CreateUnitTest(MoreAdvancedComponentTest, "Component/MoreAdvancedComponent")
-{
-   void run()
-   {
-      // Create component instances and compose them.
-      SimComponent *parentComponent = new SimComponent();
-      SimpleComponent *simpleComponent = new SimpleComponent();
-      MoreAdvancedComponent *moreAdvComponent = new MoreAdvancedComponent();
-      // CodeReview note that the interface pointer isn't initialized in a ctor
-      //  on the components, so it's bad memory against which you might
-      //  be checking in testDependentInterface [3/3/2007 justind]
-      parentComponent->addComponent( simpleComponent );
-      parentComponent->addComponent( moreAdvComponent );
-
-      simpleComponent->registerObject();
-      moreAdvComponent->registerObject();
-
-      // Put a break-point here, follow the onAdd call, and observe the order in
-      // which the SimComponent::onAdd function executes. You will see the interfaces
-      // get cached, and the dependent interface query being made.
-      parentComponent->registerObject();
-
-      // If the MoreAdvancedComponent found an interface, than the parentComponent
-      // should have returned true, from onAdd, and should therefore be registered
-      // properly with the Sim
-      test( parentComponent->isProperlyAdded(), "Parent component not properly added!" );
-
-      // Now lets test the interface. You can step through this, as well.
-      test( moreAdvComponent->testDependentInterface(), "Dependent interface test failed." ); 
-
-      // CodeReview is there a reason we can't just delete the parentComponent here? [3/3/2007 justind]
-      //
-      // Clean up
-      parentComponent->removeComponent( simpleComponent );
-      parentComponent->removeComponent( moreAdvComponent );
-
-      parentComponent->deleteObject();
-      moreAdvComponent->deleteObject();
-      simpleComponent->deleteObject();
-   }
-};
+}

+ 1 - 121
Engine/source/component/simpleComponent.cpp

@@ -28,124 +28,4 @@ ConsoleDocClass( SimpleComponent,
 				"@brief The purpose of this component is to provide a minimalistic component that "
 				"exposes a simple, cached interface\n\n"
 				"Soon to be deprecated, internal only.\n\n "
-				"@internal");
-
-//////////////////////////////////////////////////////////////////////////
-// It may seem like some weak sauce to use a unit test for this, however
-// it is very, very easy to set breakpoints in a unit test, and trace 
-// execution in the debugger, so I will use a unit test.
-//
-// Note I am not using much actual 'test' functionality, just providing
-// an easy place to examine the functionality that was described and implemented
-// in the header file.
-//
-// If you want to run this code, simply run Torque, pull down the console, and
-// type:
-//    unitTest_runTests("Components/SimpleComponent");
-
-#include "unit/test.h"
-using namespace UnitTesting;
-
-CreateUnitTest(TestSimpleComponent, "Components/SimpleComponent")
-{
-   void run()
-   {
-      // When instantiating, and working with a SimObject in C++ code, such as
-      // a unit test, you *may not* allocate a SimObject off of the stack. 
-      //
-      // For example:
-      //    SimpleComponent sc; 
-      // is a stack allocation. This memory is allocated off of the program stack
-      // when the function is called. SimObject deletion is done via SimObject::deleteObject()
-      // and the last command of this method is 'delete this;' That command will
-      // cause an assert if it is called on stack-allocated memory. Therefor, when
-      // instantiating SimObjects in C++ code, it is imperitive that you keep in
-      // mind that if any script calls 'delete()' on that SimObject, or any other
-      // C++ code calls 'deleteObject()' on that SimObject, it will crash.
-      SimpleComponent *sc = new SimpleComponent();
-
-      // SimObject::registerObject must be called on a SimObject before it is
-      // fully 'hooked in' to the engine. 
-      //
-      // Tracing execution of this function will let you see onAdd get called on
-      // the component, and you will see it cache the interface we exposed.
-      sc->registerObject();
-
-      // It is *not* required that a component always be owned by a component (obviously)
-      // however I am using an owner so that you can trace execution of recursive
-      // calls to cache interfaces and such.
-      SimComponent *testOwner = new SimComponent();
-
-      // Add the test component to it's owner. This will set the 'mOwner' field
-      // of 'sc' to the address of 'testOwner'
-      testOwner->addComponent( sc );
-
-      // If you step-into this registerObject the same way as the previous one, 
-      // you will be able to see the recursive caching of the exposed interface.
-      testOwner->registerObject();
-
-      // Now to prove that object composition is working properly, lets ask 
-      // both of these components for their interface lists...
-
-      // The ComponentInterfaceList is a typedef for type 'VectorPtr<ComponentInterface *>'
-      // and it will be used by getInterfaces() to store the results of the interface
-      // query. This is the "complete" way to obtain an interface, and it is too
-      // heavy-weight for most cases. A simplified query will be performed next, 
-      // to demonstrate the usage of both.
-      ComponentInterfaceList iLst;
-
-      // This query requests all interfaces, on all components, regardless of name
-      // or owner.
-      sc->getInterfaces( &iLst, 
-         // This is the type field. I am passing NULL here to signify that the query
-         // should match all values of 'type' in the list.
-         NULL,
-
-         // The name field, let's pass NULL again just so when you trace execution
-         // you can see how queries work in the simple case, first.
-         NULL );
-
-      // Lets process the list that we've gotten back, and find the interface that
-      // we want.
-      SimpleComponentInterface *scQueriedInterface = NULL;
-
-      for( ComponentInterfaceListIterator i = iLst.begin(); i != iLst.end(); i++ )
-      {
-         scQueriedInterface = dynamic_cast<SimpleComponentInterface *>( *i );
-
-         if( scQueriedInterface != NULL )
-            break;
-      }
-
-      AssertFatal( scQueriedInterface != NULL, "No valid SimpleComponentInterface was found in query" );
-
-      // Lets do it again, only we will execute the query on the parent instead,
-      // in a simplified way. Remember the parent component doesn't expose any 
-      // interfaces at all, so the success of this behavior is entirely dependent 
-      // on the recursive registration that occurs in registerInterfaces()
-      SimpleComponentInterface *ownerQueriedInterface = testOwner->getInterface<SimpleComponentInterface>();
-
-      AssertFatal( ownerQueriedInterface != NULL, "No valid SimpleComponentInterface was found in query" );
-
-      // We should now have two pointers to the same interface obtained by querying
-      // different components.
-      test( ownerQueriedInterface == scQueriedInterface, "This really shouldn't be possible to fail given the setup of the test" );
-
-      // Lets call the method that was exposed on the component via the interface.
-      // Trace the execution of this function, if you wish.
-      test( ownerQueriedInterface->isFortyTwo( 42 ), "Don't panic, but it's a bad day in the component system." );
-      test( scQueriedInterface->isFortyTwo( 42 ), "Don't panic, but it's a bad day in the component system." );
-
-      // So there you have it. Writing a simple component that exposes a cached
-      // interface, and testing it. It's time to clean up.
-      testOwner->removeComponent( sc );
-
-      sc->deleteObject();
-      testOwner->deleteObject();
-
-      // Interfaces do not need to be freed. In Juggernaught, these will be ref-counted
-      // for more robust behavior. Right now, however, the values of our two interface
-      // pointers, scQueriedInterface and ownerQueriedInterface, reference invalid
-      // memory. 
-   }
-};
+				"@internal");

+ 68 - 0
Engine/source/component/test/moreAdvancedComponentTest.cpp

@@ -0,0 +1,68 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2014 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifdef TORQUE_TESTS_ENABLED
+#include "testing/unitTesting.h"
+#include "component/moreAdvancedComponent.h"
+
+TEST(MoreAdvancedComponent, MoreAdvancedComponent)
+{
+   // Create component instances and compose them.
+   SimComponent *parentComponent = new SimComponent();
+   SimpleComponent *simpleComponent = new SimpleComponent();
+   MoreAdvancedComponent *moreAdvComponent = new MoreAdvancedComponent();
+   // CodeReview note that the interface pointer isn't initialized in a ctor
+   //  on the components, so it's bad memory against which you might
+   //  be checking in testDependentInterface [3/3/2007 justind]
+   parentComponent->addComponent( simpleComponent );
+   parentComponent->addComponent( moreAdvComponent );
+
+   simpleComponent->registerObject();
+   moreAdvComponent->registerObject();
+
+   // Put a break-point here, follow the onAdd call, and observe the order in
+   // which the SimComponent::onAdd function executes. You will see the interfaces
+   // get cached, and the dependent interface query being made.
+   parentComponent->registerObject();
+
+   // If the MoreAdvancedComponent found an interface, than the parentComponent
+   // should have returned true, from onAdd, and should therefore be registered
+   // properly with the Sim
+   EXPECT_TRUE( parentComponent->isProperlyAdded() )
+      << "Parent component not properly added!";
+
+   // Now lets test the interface. You can step through this, as well.
+   EXPECT_TRUE( moreAdvComponent->testDependentInterface() )
+      << "Dependent interface test failed.";
+
+   // CodeReview is there a reason we can't just delete the parentComponent here? [3/3/2007 justind]
+   //
+   // Clean up
+   parentComponent->removeComponent( simpleComponent );
+   parentComponent->removeComponent( moreAdvComponent );
+
+   parentComponent->deleteObject();
+   moreAdvComponent->deleteObject();
+   simpleComponent->deleteObject();
+};
+
+#endif

+ 50 - 51
Engine/source/unit/tests/testComponents.cpp → Engine/source/component/test/simComponentTest.cpp

@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
+// Copyright (c) 2014 GarageGames, LLC
 //
 // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to
@@ -20,14 +20,10 @@
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 
-#include "unit/test.h"
-#include "unit/memoryTester.h"
+#ifdef TORQUE_TESTS_ENABLED
+#include "testing/unitTesting.h"
 #include "component/simComponent.h"
 
-using namespace UnitTesting;
-
-//////////////////////////////////////////////////////////////////////////
-
 class CachedInterfaceExampleComponent : public SimComponent
 {
    typedef SimComponent Parent;
@@ -89,18 +85,16 @@ public:
 
    // CodeReview [patw, 2, 17, 2007] I'm going to make another lightweight interface
    // for this functionality later
-   void unit_test( UnitTest *test )
+   void unit_test()
    {
-      AssertFatal(test, "CachedInterfaceExampleComponent::unit_test - NULL UnitTest");
-
-      if( !test )
-         return;
-
-      test->test( mpU32 != NULL, "Pointer to dependent interface is NULL" );
+      EXPECT_TRUE( mpU32 != NULL )
+         << "Pointer to dependent interface is NULL";
       if( mpU32 )
       {
-         test->test( *(*mpU32) & ( 1 << 24 ), "Pointer to interface data is bogus." );
-         test->test( *(*mpU32) != *mMyId, "Two of me have the same ID, bad!" );
+         EXPECT_TRUE( *(*mpU32) & ( 1 << 24 ))
+            << "Pointer to interface data is bogus.";
+         EXPECT_TRUE( *(*mpU32) != *mMyId)
+            << "Two of me have the same ID, bad!";
       }
    }
 };
@@ -113,42 +107,47 @@ ConsoleDocClass( CachedInterfaceExampleComponent,
 				"Not intended for game development, for editors or internal use only.\n\n "
 				"@internal");
 
-//////////////////////////////////////////////////////////////////////////
-
-CreateUnitTest(TestComponentInterfacing, "Components/Composition")
+TEST(SimComponent, Composition)
 {
-   void run()
+   SimComponent *testComponent = new SimComponent();
+   CachedInterfaceExampleComponent *componentA = new CachedInterfaceExampleComponent();
+   CachedInterfaceExampleComponent *componentB = new CachedInterfaceExampleComponent();
+
+   // Register sub-components
+   EXPECT_TRUE( componentA->registerObject())
+      << "Failed to register componentA";
+   EXPECT_TRUE( componentB->registerObject())
+      << "Failed to register componentB";
+
+   // Add the components
+   EXPECT_TRUE( testComponent->addComponent( componentA ))
+      << "Failed to add component a to testComponent";
+   EXPECT_TRUE( testComponent->addComponent( componentB ))
+      << "Failed to add component b to testComponent";
+
+   EXPECT_EQ( componentA->getOwner(), testComponent)
+      << "testComponent did not properly set the mOwner field of componentA to NULL.";
+   EXPECT_EQ( componentB->getOwner(), testComponent)
+      << "testComponent did not properly set the mOwner field of componentB to NULL.";
+
+   // Register the object with the simulation, kicking off the interface registration
+   const bool registered = testComponent->registerObject();
+   EXPECT_TRUE( registered )
+      << "Failed to register testComponent";
+
+   // Interface tests
+   if( registered )
    {
-      MemoryTester m;
-      m.mark();
-
-      SimComponent *testComponent = new SimComponent();
-      CachedInterfaceExampleComponent *componentA = new CachedInterfaceExampleComponent();
-      CachedInterfaceExampleComponent *componentB = new CachedInterfaceExampleComponent();
-
-      // Register sub-components
-      test( componentA->registerObject(), "Failed to register componentA" );
-      test( componentB->registerObject(), "Failed to register componentB" );
-
-      // Add the components
-      test( testComponent->addComponent( componentA ), "Failed to add component a to testComponent" );
-      test( testComponent->addComponent( componentB ), "Failed to add component b to testComponent" );
-
-      test( componentA->getOwner() == testComponent, "testComponent did not properly set the mOwner field of componentA to NULL." );
-      test( componentB->getOwner() == testComponent, "testComponent did not properly set the mOwner field of componentB to NULL." );
-
-      // Register the object with the simulation, kicking off the interface registration
-      const bool registered = testComponent->registerObject();
-      test( registered, "Failed to register testComponent" );
-
-      // Interface tests
-      if( registered )
       {
-         componentA->unit_test( this );
-         componentB->unit_test( this );
-         testComponent->deleteObject();
-      } 
-
-      test( m.check(), "Component composition test leaked memory." );
+         SCOPED_TRACE("componentA");
+         componentA->unit_test();
+      }
+      {
+         SCOPED_TRACE("componentB");
+         componentB->unit_test();
+      }
+      testComponent->deleteObject();
    }
-};
+};
+
+#endif

+ 131 - 0
Engine/source/component/test/simpleComponentTest.cpp

@@ -0,0 +1,131 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2014 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifdef TORQUE_TESTS_ENABLED
+#include "testing/unitTesting.h"
+#include "component/simpleComponent.h"
+
+TEST(SimpleComponent, SimpleComponent)
+{
+   // When instantiating, and working with a SimObject in C++ code, such as
+   // a unit test, you *may not* allocate a SimObject off of the stack. 
+   //
+   // For example:
+   //    SimpleComponent sc; 
+   // is a stack allocation. This memory is allocated off of the program stack
+   // when the function is called. SimObject deletion is done via SimObject::deleteObject()
+   // and the last command of this method is 'delete this;' That command will
+   // cause an assert if it is called on stack-allocated memory. Therefor, when
+   // instantiating SimObjects in C++ code, it is imperitive that you keep in
+   // mind that if any script calls 'delete()' on that SimObject, or any other
+   // C++ code calls 'deleteObject()' on that SimObject, it will crash.
+   SimpleComponent *sc = new SimpleComponent();
+
+   // SimObject::registerObject must be called on a SimObject before it is
+   // fully 'hooked in' to the engine. 
+   //
+   // Tracing execution of this function will let you see onAdd get called on
+   // the component, and you will see it cache the interface we exposed.
+   sc->registerObject();
+
+   // It is *not* required that a component always be owned by a component (obviously)
+   // however I am using an owner so that you can trace execution of recursive
+   // calls to cache interfaces and such.
+   SimComponent *testOwner = new SimComponent();
+
+   // Add the test component to it's owner. This will set the 'mOwner' field
+   // of 'sc' to the address of 'testOwner'
+   testOwner->addComponent( sc );
+
+   // If you step-into this registerObject the same way as the previous one, 
+   // you will be able to see the recursive caching of the exposed interface.
+   testOwner->registerObject();
+
+   // Now to prove that object composition is working properly, lets ask 
+   // both of these components for their interface lists...
+
+   // The ComponentInterfaceList is a typedef for type 'VectorPtr<ComponentInterface *>'
+   // and it will be used by getInterfaces() to store the results of the interface
+   // query. This is the "complete" way to obtain an interface, and it is too
+   // heavy-weight for most cases. A simplified query will be performed next, 
+   // to demonstrate the usage of both.
+   ComponentInterfaceList iLst;
+
+   // This query requests all interfaces, on all components, regardless of name
+   // or owner.
+   sc->getInterfaces( &iLst, 
+      // This is the type field. I am passing NULL here to signify that the query
+      // should match all values of 'type' in the list.
+      NULL,
+
+      // The name field, let's pass NULL again just so when you trace execution
+      // you can see how queries work in the simple case, first.
+      NULL );
+
+   // Lets process the list that we've gotten back, and find the interface that
+   // we want.
+   SimpleComponentInterface *scQueriedInterface = NULL;
+
+   for( ComponentInterfaceListIterator i = iLst.begin(); i != iLst.end(); i++ )
+   {
+      scQueriedInterface = dynamic_cast<SimpleComponentInterface *>( *i );
+
+      if( scQueriedInterface != NULL )
+         break;
+   }
+
+   AssertFatal( scQueriedInterface != NULL, "No valid SimpleComponentInterface was found in query" );
+
+   // Lets do it again, only we will execute the query on the parent instead,
+   // in a simplified way. Remember the parent component doesn't expose any 
+   // interfaces at all, so the success of this behavior is entirely dependent 
+   // on the recursive registration that occurs in registerInterfaces()
+   SimpleComponentInterface *ownerQueriedInterface = testOwner->getInterface<SimpleComponentInterface>();
+
+   AssertFatal( ownerQueriedInterface != NULL, "No valid SimpleComponentInterface was found in query" );
+
+   // We should now have two pointers to the same interface obtained by querying
+   // different components.
+   EXPECT_EQ( ownerQueriedInterface, scQueriedInterface )
+      << "This really shouldn't be possible to fail given the setup of the test";
+
+   // Lets call the method that was exposed on the component via the interface.
+   // Trace the execution of this function, if you wish.
+   EXPECT_TRUE( ownerQueriedInterface->isFortyTwo( 42 ) )
+      << "Don't panic, but it's a bad day in the component system.";
+   EXPECT_TRUE( scQueriedInterface->isFortyTwo( 42 ) )
+      << "Don't panic, but it's a bad day in the component system.";
+
+   // So there you have it. Writing a simple component that exposes a cached
+   // interface, and testing it. It's time to clean up.
+   testOwner->removeComponent( sc );
+
+   sc->deleteObject();
+   testOwner->deleteObject();
+
+   // Interfaces do not need to be freed. In Juggernaught, these will be ref-counted
+   // for more robust behavior. Right now, however, the values of our two interface
+   // pointers, scQueriedInterface and ownerQueriedInterface, reference invalid
+   // memory. 
+};
+
+#endif