File indexing completed on 2024-05-12 15:34:03
0001 /* 0002 SPDX-FileCopyrightText: 2014 Alexander Richardson <alex.richardson@gmx.de> 0003 0004 SPDX-License-Identifier: MIT 0005 */ 0006 0007 #include "signals_test_no_singleton.h" 0008 #include "signals_test_no_singleton_dpointer.h" 0009 #include "signals_test_singleton.h" 0010 #include "signals_test_singleton_dpointer.h" 0011 #include "signals_test_singleton_itemaccessors.h" 0012 #include <QDebug> 0013 #include <QFileInfo> 0014 #include <QSignalSpy> 0015 #include <QTemporaryFile> 0016 #include <QtGlobal> 0017 #include <QtTestGui> 0018 #include <functional> 0019 0020 class KConfigCompiler_Test_Signals : public QObject 0021 { 0022 Q_OBJECT 0023 private Q_SLOTS: 0024 void testSetters(); 0025 void testSetters_data(); 0026 void testSetProperty(); 0027 void testSetProperty_data(); 0028 void initTestCase(); 0029 void cleanupTestCase(); 0030 }; 0031 0032 static SignalsTestNoSingleton *noSingleton; 0033 static SignalsTestNoSingletonDpointer *noSingletonDpointer; 0034 0035 void KConfigCompiler_Test_Signals::initTestCase() 0036 { 0037 // These tests do a lot quite a few I/O operations, speed that up by using a QTemporaryFile. 0038 // At least on Linux this is often a tmpfs which means only RAM operations 0039 QTemporaryFile *tempFile1 = new QTemporaryFile(this); 0040 QTemporaryFile *tempFile2 = new QTemporaryFile(this); 0041 QTemporaryFile *tempFile3 = new QTemporaryFile(this); 0042 QTemporaryFile *tempFile4 = new QTemporaryFile(this); 0043 QTemporaryFile *tempFile5 = new QTemporaryFile(this); 0044 QVERIFY(tempFile1->open()); 0045 QVERIFY(tempFile2->open()); 0046 QVERIFY(tempFile3->open()); 0047 QVERIFY(tempFile4->open()); 0048 QVERIFY(tempFile5->open()); 0049 0050 SignalsTestSingleton::instance(QFileInfo(*tempFile1).absoluteFilePath()); 0051 SignalsTestSingletonDpointer::instance(QFileInfo(*tempFile2).absoluteFilePath()); 0052 noSingleton = new SignalsTestNoSingleton(KSharedConfig::openConfig(QFileInfo(*tempFile3).absoluteFilePath(), KConfig::SimpleConfig)); 0053 noSingletonDpointer = new SignalsTestNoSingletonDpointer(KSharedConfig::openConfig(QFileInfo(*tempFile4).absoluteFilePath(), KConfig::SimpleConfig)); 0054 SignalsTestSingletonItemAccessors::instance(QFileInfo(*tempFile5).absoluteFilePath()); 0055 } 0056 0057 void KConfigCompiler_Test_Signals::cleanupTestCase() 0058 { 0059 // ensure these instances are deleted before the temporary files are closed 0060 delete noSingleton; 0061 delete noSingletonDpointer; 0062 delete SignalsTestSingleton::self(); 0063 delete SignalsTestSingletonDpointer::self(); 0064 delete SignalsTestSingletonItemAccessors::self(); 0065 } 0066 0067 struct TestSettersArg { 0068 // default constructor required for Q_DECLARE_METATYPE 0069 TestSettersArg() 0070 : obj(nullptr) 0071 { 0072 } 0073 template<typename T> 0074 TestSettersArg(T *object) 0075 : obj(object) 0076 { 0077 // we can also call static methods using object->foo() so this works for all four cases 0078 getter = [object]() { 0079 return object->foo(); 0080 }; 0081 defaultGetter = [object]() { 0082 return object->defaultFooValue(); 0083 }; 0084 setter = [object](const QString &s) { 0085 object->setFoo(s); 0086 }; 0087 } 0088 KCoreConfigSkeleton *obj; 0089 std::function<QString()> getter; 0090 std::function<QString()> defaultGetter; 0091 std::function<void(const QString &)> setter; 0092 }; 0093 0094 Q_DECLARE_METATYPE(TestSettersArg) // so that QFETCH works 0095 0096 void KConfigCompiler_Test_Signals::testSetters_data() 0097 { 0098 QTest::addColumn<TestSettersArg>("params"); 0099 QTest::newRow("singleton") << TestSettersArg(SignalsTestSingleton::self()); 0100 QTest::newRow("singleton dpointer") << TestSettersArg(SignalsTestSingletonDpointer::self()); 0101 QTest::newRow("non-singleton") << TestSettersArg(noSingleton); 0102 QTest::newRow("non-singleton dpointer") << TestSettersArg(noSingleton); 0103 QTest::newRow("singleton itemaccessors") << TestSettersArg(SignalsTestSingletonItemAccessors::self()); 0104 } 0105 0106 /** Ensure that a signal is emitted whenever the data is changed by using the generated setters */ 0107 void KConfigCompiler_Test_Signals::testSetters() 0108 { 0109 QFETCH(TestSettersArg, params); 0110 const char *signal = SIGNAL(fooChanged(QString)); 0111 const QString defaultValue = QStringLiteral("default"); 0112 const QString changedValue = QStringLiteral("changed"); 0113 0114 // make sure we are in the default state 0115 params.obj->setDefaults(); 0116 params.obj->save(); 0117 0118 QList<QVariant> args; 0119 QSignalSpy spy(params.obj, signal); 0120 QVERIFY2(spy.isValid(), signal); 0121 0122 // change value via setter, should get signal 0123 QCOMPARE(params.getter(), defaultValue); 0124 QCOMPARE(defaultValue, params.defaultGetter()); 0125 QCOMPARE(params.getter(), params.defaultGetter()); 0126 QVERIFY(changedValue != params.getter()); 0127 params.setter(changedValue); 0128 QCOMPARE(params.getter(), changedValue); 0129 QCOMPARE(spy.count(), 0); // should have no change yet, only after save() 0130 params.obj->save(); 0131 QCOMPARE(spy.count(), 1); 0132 args = spy.takeFirst(); 0133 QCOMPARE(args.size(), 1); 0134 QCOMPARE(args[0].toString(), changedValue); 0135 0136 // reset to default values via setDefaults() 0137 QVERIFY(params.getter() != params.defaultGetter()); 0138 QVERIFY(params.getter() != defaultValue); 0139 QCOMPARE(params.getter(), changedValue); 0140 params.obj->setDefaults(); 0141 QCOMPARE(params.getter(), params.defaultGetter()); 0142 QCOMPARE(params.getter(), defaultValue); 0143 0144 QCOMPARE(spy.count(), 0); // should have no change yet, only after save() 0145 params.obj->save(); 0146 // TODO: This currently fails since setDefaults() does not yet cause emitting a signal 0147 QCOMPARE(spy.count(), 1); 0148 args = spy.takeFirst(); 0149 QCOMPARE(args.size(), 1); 0150 QCOMPARE(args[0].value<QString>(), defaultValue); 0151 } 0152 0153 Q_DECLARE_METATYPE(KCoreConfigSkeleton *) 0154 0155 void KConfigCompiler_Test_Signals::testSetProperty_data() 0156 { 0157 QTest::addColumn<KCoreConfigSkeleton *>("obj"); 0158 QTest::newRow("singleton") << static_cast<KCoreConfigSkeleton *>(SignalsTestSingleton::self()); 0159 QTest::newRow("singleton dpointer") << static_cast<KCoreConfigSkeleton *>(SignalsTestSingletonDpointer::self()); 0160 QTest::newRow("non-singleton") << static_cast<KCoreConfigSkeleton *>(noSingleton); 0161 QTest::newRow("non-singleton dpointer") << static_cast<KCoreConfigSkeleton *>(noSingletonDpointer); 0162 QTest::newRow("singleton itemaccessors") << static_cast<KCoreConfigSkeleton *>(SignalsTestSingletonItemAccessors::self()); 0163 } 0164 0165 /** Test that the signal is emitted when modifying the values using the underlying KConfigSkeletonItem (bypassing the setters) */ 0166 void KConfigCompiler_Test_Signals::testSetProperty() 0167 { 0168 QFETCH(KCoreConfigSkeleton *, obj); 0169 const char *signal = SIGNAL(fooChanged(QString)); 0170 const QString propertyName = QStringLiteral("foo"); 0171 const QString defaultValue = QStringLiteral("default"); 0172 const QString newValue = QStringLiteral("changed"); 0173 obj->setDefaults(); 0174 obj->save(); 0175 0176 KConfigSkeletonItem *item = obj->findItem(propertyName); 0177 QVERIFY2(item, "Item must exist"); 0178 QVERIFY2(!item->isImmutable(), "Item must not be immutable"); 0179 QVERIFY2(!obj->isImmutable(propertyName), "Item must not be immutable"); 0180 0181 // listen for all expected signals 0182 QSignalSpy spy(obj, signal); 0183 QVERIFY2(spy.isValid(), signal); 0184 0185 QVERIFY(item->isEqual(defaultValue)); 0186 QVERIFY(!item->isEqual(newValue)); 0187 0188 item->setProperty(newValue); // change value now 0189 // should have no change yet, only after save() 0190 QCOMPARE(spy.count(), 0); 0191 obj->save(); 0192 // now check for the signal emissions 0193 QCOMPARE(spy.count(), 1); 0194 QList<QVariant> args = spy.takeFirst(); 0195 QCOMPARE(args.size(), 1); 0196 QVERIFY(item->isEqual(args[0])); 0197 0198 // now reset to default 0199 QVERIFY(!item->isEqual(defaultValue)); 0200 item->setDefault(); 0201 QVERIFY(item->isEqual(defaultValue)); 0202 // should have no change yet, only after save() 0203 QCOMPARE(spy.count(), 0); 0204 obj->save(); 0205 // now check for the signal emissions 0206 QCOMPARE(spy.count(), 1); 0207 args = spy.takeFirst(); 0208 QCOMPARE(args.size(), 1); 0209 QVERIFY(item->isEqual(args[0])); 0210 } 0211 0212 QTEST_MAIN(KConfigCompiler_Test_Signals) 0213 0214 #include "kconfigcompiler_test_signals.moc"