File indexing completed on 2024-05-12 04:44:21
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 "asyncimageprovider.h" 0007 0008 #include "asyncimagerendercallback.h" 0009 #include <qglobal.h> 0010 #include <qimage.h> 0011 #include <qmetatype.h> 0012 #include <qobject.h> 0013 #include <qtest.h> 0014 #include <qtestcase.h> 0015 #include <qvariant.h> 0016 0017 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0018 #include <qtmetamacros.h> 0019 #else 0020 #include <qobjectdefs.h> 0021 #include <qstring.h> 0022 #endif 0023 0024 //! [How to create] 0025 // Provide a data type that contains 0026 // all necessary data to render the image, 0027 // and a rendering function. 0028 struct MyImageParameters { 0029 public: 0030 // Data members, that contain all necessary 0031 // information to render the image. 0032 int myFirstValue = 0; // Example 0033 int mySecondValue = 0; // Example 0034 0035 // A public constructor, copy constructor 0036 // and destructor are required: 0037 MyImageParameters() = default; 0038 MyImageParameters(const MyImageParameters &) = default; 0039 ~MyImageParameters() = default; 0040 0041 // Define also these functions recommended by “rule of five”: 0042 MyImageParameters &operator=(const MyImageParameters &) = default; // clazy:exclude=function-args-by-value 0043 MyImageParameters &operator=(MyImageParameters &&) = default; 0044 MyImageParameters(MyImageParameters &&) = default; 0045 0046 // An “equal” operator is required: 0047 [[nodiscard]] bool operator==(const MyImageParameters other) const; 0048 0049 // A thread-safe render function with exactly the 0050 // following signature is required: 0051 static void render( 0052 // A QVariant that will contain an object 0053 // of this very same type: 0054 const QVariant &variantParameters, 0055 // A callback object: 0056 PerceptualColor::AsyncImageRenderCallback &callbackObject); 0057 }; 0058 0059 // Use Q_DECLARE_METATYPE with this data type. 0060 // Attention: This must be done outside of all name-spaces. 0061 Q_DECLARE_METATYPE(MyImageParameters) 0062 0063 // Now you are ready to use the image provider: 0064 class MyClass 0065 { 0066 PerceptualColor::AsyncImageProvider<MyImageParameters> myImageProvider; 0067 }; 0068 //! [How to create] 0069 0070 void MyImageParameters::render( // 0071 const QVariant &variantParameters, // 0072 PerceptualColor::AsyncImageRenderCallback &callbackObject) 0073 { 0074 Q_UNUSED(variantParameters) 0075 Q_UNUSED(callbackObject.shouldAbort()) 0076 } 0077 0078 bool MyImageParameters::operator==(const MyImageParameters other) const 0079 { 0080 return ((myFirstValue == other.myFirstValue) // 0081 && (mySecondValue == other.mySecondValue)); 0082 } 0083 0084 struct MockupParameters { 0085 public: 0086 // Some values: 0087 int imageWidth = 1; 0088 bool produceCorrectImage = true; 0089 int arbitraryNumber = 0; 0090 // Equal operator is required: 0091 [[nodiscard]] bool operator==(const MockupParameters other) const 0092 { 0093 return ((imageWidth == other.imageWidth) // 0094 && (arbitraryNumber == other.arbitraryNumber) // 0095 && (produceCorrectImage == other.produceCorrectImage)); 0096 } 0097 static void render( // 0098 const QVariant &variantParameters, // 0099 const PerceptualColor::AsyncImageRenderCallback &callbackObject) 0100 { 0101 Q_UNUSED(variantParameters) 0102 Q_UNUSED(callbackObject) 0103 } 0104 }; 0105 Q_DECLARE_METATYPE(MockupParameters) 0106 0107 namespace PerceptualColor 0108 { 0109 class TestAsyncImageProvider : public QObject 0110 { 0111 Q_OBJECT 0112 0113 public: 0114 explicit TestAsyncImageProvider(QObject *parent = nullptr) 0115 : QObject(parent) 0116 { 0117 } 0118 0119 private Q_SLOTS: 0120 void initTestCase() 0121 { 0122 // Called before the first test function is executed 0123 } 0124 0125 void cleanupTestCase() 0126 { 0127 // Called after the last test function was executed 0128 } 0129 0130 void init() 0131 { 0132 // Called before each test function is executed 0133 } 0134 0135 void cleanup() 0136 { 0137 // Called after every test function 0138 } 0139 0140 #ifndef MSVC_DLL 0141 // The automatic export of otherwise private symbols on MSVC 0142 // shared libraries via CMake's WINDOWS_EXPORT_ALL_SYMBOLS property 0143 // does not work well for Qt meta objects. AsyncImageProvider inherits 0144 // from AsyncImageProviderBase, which relies on Qt meta object 0145 // functionality and whose API is private. Therefore, instantiation of 0146 // AsyncImageProvider is not possible, so the following unit tests cannot 0147 // be built for MSVC shared libraries. 0148 0149 void testMakeSureTheSnippetCorrectlyInstanciatesTheTemplate() 0150 { 0151 MyClass temp; 0152 } 0153 0154 void testConstructorDestructor() 0155 { 0156 // Make sure that constructor and destructor do not crash: 0157 AsyncImageProvider<MockupParameters> test; 0158 } 0159 0160 void testOnExampleImplementationNoCrashGetCache() 0161 { 0162 AsyncImageProvider<MockupParameters> image; 0163 Q_UNUSED(image.getCache()); 0164 } 0165 0166 void testOnExampleImplementationNoCrashImageParameters() 0167 { 0168 AsyncImageProvider<MockupParameters> image; 0169 Q_UNUSED(image.imageParameters()); 0170 } 0171 0172 void testOnExampleImplementationNoCrashRefreshAsync() 0173 { 0174 AsyncImageProvider<MockupParameters> image; 0175 image.refreshAsync(); 0176 } 0177 0178 void testOnExampleImplementationNoCrashRefreshSync() 0179 { 0180 AsyncImageProvider<MockupParameters> image; 0181 image.refreshSync(); 0182 } 0183 0184 void testOnExampleImplementationNoCrashRefreshAsynchSyncMix() 0185 { 0186 AsyncImageProvider<MockupParameters> image; 0187 image.refreshAsync(); 0188 image.refreshSync(); 0189 } 0190 0191 void testOnExampleImplementationNoCrashRefreshAsynchSyncMixMultiple() 0192 { 0193 AsyncImageProvider<MockupParameters> image; 0194 image.refreshAsync(); 0195 image.refreshSync(); 0196 image.refreshAsync(); 0197 image.refreshSync(); 0198 } 0199 0200 void testOnExampleImplementationNoCrashSetImageParameters() 0201 { 0202 AsyncImageProvider<MockupParameters> image; 0203 MockupParameters parameters; 0204 image.setImageParameters(parameters); 0205 } 0206 0207 void testOnExampleImplementationNoCrashProcessInterlacingPassResult() 0208 { 0209 AsyncImageProvider<MockupParameters> image; 0210 image.processInterlacingPassResult(QImage{}); 0211 } 0212 0213 void testImageParameters() 0214 { 0215 AsyncImageProvider<MockupParameters> image; 0216 MockupParameters parameters; 0217 parameters.imageWidth = 3; 0218 image.setImageParameters(parameters); 0219 QCOMPARE(image.imageParameters(), parameters); 0220 parameters.imageWidth = 4; 0221 image.setImageParameters(parameters); 0222 QCOMPARE(image.imageParameters(), parameters); 0223 } 0224 0225 void testDefaultCacheContent() 0226 { 0227 AsyncImageProvider<MockupParameters> image; 0228 // Cache is expected to be empty at startup: 0229 QVERIFY(image.getCache().isNull()); 0230 } 0231 0232 void testGetCache() 0233 { 0234 AsyncImageProvider<MockupParameters> test; 0235 Q_UNUSED(test.getCache()) 0236 } 0237 0238 #endif 0239 }; 0240 0241 } // namespace PerceptualColor 0242 0243 QTEST_MAIN(PerceptualColor::TestAsyncImageProvider) 0244 0245 // The following “include” is necessary because we do not use a header file: 0246 #include "testasyncimageprovider.moc"