File indexing completed on 2025-04-20 04:21:48
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 "perceptualsettings.h" 0007 0008 #include "setting.h" 0009 #include "settingbase.h" 0010 #include <qcolor.h> 0011 #include <qglobal.h> 0012 #include <qnamespace.h> 0013 #include <qobject.h> 0014 #include <qsignalspy.h> 0015 #include <qstring.h> 0016 #include <qstringliteral.h> 0017 #include <qtest.h> 0018 #include <qtest_gui.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 #endif 0026 0027 static void snippet01() 0028 { 0029 // cppcheck-suppress constVariableReference // snippet for documentation 0030 //! [PerceptualSettings Instance] 0031 auto &mySettings = PerceptualColor::PerceptualSettings::instance(); 0032 //! [PerceptualSettings Instance] 0033 Q_UNUSED(mySettings) 0034 } 0035 0036 namespace PerceptualColor 0037 { 0038 class TestPerceptualSettings : public QObject 0039 { 0040 Q_OBJECT 0041 0042 public: 0043 explicit TestPerceptualSettings(QObject *parent = nullptr) 0044 : QObject(parent) 0045 { 0046 } 0047 0048 private Q_SLOTS: 0049 void initTestCase() 0050 { 0051 // Called before the first test function is executed 0052 } 0053 0054 void cleanupTestCase() 0055 { 0056 // Called after the last test function was executed 0057 } 0058 0059 void init() 0060 { 0061 // Called before each test function is executed 0062 } 0063 0064 void cleanup() 0065 { 0066 // Called after every test function 0067 } 0068 0069 void testSnippet01() 0070 { 0071 snippet01(); 0072 } 0073 0074 void testColorListConstructor() 0075 { 0076 PerceptualSettings::ColorList myList; 0077 Q_UNUSED(myList); 0078 } 0079 0080 void testConstructorDestructor() 0081 { 0082 // There should be no crash: 0083 const auto &mySettings = PerceptualSettings::instance(); 0084 Q_UNUSED(mySettings) 0085 } 0086 0087 #ifndef MSVC_DLL 0088 // The automatic export of otherwise private symbols on MSVC 0089 // shared libraries via CMake's WINDOWS_EXPORT_ALL_SYMBOLS property 0090 // does not work well for Qt meta objects, resulting in non-functional 0091 // signals. Since the following unit tests require signals, it cannot be 0092 // built for MSVC shared libraries. 0093 0094 void testCustomColors() 0095 { 0096 auto &mySettings = PerceptualSettings::instance(); 0097 0098 const PerceptualColor::PerceptualSettings::ColorList newColors1 = {QColor(Qt::red), QColor(Qt::green), QColor(Qt::blue)}; 0099 mySettings.customColors.setValue(newColors1); 0100 QCOMPARE(mySettings.customColors.value(), newColors1); 0101 0102 QSignalSpy spy(&mySettings.customColors, &PerceptualColor::SettingBase::valueChanged); 0103 0104 const PerceptualColor::PerceptualSettings::ColorList newColors2 = {QColor(Qt::cyan), QColor(Qt::magenta), QColor(Qt::yellow)}; 0105 mySettings.customColors.setValue(newColors2); 0106 mySettings.customColors.setValue(newColors2); // Intentional duplicate 0107 QCOMPARE(mySettings.customColors.value(), newColors2); 0108 QVERIFY(spy.isValid()); 0109 // The second call to the setter with an identical value 0110 // should not trigger a signal. 0111 QCOMPARE(spy.count(), 1); 0112 } 0113 0114 void testTab() 0115 { 0116 auto &mySettings = PerceptualSettings::instance(); 0117 0118 const QString newTab1 = QStringLiteral("testTab"); 0119 mySettings.tab.setValue(newTab1); 0120 QCOMPARE(mySettings.tab.value(), newTab1); 0121 0122 QSignalSpy spy(&mySettings.tab, &PerceptualColor::SettingBase::valueChanged); 0123 0124 const QString newTab2 = QStringLiteral("differentTestTab"); 0125 mySettings.tab.setValue(newTab2); 0126 mySettings.tab.setValue(newTab2); // Intentional duplicate 0127 QCOMPARE(mySettings.tab.value(), newTab2); 0128 QVERIFY(spy.isValid()); 0129 // The second call to the setter with an identical value 0130 // should not trigger a signal. 0131 QCOMPARE(spy.count(), 1); 0132 } 0133 0134 void testInstancesAreIdenticalForTab() 0135 { 0136 // As this is implemented as singleton, calling the singleton function 0137 // various times should still produce interchangeable results. 0138 0139 auto &mySettings1 = PerceptualSettings::instance(); 0140 auto &mySettings2 = PerceptualSettings::instance(); 0141 0142 const QString newTab1 = QStringLiteral("testTabInstance"); 0143 mySettings1.tab.setValue(newTab1); 0144 QCOMPARE(mySettings1.tab.value(), newTab1); 0145 QCOMPARE(mySettings2.tab.value(), newTab1); 0146 0147 QSignalSpy spy1(&mySettings1.tab, &PerceptualColor::SettingBase::valueChanged); 0148 QSignalSpy spy2(&mySettings1.tab, &PerceptualColor::SettingBase::valueChanged); 0149 0150 const QString newTab2 = QStringLiteral("differentTestTabInstance"); 0151 mySettings2.tab.setValue(newTab2); 0152 mySettings2.tab.setValue(newTab2); // Intentional duplicate 0153 QCOMPARE(mySettings1.tab.value(), newTab2); 0154 QCOMPARE(mySettings2.tab.value(), newTab2); 0155 QVERIFY(spy1.isValid()); 0156 // The second call to the setter with an identical value 0157 // should not trigger a signal. 0158 QCOMPARE(spy1.count(), 1); 0159 QVERIFY(spy2.isValid()); 0160 // The second call to the setter with an identical value 0161 // should not trigger a signal. 0162 QCOMPARE(spy2.count(), 1); 0163 } 0164 0165 void testTabExpanded() 0166 { 0167 auto &mySettings = PerceptualSettings::instance(); 0168 0169 const QString newTab1 = QStringLiteral("testTabExpanded"); 0170 mySettings.tabExpanded.setValue(newTab1); 0171 QCOMPARE(mySettings.tabExpanded.value(), newTab1); 0172 0173 QSignalSpy spy(&mySettings.tabExpanded, &PerceptualColor::SettingBase::valueChanged); 0174 0175 const QString newTab2 = QStringLiteral("differentTestTab"); 0176 mySettings.tabExpanded.setValue(newTab2); 0177 mySettings.tabExpanded.setValue(newTab2); // Intentional duplicate 0178 QCOMPARE(mySettings.tabExpanded.value(), newTab2); 0179 QVERIFY(spy.isValid()); 0180 // The second call to the setter with an identical value 0181 // should not trigger a signal. 0182 QCOMPARE(spy.count(), 1); 0183 } 0184 0185 void testInstancesAreIdenticalForTabExpanded() 0186 { 0187 auto &mySettings1 = PerceptualSettings::instance(); 0188 auto &mySettings2 = PerceptualSettings::instance(); 0189 0190 const QString newTabExpanded1 = QStringLiteral("testTabExpandedInstance"); 0191 mySettings1.tabExpanded.setValue(newTabExpanded1); 0192 QCOMPARE(mySettings1.tabExpanded.value(), newTabExpanded1); 0193 QCOMPARE(mySettings2.tabExpanded.value(), newTabExpanded1); 0194 0195 QSignalSpy spy1(&mySettings1.tabExpanded, &PerceptualColor::SettingBase::valueChanged); 0196 QSignalSpy spy2(&mySettings2.tabExpanded, &PerceptualColor::SettingBase::valueChanged); 0197 0198 const QString newTabExpanded2 = QStringLiteral("differentTestTabExpandedInstance"); 0199 mySettings2.tabExpanded.setValue(newTabExpanded2); 0200 mySettings2.tabExpanded.setValue(newTabExpanded2); // Intentional duplicate 0201 QCOMPARE(mySettings1.tabExpanded.value(), newTabExpanded2); 0202 QCOMPARE(mySettings2.tabExpanded.value(), newTabExpanded2); 0203 QVERIFY(spy1.isValid()); 0204 // The second call to the setter with an identical value 0205 // should not trigger a signal. 0206 QCOMPARE(spy1.count(), 1); 0207 QVERIFY(spy2.isValid()); 0208 // The second call to the setter with an identical value 0209 // should not trigger a signal. 0210 QCOMPARE(spy2.count(), 1); 0211 } 0212 0213 #endif 0214 }; 0215 0216 } // namespace PerceptualColor 0217 0218 QTEST_MAIN(PerceptualColor::TestPerceptualSettings) 0219 0220 // The following “include” is necessary because we do not use a header file: 0221 #include "testperceptualsettings.moc"