File indexing completed on 2024-12-01 10:31:07

0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com>
0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT
0003 
0004 // First included header is the public header of the class we are testing;
0005 // this forces the header to be self-contained.
0006 #include "setting.h"
0007 
0008 #include "settingbase.h"
0009 #include "settings.h"
0010 #include <qfile.h>
0011 #include <qglobal.h>
0012 #include <qobject.h>
0013 #include <qpointer.h>
0014 #include <qsettings.h>
0015 #include <qsignalspy.h>
0016 #include <qstring.h>
0017 #include <qstringliteral.h>
0018 #include <qtest.h>
0019 #include <qtestcase.h>
0020 
0021 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0022 #include <qtmetamacros.h>
0023 #else
0024 #include <qobjectdefs.h>
0025 #include <qstring.h>
0026 #endif
0027 
0028 namespace PerceptualColor
0029 {
0030 class TestSetting : public QObject
0031 {
0032     Q_OBJECT
0033 
0034 public:
0035     explicit TestSetting(QObject *parent = nullptr)
0036         : QObject(parent)
0037     {
0038     }
0039 
0040 private:
0041     static const inline QString organization = QStringLiteral("kde.org");
0042     // Avoid side-effects on the actual configuration file of the actual
0043     // library: Use a value different application name:
0044     static const inline QString application = QStringLiteral("libperceptualcolortestsettings");
0045 
0046 private Q_SLOTS:
0047     void initTestCase()
0048     {
0049         // Called before the first test function is executedQFile file(fileName);
0050 
0051         const QString fileName = QSettings(QSettings::IniFormat, //
0052                                            QSettings::UserScope, //
0053                                            organization, //
0054                                            application)
0055                                      .fileName();
0056         QFile(fileName).remove();
0057     }
0058 
0059     void cleanupTestCase()
0060     {
0061         // Called after the last test function was executed
0062 
0063         const QString fileName = QSettings(QSettings::IniFormat, //
0064                                            QSettings::UserScope, //
0065                                            organization, //
0066                                            application)
0067                                      .fileName();
0068         QFile(fileName).remove();
0069     }
0070 
0071     void init()
0072     {
0073         // Called before each test function is executed
0074 
0075         const QString fileName = QSettings(QSettings::IniFormat, //
0076                                            QSettings::UserScope, //
0077                                            organization, //
0078                                            application)
0079                                      .fileName();
0080         QFile(fileName).remove();
0081     }
0082 
0083     void cleanup()
0084     {
0085         // Called after every test function
0086 
0087         const QString fileName = QSettings(QSettings::IniFormat, //
0088                                            QSettings::UserScope, //
0089                                            organization, //
0090                                            application)
0091                                      .fileName();
0092         QFile(fileName).remove();
0093     }
0094 
0095 #ifndef MSVC_DLL
0096     // The automatic export of otherwise private symbols on MSVC
0097     // shared libraries via CMake's WINDOWS_EXPORT_ALL_SYMBOLS property
0098     // does not work well for Qt meta objects, resulting in non-functional
0099     // signals. Since the following unit tests require signals, it cannot be
0100     // built for MSVC shared libraries.
0101 
0102     void testConstuctorDestructor()
0103     {
0104         Settings mySettings(QSettings::UserScope, //
0105                             organization, //
0106                             application);
0107         {
0108             Setting<int> mySetting(QStringLiteral("group/key"), //
0109                                    &mySettings,
0110                                    nullptr);
0111         }
0112     }
0113 
0114     void testParent()
0115     {
0116         Settings mySettings(QSettings::UserScope, //
0117                             organization, //
0118                             application);
0119         QPointer<Setting<int>> mySetting;
0120         {
0121             QObject myParent;
0122             mySetting = new Setting<int>( //
0123                 QStringLiteral("group/key"), //
0124                 &mySettings,
0125                 &myParent);
0126             QCOMPARE(mySetting.data()->parent(), &myParent);
0127         }
0128         QVERIFY(mySetting.isNull());
0129     }
0130 
0131     void testGetSetSignal()
0132     {
0133         Settings mySettings(QSettings::UserScope, //
0134                             organization, //
0135                             application);
0136 
0137         Setting<QString> tab(QStringLiteral("group/testSetting"), &mySettings);
0138 
0139         const QString newTab1 = QStringLiteral("testTab");
0140         tab.setValue(newTab1);
0141         QCOMPARE(tab.m_value, newTab1);
0142         QCOMPARE(tab.value(), newTab1);
0143 
0144         QSignalSpy spy(&tab, &PerceptualColor::SettingBase::valueChanged);
0145 
0146         const QString newTab2 = QStringLiteral("differentTestTab");
0147         tab.setValue(newTab2);
0148         tab.setValue(newTab2); // Intentional duplicate
0149         QCOMPARE(tab.m_value, newTab2);
0150         QCOMPARE(tab.value(), newTab2);
0151         QVERIFY(spy.isValid());
0152         // The second call to the setter with an identical value
0153         // should not trigger a signal.
0154         QCOMPARE(spy.count(), 1);
0155     }
0156 
0157     void testUpdateFromSettings()
0158     {
0159         Settings mySettings(QSettings::UserScope, //
0160                             organization, //
0161                             application);
0162 
0163         const QString key = QStringLiteral("group/testUpdateFromSetting");
0164         Setting<QString> tab(key, //
0165                              &mySettings);
0166 
0167         const QString newTab1 = QStringLiteral("testTab");
0168         tab.setValue(newTab1);
0169         QCOMPARE(tab.m_value, newTab1);
0170         QCOMPARE(tab.value(), newTab1);
0171 
0172         const QString newTab2 = QStringLiteral("differentTestTab");
0173         tab.underlyingQSettings()->setValue(key, newTab2);
0174         QCOMPARE(tab.m_value, newTab1);
0175         QCOMPARE(tab.value(), newTab1);
0176 
0177         tab.updateFromQSettings();
0178         QCOMPARE(tab.m_value, newTab2);
0179         QCOMPARE(tab.value(), newTab2);
0180     }
0181 #endif
0182 };
0183 
0184 } // namespace PerceptualColor
0185 
0186 QTEST_MAIN(PerceptualColor::TestSetting)
0187 
0188 // The following “include” is necessary because we do not use a header file:
0189 #include "testsetting.moc"