// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include #include #include namespace Utils { struct TestData { TestData() = default; TestData(int iValue) : i(iValue) {} bool operator==(const TestData &other) const { return i == other.i && str == other.str; } bool operator!=(const TestData &other) const { return !(*this == other); } QString str; int i{20}; }; class tst_synchronizedvalue : public QObject { Q_OBJECT private slots: void initTestCase() {} void read() { SynchronizedValue data; data.read([](const auto &d) { QCOMPARE(d.str, QString()); QCOMPARE(d.i, 20); }); } void ctor() { SynchronizedValue data(200); QCOMPARE(data.get([](const auto &d) { return d.i; }), 200); } void initializerCtor() { SynchronizedValue> data({1, 2, 3}); QCOMPARE(data.get>([](const auto &d) { return d; }), QList({1, 2, 3})); } void get() { SynchronizedValue data(200); QCOMPARE(data.get([](const auto &d) { return d.i; }), 200); } void constLock() { SynchronizedValue data(200); QCOMPARE(data.readLocked()->i, 200); QCOMPARE(data.get().i, 200); auto lk = data.readLocked(); QCOMPARE(lk->i, 200); // This should fail to compile: // data.readLocked()->i = 200; } void lock() { SynchronizedValue data(123); data.writeLocked()->i = 200; QCOMPARE(data.get([](const auto &d) { return d.i; }), 200); { auto wlk = data.writeLocked(); wlk->str = "Write locked"; } QCOMPARE(data.readLocked()->str, "Write locked"); SynchronizedValue lockedStr("Hello World"); QCOMPARE(*lockedStr.readLocked(), "Hello World"); *lockedStr.writeLocked() = "Hello World 2"; QCOMPARE(*lockedStr.readLocked(), "Hello World 2"); } void trivialGet() { SynchronizedValue data(200); TestData d = data.get(); QCOMPARE(data, d); QCOMPARE(d.i, 200); } void equalop() { SynchronizedValue data(200); SynchronizedValue data2(300); data = data2; QCOMPARE(data.get([](const auto &d) { return d.i; }), 300); QCOMPARE(data2.get([](const auto &d) { return d.i; }), 300); TestData dataNoLock(1337); data = dataNoLock; QCOMPARE(data.get([](const auto &d) { return d.i; }), 1337); } void compareEq() { SynchronizedValue data(200); SynchronizedValue data2(300); QVERIFY(data != data2); QVERIFY(!(data == data2)); data2.write([](auto &d) { d.i = 200; }); QVERIFY(data == data2); QVERIFY(!(data != data2)); } void operators() { SynchronizedValue data(200); SynchronizedValue data2(300); QVERIFY(data < data2); QVERIFY(data <= data2); QVERIFY(data2 > data); QVERIFY(data2 >= data); QVERIFY(data2 != data); QVERIFY(!(data2 == data)); QVERIFY(data > 100); QVERIFY(data >= 100); QVERIFY(data >= 200); QVERIFY(data < 300); QVERIFY(data <= 300); QVERIFY(100 < data); QVERIFY(200 <= data); QVERIFY(199 <= data); QVERIFY(300 > data); QVERIFY(200 >= data); QVERIFY(201 >= data); QVERIFY(200 == data); QVERIFY(200 != data2); } void copyCtor() { SynchronizedValue data(123); SynchronizedValue data2(data); QCOMPARE(data.get([](const auto &d) { return d.i; }), 123); QCOMPARE(data2.get([](const auto &d) { return d.i; }), 123); TestData dataNoLock(1337); SynchronizedValue data3(dataNoLock); QCOMPARE(data3.get([](const auto &d) { return d.i; }), 1337); } void multilock() { SynchronizedValue value(100); // Multiple reader, no writer { QCOMPARE(value.get(), 100); auto firstLock = value.readLocked(); QVERIFY(firstLock.ownsLock()); auto secondLock = value.readLocked(); QVERIFY(secondLock.ownsLock()); QCOMPARE(*firstLock, 100); QCOMPARE(*secondLock, 100); auto thirdLock = value.writeLocked(std::try_to_lock); QVERIFY(!thirdLock.ownsLock()); } // Single writer, no readers { auto firstLock = value.writeLocked(); QVERIFY(firstLock.ownsLock()); auto secondLock = value.writeLocked(std::try_to_lock); QVERIFY(!secondLock.ownsLock()); auto readLock = value.readLocked(std::try_to_lock); QVERIFY(!readLock.ownsLock()); } } void synchronizeMultiple() { SynchronizedValue sv1; SynchronizedValue sv2; auto [lk1, lk2] = synchronize(sv1, sv2); QVERIFY(lk1.ownsLock()); QVERIFY(lk2.ownsLock()); } }; } // namespace Utils QTEST_GUILESS_MAIN(Utils::tst_synchronizedvalue) #include "tst_synchronizedvalue.moc"