diff --git a/TelepathyQt4/contact.h b/TelepathyQt4/contact.h index e941cab..c6c6149 100644 --- a/TelepathyQt4/contact.h +++ b/TelepathyQt4/contact.h @@ -184,11 +184,6 @@ private: typedef QSet Contacts; -inline uint qHash(const ContactPtr &contact) -{ - return qHash(contact.data()); -} - } // Tp #endif diff --git a/TelepathyQt4/shared-ptr.h b/TelepathyQt4/shared-ptr.h index a3e043d..2faec9c 100644 --- a/TelepathyQt4/shared-ptr.h +++ b/TelepathyQt4/shared-ptr.h @@ -29,6 +29,7 @@ #include #include +#include namespace Tp { @@ -105,8 +106,9 @@ public: inline T *operator->() const { return d; } inline bool isNull() const { return !d; } - inline operator bool() const { return !isNull(); } inline bool operator!() const { return isNull(); } + typedef T* SharedPtr::*UnspecifiedBoolType; + operator UnspecifiedBoolType() const { return isNull() ? 0 : &SharedPtr::d; } inline bool operator==(const SharedPtr &o) const { return d == o.d; } inline bool operator!=(const SharedPtr &o) const { return d != o.d; } @@ -156,6 +158,14 @@ private: T *d; }; +template +inline uint qHash(const SharedPtr &ptr) +{ + return QT_PREPEND_NAMESPACE(qHash(ptr.data())); +} + +template inline uint qHash(const WeakPtr &ptr); + template class WeakPtr { @@ -185,8 +195,10 @@ public: } inline bool isNull() const { return !wd || !wd->d || wd->d->strongref == 0; } - inline operator bool() const { return !isNull(); } inline bool operator!() const { return isNull(); } + typedef WeakData* WeakPtr::*UnspecifiedBoolType; + //typedef T* RefCounted::*UnspecifiedBoolType; + operator UnspecifiedBoolType() const { return isNull() ? 0 : &WeakPtr::wd; } inline WeakPtr &operator=(const WeakPtr &o) { @@ -211,10 +223,18 @@ public: private: friend class SharedPtr; + friend uint qHash(const WeakPtr &ptr); WeakData *wd; }; +template +inline uint qHash(const WeakPtr &ptr) +{ + T *actualPtr = ptr.wd ? ptr.wd.d : 0; + return QT_PREPEND_NAMESPACE(qHash(actualPtr)); +} + } // Tp #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ab4bbc1..d6e8ff0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -33,6 +33,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILER_COVERAGE_FLAGS}") tpqt4_add_generic_unit_test(KeyFile key-file) tpqt4_add_generic_unit_test(ManagerFile manager-file) tpqt4_add_generic_unit_test(Profile profile) +tpqt4_add_generic_unit_test(Ptr ptr) add_subdirectory(dbus-1) add_subdirectory(dbus) diff --git a/tests/ptr.cpp b/tests/ptr.cpp new file mode 100644 index 0000000..62a12d9 --- /dev/null +++ b/tests/ptr.cpp @@ -0,0 +1,248 @@ +#include + +#include +#include + +using namespace Tp; + +class TestSharedPtr : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void testSharedPtrDict(); + void testWeakPtrDict(); + void testSharedPtrBoolConversion(); + void testWeakPtrBoolConversion(); +}; + +class Data; +typedef SharedPtr DataPtr; + +class Data : public QObject, + public RefCounted +{ + Q_OBJECT + Q_DISABLE_COPY(Data); + +public: + static DataPtr create() { return DataPtr(new Data()); } + static DataPtr createNull() { return DataPtr(0); } + +private: + Data() {} +}; + +void TestSharedPtr::testSharedPtrDict() +{ + QHash dict; + DataPtr nullPtr = Data::createNull(); + dict[nullPtr] = 1; + QCOMPARE(dict.size(), 1); + QCOMPARE(dict[nullPtr], 1); + + DataPtr validPtr1 = Data::create(); + QCOMPARE(qHash(validPtr1.data()), qHash(validPtr1)); + dict[validPtr1] = 2; + QCOMPARE(dict.size(), 2); + QCOMPARE(dict[nullPtr], 1); + QCOMPARE(dict[validPtr1], 2); + + DataPtr validPtr2 = validPtr1; + QCOMPARE(validPtr1.data(), validPtr2.data()); + QCOMPARE(qHash(validPtr1), qHash(validPtr2)); + dict[validPtr2] = 3; + QCOMPARE(dict.size(), 2); + QCOMPARE(dict[nullPtr], 1); + QCOMPARE(dict[validPtr1], 3); + QCOMPARE(dict[validPtr2], 3); + + DataPtr validPtrAlternative = Data::create(); + QVERIFY(validPtr1.data() != validPtrAlternative.data()); + QVERIFY(validPtr1 != validPtrAlternative); + QVERIFY(qHash(validPtr1) != qHash(validPtrAlternative)); + dict[validPtrAlternative] = 4; + QCOMPARE(dict.size(), 3); + QCOMPARE(dict[nullPtr], 1); + QCOMPARE(dict[validPtr1], 3); + QCOMPARE(dict[validPtr2], 3); + QCOMPARE(dict[validPtrAlternative], 4); +} + +void TestSharedPtr::testWeakPtrDict() +{ +} + +void TestSharedPtr::testSharedPtrBoolConversion() +{ + DataPtr nullPtr1; + DataPtr nullPtr2 = Data::createNull(); + DataPtr validPtr1 = Data::create(); + DataPtr validPtr2 = validPtr1; + DataPtr validPtrAlternative = Data::create(); + + // Boolean conditions + QVERIFY(!validPtr1.isNull()); + QVERIFY(nullPtr1.isNull()); + QVERIFY(validPtr1 ? true : false); + QVERIFY(!validPtr1 ? false : true); + QVERIFY(nullPtr1 ? false : true); + QVERIFY(!nullPtr1 ? true : false); + QVERIFY(validPtr1); + QVERIFY(!!validPtr1); + QVERIFY(!nullPtr1); + + // Supported operators + QVERIFY(nullPtr1 == nullPtr1); + QVERIFY(nullPtr1 == nullPtr2); + + QVERIFY(validPtr1 == validPtr1); + QVERIFY(validPtr1 == validPtr2); + QVERIFY(validPtr1 != validPtrAlternative); + QCOMPARE(validPtr1 == validPtrAlternative, false); + + QVERIFY(validPtr1 != nullPtr1); + QCOMPARE(validPtr1 == nullPtr1, false); + + // Supported conversions, constructors and copy operators + bool trueBool1 = validPtr1; + QVERIFY(trueBool1); + bool trueBool2(validPtr2); + QVERIFY(trueBool2); + trueBool1 = validPtrAlternative; + QVERIFY(trueBool1); + + bool falseBool1 = nullPtr1; + QVERIFY(!falseBool1); + bool falseBool2(nullPtr2); + QVERIFY(!falseBool2); + falseBool1 = nullPtr1; + QVERIFY(!falseBool1); + +#if 0 + // Unsupported operators, this should not compile + bool condition; + condition = validPtr1 > nullPtr1; + condition = validPtr1 + nullPtr1; + + // Unsupported conversions, this should not compile + int validInt1 = validPtr1; + int validInt2(validPtr1); + validInt1 = validPtr1; + + int nullInt1 = nullPtr1; + int nullInt2(nullPtr1); + nullInt1 = nullPtr1; + + float validFloat1 = validPtr1; + float validFloat2(validPtr1); + validFloat1 = validPtr1; + + float nullFloat1 = nullPtr1; + float nullFloat2(nullPtr1); + nullFloat1 = nullPtr1; + + Q_UNUSED(validInt1); + Q_UNUSED(validInt2); + Q_UNUSED(nullInt1); + Q_UNUSED(nullInt2); + Q_UNUSED(validFloat1); + Q_UNUSED(validFloat2); + Q_UNUSED(nullFloat1); + Q_UNUSED(nullFloat2); +#endif +} + +void TestSharedPtr::testWeakPtrBoolConversion() +{ + WeakPtr nullPtr1; + DataPtr strongNullPtr2 = Data::createNull(); + WeakPtr nullPtr2 = strongNullPtr2; + DataPtr strongValidPtr1 = Data::create(); + WeakPtr validPtr1 = strongValidPtr1; + WeakPtr validPtr2 = validPtr1; + DataPtr strongValidPtrAlternative = Data::create(); + WeakPtr validPtrAlternative = strongValidPtrAlternative; + + // Boolean conditions + QVERIFY(!validPtr1.isNull()); + QVERIFY(nullPtr1.isNull()); + QVERIFY(validPtr1 ? true : false); + QVERIFY(!validPtr1 ? false : true); + QVERIFY(nullPtr1 ? false : true); + QVERIFY(!nullPtr1 ? true : false); + QVERIFY(validPtr1); + QVERIFY(!!validPtr1); + QVERIFY(!nullPtr1); + + // Supported operators + QVERIFY(nullPtr1 == nullPtr1); + QVERIFY(nullPtr1 == nullPtr2); + + QVERIFY(validPtr1 == validPtr1); + QVERIFY(validPtr1 == validPtr2); + // XXX why not comparison operator? + //QVERIFY(validPtr1 != validPtrAlternative); + //QCOMPARE(validPtr1 == validPtrAlternative, false); + + QVERIFY(validPtr1 != nullPtr1); + QCOMPARE(validPtr1 == nullPtr1, false); + + // Supported conversions, constructors and copy operators + bool trueBool1 = validPtr1; + QVERIFY(trueBool1); + bool trueBool2(validPtr2); + QVERIFY(trueBool2); + trueBool1 = validPtrAlternative; + QVERIFY(trueBool1); + + bool falseBool1 = nullPtr1; + QVERIFY(!falseBool1); + bool falseBool2(nullPtr2); + QVERIFY(!falseBool2); + falseBool1 = nullPtr1; + QVERIFY(!falseBool1); + +#if 0 + // Unsupported operators, this should not compile + bool condition; + condition = validPtr1 > nullPtr1; + condition = validPtr1 + nullPtr1; + + // Unsupported conversions, this should not compile + int validInt1 = validPtr1; + int validInt2(validPtr1); + validInt1 = validPtr1; + + int nullInt1 = nullPtr1; + int nullInt2(nullPtr1); + nullInt1 = nullPtr1; + + float validFloat1 = validPtr1; + float validFloat2(validPtr1); + validFloat1 = validPtr1; + + float nullFloat1 = nullPtr1; + float nullFloat2(nullPtr1); + nullFloat1 = nullPtr1; + + Q_UNUSED(validInt1); + Q_UNUSED(validInt2); + Q_UNUSED(nullInt1); + Q_UNUSED(nullInt2); + Q_UNUSED(validFloat1); + Q_UNUSED(validFloat2); + Q_UNUSED(nullFloat1); + Q_UNUSED(nullFloat2); +#endif + + // Test the boolean operations after the main SharedPtr is gone + strongValidPtrAlternative.reset(); + QVERIFY(validPtrAlternative.isNull()); + QVERIFY(validPtrAlternative ? false : true); + QVERIFY(!validPtrAlternative ? true : false); +} + +QTEST_MAIN(TestSharedPtr) + +#include "_gen/ptr.cpp.moc.hpp"