diff --git a/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id b/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id index f4c592ceca..e0dd23cece 100644 --- a/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/build/cocos2d_libs.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -feee3c038221d15aa270c3c33e2187ed35630b45 \ No newline at end of file +1f2c191d1027ab72afff7e81d1fb31fce82ce4b1 \ No newline at end of file diff --git a/build/cocos2d_tests.xcodeproj/project.pbxproj.REMOVED.git-id b/build/cocos2d_tests.xcodeproj/project.pbxproj.REMOVED.git-id index 4fb484e365..9417e3a13c 100644 --- a/build/cocos2d_tests.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/build/cocos2d_tests.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -20d3130f1f163df349f4503d05a21797039f1b40 \ No newline at end of file +e569f7828939a72dd90b17fea3e60f6b9fe3da16 \ No newline at end of file diff --git a/cocos/base/CCRefPtr.h b/cocos/base/CCRefPtr.h new file mode 100644 index 0000000000..2a082fb173 --- /dev/null +++ b/cocos/base/CCRefPtr.h @@ -0,0 +1,309 @@ +/**************************************************************************** + Copyright (c) 2014 PlayFirst Inc. + Copyright (c) 2014 Chukong Technologies Inc. + + http://www.cocos2d-x.org + + 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. + ****************************************************************************/ + +#ifndef __CC_REF_PTR_H__ +#define __CC_REF_PTR_H__ + +#include "CCRef.h" +#include + +NS_CC_BEGIN + +/** + * Utility/support macros. Defined to enable RefPtr to contain types like 'const T' because we do not + * regard retain()/release() as affecting mutability of state. + */ +#define CC_REF_PTR_SAFE_RETAIN(ptr)\ + \ + do\ + {\ + if (ptr)\ + {\ + const_cast(static_cast(ptr))->retain();\ + }\ + \ + } while (0); + +#define CC_REF_PTR_SAFE_RELEASE(ptr)\ + \ + do\ + {\ + if (ptr)\ + {\ + const_cast(static_cast(ptr))->release();\ + }\ + \ + } while (0); + +#define CC_REF_PTR_SAFE_RELEASE_NULL(ptr)\ + \ + do\ + {\ + if (ptr)\ + {\ + const_cast(static_cast(ptr))->release();\ + ptr = nullptr;\ + }\ + \ + } while (0); + +/** + * Wrapper class which maintains a strong reference to a cocos2dx cocos2d::Ref* type object. + * Similar in concept to a boost smart pointer. + * + * Enables the use of the RAII idiom with Cocos2dx objects and helps automate some of the more + * mundane tasks of pointer initialization and cleanup. + * + * The class itself is modelled on C++ 11 std::shared_ptr, and trys to keep some of the methods + * and functionality consistent with std::shared_ptr. + */ +template class RefPtr +{ +public: + + inline RefPtr() + : + _ptr(nullptr) + { + + } + + inline RefPtr(RefPtr && other) + { + _ptr = other._ptr; + other._ptr = nullptr; + } + + inline RefPtr(T * ptr) + : + _ptr(const_cast::type*>(ptr)) // Const cast allows RefPtr to reference objects marked const too. + { + CC_REF_PTR_SAFE_RETAIN(_ptr); + } + + inline RefPtr(std::nullptr_t ptr) + : + _ptr(nullptr) + { + + } + + inline RefPtr(const RefPtr & other) + : + _ptr(other._ptr) + { + CC_REF_PTR_SAFE_RETAIN(_ptr); + } + + inline ~RefPtr() + { + CC_REF_PTR_SAFE_RELEASE_NULL(_ptr); + } + + inline RefPtr & operator = (const RefPtr & other) + { + if (other._ptr != _ptr) + { + CC_REF_PTR_SAFE_RETAIN(other._ptr); + CC_REF_PTR_SAFE_RELEASE(_ptr); + _ptr = other._ptr; + } + + return *this; + } + + inline RefPtr & operator = (RefPtr && other) + { + if (&other != this) + { + CC_REF_PTR_SAFE_RELEASE(_ptr); + _ptr = other._ptr; + other._ptr = nullptr; + } + + return *this; + } + + inline RefPtr & operator = (T * other) + { + if (other != _ptr) + { + CC_REF_PTR_SAFE_RETAIN(other); + CC_REF_PTR_SAFE_RELEASE(_ptr); + _ptr = const_cast::type*>(other); // Const cast allows RefPtr to reference objects marked const too. + } + + return *this; + } + + inline RefPtr & operator = (std::nullptr_t other) + { + CC_REF_PTR_SAFE_RELEASE_NULL(_ptr); + return *this; + } + + // Note: using reinterpret_cast<> instead of static_cast<> here because it doesn't require type info. + // Since we verify the correct type cast at compile time on construction/assign we don't need to know the type info + // here. Not needing the type info here enables us to use these operations in inline functions in header files when + // the type pointed to by this class is only forward referenced. + + inline operator T * () const { return reinterpret_cast(_ptr); } + + inline T & operator * () const + { + CCASSERT(_ptr, "Attempt to dereference a null pointer!"); + return reinterpret_cast(*_ptr); + } + + inline T * operator->() const + { + CCASSERT(_ptr, "Attempt to dereference a null pointer!"); + return reinterpret_cast(_ptr); + } + + inline T * get() const { return reinterpret_cast(_ptr); } + + + inline bool operator == (const RefPtr & other) const { return _ptr == other._ptr; } + + inline bool operator == (const T * other) const { return _ptr == other; } + + inline bool operator == (typename std::remove_const::type * other) const { return _ptr == other; } + + inline bool operator == (const std::nullptr_t other) const { return _ptr == other; } + + + inline bool operator != (const RefPtr & other) const { return _ptr != other._ptr; } + + inline bool operator != (const T * other) const { return _ptr != other; } + + inline bool operator != (typename std::remove_const::type * other) const { return _ptr != other; } + + inline bool operator != (const std::nullptr_t other) const { return _ptr != other; } + + + inline bool operator > (const RefPtr & other) const { return _ptr > other._ptr; } + + inline bool operator > (const T * other) const { return _ptr > other; } + + inline bool operator > (typename std::remove_const::type * other) const { return _ptr > other; } + + inline bool operator > (const std::nullptr_t other) const { return _ptr > other; } + + + inline bool operator < (const RefPtr & other) const { return _ptr < other._ptr; } + + inline bool operator < (const T * other) const { return _ptr < other; } + + inline bool operator < (typename std::remove_const::type * other) const { return _ptr < other; } + + inline bool operator < (const std::nullptr_t other) const { return _ptr < other; } + + + inline bool operator >= (const RefPtr & other) const { return _ptr >= other._ptr; } + + inline bool operator >= (const T * other) const { return _ptr >= other; } + + inline bool operator >= (typename std::remove_const::type * other) const { return _ptr >= other; } + + inline bool operator >= (const std::nullptr_t other) const { return _ptr >= other; } + + + inline bool operator <= (const RefPtr & other) const { return _ptr <= other._ptr; } + + inline bool operator <= (const T * other) const { return _ptr <= other; } + + inline bool operator <= (typename std::remove_const::type * other) const { return _ptr <= other; } + + inline bool operator <= (const std::nullptr_t other) const { return _ptr <= other; } + + + inline operator bool() const { return _ptr != nullptr; } + + inline void reset() + { + CC_REF_PTR_SAFE_RELEASE_NULL(_ptr); + } + + inline void swap(RefPtr & other) + { + if (&other != this) + { + Ref * tmp = _ptr; + _ptr = other._ptr; + other._ptr = tmp; + } + } + + /** + * This function assigns to this RefPtr but does not increase the reference count of the object pointed to. + * Useful for assigning an object created through the 'new' operator to a RefPtr. Basically used in scenarios + * where the RefPtr has the initial ownership of the object. + * + * E.G: + * RefPtr image; + * image.weakAssign(new cocos2d::Image()); + * + * Instead of: + * RefPtr image; + * image = new cocos2d::Image(); + * image->release(); // Required because new'd object already has a reference count of '1'. + */ + inline void weakAssign(const RefPtr & other) + { + CC_REF_PTR_SAFE_RELEASE(_ptr); + _ptr = other._ptr; + } + +private: + Ref * _ptr; +}; + +/** + * Cast between RefPtr types statically. + */ +template RefPtr static_pointer_cast(const RefPtr & r) +{ + return RefPtr(static_cast(r.get())); +} + +/** + * Cast between RefPtr types dynamically. + */ +template RefPtr dynamic_pointer_cast(const RefPtr & r) +{ + return RefPtr(dynamic_cast(r.get())); +} + +/** + * Done with these macros. + */ +#undef CC_REF_PTR_SAFE_RETAIN +#undef CC_REF_PTR_SAFE_RELEASE +#undef CC_REF_PTR_SAFE_RELEASE_NULL + +NS_CC_END + +#endif // __CC_REF_PTR_H__ diff --git a/tests/cpp-tests/Android.mk b/tests/cpp-tests/Android.mk index c2d2c02978..7fd692f58f 100644 --- a/tests/cpp-tests/Android.mk +++ b/tests/cpp-tests/Android.mk @@ -171,6 +171,7 @@ Classes/TouchesTest/Ball.cpp \ Classes/TouchesTest/Paddle.cpp \ Classes/TouchesTest/TouchesTest.cpp \ Classes/TransitionsTest/TransitionsTest.cpp \ +Classes/UnitTest/RefPtrTest.cpp \ Classes/UnitTest/UnitTest.cpp \ Classes/UserDefaultTest/UserDefaultTest.cpp \ Classes/ZwoptexTest/ZwoptexTest.cpp diff --git a/tests/cpp-tests/CMakeLists.txt b/tests/cpp-tests/CMakeLists.txt index 7a36508532..22995708d1 100644 --- a/tests/cpp-tests/CMakeLists.txt +++ b/tests/cpp-tests/CMakeLists.txt @@ -172,6 +172,7 @@ set(SAMPLE_SRC Classes/DataVisitorTest/DataVisitorTest.cpp Classes/ConfigurationTest/ConfigurationTest.cpp Classes/ConsoleTest/ConsoleTest.cpp + Classes/UnitTest/RefPtrTest.cpp Classes/UnitTest/UnitTest.cpp Classes/controller.cpp Classes/testBasic.cpp diff --git a/tests/cpp-tests/Classes/UnitTest/RefPtrTest.cpp b/tests/cpp-tests/Classes/UnitTest/RefPtrTest.cpp new file mode 100644 index 0000000000..18df8c1535 --- /dev/null +++ b/tests/cpp-tests/Classes/UnitTest/RefPtrTest.cpp @@ -0,0 +1,322 @@ +#include "RefPtrTest.h" +#include "CCRefPtr.h" + +void RefPtrTest::onEnter() +{ + UnitTestDemo::onEnter(); + + // TEST(constructors) + { + // Default constructor + RefPtr ref1; + CC_ASSERT(nullptr == ref1.get()); + + // Parameter constructor + RefPtr<__String> ref2(cocos2d::String::create("Hello")); + CC_ASSERT(strcmp("Hello", ref2->getCString()) == 0); + CC_ASSERT(2 == ref2->getReferenceCount()); + + // Parameter constructor with nullptr + RefPtr<__String> ref3(nullptr); + CC_ASSERT((__String*) nullptr == ref3.get()); + + // Copy constructor + RefPtr<__String> ref4(ref2); + CC_ASSERT(strcmp("Hello", ref4->getCString()) == 0); + CC_ASSERT(3 == ref2->getReferenceCount()); + CC_ASSERT(3 == ref4->getReferenceCount()); + + // Copy constructor with nullptr reference + RefPtr ref5(ref1); + CC_ASSERT((Ref*) nullptr == ref5.get()); + } + + // TEST(destructor) + { + __String * hello = __String::create("Hello"); + CC_ASSERT(1 == hello->getReferenceCount()); + + { + RefPtr ref(hello); + CC_ASSERT(2 == hello->getReferenceCount()); + } + + CC_ASSERT(1 == hello->getReferenceCount()); + } + + // TEST(assignmentOperator) + { + // Test basic assignment with pointer + RefPtr<__String> ref1; + CC_ASSERT((Ref*) nullptr == ref1.get()); + + ref1 = __String::create("World"); + CC_ASSERT(strcmp("World", ref1->getCString()) == 0); + CC_ASSERT(2 == ref1->getReferenceCount()); + + // Assigment back to nullptr + __String * world = ref1; + CC_ASSERT(2 == world->getReferenceCount()); + + ref1 = nullptr; + CC_ASSERT(1 == world->getReferenceCount()); + + // Assignment swapping + ref1 = __String::create("Hello"); + CC_ASSERT(strcmp("Hello", ref1->getCString()) == 0); + CC_ASSERT(2 == ref1->getReferenceCount()); + + __String * hello = (__String*) ref1; + CC_ASSERT(2 == hello->getReferenceCount()); + + ref1 = world; + CC_ASSERT(1 == hello->getReferenceCount()); + CC_ASSERT(2 == world->getReferenceCount()); + + // Test assignment with another reference + RefPtr<__String> ref2 = __String::create("blah"); + __String * blah = ref2; + CC_ASSERT(2 == blah->getReferenceCount()); + + ref2 = ref1; + CC_ASSERT(1 == blah->getReferenceCount()); + CC_ASSERT(3 == world->getReferenceCount()); + } + + // TEST(castBackToPointerOperator) + { + RefPtr<__String> ref1 = __String::create("Hello"); + __String * helloPtr = ref1; + Ref * objectPtr = ref1; + + CC_ASSERT(helloPtr == objectPtr); + } + + // TEST(dereferenceOperators) + { + RefPtr<__String> ref1 = __String::create("Hello"); + CC_ASSERT(strcmp("Hello", ref1->getCString()) == 0); + CC_ASSERT(strcmp("Hello", (*ref1).getCString()) == 0); + } + + // TEST(convertToBooleanOperator) + { + RefPtr<__String> ref1 = __String::create("Hello"); + CC_ASSERT(true == (bool) ref1); + + ref1 = nullptr; + CC_ASSERT(false == (bool) ref1); + } + + // TEST(get) + { + RefPtr<__String> ref1 = __String::create("Hello"); + CC_ASSERT(strcmp("Hello", ref1.get()->getCString()) == 0); + + ref1.reset(); + CC_ASSERT((__String*) nullptr == ref1.get()); + } + + // TEST(reset) + { + RefPtr<__String> ref1; + CC_ASSERT((__String*) nullptr == ref1.get()); + + ref1.reset(); + CC_ASSERT((__String*) nullptr == ref1.get()); + + ref1 = __String::create("Hello"); + CC_ASSERT(strcmp("Hello", ref1.get()->getCString()) == 0); + + __String * hello = ref1.get(); + CC_ASSERT(2 == hello->getReferenceCount()); + + ref1.reset(); + CC_ASSERT((__String*) nullptr == ref1.get()); + CC_ASSERT(1 == hello->getReferenceCount()); + } + + // TEST(swap) + { + RefPtr<__String> ref1; + RefPtr<__String> ref2; + + CC_ASSERT((__String*) nullptr == ref1.get()); + CC_ASSERT((__String*) nullptr == ref2.get()); + + ref1.swap(ref2); + + CC_ASSERT((__String*) nullptr == ref1.get()); + CC_ASSERT((__String*) nullptr == ref2.get()); + + __String * hello = __String::create("Hello"); + CC_ASSERT(1 == hello->getReferenceCount()); + + ref1 = hello; + CC_ASSERT(2 == hello->getReferenceCount()); + + ref1.swap(ref2); + CC_ASSERT(2 == hello->getReferenceCount()); + CC_ASSERT((__String*) nullptr == ref1.get()); + CC_ASSERT(strcmp("Hello", ref2->getCString()) == 0); + + ref1.swap(ref2); + CC_ASSERT(2 == hello->getReferenceCount()); + CC_ASSERT(strcmp("Hello", ref1->getCString()) == 0); + CC_ASSERT((__String*) nullptr == ref2.get()); + + __String * world = __String::create("World"); + CC_ASSERT(1 == world->getReferenceCount()); + + ref2 = world; + CC_ASSERT(2 == world->getReferenceCount()); + + ref2.swap(ref1); + CC_ASSERT(strcmp("World", ref1->getCString()) == 0); + CC_ASSERT(strcmp("Hello", ref2->getCString()) == 0); + + CC_ASSERT(2 == hello->getReferenceCount()); + CC_ASSERT(2 == world->getReferenceCount()); + + ref1.swap(ref2); + + CC_ASSERT(strcmp("Hello", ref1->getCString()) == 0); + CC_ASSERT(strcmp("World", ref2->getCString()) == 0); + + CC_ASSERT(2 == hello->getReferenceCount()); + CC_ASSERT(2 == world->getReferenceCount()); + } + + // TEST(staticPointerCast) + { + RefPtr<__String> ref1 = __String::create("Hello"); + CC_ASSERT(2 == ref1->getReferenceCount()); + + RefPtr ref2 = static_pointer_cast(ref1); + CC_ASSERT(strcmp("Hello", ((__String*) ref2.get())->getCString()) == 0); + CC_ASSERT(3 == ref1->getReferenceCount()); + } + + // TEST(dynamicPointerCast) + { + RefPtr<__String> ref1 = cocos2d::String::create("Hello"); + CC_ASSERT(2 == ref1->getReferenceCount()); + + RefPtr ref2 = dynamic_pointer_cast(ref1); + CC_ASSERT(strcmp("Hello", ((__String*) ref2.get())->getCString()) == 0); + CC_ASSERT(3 == ref1->getReferenceCount()); + + RefPtr<__String> ref3 = dynamic_pointer_cast<__String>(ref2); + CC_ASSERT(strcmp("Hello", ref3->getCString()) == 0); + CC_ASSERT(4 == ref1->getReferenceCount()); + + RefPtr ref4 = dynamic_pointer_cast(ref2); + CC_ASSERT((Ref*) nullptr == ref4.get()); + } + + // TEST(weakAssign) + { + RefPtr<__String> ref1; + + __String * string1 = new __String("Hello"); + ref1.weakAssign(string1); + CC_ASSERT(1 == string1->getReferenceCount()); + + RefPtr<__String> ref2 = ref1; + CC_ASSERT(2 == string1->getReferenceCount()); + + __String * string2 = new __String("World"); + ref1.weakAssign(string2); + + CC_ASSERT(1 == string1->getReferenceCount()); + CC_ASSERT(1 == ref2->getReferenceCount()); + + __String * string3 = new __String("Blah"); + RefPtr<__String> ref3; + ref3.weakAssign(string3); + CC_ASSERT(1 == string3->getReferenceCount()); + + string3->retain(); + CC_ASSERT(2 == string3->getReferenceCount()); + + ref3.weakAssign(nullptr); + CC_ASSERT(1 == string3->getReferenceCount()); + CC_SAFE_RELEASE_NULL(string3); + } + + // TEST(comparisonOperators) + { + RefPtr ref1; + RefPtr ref2; + + CC_ASSERT(true == (ref1 == ref2)); + CC_ASSERT(false == (ref1 != ref2)); + CC_ASSERT(false == (ref1 < ref2)); + CC_ASSERT(false == (ref1 > ref2)); + CC_ASSERT(true == (ref1 <= ref2)); + CC_ASSERT(true == (ref1 >= ref2)); + + CC_ASSERT(true == (ref1 == nullptr)); + CC_ASSERT(false == (ref1 != nullptr)); + CC_ASSERT(false == (ref1 < nullptr)); + CC_ASSERT(false == (ref1 > nullptr)); + CC_ASSERT(true == (ref1 <= nullptr)); + CC_ASSERT(true == (ref1 >= nullptr)); + + CC_ASSERT(false == (ref1 == __String::create("Hello"))); + CC_ASSERT(true == (ref1 != __String::create("Hello"))); + CC_ASSERT(true == (ref1 < __String::create("Hello"))); + CC_ASSERT(false == (ref1 > __String::create("Hello"))); + CC_ASSERT(true == (ref1 <= __String::create("Hello"))); + CC_ASSERT(false == (ref1 >= __String::create("Hello"))); + + ref1 = __String::create("Hello"); + + CC_ASSERT(false == (ref1 == ref2)); + CC_ASSERT(true == (ref1 != ref2)); + CC_ASSERT(false == (ref1 < ref2)); + CC_ASSERT(true == (ref1 > ref2)); + CC_ASSERT(false == (ref1 <= ref2)); + CC_ASSERT(true == (ref1 >= ref2)); + } + + // TEST(moveConstructor) + { + auto someFunc = []() -> RefPtr<__String> + { + return __String::create("Hello world!"); + }; + + // Note: std::move will turn the rvalue into an rvalue reference and thus cause the move constructor to be invoked. + // Have to use this because the compiler will try and optimize how we handle the return value otherwise and skip the move constructor. + RefPtr<__String> theString(std::move(someFunc())); + CC_ASSERT(theString->getReferenceCount() == 2); + CC_ASSERT(theString->compare("Hello world!") == 0); + + __String * theStringPtr = theString; + theString.reset(); + CC_ASSERT(theStringPtr->getReferenceCount() == 1); + CC_ASSERT(theStringPtr->compare("Hello world!") == 0); + } + + // TEST(moveAssignmentOperator) + { + auto someFunc = []() -> RefPtr<__String> + { + return __String::create("Hello world!"); + }; + + RefPtr<__String> theString(someFunc()); + CC_ASSERT(theString->getReferenceCount() == 2); + CC_ASSERT(theString->compare("Hello world!") == 0); + + theString = someFunc(); // No need to use std::move here, compiler should figure out that move semantics are appropriate for this statement. + CC_ASSERT(theString->getReferenceCount() == 2); + CC_ASSERT(theString->compare("Hello world!") == 0); + } +} + +std::string RefPtrTest::subtitle() const +{ + return "RefPtrTest, should not crash!"; +} diff --git a/tests/cpp-tests/Classes/UnitTest/RefPtrTest.h b/tests/cpp-tests/Classes/UnitTest/RefPtrTest.h new file mode 100644 index 0000000000..e8004436ba --- /dev/null +++ b/tests/cpp-tests/Classes/UnitTest/RefPtrTest.h @@ -0,0 +1,17 @@ +#ifndef __REF_PTR_TEST_H__ +#define __REF_PTR_TEST_H__ + +#include "UnitTest.h" + +class RefPtrTest : public UnitTestDemo +{ +public: + + CREATE_FUNC(RefPtrTest); + + virtual void onEnter() override; + + virtual std::string subtitle() const override; +}; + +#endif /* __REF_PTR_TEST_H__ */ diff --git a/tests/cpp-tests/Classes/UnitTest/UnitTest.cpp b/tests/cpp-tests/Classes/UnitTest/UnitTest.cpp index 57392bc388..ae7677c1b5 100644 --- a/tests/cpp-tests/Classes/UnitTest/UnitTest.cpp +++ b/tests/cpp-tests/Classes/UnitTest/UnitTest.cpp @@ -1,11 +1,13 @@ #include "UnitTest.h" +#include "RefPtrTest.h" // For ' < o > ' multiply test scene. static std::function createFunctions[] = { CL(TemplateVectorTest), CL(TemplateMapTest), - CL(ValueTest) + CL(ValueTest), + CL(RefPtrTest) }; static int sceneIdx = -1; diff --git a/tests/cpp-tests/proj.win32/cpp-tests.vcxproj b/tests/cpp-tests/proj.win32/cpp-tests.vcxproj index b37c6a7ce9..17f791c1ef 100644 --- a/tests/cpp-tests/proj.win32/cpp-tests.vcxproj +++ b/tests/cpp-tests/proj.win32/cpp-tests.vcxproj @@ -224,6 +224,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\external\websockets\prebuilt\win32\*.*" "$(Ou + @@ -402,6 +403,7 @@ xcopy /Y /Q "$(ProjectDir)..\..\..\external\websockets\prebuilt\win32\*.*" "$(Ou + diff --git a/tests/cpp-tests/proj.win32/cpp-tests.vcxproj.filters b/tests/cpp-tests/proj.win32/cpp-tests.vcxproj.filters index a6317dd4a6..0cf88b687e 100644 --- a/tests/cpp-tests/proj.win32/cpp-tests.vcxproj.filters +++ b/tests/cpp-tests/proj.win32/cpp-tests.vcxproj.filters @@ -831,6 +831,9 @@ Classes\ShaderTest + + Classes\UnitTest + @@ -1535,5 +1538,8 @@ Classes\ShaderTest + + Classes\UnitTest + \ No newline at end of file