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"