summaryrefslogtreecommitdiffstats
path: root/tests/auto/unit/multimedia/qmaybe/tst_qmaybe.cpp
blob: fbf21a26d0786bc0d78ef5f3bf3ca62144b07453 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only

#include <QtTest/QtTest>
#include <private/qmaybe_p.h>
#include <QtCore/private/quniquehandle_p.h>
#ifdef Q_OS_WINDOWS
#include <private/qcomptr_p.h>
#include <private/qcomobject_p.h>
#endif

QT_USE_NAMESPACE

using namespace Qt::StringLiterals;

namespace {

// Helpers used to verify interop with QUniqueHandle and ComPtr which
// overloads operator&
struct DummyHandleTraits
{
    using Type = int;
    static Type invalidValue() { return -1; }
    static bool close(Type /*handle*/) { return true; }
};

using DummyHandle = QUniqueHandle<DummyHandleTraits>;

#ifdef Q_OS_WINDOWS
struct DummyComObject : QComObject<IUnknown>
{
};
#endif

} // namespace

//clang-format off

class tst_QMaybe : public QObject
{
    Q_OBJECT

private slots:
    void operatorBool_returnsFalse_onlyWhenErrorSet()
    {
        {
            const QMaybe<QString, int> error{ -1 }; // TOOD: Is it safe to deduce expected/unexpected only based on type?
            QVERIFY(!static_cast<bool>(error));
        }

        {
            const QMaybe<QString, int> success{ "It worked!"_L1 };
            QVERIFY(static_cast<bool>(success));
        }
    }

    void value_returnsReferenceToValue_whenValueSet()
    {
        {
            QMaybe mutableVal{ 1 };
            mutableVal.value() = 2;
            QCOMPARE_EQ(*mutableVal, 2); // value() must have returned a mutable reference
        }

        {
            const QMaybe immutableVal{ 2 };
            QCOMPARE_EQ(*std::addressof(immutableVal.value()), 2); // value() must have returned a reference
            static_assert(std::is_const_v<std::remove_reference_t<decltype(immutableVal.value())>>); // And it is const
        }
    }

    void dereferenceOperator_returnsPointerToValue_whenValueTypeOverloadsAddressOfOperator()
    {
        {
            QMaybe<DummyHandle, int> mutableValue{ DummyHandle{ 1 } };
            QCOMPARE_EQ(mutableValue->get(), 1);
            QVERIFY(mutableValue->isValid()); // We did not accidentally call operator& that resets
                                              // QUniqueHandle
        }

        {
            const QMaybe<DummyHandle, int> immutableValue{ DummyHandle{ 2 } };
            QCOMPARE_EQ(immutableValue->get(), 2);
            QVERIFY(immutableValue->isValid()); // We did not accidentally call operator& that
                                                // resets QUniqueHandle
        }
    }

#ifdef Q_OS_WINDOWS
    void dereferenceOperator_returnsPointerToValue_whenValueIsComPtr()
    {
        // Similar test as with QUniqueHandle, but with ComPtr that is used
        // frequently on Windows and may behave slightly differently

        {
            QMaybe<ComPtr<DummyComObject>, HRESULT> mutableObject{
                makeComObject<DummyComObject>()
            };
            QCOMPARE_NE(mutableObject->Get(), nullptr);

            const ComPtr<IUnknown> unknownFromMutable = mutableObject.value();
            QVERIFY(unknownFromMutable); // We did not accidentally call operator& that resets
                                         // QUniqueHandle
        }

        {
            QMaybe<ComPtr<DummyComObject>, HRESULT> immutableObject{
                makeComObject<DummyComObject>()
            };
            QCOMPARE_NE(immutableObject->Get(), nullptr);

            const ComPtr<IUnknown> unknownFromImmutable = immutableObject.value();
            QVERIFY(unknownFromImmutable); // We did not accidentally call operator& that resets
                                           // QUniqueHandle
        }
    }
#endif
};

QTEST_APPLESS_MAIN(tst_QMaybe)

#include "tst_qmaybe.moc"

//clang-format on