From 0c42ceb6b4c7e17f7fd9990fedeebeb13fb29f2c Mon Sep 17 00:00:00 2001 From: ExMix Date: Thu, 16 Jan 2014 12:39:34 +0300 Subject: [PATCH] [drape] pointers-tests --- drape/drape_tests/drape_tests.pro | 3 +- drape/drape_tests/pointers_tests.cpp | 361 +++++++++++++++++++++++++++ drape/pointers.hpp | 2 + 3 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 drape/drape_tests/pointers_tests.cpp diff --git a/drape/drape_tests/drape_tests.pro b/drape/drape_tests/drape_tests.pro index e7a4657c95..7b26683297 100644 --- a/drape/drape_tests/drape_tests.pro +++ b/drape/drape_tests/drape_tests.pro @@ -35,7 +35,8 @@ SOURCES += \ uniform_value_tests.cpp \ attribute_provides_tests.cpp \ compile_shaders_test.cpp \ - batcher_tests.cpp + batcher_tests.cpp \ + pointers_tests.cpp HEADERS += \ glmock_functions.hpp \ diff --git a/drape/drape_tests/pointers_tests.cpp b/drape/drape_tests/pointers_tests.cpp new file mode 100644 index 0000000000..4ad45d3d92 --- /dev/null +++ b/drape/drape_tests/pointers_tests.cpp @@ -0,0 +1,361 @@ +#include "../../testing/testing.hpp" + +#include "../../base/assert.hpp" +#include "../../drape/pointers.hpp" + +#include "../../std/string.hpp" +#include "../../std/shared_ptr.hpp" + +#include + +using ::testing::_; +using ::testing::MatcherInterface; +using ::testing::MatchResultListener; +using ::testing::Matcher; + +using my::SrcPoint; + +namespace +{ + template + void EmptyFunction(RefPointer p){} + + template + void EmptyFunction(TransferPointer p, ToDo & toDo) + { + toDo(p); + } + + template + void PointerDeleter(TransferPointer p) + { + p.Destroy(); + } + +#ifdef DEBUG + class MockAssertExpector + { + public: + MOCK_CONST_METHOD2(Assert, void(SrcPoint const &, string const &)); + }; + + MockAssertExpector * g_asserter; + my::AssertFailedFn m_defaultAssertFn; + void MyOnAssertFailed(SrcPoint const & src, string const & msg) + { + g_asserter->Assert(src, msg); + } + + MockAssertExpector * InitAsserter() + { + if (g_asserter != NULL) + { + delete g_asserter; + g_asserter = NULL; + } + + g_asserter = new MockAssertExpector(); + + m_defaultAssertFn = my::SetAssertFunction(MyOnAssertFailed); + + return g_asserter; + } + + void DestroyAsserter() + { + my::SetAssertFunction(m_defaultAssertFn); + delete g_asserter; + g_asserter = NULL; + } + + SrcPoint ConstructSrcPoint(const char * fileName, const char * function, int line) + { +#ifndef __OBJC__ + return SrcPoint(fileName, line, function, "()"); +#else + return SrcPoint(fileName, line, function); +#endif + } +#endif +} + +#ifdef DEBUG + +class SrcPointMatcher : public MatcherInterface +{ +public: + SrcPointMatcher(const char * fileName, const char * function, int line) + : m_srcPoint(ConstructSrcPoint(fileName, function, line)) + { + } + + virtual bool MatchAndExplain(const SrcPoint & x, MatchResultListener * listener) const + { + bool res = strcmp(x.FileName(), m_srcPoint.FileName()) == 0 && + strcmp(x.Function(), m_srcPoint.Function()) == 0 && + x.Line() == m_srcPoint.Line(); + + if (res == false) + (*listener) << "Actual parameter : " << DebugPrint(x); + + return res; + } + + virtual void DescribeTo(::std::ostream* os) const + { + *os << "Expected assert : " << DebugPrint(m_srcPoint); + } + + virtual void DescribeNegationTo(::std::ostream* os) const + { + *os << "Unexpected assert. Expect this : " << DebugPrint(m_srcPoint); + } + +private: + SrcPoint m_srcPoint; +}; + +inline Matcher SrcPointEq(const char * fileName, const char * function, int line) +{ + return ::testing::MakeMatcher(new SrcPointMatcher(fileName, function, line)); +} + +#endif + +UNIT_TEST(RefPointer_Positive) +{ + MasterPointer p(new int); + RefPointer refP = p.GetRefPointer(); + + TEST_EQUAL(p.IsNull(), false, ()); + TEST_EQUAL(p.GetRaw(), refP.GetRaw(), ()); + + RefPointer refP2(refP); + + TEST_EQUAL(p.IsNull(), false, ()); + TEST_EQUAL(p.GetRaw(), refP.GetRaw(), ()); + TEST_EQUAL(refP2.GetRaw(), refP.GetRaw(), ()); + + *refP.GetRaw() = 10; + + EmptyFunction(refP); + TEST_EQUAL(p.IsNull(), false, ()); + TEST_EQUAL(p.GetRaw(), refP.GetRaw(), ()); + TEST_EQUAL(refP2.GetRaw(), refP.GetRaw(), ()); + + EmptyFunction(refP2); + TEST_EQUAL(p.IsNull(), false, ()); + TEST_EQUAL(p.GetRaw(), refP.GetRaw(), ()); + TEST_EQUAL(refP2.GetRaw(), refP.GetRaw(), ()); + + refP2 = refP = RefPointer(); + + TEST_EQUAL(p.IsNull(), false, ()); + TEST_EQUAL(refP.IsNull(), true, ()); + TEST_EQUAL(refP2.GetRaw(), refP.GetRaw(), ()); + + p.Destroy(); + TEST_EQUAL(p.IsNull(), true, ()); +} + +#ifdef DEBUG + UNIT_TEST(MasterPointerDestroy_Negative) + { + MockAssertExpector * asserter = InitAsserter(); + + EXPECT_CALL(*asserter, Assert(SrcPointEq("drape/pointers.cpp", "Destroy", 35), _)).Times(1); + + MasterPointer p(new int); + RefPointer refP(p.GetRefPointer()); + p.Destroy(); + + DestroyAsserter(); + } + + UNIT_TEST(MasterPointer_Leak) + { + MockAssertExpector * asserter = InitAsserter(); + + ::testing::InSequence s; + + EXPECT_CALL(*asserter, Assert(SrcPointEq("drape/pointers.cpp", "Deref", 20), _)); + + { + MasterPointer p(new int); + } + + DestroyAsserter(); + } +#endif + +UNIT_TEST(TransferPointerConvertion_Positive) +{ + MasterPointer p(new int); + TEST_EQUAL(p.IsNull(), false, ()); + + int * rawP = p.GetRaw(); + + TransferPointer trP = p.Move(); + TEST_EQUAL(p.IsNull(), true, ()); + TEST_EQUAL(trP.IsNull(), false, ()); + + MasterPointer p2(trP); + TEST_EQUAL(p.IsNull(), true, ()); + TEST_EQUAL(trP.IsNull(), true, ()); + TEST_EQUAL(p2.GetRaw(), rawP, ()); + + p2.Destroy(); +} + +UNIT_TEST(TransferPointer_Positive) +{ + MasterPointer p(new int); + TEST_EQUAL(p.IsNull(), false, ()); + + TransferPointer trP = p.Move(); + TEST_EQUAL(p.IsNull(), true, ()); + TEST_EQUAL(trP.IsNull(), false, ()); + PointerDeleter(trP); +} + +namespace +{ + template + struct MasterPointerAccum + { + public: + MasterPointer m_p; + + void operator() (TransferPointer p) + { + TEST_EQUAL(p.IsNull(), false, ()); + m_p = MasterPointer(p); + TEST_EQUAL(p.IsNull(), true, ()); + } + }; +} + +UNIT_TEST(TransferPointerConvertion2_Positive) +{ + MasterPointer p(new int); + TEST_EQUAL(p.IsNull(), false, ()); + + int * rawP = p.GetRaw(); + + MasterPointerAccum accum; + EmptyFunction(p.Move(), accum); + TEST_EQUAL(p.IsNull(), true, ()); + TEST_EQUAL(accum.m_p.GetRaw(), rawP, ()); + + accum.m_p.Destroy(); +} + +#ifdef DEBUG + + namespace + { + template + struct EmptyTransferAccepter + { + public: + void operator() (TransferPointer p) + { + TEST_EQUAL(p.IsNull(), false, ()); + TransferPointer p2(p); + TEST_EQUAL(p.IsNull(), true, ()); + TEST_EQUAL(p2.IsNull(), false, ()); + } + }; + } + + UNIT_TEST(TransferPointer_Leak) + { + MockAssertExpector * asserter = InitAsserter(); + MasterPointer p(new int); + TEST_EQUAL(p.IsNull(), false, ()); + + EXPECT_CALL(*asserter, Assert(SrcPointEq("drape/pointers.hpp", "~TransferPointer", 158), _)); + + EmptyTransferAccepter toDo; + EmptyFunction(p.Move(), toDo); + TEST_EQUAL(p.IsNull(), true, ()); + + DestroyAsserter(); + } + + UNIT_TEST(PointerConversionAndLeak) + { + MockAssertExpector * asserter = InitAsserter(); + + EXPECT_CALL(*asserter, Assert(SrcPointEq("drape/pointers.cpp", "Deref", 20), _)); + + { + MasterPointer p(new int); + TEST_EQUAL(p.IsNull(), false, ()); + + int * rawP = p.GetRaw(); + + MasterPointerAccum accum; + EmptyFunction(p.Move(), accum); + TEST_EQUAL(p.IsNull(), true, ()); + TEST_EQUAL(accum.m_p.GetRaw(), rawP, ()); + } + + DestroyAsserter(); + } + +#endif + +class Base +{ +public: + Base() {} + virtual ~Base() {} +}; + +class Derived : public Base +{ +public: + Derived() {} +}; + +UNIT_TEST(RefPointerCast) +{ + MasterPointer p(new Derived()); + TEST_EQUAL(p.IsNull(), false, ()); + + { + RefPointer refP(p.GetRefPointer()); + TEST_EQUAL(p.IsNull(), false, ()); + TEST_EQUAL(p.GetRaw(), refP.GetRaw(), ()); + + RefPointer refBaseP(refP); + TEST_EQUAL(p.IsNull(), false, ()); + TEST_EQUAL(p.GetRaw(), refP.GetRaw(), ()); + TEST_EQUAL(p.GetRaw(), refBaseP.GetRaw(), ()); + } + + p.Destroy(); +} + +UNIT_TEST(StackPointers) +{ + int data[10]; + { + RefPointer p = MakeStackRefPointer(data); + TEST_EQUAL(p.GetRaw(), data, ()); + } +} + +UNIT_TEST(MoveFreePointers) +{ + int * data = new int; + TransferPointer p = MovePointer(data); + TEST_EQUAL(p.IsNull(), false, ()); + + MasterPointer mP(p); + TEST_EQUAL(p.IsNull(), true, ()); + TEST_EQUAL(mP.GetRaw(), data, ()); + + mP.Destroy(); +} diff --git a/drape/pointers.hpp b/drape/pointers.hpp index e10612ad91..c2531d4408 100644 --- a/drape/pointers.hpp +++ b/drape/pointers.hpp @@ -159,6 +159,8 @@ public: Destroy(); } void Destroy() { base_t::Destroy(); } + // IsNull need for test + bool IsNull() { return base_t::GetRaw() == NULL; } private: friend class MasterPointer;