File indexing completed on 2024-05-12 05:46:54

0001 /*
0002 Copyright (c) 2014 Alexander Richardson <alex.richardson@gmx.de>
0003 
0004 Permission is hereby granted, free of charge, to any person obtaining a copy
0005 of this software and associated documentation files (the "Software"), to deal
0006 in the Software without restriction, including without limitation the rights
0007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0008 copies of the Software, and to permit persons to whom the Software is
0009 furnished to do so, subject to the following conditions:
0010 
0011 The above copyright notice and this permission notice shall be included in
0012 all copies or substantial portions of the Software.
0013 
0014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
0017 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
0018 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0019 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0020 */
0021 
0022 #include "signals_test_singleton.h"
0023 #include "signals_test_no_singleton.h"
0024 #include "signals_test_singleton_dpointer.h"
0025 #include "signals_test_no_singleton_dpointer.h"
0026 #include <QtTestGui>
0027 #include <QSignalSpy>
0028 #include <QSharedPointer>
0029 #include <QtGlobal>
0030 #include <QDebug>
0031 #include <QTemporaryFile>
0032 #include <QFileInfo>
0033 #include <functional>
0034 
0035 class KConfigCompiler_Test_Signals : public QObject
0036 {
0037     Q_OBJECT
0038 private Q_SLOTS:
0039     void testSetters();
0040     void testSetters_data();
0041     void testSetProperty();
0042     void testSetProperty_data();
0043     void initTestCase();
0044     void cleanupTestCase();
0045 };
0046 
0047 static SignalsTestNoSingleton* noSingleton;
0048 static SignalsTestNoSingletonDpointer* noSingletonDpointer;
0049 
0050 void KConfigCompiler_Test_Signals::initTestCase()
0051 {
0052     // These tests do a lot quite a few I/O operations, speed that up by using a QTemporaryFile.
0053     // At least on Linux this is often a tmpfs which means only RAM operations
0054     QTemporaryFile* tempFile1 = new QTemporaryFile(this);
0055     QTemporaryFile* tempFile2 = new QTemporaryFile(this);
0056     QTemporaryFile* tempFile3 = new QTemporaryFile(this);
0057     QTemporaryFile* tempFile4 = new QTemporaryFile(this);
0058     QVERIFY(tempFile1->open());
0059     QVERIFY(tempFile2->open());
0060     QVERIFY(tempFile3->open());
0061     QVERIFY(tempFile4->open());
0062 
0063     SignalsTestSingleton::instance(QFileInfo(*tempFile1).absoluteFilePath());
0064     SignalsTestSingletonDpointer::instance(QFileInfo(*tempFile2).absoluteFilePath());
0065     noSingleton = new SignalsTestNoSingleton(
0066                 KSharedConfig::openConfig(QFileInfo(*tempFile3).absoluteFilePath(), KConfig::SimpleConfig));
0067     noSingletonDpointer = new SignalsTestNoSingletonDpointer(
0068                 KSharedConfig::openConfig(QFileInfo(*tempFile4).absoluteFilePath(), KConfig::SimpleConfig));
0069 }
0070 
0071 void KConfigCompiler_Test_Signals::cleanupTestCase()
0072 {
0073     //ensure these instances are deleted before the temporary files are closed
0074     delete noSingleton;
0075     delete noSingletonDpointer;
0076     delete SignalsTestSingleton::self();
0077     delete SignalsTestSingletonDpointer::self();
0078 }
0079 
0080 struct TestSettersArg {
0081     // default constructor required for Q_DECLARE_METATYPE
0082     TestSettersArg() : obj(nullptr) {}
0083     template<typename T>
0084     TestSettersArg(T* object) : obj(object) {
0085         // we can also call static methods using object->foo() so this works for all four cases
0086         getter = [object]() { return object->foo(); };
0087         defaultGetter = [object]() { return object->defaultFooValue(); };
0088         setter = [object](const QString& s) { object->setFoo(s); };
0089     }
0090     KCoreConfigSkeleton* obj;
0091     std::function<QString()> getter;
0092     std::function<QString()> defaultGetter;
0093     std::function<void(const QString&)> setter;
0094 };
0095 
0096 Q_DECLARE_METATYPE(TestSettersArg) // so that QFETCH works
0097 
0098 void KConfigCompiler_Test_Signals::testSetters_data()
0099 {
0100     QTest::addColumn<TestSettersArg>("params");
0101     QTest::newRow("singleton") << TestSettersArg(SignalsTestSingleton::self());
0102     QTest::newRow("singleton dpointer") << TestSettersArg(SignalsTestSingletonDpointer::self());
0103     QTest::newRow("non-singleton") << TestSettersArg(noSingleton);
0104     QTest::newRow("non-singleton dpointer") << TestSettersArg(noSingleton);
0105 }
0106 
0107 /** Ensure that a signal is emitted whenever the data is changed by using the generated setters */
0108 void KConfigCompiler_Test_Signals::testSetters()
0109 {
0110     QFETCH(TestSettersArg, params);
0111     const char* signal = SIGNAL(fooChanged(QString));
0112     const QString defaultValue = QStringLiteral("default");
0113     const QString changedValue = QStringLiteral("changed");
0114 
0115     // make sure we are in the default state
0116     params.obj->setDefaults();
0117     params.obj->save();
0118 
0119     QList<QVariant> args;
0120     QSignalSpy spy(params.obj, signal);
0121     QVERIFY2(spy.isValid(), signal);
0122 
0123     //change value via setter, should get signal
0124     QCOMPARE(params.getter(), defaultValue);
0125     QCOMPARE(defaultValue, params.defaultGetter());
0126     QCOMPARE(params.getter(), params.defaultGetter());
0127     QVERIFY(changedValue != params.getter());
0128     params.setter(changedValue);
0129     QCOMPARE(params.getter(), changedValue);
0130     QCOMPARE(spy.count(), 0); //should have no change yet, only after save()
0131     params.obj->save();
0132     QCOMPARE(spy.count(), 1);
0133     args = spy.takeFirst();
0134     QCOMPARE(args.size(), 1);
0135     QCOMPARE(args[0].toString(), changedValue);
0136 
0137     //reset to default values via setDefaults()
0138     QVERIFY(params.getter() != params.defaultGetter());
0139     QVERIFY(params.getter() != defaultValue);
0140     QCOMPARE(params.getter(), changedValue);
0141     params.obj->setDefaults();
0142     QCOMPARE(params.getter(), params.defaultGetter());
0143     QCOMPARE(params.getter(), defaultValue);
0144 
0145     QCOMPARE(spy.count(), 0); //should have no change yet, only after save()
0146     params.obj->save();
0147     //TODO: This currently fails since setDefaults() does not yet cause emitting a signal
0148     QCOMPARE(spy.count(), 1);
0149     args = spy.takeFirst();
0150     QCOMPARE(args.size(), 1);
0151     QCOMPARE(args[0].value<QString>(), defaultValue);
0152 }
0153 
0154 Q_DECLARE_METATYPE(KCoreConfigSkeleton*)
0155 
0156 void KConfigCompiler_Test_Signals::testSetProperty_data()
0157 {
0158     QTest::addColumn<KCoreConfigSkeleton*>("obj");
0159     QTest::newRow("singleton") << static_cast<KCoreConfigSkeleton*>(SignalsTestSingleton::self());
0160     QTest::newRow("singleton dpointer") << static_cast<KCoreConfigSkeleton*>(SignalsTestSingletonDpointer::self());
0161     QTest::newRow("non-singleton") << static_cast<KCoreConfigSkeleton*>(noSingleton);
0162     QTest::newRow("non-singleton dpointer") << static_cast<KCoreConfigSkeleton*>(noSingletonDpointer);
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"