aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2020-09-16 13:44:43 +0200
committerTim Jenssen <tim.jenssen@qt.io>2020-10-16 10:01:21 +0000
commitd1b0c12d6b6c4698492851716b3931bc9cae5fd3 (patch)
tree9aa7d8fddbafced065e392b84939c59d6ae8726e /tests
parent58e612c85fb8320fd99a28d573372220cbfe309a (diff)
QmlDesigner: Add image cache
The image cache is saving images and icon of this images in a sqlite database. If there are no images they are generated in the backgound. The icons are fetched by item library. Task-number: QDS-2782 Task-number: QDS-2783 Task-number: QDS-2858 Change-Id: I5a32cccfef7f8fd8eb78902605a09f5da18ce88e Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/unit/mockup/qmldesigner/designercore/include/nodeinstanceview.h6
-rw-r--r--tests/unit/unittest/CMakeLists.txt21
-rw-r--r--tests/unit/unittest/gmock_dependency.pri6
-rw-r--r--tests/unit/unittest/google-using-declarations.h4
-rw-r--r--tests/unit/unittest/gtest-creator-printing.cpp10
-rw-r--r--tests/unit/unittest/gtest-creator-printing.h7
-rw-r--r--tests/unit/unittest/gtest-qt-printing.cpp5
-rw-r--r--tests/unit/unittest/gtest-qt-printing.h2
-rw-r--r--tests/unit/unittest/imagecache-test.cpp326
-rw-r--r--tests/unit/unittest/imagecachecollectormock.h41
-rw-r--r--tests/unit/unittest/imagecachegenerator-test.cpp240
-rw-r--r--tests/unit/unittest/imagecachestorage-test.cpp334
-rw-r--r--tests/unit/unittest/mockimagecachegenerator.h43
-rw-r--r--tests/unit/unittest/mockimagecachestorage.h50
-rw-r--r--tests/unit/unittest/mocktimestampprovider.h36
-rw-r--r--tests/unit/unittest/notification.h56
-rw-r--r--tests/unit/unittest/sqlitedatabasemock.h72
-rw-r--r--tests/unit/unittest/sqlitereadstatementmock.cpp60
-rw-r--r--tests/unit/unittest/sqlitereadstatementmock.h93
-rw-r--r--tests/unit/unittest/sqlitestatement-test.cpp50
-rw-r--r--tests/unit/unittest/sqlitestatementmock.h105
-rw-r--r--tests/unit/unittest/sqlitetransactionbackendmock.h46
-rw-r--r--tests/unit/unittest/sqlitewritestatementmock.cpp35
-rw-r--r--tests/unit/unittest/sqlitewritestatementmock.h84
-rw-r--r--tests/unit/unittest/unittest.pro19
-rw-r--r--tests/unit/unittest/unittest.qbs13
26 files changed, 1725 insertions, 39 deletions
diff --git a/tests/unit/mockup/qmldesigner/designercore/include/nodeinstanceview.h b/tests/unit/mockup/qmldesigner/designercore/include/nodeinstanceview.h
index 50d0e22a2d..50dcf529b6 100644
--- a/tests/unit/mockup/qmldesigner/designercore/include/nodeinstanceview.h
+++ b/tests/unit/mockup/qmldesigner/designercore/include/nodeinstanceview.h
@@ -28,6 +28,10 @@
#include "qmldesignercorelib_global.h"
#include "abstractview.h"
+namespace ProjectExplorer {
+class Target;
+}
+
namespace QmlDesigner {
class NodeInstanceView : public AbstractView
@@ -88,6 +92,8 @@ public:
void requestModelNodePreviewImage(const ModelNode &node) {}
void sendToken(const QString &token, int number, const QVector<ModelNode> &nodeVector) {}
+ void setTarget(ProjectExplorer::Target *newTarget) {}
+ void setCrashCallback(std::function<void()>) {}
};
} // namespace QmlDesigner
diff --git a/tests/unit/unittest/CMakeLists.txt b/tests/unit/unittest/CMakeLists.txt
index ff0c1abaad..13741ae478 100644
--- a/tests/unit/unittest/CMakeLists.txt
+++ b/tests/unit/unittest/CMakeLists.txt
@@ -174,6 +174,19 @@ add_qtc_test(unittest GTEST
sqlstatementbuilder-test.cpp
createtablesqlstatementbuilder-test.cpp
sqlitevalue-test.cpp
+ imagecache-test.cpp
+ imagecachegenerator-test.cpp
+ imagecachestorage-test.cpp
+ sqlitedatabasemock.h
+ sqlitereadstatementmock.cpp sqlitereadstatementmock.h
+ sqlitestatementmock.h
+ sqlitetransactionbackendmock.h
+ sqlitewritestatementmock.cpp sqlitewritestatementmock.h
+ notification.h
+ mocktimestampprovider.h
+ imagecachecollectormock.h
+ mockimagecachegenerator.h
+ mockimagecachestorage.h
)
function(extend_qtc_test_with_target_sources target)
@@ -335,6 +348,7 @@ extend_qtc_test(unittest
"${QmlDesignerDir}"
"${QmlDesignerDir}/designercore"
"${QmlDesignerDir}/designercore/include"
+ "${QmlDesignerDir}/designercore/imagecache"
"${QmlDesignerDir}/../../../share/qtcreator/qml/qmlpuppet/interfaces"
"${QmlDesignerDir}/../../../share/qtcreator/qml/qmlpuppet/types"
DEFINES
@@ -382,6 +396,13 @@ extend_qtc_test(unittest
model/signalhandlerproperty.cpp include/signalhandlerproperty.h
model/variantproperty.cpp include/variantproperty.h
rewritertransaction.cpp rewritertransaction.h
+ imagecache/imagecache.cpp include/imagecache.h
+ imagecache/imagecachecollectorinterface.h
+ imagecache/imagecachegenerator.cpp imagecache/imagecachegenerator.h
+ imagecache/imagecachegeneratorinterface.h
+ imagecache/imagecachestorage.h
+ imagecache/imagecachestorageinterface.h
+ imagecache/timestampproviderinterface.h
include/qmldesignercorelib_global.h
diff --git a/tests/unit/unittest/gmock_dependency.pri b/tests/unit/unittest/gmock_dependency.pri
index 1af7b95f09..614c6379d3 100644
--- a/tests/unit/unittest/gmock_dependency.pri
+++ b/tests/unit/unittest/gmock_dependency.pri
@@ -14,10 +14,8 @@ defineTest(setGoogleTestDirectories) {
}
isEmpty(GOOGLETEST_DIR) {
- exists($$PWD/../../../../googletest) {
- setGoogleTestDirectories($$PWD/../../../../googletest)
- } else: exists($$PWD/../../../../../googletest) {
- setGoogleTestDirectories($$PWD/../../../../../googletest)
+ exists($$PWD/3rdparty/googletest) {
+ setGoogleTestDirectories($$PWD/3rdparty/googletest)
} else: linux {
GTEST_INCLUDE_DIR = /usr/include/gtest
GMOCK_INCLUDE_DIR = /usr/include/gmock
diff --git a/tests/unit/unittest/google-using-declarations.h b/tests/unit/unittest/google-using-declarations.h
index 99514fe9b4..4419c8236d 100644
--- a/tests/unit/unittest/google-using-declarations.h
+++ b/tests/unit/unittest/google-using-declarations.h
@@ -35,12 +35,16 @@ using testing::An;
using testing::AnyNumber;
using testing::AnyOf;
using testing::Assign;
+using testing::AtLeast;
+using testing::AtMost;
+using testing::Between;
using testing::ByMove;
using testing::ByRef;
using testing::ContainerEq;
using testing::Contains;
using testing::ElementsAre;
using testing::Eq;
+using testing::Exactly;
using testing::Field;
using testing::Ge;
using testing::Gt;
diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp
index 8d84ad4d2e..c9c871475d 100644
--- a/tests/unit/unittest/gtest-creator-printing.cpp
+++ b/tests/unit/unittest/gtest-creator-printing.cpp
@@ -70,6 +70,7 @@
#include <usedmacro.h>
#include <utils/link.h>
#include <variantproperty.h>
+#include <qmldesigner/designercore/imagecache/imagecachestorageinterface.h>
#include <sqlite3ext.h>
@@ -1468,6 +1469,15 @@ std::ostream &operator<<(std::ostream &out, const VariantProperty &property)
return out << "(" << property.parentModelNode() << ", " << property.name() << ", "
<< property.value() << ")";
}
+
+namespace Internal {
+std::ostream &operator<<(std::ostream &out, const ImageCacheStorageEntry &entry)
+{
+ return out << "(" << entry.image << ", " << entry.hasEntry << ")";
+}
+
+} // namespace Internal
+
} // namespace QmlDesigner
void setFilePathCache(ClangBackEnd::FilePathCaching *cache)
diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h
index 565479be03..cdef782578 100644
--- a/tests/unit/unittest/gtest-creator-printing.h
+++ b/tests/unit/unittest/gtest-creator-printing.h
@@ -356,6 +356,13 @@ class VariantProperty;
std::ostream &operator<<(std::ostream &out, const ModelNode &node);
std::ostream &operator<<(std::ostream &out, const VariantProperty &property);
+
+namespace Internal {
+class ImageCacheStorageEntry;
+
+std::ostream &operator<<(std::ostream &out, const ImageCacheStorageEntry &entry);
+
+} // namespace Internal
} // namespace QmlDesigner
void setFilePathCache(ClangBackEnd::FilePathCaching *filePathCache);
diff --git a/tests/unit/unittest/gtest-qt-printing.cpp b/tests/unit/unittest/gtest-qt-printing.cpp
index c097fd0b4c..445ebf7f51 100644
--- a/tests/unit/unittest/gtest-qt-printing.cpp
+++ b/tests/unit/unittest/gtest-qt-printing.cpp
@@ -85,6 +85,11 @@ std::ostream &operator<<(std::ostream &out, const QTextCharFormat &format)
return out;
}
+std::ostream &operator<<(std::ostream &out, const QImage &image)
+{
+ return out << "(" << image.width() << ", " << image.height() << ", " << image.format() << ")";
+}
+
void PrintTo(const QString &text, std::ostream *os)
{
*os << text;
diff --git a/tests/unit/unittest/gtest-qt-printing.h b/tests/unit/unittest/gtest-qt-printing.h
index ebaeb2c785..54db4ee105 100644
--- a/tests/unit/unittest/gtest-qt-printing.h
+++ b/tests/unit/unittest/gtest-qt-printing.h
@@ -34,11 +34,13 @@ QT_BEGIN_NAMESPACE
class QVariant;
class QString;
class QTextCharFormat;
+class QImage;
std::ostream &operator<<(std::ostream &out, const QVariant &QVariant);
std::ostream &operator<<(std::ostream &out, const QString &text);
std::ostream &operator<<(std::ostream &out, const QByteArray &byteArray);
std::ostream &operator<<(std::ostream &out, const QTextCharFormat &format);
+std::ostream &operator<<(std::ostream &out, const QImage &image);
void PrintTo(const QString &text, std::ostream *os);
void PrintTo(const QVariant &variant, std::ostream *os);
diff --git a/tests/unit/unittest/imagecache-test.cpp b/tests/unit/unittest/imagecache-test.cpp
new file mode 100644
index 0000000000..4219335774
--- /dev/null
+++ b/tests/unit/unittest/imagecache-test.cpp
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+
+#include "mockimagecachegenerator.h"
+#include "mockimagecachestorage.h"
+#include "mocktimestampprovider.h"
+#include "notification.h"
+
+#include <imagecache.h>
+
+namespace {
+
+class ImageCache : public testing::Test
+{
+protected:
+ Notification notification;
+ Notification waitInThread;
+ NiceMock<MockImageCacheStorage> mockStorage;
+ NiceMock<MockImageCacheGenerator> mockGenerator;
+ NiceMock<MockTimeStampProvider> mockTimeStampProvider;
+ QmlDesigner::ImageCache cache{mockStorage, mockGenerator, mockTimeStampProvider};
+ NiceMock<MockFunction<void()>> mockAbortCallback;
+ NiceMock<MockFunction<void(const QImage &image)>> mockCaptureCallback;
+ QImage image1{10, 10, QImage::Format_ARGB32};
+};
+
+TEST_F(ImageCache, RequestImageFetchesImageFromStorage)
+{
+ EXPECT_CALL(mockStorage, fetchImage(Eq("/path/to/Component.qml"), _))
+ .WillRepeatedly([&](Utils::SmallStringView, auto) {
+ notification.notify();
+ return QmlDesigner::ImageCacheStorageInterface::Entry{{}, false};
+ });
+
+ cache.requestImage("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, RequestImageFetchesImageFromStorageWithTimeStamp)
+{
+ EXPECT_CALL(mockTimeStampProvider, timeStamp(Eq("/path/to/Component.qml")))
+ .WillRepeatedly(Return(Sqlite::TimeStamp{123}));
+ EXPECT_CALL(mockStorage, fetchImage(Eq("/path/to/Component.qml"), Eq(Sqlite::TimeStamp{123})))
+ .WillRepeatedly([&](Utils::SmallStringView, auto) {
+ notification.notify();
+ return QmlDesigner::ImageCacheStorageInterface::Entry{QImage{}, false};
+ });
+
+ cache.requestImage("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, RequestImageCallsCaptureCallbackWithImageFromStorage)
+{
+ ON_CALL(mockStorage, fetchImage(Eq("/path/to/Component.qml"), _))
+ .WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::Entry{image1, true}));
+
+ EXPECT_CALL(mockCaptureCallback, Call(Eq(image1))).WillRepeatedly([&](const QImage &) {
+ notification.notify();
+ });
+
+ cache.requestImage("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, RequestImageCallsAbortCallbackWithoutImage)
+{
+ ON_CALL(mockStorage, fetchImage(Eq("/path/to/Component.qml"), _))
+ .WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::Entry{QImage{}, true}));
+
+ EXPECT_CALL(mockAbortCallback, Call()).WillRepeatedly([&] { notification.notify(); });
+
+ cache.requestImage("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, RequestImageRequestImageFromGenerator)
+{
+ ON_CALL(mockTimeStampProvider, timeStamp(Eq("/path/to/Component.qml")))
+ .WillByDefault(Return(Sqlite::TimeStamp{123}));
+
+ EXPECT_CALL(mockGenerator,
+ generateImage(Eq("/path/to/Component.qml"), Eq(Sqlite::TimeStamp{123}), _, _))
+ .WillRepeatedly([&](auto &&, auto, auto &&callback, auto) { notification.notify(); });
+
+ cache.requestImage("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, RequestImageCallsCaptureCallbackWithImageFromGenerator)
+{
+ ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _))
+ .WillByDefault([&](auto &&, auto, auto &&callback, auto) {
+ callback(QImage{image1});
+ notification.notify();
+ });
+
+ EXPECT_CALL(mockCaptureCallback, Call(Eq(image1)));
+
+ cache.requestImage("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, RequestImageCallsAbortCallbackFromGenerator)
+{
+ ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _))
+ .WillByDefault([&](auto &&, auto, auto &&, auto &&abortCallback) {
+ abortCallback();
+ notification.notify();
+ });
+
+ EXPECT_CALL(mockAbortCallback, Call());
+
+ cache.requestImage("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, RequestIconFetchesIconFromStorage)
+{
+ EXPECT_CALL(mockStorage, fetchIcon(Eq("/path/to/Component.qml"), _))
+ .WillRepeatedly([&](Utils::SmallStringView, auto) {
+ notification.notify();
+ return QmlDesigner::ImageCacheStorageInterface::Entry{{}, false};
+ });
+
+ cache.requestIcon("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, RequestIconFetchesIconFromStorageWithTimeStamp)
+{
+ EXPECT_CALL(mockTimeStampProvider, timeStamp(Eq("/path/to/Component.qml")))
+ .WillRepeatedly(Return(Sqlite::TimeStamp{123}));
+ EXPECT_CALL(mockStorage, fetchIcon(Eq("/path/to/Component.qml"), Eq(Sqlite::TimeStamp{123})))
+ .WillRepeatedly([&](Utils::SmallStringView, auto) {
+ notification.notify();
+ return QmlDesigner::ImageCacheStorageInterface::Entry{QImage{}, false};
+ });
+
+ cache.requestIcon("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, RequestIconCallsCaptureCallbackWithImageFromStorage)
+{
+ ON_CALL(mockStorage, fetchIcon(Eq("/path/to/Component.qml"), _))
+ .WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::Entry{image1, true}));
+
+ EXPECT_CALL(mockCaptureCallback, Call(Eq(image1))).WillRepeatedly([&](const QImage &) {
+ notification.notify();
+ });
+
+ cache.requestIcon("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, RequestIconCallsAbortCallbackWithoutIcon)
+{
+ ON_CALL(mockStorage, fetchIcon(Eq("/path/to/Component.qml"), _))
+ .WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::Entry{QImage{}, true}));
+
+ EXPECT_CALL(mockAbortCallback, Call()).WillRepeatedly([&] { notification.notify(); });
+
+ cache.requestIcon("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, RequestIconRequestImageFromGenerator)
+{
+ ON_CALL(mockTimeStampProvider, timeStamp(Eq("/path/to/Component.qml")))
+ .WillByDefault(Return(Sqlite::TimeStamp{123}));
+
+ EXPECT_CALL(mockGenerator,
+ generateImage(Eq("/path/to/Component.qml"), Eq(Sqlite::TimeStamp{123}), _, _))
+ .WillRepeatedly([&](auto &&, auto, auto &&callback, auto) { notification.notify(); });
+
+ cache.requestIcon("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, RequestIconCallsCaptureCallbackWithImageFromGenerator)
+{
+ ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _))
+ .WillByDefault([&](auto &&, auto, auto &&callback, auto) {
+ callback(QImage{image1});
+ notification.notify();
+ });
+
+ EXPECT_CALL(mockCaptureCallback, Call(Eq(image1)));
+
+ cache.requestIcon("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, RequestIconCallsAbortCallbackFromGenerator)
+{
+ ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _))
+ .WillByDefault([&](auto &&, auto, auto &&, auto &&abortCallback) {
+ abortCallback();
+ notification.notify();
+ });
+
+ EXPECT_CALL(mockAbortCallback, Call());
+
+ cache.requestIcon("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCache, CleanRemovesEntries)
+{
+ EXPECT_CALL(mockGenerator, generateImage(Eq("/path/to/Component1.qml"), _, _, _))
+ .WillRepeatedly([&](auto &&, auto, auto &&mockCaptureCallback, auto &&) {
+ mockCaptureCallback(QImage{});
+ waitInThread.wait();
+ });
+ EXPECT_CALL(mockGenerator, generateImage(_, _, _, _))
+ .WillRepeatedly([&](auto &&, auto, auto &&mockCaptureCallback, auto &&) {
+ mockCaptureCallback(QImage{});
+ });
+ cache.requestIcon("/path/to/Component1.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+
+ EXPECT_CALL(mockCaptureCallback, Call(_)).Times(AtMost(1));
+
+ cache.requestIcon("/path/to/Component3.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ cache.clean();
+ waitInThread.notify();
+}
+
+TEST_F(ImageCache, CleanCallsAbort)
+{
+ ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component1.qml"), _, _, _))
+ .WillByDefault(
+ [&](auto &&, auto, auto &&mockCaptureCallback, auto &&) { waitInThread.wait(); });
+ cache.requestIcon("/path/to/Component1.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ cache.requestIcon("/path/to/Component2.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+
+ EXPECT_CALL(mockAbortCallback, Call()).Times(AtLeast(2));
+
+ cache.requestIcon("/path/to/Component3.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ cache.clean();
+ waitInThread.notify();
+}
+
+TEST_F(ImageCache, CleanCallsGeneratorClean)
+{
+ EXPECT_CALL(mockGenerator, clean()).Times(AtLeast(1));
+
+ cache.clean();
+}
+
+TEST_F(ImageCache, AfterCleanNewJobsWorks)
+{
+ cache.clean();
+
+ EXPECT_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _))
+ .WillRepeatedly([&](auto &&, auto, auto &&, auto &&) { notification.notify(); });
+
+ cache.requestIcon("/path/to/Component.qml",
+ mockCaptureCallback.AsStdFunction(),
+ mockAbortCallback.AsStdFunction());
+ notification.wait();
+}
+
+} // namespace
diff --git a/tests/unit/unittest/imagecachecollectormock.h b/tests/unit/unittest/imagecachecollectormock.h
new file mode 100644
index 0000000000..93520c418d
--- /dev/null
+++ b/tests/unit/unittest/imagecachecollectormock.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "googletest.h"
+
+#include <imagecachecollectorinterface.h>
+
+class ImageCacheCollectorMock : public QmlDesigner::ImageCacheCollectorInterface
+{
+public:
+ MOCK_METHOD(void,
+ start,
+ (Utils::SmallStringView filePath,
+ ImageCacheCollectorInterface::CaptureCallback captureCallback,
+ ImageCacheCollectorInterface::AbortCallback abortCallback),
+ (override));
+};
diff --git a/tests/unit/unittest/imagecachegenerator-test.cpp b/tests/unit/unittest/imagecachegenerator-test.cpp
new file mode 100644
index 0000000000..f152bd83ad
--- /dev/null
+++ b/tests/unit/unittest/imagecachegenerator-test.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+
+#include "imagecachecollectormock.h"
+#include "mockimagecachestorage.h"
+#include "notification.h"
+
+#include <imagecachegenerator.h>
+
+#include <mutex>
+
+namespace {
+
+class ImageCacheGenerator : public testing::Test
+{
+protected:
+ template<typename Callable, typename... Arguments>
+ static void executeAsync(Callable &&call, Arguments... arguments)
+ {
+ std::thread thread(
+ [](Callable &&call, Arguments... arguments) {
+ call(std::forward<Arguments>(arguments)...);
+ },
+ std::forward<Callable>(call),
+ std::forward<Arguments>(arguments)...);
+ thread.detach();
+ }
+
+protected:
+ Notification waitInThread;
+ Notification notification;
+ QImage image1{10, 10, QImage::Format_ARGB32};
+ NiceMock<MockFunction<void(const QImage &)>> imageCallbackMock;
+ NiceMock<MockFunction<void()>> abortCallbackMock;
+ NiceMock<ImageCacheCollectorMock> collectorMock;
+ NiceMock<MockImageCacheStorage> storageMock;
+ QmlDesigner::ImageCacheGenerator generator{collectorMock, storageMock};
+};
+
+TEST_F(ImageCacheGenerator, CallsCollectorWithCaptureCallback)
+{
+ EXPECT_CALL(collectorMock, start(Eq("name"), _, _))
+ .WillRepeatedly([&](auto, auto captureCallback, auto) { captureCallback(QImage{image1}); });
+ EXPECT_CALL(imageCallbackMock, Call(_)).WillRepeatedly([&](const QImage &) {
+ notification.notify();
+ });
+
+ generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {});
+ notification.wait();
+}
+
+TEST_F(ImageCacheGenerator, CallsCollectorOnlyIfNotProcessing)
+{
+ EXPECT_CALL(collectorMock, start(Eq("name"), _, _)).WillRepeatedly([&](auto, auto, auto) {
+ notification.notify();
+ });
+
+ generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {});
+ generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {});
+ notification.wait(2);
+}
+
+TEST_F(ImageCacheGenerator, ProcessTaskAfterFirstFinished)
+{
+ ON_CALL(imageCallbackMock, Call(_)).WillByDefault([&](const QImage &) { notification.notify(); });
+
+ EXPECT_CALL(collectorMock, start(Eq("name"), _, _)).WillOnce([&](auto, auto captureCallback, auto) {
+ captureCallback(QImage{image1});
+ });
+ EXPECT_CALL(collectorMock, start(Eq("name2"), _, _)).WillOnce([&](auto, auto captureCallback, auto) {
+ captureCallback(QImage{image1});
+ });
+
+ generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {});
+ generator.generateImage("name2", {}, imageCallbackMock.AsStdFunction(), {});
+ notification.wait(2);
+}
+
+TEST_F(ImageCacheGenerator, DontCrashAtDestructingGenerator)
+{
+ ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
+ captureCallback(QImage{image1});
+ });
+
+ generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {});
+ generator.generateImage("name2", {}, imageCallbackMock.AsStdFunction(), {});
+ generator.generateImage("name3", {}, imageCallbackMock.AsStdFunction(), {});
+ generator.generateImage("name4", {}, imageCallbackMock.AsStdFunction(), {});
+}
+
+TEST_F(ImageCacheGenerator, StoreImage)
+{
+ ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
+ captureCallback(QImage{image1});
+ });
+
+ EXPECT_CALL(storageMock, storeImage(Eq("name"), Eq(Sqlite::TimeStamp{11}), Eq(image1)))
+ .WillRepeatedly([&](auto, auto, auto) { notification.notify(); });
+
+ generator.generateImage("name", {11}, imageCallbackMock.AsStdFunction(), {});
+ notification.wait();
+}
+
+TEST_F(ImageCacheGenerator, StoreNullImage)
+{
+ ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
+ captureCallback(QImage{});
+ });
+
+ EXPECT_CALL(storageMock, storeImage(Eq("name"), Eq(Sqlite::TimeStamp{11}), Eq(QImage{})))
+ .WillRepeatedly([&](auto, auto, auto) { notification.notify(); });
+
+ generator.generateImage("name",
+ {11},
+ imageCallbackMock.AsStdFunction(),
+ abortCallbackMock.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCacheGenerator, AbortCallback)
+{
+ ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
+ captureCallback(QImage{image1});
+ });
+ ON_CALL(collectorMock, start(Eq("name2"), _, _)).WillByDefault([&](auto, auto, auto abortCallback) {
+ abortCallback();
+ });
+
+ EXPECT_CALL(imageCallbackMock, Call(_)).WillOnce([&](const QImage &) { notification.notify(); });
+ EXPECT_CALL(abortCallbackMock, Call()).WillOnce([&]() { notification.notify(); });
+
+ generator.generateImage("name",
+ {},
+ imageCallbackMock.AsStdFunction(),
+ abortCallbackMock.AsStdFunction());
+ generator.generateImage("name2",
+ {},
+ imageCallbackMock.AsStdFunction(),
+ abortCallbackMock.AsStdFunction());
+ notification.wait(2);
+}
+
+TEST_F(ImageCacheGenerator, StoreNullImageForAbortCallback)
+{
+ ON_CALL(collectorMock, start(_, _, _)).WillByDefault([&](auto, auto, auto abortCallback) {
+ abortCallback();
+ notification.notify();
+ });
+
+ EXPECT_CALL(abortCallbackMock, Call()).WillOnce([&]() { notification.notify(); });
+ EXPECT_CALL(storageMock, storeImage(Eq("name"), Eq(Sqlite::TimeStamp{11}), Eq(QImage{})));
+
+ generator.generateImage("name",
+ {11},
+ imageCallbackMock.AsStdFunction(),
+ abortCallbackMock.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCacheGenerator, AbortForEmptyImage)
+{
+ NiceMock<MockFunction<void()>> abortCallbackMock;
+ ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
+ captureCallback(QImage{});
+ });
+
+ EXPECT_CALL(abortCallbackMock, Call()).WillOnce([&]() { notification.notify(); });
+
+ generator.generateImage("name",
+ {},
+ imageCallbackMock.AsStdFunction(),
+ abortCallbackMock.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCacheGenerator, CallWalCheckpointFullIfQueueIsEmpty)
+{
+ ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
+ captureCallback({});
+ });
+
+ EXPECT_CALL(storageMock, walCheckpointFull()).WillRepeatedly([&]() { notification.notify(); });
+
+ generator.generateImage("name",
+ {11},
+ imageCallbackMock.AsStdFunction(),
+ abortCallbackMock.AsStdFunction());
+ generator.generateImage("name2",
+ {11},
+ imageCallbackMock.AsStdFunction(),
+ abortCallbackMock.AsStdFunction());
+ notification.wait();
+}
+
+TEST_F(ImageCacheGenerator, Clean)
+{
+ ON_CALL(collectorMock, start(_, _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
+ captureCallback({});
+ waitInThread.wait();
+ });
+ generator.generateImage("name",
+ {11},
+ imageCallbackMock.AsStdFunction(),
+ abortCallbackMock.AsStdFunction());
+ generator.generateImage("name2",
+ {11},
+ imageCallbackMock.AsStdFunction(),
+ abortCallbackMock.AsStdFunction());
+
+ EXPECT_CALL(imageCallbackMock, Call(_)).Times(0);
+
+ generator.clean();
+ waitInThread.notify();
+}
+
+} // namespace
diff --git a/tests/unit/unittest/imagecachestorage-test.cpp b/tests/unit/unittest/imagecachestorage-test.cpp
new file mode 100644
index 0000000000..aaf30526b6
--- /dev/null
+++ b/tests/unit/unittest/imagecachestorage-test.cpp
@@ -0,0 +1,334 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+
+#include "sqlitedatabasemock.h"
+
+#include <imagecachestorage.h>
+#include <sqlitedatabase.h>
+
+namespace {
+
+MATCHER_P2(IsEntry,
+ image,
+ hasEntry,
+ std::string(negation ? "is't" : "is")
+ + PrintToString(QmlDesigner::ImageCacheStorageInterface::Entry{image, hasEntry}))
+{
+ const QmlDesigner::ImageCacheStorageInterface::Entry &entry = arg;
+ return entry.image == image && entry.hasEntry == hasEntry;
+}
+
+class ImageCacheStorageTest : public testing::Test
+{
+protected:
+ QImage createImage()
+ {
+ QImage image{150, 150, QImage::Format_ARGB32};
+ image.fill(QColor{128, 64, 0, 11});
+ image.setPixelColor(75, 75, QColor{1, 255, 33, 196});
+
+ return image;
+ }
+
+protected:
+ using ReadStatement = QmlDesigner::ImageCacheStorage<SqliteDatabaseMock>::ReadStatement;
+ using WriteStatement = QmlDesigner::ImageCacheStorage<SqliteDatabaseMock>::WriteStatement;
+
+ NiceMock<SqliteDatabaseMock> databaseMock;
+ QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock};
+ ReadStatement &selectImageStatement = storage.selectImageStatement;
+ ReadStatement &selectIconStatement = storage.selectIconStatement;
+ WriteStatement &upsertImageStatement = storage.upsertImageStatement;
+ QImage image1{createImage()};
+};
+
+TEST_F(ImageCacheStorageTest, Initialize)
+{
+ InSequence s;
+
+ EXPECT_CALL(databaseMock, exclusiveBegin());
+ EXPECT_CALL(databaseMock,
+ execute(Eq("CREATE TABLE IF NOT EXISTS images(id INTEGER PRIMARY KEY, name TEXT "
+ "NOT NULL UNIQUE, mtime INTEGER, image BLOB, icon BLOB)")));
+ EXPECT_CALL(databaseMock, commit());
+ EXPECT_CALL(databaseMock, immediateBegin());
+ EXPECT_CALL(databaseMock, prepare(Eq(selectImageStatement.sqlStatement)));
+ EXPECT_CALL(databaseMock, prepare(Eq(selectIconStatement.sqlStatement)));
+ EXPECT_CALL(databaseMock, prepare(Eq(upsertImageStatement.sqlStatement)));
+ EXPECT_CALL(databaseMock, commit());
+
+ QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock};
+}
+
+TEST_F(ImageCacheStorageTest, FetchImageCalls)
+{
+ InSequence s;
+
+ EXPECT_CALL(databaseMock, deferredBegin());
+ EXPECT_CALL(selectImageStatement,
+ valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
+ TypedEq<long long>(123)));
+ EXPECT_CALL(databaseMock, commit());
+
+ storage.fetchImage("/path/to/component", {123});
+}
+
+TEST_F(ImageCacheStorageTest, FetchImageCallsIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(databaseMock, deferredBegin());
+ EXPECT_CALL(selectImageStatement,
+ valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
+ TypedEq<long long>(123)))
+ .WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
+ EXPECT_CALL(databaseMock, rollback());
+ EXPECT_CALL(databaseMock, deferredBegin());
+ EXPECT_CALL(selectImageStatement,
+ valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
+ TypedEq<long long>(123)));
+ EXPECT_CALL(databaseMock, commit());
+
+ storage.fetchImage("/path/to/component", {123});
+}
+
+TEST_F(ImageCacheStorageTest, FetchIconCalls)
+{
+ InSequence s;
+
+ EXPECT_CALL(databaseMock, deferredBegin());
+ EXPECT_CALL(selectIconStatement,
+ valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
+ TypedEq<long long>(123)));
+ EXPECT_CALL(databaseMock, commit());
+
+ storage.fetchIcon("/path/to/component", {123});
+}
+
+TEST_F(ImageCacheStorageTest, FetchIconCallsIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(databaseMock, deferredBegin());
+ EXPECT_CALL(selectIconStatement,
+ valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
+ TypedEq<long long>(123)))
+ .WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
+ EXPECT_CALL(databaseMock, rollback());
+ EXPECT_CALL(databaseMock, deferredBegin());
+ EXPECT_CALL(selectIconStatement,
+ valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
+ TypedEq<long long>(123)));
+ EXPECT_CALL(databaseMock, commit());
+
+ storage.fetchIcon("/path/to/component", {123});
+}
+
+TEST_F(ImageCacheStorageTest, StoreImageCalls)
+{
+ InSequence s;
+
+ EXPECT_CALL(databaseMock, immediateBegin());
+ EXPECT_CALL(upsertImageStatement,
+ write(TypedEq<Utils::SmallStringView>("/path/to/component"),
+ TypedEq<long long>(123),
+ A<Sqlite::BlobView>(),
+ A<Sqlite::BlobView>()));
+ EXPECT_CALL(databaseMock, commit());
+
+ storage.storeImage("/path/to/component", {123}, image1);
+}
+
+TEST_F(ImageCacheStorageTest, StoreEmptyImageCalls)
+{
+ InSequence s;
+
+ EXPECT_CALL(databaseMock, immediateBegin());
+ EXPECT_CALL(upsertImageStatement,
+ write(TypedEq<Utils::SmallStringView>("/path/to/component"),
+ TypedEq<long long>(123),
+ A<Sqlite::NullValue>(),
+ A<Sqlite::NullValue>()));
+ EXPECT_CALL(databaseMock, commit());
+
+ storage.storeImage("/path/to/component", {123}, QImage{});
+}
+
+TEST_F(ImageCacheStorageTest, StoreImageCallsIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(databaseMock, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
+ EXPECT_CALL(databaseMock, immediateBegin());
+ EXPECT_CALL(upsertImageStatement,
+ write(TypedEq<Utils::SmallStringView>("/path/to/component"),
+ TypedEq<long long>(123),
+ A<Sqlite::NullValue>(),
+ A<Sqlite::NullValue>()));
+ EXPECT_CALL(databaseMock, commit());
+
+ storage.storeImage("/path/to/component", {123}, QImage{});
+}
+
+TEST_F(ImageCacheStorageTest, CallWalCheckointFull)
+{
+ EXPECT_CALL(databaseMock, walCheckpointFull());
+
+ storage.walCheckpointFull();
+}
+
+TEST_F(ImageCacheStorageTest, CallWalCheckointFullIsBusy)
+{
+ InSequence s;
+
+ EXPECT_CALL(databaseMock, walCheckpointFull()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
+ EXPECT_CALL(databaseMock, walCheckpointFull());
+
+ storage.walCheckpointFull();
+}
+
+class ImageCacheStorageSlowTest : public testing::Test
+{
+protected:
+ QImage createImage()
+ {
+ QImage image{150, 150, QImage::Format_ARGB32};
+ image.fill(QColor{128, 64, 0, 11});
+ image.setPixelColor(1, 1, QColor{1, 255, 33, 196});
+
+ return image;
+ }
+
+protected:
+ Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
+ QmlDesigner::ImageCacheStorage<Sqlite::Database> storage{database};
+ QImage image1{createImage()};
+ QImage image2{10, 10, QImage::Format_ARGB32};
+ QImage icon1{image1.scaled(96, 96)};
+};
+
+TEST_F(ImageCacheStorageSlowTest, StoreImage)
+{
+ storage.storeImage("/path/to/component", {123}, image1);
+
+ ASSERT_THAT(storage.fetchImage("/path/to/component", {123}), IsEntry(image1, true));
+}
+
+TEST_F(ImageCacheStorageSlowTest, StoreEmptyImageAfterEntry)
+{
+ storage.storeImage("/path/to/component", {123}, image1);
+
+ storage.storeImage("/path/to/component", {123}, QImage{});
+
+ ASSERT_THAT(storage.fetchImage("/path/to/component", {123}), IsEntry(QImage{}, true));
+}
+
+TEST_F(ImageCacheStorageSlowTest, StoreEmptyEntry)
+{
+ storage.storeImage("/path/to/component", {123}, QImage{});
+
+ ASSERT_THAT(storage.fetchImage("/path/to/component", {123}), IsEntry(QImage{}, true));
+}
+
+TEST_F(ImageCacheStorageSlowTest, FetchNonExistingImageIsEmpty)
+{
+ auto image = storage.fetchImage("/path/to/component", {123});
+
+ ASSERT_THAT(image, IsEntry(QImage{}, false));
+}
+
+TEST_F(ImageCacheStorageSlowTest, FetchSameTimeImage)
+{
+ storage.storeImage("/path/to/component", {123}, image1);
+
+ auto image = storage.fetchImage("/path/to/component", {123});
+
+ ASSERT_THAT(image, IsEntry(image1, true));
+}
+
+TEST_F(ImageCacheStorageSlowTest, DoNotFetchOlderImage)
+{
+ storage.storeImage("/path/to/component", {123}, image1);
+
+ auto image = storage.fetchImage("/path/to/component", {124});
+
+ ASSERT_THAT(image, IsEntry(QImage{}, false));
+}
+
+TEST_F(ImageCacheStorageSlowTest, FetchNewerImage)
+{
+ storage.storeImage("/path/to/component", {123}, image1);
+
+ auto image = storage.fetchImage("/path/to/component", {122});
+
+ ASSERT_THAT(image, IsEntry(image1, true));
+}
+
+TEST_F(ImageCacheStorageSlowTest, FetchNonExistingIconIsEmpty)
+{
+ auto image = storage.fetchIcon("/path/to/component", {123});
+
+ ASSERT_THAT(image, IsEntry(QImage{}, false));
+}
+
+TEST_F(ImageCacheStorageSlowTest, FetchSameTimeIcon)
+{
+ storage.storeImage("/path/to/component", {123}, image1);
+
+ auto image = storage.fetchIcon("/path/to/component", {123});
+
+ ASSERT_THAT(image, IsEntry(icon1, true));
+}
+
+TEST_F(ImageCacheStorageSlowTest, DoNotFetchOlderIcon)
+{
+ storage.storeImage("/path/to/component", {123}, image1);
+
+ auto image = storage.fetchIcon("/path/to/component", {124});
+
+ ASSERT_THAT(image, IsEntry(QImage{}, false));
+}
+
+TEST_F(ImageCacheStorageSlowTest, FetchNewerIcon)
+{
+ storage.storeImage("/path/to/component", {123}, image1);
+
+ auto image = storage.fetchIcon("/path/to/component", {122});
+
+ ASSERT_THAT(image, IsEntry(icon1, true));
+}
+
+TEST_F(ImageCacheStorageSlowTest, DontScaleSmallerIcon)
+{
+ storage.storeImage("/path/to/component", {123}, image2);
+
+ auto image = storage.fetchImage("/path/to/component", {122});
+
+ ASSERT_THAT(image, IsEntry(image2, true));
+}
+
+} // namespace
diff --git a/tests/unit/unittest/mockimagecachegenerator.h b/tests/unit/unittest/mockimagecachegenerator.h
new file mode 100644
index 0000000000..ffe8d9c709
--- /dev/null
+++ b/tests/unit/unittest/mockimagecachegenerator.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "googletest.h"
+
+#include <imagecachegeneratorinterface.h>
+
+class MockImageCacheGenerator : public QmlDesigner::ImageCacheGeneratorInterface
+{
+public:
+ MOCK_METHOD(void,
+ generateImage,
+ (Utils::SmallStringView name,
+ Sqlite::TimeStamp timeStamp,
+ CaptureCallback &&captureCallback,
+ AbortCallback &&abortCallback),
+ (override));
+ MOCK_METHOD(void, clean, (), (override));
+};
diff --git a/tests/unit/unittest/mockimagecachestorage.h b/tests/unit/unittest/mockimagecachestorage.h
new file mode 100644
index 0000000000..add2cfaa96
--- /dev/null
+++ b/tests/unit/unittest/mockimagecachestorage.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "googletest.h"
+
+#include <imagecachestorageinterface.h>
+
+class MockImageCacheStorage : public QmlDesigner::ImageCacheStorageInterface
+{
+public:
+ MOCK_METHOD(QmlDesigner::ImageCacheStorageInterface::Entry,
+ fetchImage,
+ (Utils::SmallStringView name, Sqlite::TimeStamp minimumTimeStamp),
+ (const, override));
+
+ MOCK_METHOD(QmlDesigner::ImageCacheStorageInterface::Entry,
+ fetchIcon,
+ (Utils::SmallStringView name, Sqlite::TimeStamp minimumTimeStamp),
+ (const, override));
+
+ MOCK_METHOD(void,
+ storeImage,
+ (Utils::SmallStringView name, Sqlite::TimeStamp newTimeStamp, const QImage &image),
+ (override));
+ MOCK_METHOD(void, walCheckpointFull, (), (override));
+};
diff --git a/tests/unit/unittest/mocktimestampprovider.h b/tests/unit/unittest/mocktimestampprovider.h
new file mode 100644
index 0000000000..0adad4c030
--- /dev/null
+++ b/tests/unit/unittest/mocktimestampprovider.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "googletest.h"
+
+#include <timestampproviderinterface.h>
+
+class MockTimeStampProvider : public QmlDesigner::TimeStampProviderInterface
+{
+public:
+ MOCK_METHOD(Sqlite::TimeStamp, timeStamp, (Utils::SmallStringView name), (const, override));
+};
diff --git a/tests/unit/unittest/notification.h b/tests/unit/unittest/notification.h
new file mode 100644
index 0000000000..a27d9acb76
--- /dev/null
+++ b/tests/unit/unittest/notification.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "googletest.h"
+
+#include <condition_variable>
+#include <mutex>
+
+class Notification
+{
+public:
+ void wait(int count = 1)
+ {
+ std::unique_lock<std::mutex> lock{m_mutex};
+ m_waitCount += count;
+ if (m_waitCount > 0)
+ m_condition.wait(lock, [&] { return m_waitCount <= 0; });
+ }
+
+ void notify()
+ {
+ {
+ std::unique_lock<std::mutex> lock{m_mutex};
+ --m_waitCount;
+ }
+
+ m_condition.notify_all();
+ }
+
+private:
+ std::mutex m_mutex;
+ std::condition_variable m_condition;
+ int m_waitCount = 0;
+};
diff --git a/tests/unit/unittest/sqlitedatabasemock.h b/tests/unit/unittest/sqlitedatabasemock.h
new file mode 100644
index 0000000000..8c1179e424
--- /dev/null
+++ b/tests/unit/unittest/sqlitedatabasemock.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "googletest.h"
+
+#include "sqlitereadstatementmock.h"
+#include "sqlitetransactionbackendmock.h"
+#include "sqlitewritestatementmock.h"
+
+#include <sqlitedatabaseinterface.h>
+#include <sqlitetable.h>
+#include <sqlitetransaction.h>
+
+#include <utils/smallstringview.h>
+
+class SqliteDatabaseMock : public SqliteTransactionBackendMock, public Sqlite::DatabaseInterface
+{
+public:
+ using ReadStatement = NiceMock<SqliteReadStatementMock>;
+ using WriteStatement = NiceMock<SqliteWriteStatementMock>;
+
+ MOCK_METHOD(void, prepare, (Utils::SmallStringView sqlStatement), ());
+
+ MOCK_METHOD(void, execute, (Utils::SmallStringView sqlStatement), ());
+
+ MOCK_METHOD(int64_t, lastInsertedRowId, (), (const));
+
+ MOCK_METHOD(void, setLastInsertedRowId, (int64_t), (const));
+
+ MOCK_METHOD(bool, isInitialized, (), (const));
+
+ MOCK_METHOD(void, setIsInitialized, (bool), ());
+
+ MOCK_METHOD(void, walCheckpointFull, (), (override));
+
+ MOCK_METHOD(void,
+ setUpdateHook,
+ (void *object,
+ void (*)(void *object, int, char const *database, char const *, long long rowId)),
+ (override));
+
+ MOCK_METHOD(void, resetUpdateHook, (), (override));
+
+ MOCK_METHOD(void, applyAndUpdateSessions, (), (override));
+
+ MOCK_METHOD(void, setAttachedTables, (const Utils::SmallStringVector &tables), (override));
+};
+
diff --git a/tests/unit/unittest/sqlitereadstatementmock.cpp b/tests/unit/unittest/sqlitereadstatementmock.cpp
new file mode 100644
index 0000000000..e3e22d4e16
--- /dev/null
+++ b/tests/unit/unittest/sqlitereadstatementmock.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "sqlitereadstatementmock.h"
+
+#include "sqlitedatabasemock.h"
+
+SqliteReadStatementMock::SqliteReadStatementMock(Utils::SmallStringView sqlStatement,
+ SqliteDatabaseMock &databaseMock)
+ : sqlStatement(sqlStatement)
+{
+ databaseMock.prepare(sqlStatement);
+}
+
+template<>
+std::vector<Utils::SmallString> SqliteReadStatementMock::values<Utils::SmallString>(std::size_t reserveSize)
+{
+ return valuesReturnStringVector(reserveSize);
+}
+
+template<>
+std::vector<long long> SqliteReadStatementMock::values<long long>(std::size_t reserveSize)
+{
+ return valuesReturnRowIds(reserveSize);
+}
+
+template<>
+Utils::optional<long long> SqliteReadStatementMock::value<long long>()
+{
+ return valueReturnLongLong();
+}
+
+template<>
+Utils::optional<Sqlite::ByteArrayBlob> SqliteReadStatementMock::value<Sqlite::ByteArrayBlob>(
+ const Utils::SmallStringView &name, const long long &blob)
+{
+ return valueReturnBlob(name, blob);
+}
diff --git a/tests/unit/unittest/sqlitereadstatementmock.h b/tests/unit/unittest/sqlitereadstatementmock.h
new file mode 100644
index 0000000000..f74cce1e8e
--- /dev/null
+++ b/tests/unit/unittest/sqlitereadstatementmock.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "googletest.h"
+
+#include <sqliteblob.h>
+#include <utils/optional.h>
+#include <utils/smallstring.h>
+
+#include <QImage>
+
+#include <cstdint>
+#include <tuple>
+#include <vector>
+
+class SqliteDatabaseMock;
+
+class SqliteReadStatementMock
+{
+public:
+ SqliteReadStatementMock() = default;
+ SqliteReadStatementMock(Utils::SmallStringView sqlStatement, SqliteDatabaseMock &databaseMock);
+
+ MOCK_METHOD(std::vector<Utils::SmallString>, valuesReturnStringVector, (std::size_t), ());
+
+ MOCK_METHOD(std::vector<long long>, valuesReturnRowIds, (std::size_t), ());
+ MOCK_METHOD(Utils::optional<long long>, valueReturnLongLong, (), ());
+ MOCK_METHOD(Utils::optional<Sqlite::ByteArrayBlob>,
+ valueReturnBlob,
+ (Utils::SmallStringView, long long),
+ ());
+
+ template<typename ResultType, int ResultTypeCount = 1, typename... QueryType>
+ std::vector<ResultType> values(std::size_t reserveSize, const QueryType &... queryValues);
+
+ template <typename ResultType,
+ int ResultTypeCount = 1,
+ typename... QueryType>
+ std::vector<ResultType> values(std::size_t reserveSize);
+
+ template <typename ResultType,
+ int ResultTypeCount = 1,
+ template <typename...> class QueryContainerType,
+ typename QueryElementType>
+ std::vector<ResultType> values(std::size_t reserveSize,
+ const QueryContainerType<QueryElementType> &queryValues);
+
+ template <typename ResultType,
+ int ResultTypeCount = 1,
+ typename... QueryTypes>
+ Utils::optional<ResultType> value(const QueryTypes&... queryValues);
+
+public:
+ Utils::SmallString sqlStatement;
+};
+
+template<>
+std::vector<Utils::SmallString> SqliteReadStatementMock::values<Utils::SmallString>(
+ std::size_t reserveSize);
+
+template<>
+std::vector<long long> SqliteReadStatementMock::values<long long>(std::size_t reserveSize);
+
+template<>
+Utils::optional<long long> SqliteReadStatementMock::value<long long>();
+
+template<>
+Utils::optional<Sqlite::ByteArrayBlob> SqliteReadStatementMock::value<Sqlite::ByteArrayBlob>(
+ const Utils::SmallStringView &name, const long long &blob);
diff --git a/tests/unit/unittest/sqlitestatement-test.cpp b/tests/unit/unittest/sqlitestatement-test.cpp
index 341679a903..19c897f7cb 100644
--- a/tests/unit/unittest/sqlitestatement-test.cpp
+++ b/tests/unit/unittest/sqlitestatement-test.cpp
@@ -27,6 +27,7 @@
#include "mocksqlitestatement.h"
#include "sqliteteststatement.h"
+#include <sqliteblob.h>
#include <sqlitedatabase.h>
#include <sqlitereadstatement.h>
#include <sqlitereadwritestatement.h>
@@ -38,14 +39,6 @@
#include <vector>
-namespace Sqlite {
-bool operator==(Utils::span<const byte> first, Utils::span<const byte> second)
-{
- return first.size() == second.size()
- && std::memcmp(first.data(), second.data(), first.size()) == 0;
-}
-} // namespace Sqlite
-
namespace {
using Sqlite::Database;
@@ -270,7 +263,7 @@ TEST_F(SqliteStatement, BindBlob)
SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
const unsigned char chars[] = "aaafdfdlll";
auto bytePointer = reinterpret_cast<const Sqlite::byte *>(chars);
- Utils::span<const Sqlite::byte> bytes{bytePointer, sizeof(chars) - 1};
+ Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1};
statement.bind(1, bytes);
statement.next();
@@ -281,7 +274,7 @@ TEST_F(SqliteStatement, BindBlob)
TEST_F(SqliteStatement, BindEmptyBlob)
{
SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
- Utils::span<const Sqlite::byte> bytes;
+ Sqlite::BlobView bytes;
statement.bind(1, bytes);
statement.next();
@@ -341,7 +334,7 @@ TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundValu
TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundBlob)
{
SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
- Utils::span<const Sqlite::byte> bytes;
+ Sqlite::BlobView bytes;
ASSERT_THROW(statement.bind(2, bytes), Sqlite::BindingIndexIsOutOfRange);
}
@@ -408,34 +401,25 @@ TEST_F(SqliteStatement, WriteEmptyBlobs)
{
SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
- Utils::span<const Sqlite::byte> bytes;
+ Sqlite::BlobView bytes;
statement.write(bytes);
ASSERT_THAT(statement.fetchBlobValue(0), IsEmpty());
}
-class Blob
-{
-public:
- Blob(Utils::span<const Sqlite::byte> bytes)
- : bytes(bytes.begin(), bytes.end())
- {}
-
- std::vector<Sqlite::byte> bytes;
-};
-
TEST_F(SqliteStatement, WriteBlobs)
{
SqliteTestStatement statement("INSERT INTO test VALUES ('blob', 40, ?)", database);
SqliteTestStatement readStatement("SELECT value FROM test WHERE name = 'blob'", database);
const unsigned char chars[] = "aaafdfdlll";
auto bytePointer = reinterpret_cast<const Sqlite::byte *>(chars);
- Utils::span<const Sqlite::byte> bytes{bytePointer, sizeof(chars) - 1};
+ Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1};
statement.write(bytes);
- ASSERT_THAT(readStatement.template value<Blob>(), Optional(Field(&Blob::bytes, Eq(bytes))));
+ ASSERT_THAT(readStatement.template value<Sqlite::Blob>(),
+ Optional(Field(&Sqlite::Blob::bytes, Eq(bytes))));
}
TEST_F(SqliteStatement, CannotWriteToClosedDatabase)
@@ -624,38 +608,38 @@ TEST_F(SqliteStatement, GetBlobValues)
ReadStatement statement("SELECT value FROM test WHERE name='blob'", database);
const int value = 0xDDCCBBAA;
auto bytePointer = reinterpret_cast<const Sqlite::byte *>(&value);
- Utils::span<const Sqlite::byte> bytes{bytePointer, 4};
+ Sqlite::BlobView bytes{bytePointer, 4};
- auto values = statement.values<Blob>(1);
+ auto values = statement.values<Sqlite::Blob>(1);
- ASSERT_THAT(values, ElementsAre(Field(&Blob::bytes, Eq(bytes))));
+ ASSERT_THAT(values, ElementsAre(Field(&Sqlite::Blob::bytes, Eq(bytes))));
}
TEST_F(SqliteStatement, GetEmptyBlobValueForInteger)
{
ReadStatement statement("SELECT value FROM test WHERE name='poo'", database);
- auto value = statement.value<Blob>();
+ auto value = statement.value<Sqlite::Blob>();
- ASSERT_THAT(value, Optional(Field(&Blob::bytes, IsEmpty())));
+ ASSERT_THAT(value, Optional(Field(&Sqlite::Blob::bytes, IsEmpty())));
}
TEST_F(SqliteStatement, GetEmptyBlobValueForFloat)
{
ReadStatement statement("SELECT number FROM test WHERE name='foo'", database);
- auto value = statement.value<Blob>();
+ auto value = statement.value<Sqlite::Blob>();
- ASSERT_THAT(value, Optional(Field(&Blob::bytes, IsEmpty())));
+ ASSERT_THAT(value, Optional(Field(&Sqlite::Blob::bytes, IsEmpty())));
}
TEST_F(SqliteStatement, GetEmptyBlobValueForText)
{
ReadStatement statement("SELECT number FROM test WHERE name='bar'", database);
- auto value = statement.value<Blob>();
+ auto value = statement.value<Sqlite::Blob>();
- ASSERT_THAT(value, Optional(Field(&Blob::bytes, IsEmpty())));
+ ASSERT_THAT(value, Optional(Field(&Sqlite::Blob::bytes, IsEmpty())));
}
TEST_F(SqliteStatement, GetOptionalSingleValueAndMultipleQueryValue)
diff --git a/tests/unit/unittest/sqlitestatementmock.h b/tests/unit/unittest/sqlitestatementmock.h
new file mode 100644
index 0000000000..ad8a73e0a5
--- /dev/null
+++ b/tests/unit/unittest/sqlitestatementmock.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <googletest.h>
+
+#include <sqlitebasestatement.h>
+
+class BaseSqliteStatementMock
+{
+public:
+ MOCK_METHOD(bool, next, ());
+ MOCK_METHOD(void, step, ());
+ MOCK_METHOD(void, reset, ());
+
+ MOCK_METHOD(int, fetchIntValue, (int), (const));
+ MOCK_METHOD(long, fetchLongValue, (int), (const));
+ MOCK_METHOD(long long, fetchLongLongValue, (int), (const));
+ MOCK_METHOD(double, fetchDoubleValue, (int), (const));
+ MOCK_METHOD(Utils::SmallString, fetchSmallStringValue, (int), (const));
+ MOCK_METHOD(Utils::PathString, fetchPathStringValue, (int), (const));
+
+ template<typename Type>
+ Type fetchValue(int column) const;
+
+ MOCK_METHOD(void, bind, (int, int), ());
+ MOCK_METHOD(void, bind, (int, long long), ());
+ MOCK_METHOD(void, bind, (int, double), ());
+ MOCK_METHOD(void, bind, (int, Utils::SmallStringView), ());
+ MOCK_METHOD(void, bind, (int, long) );
+ MOCK_METHOD(int, bindingIndexForName, (Utils::SmallStringView name), (const));
+
+ MOCK_METHOD(void, prepare, (Utils::SmallStringView sqlStatement));
+};
+
+template<>
+int BaseSqliteStatementMock::fetchValue<int>(int column) const
+{
+ return fetchIntValue(column);
+}
+
+template<>
+long BaseSqliteStatementMock::fetchValue<long>(int column) const
+{
+ return fetchLongValue(column);
+}
+
+template<>
+long long BaseSqliteStatementMock::fetchValue<long long>(int column) const
+{
+ return fetchLongLongValue(column);
+}
+
+template<>
+double BaseSqliteStatementMock::fetchValue<double>(int column) const
+{
+ return fetchDoubleValue(column);
+}
+
+template<>
+Utils::SmallString BaseSqliteStatementMock::fetchValue<Utils::SmallString>(int column) const
+{
+ return fetchSmallStringValue(column);
+}
+
+template<>
+Utils::PathString BaseSqliteStatementMock::fetchValue<Utils::PathString>(int column) const
+{
+ return fetchPathStringValue(column);
+}
+
+class SqliteStatementMock : public Sqlite::StatementImplementation<NiceMock<BaseSqliteStatementMock>>
+{
+public:
+ explicit SqliteStatementMock()
+ : Sqlite::StatementImplementation<NiceMock<BaseSqliteStatementMock>>()
+ {}
+
+
+protected:
+ void checkIsWritableStatement();
+};
diff --git a/tests/unit/unittest/sqlitetransactionbackendmock.h b/tests/unit/unittest/sqlitetransactionbackendmock.h
new file mode 100644
index 0000000000..7aad4f1f6a
--- /dev/null
+++ b/tests/unit/unittest/sqlitetransactionbackendmock.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+
+#include "googletest.h"
+
+#include <sqlitetransaction.h>
+
+class SqliteTransactionBackendMock : public Sqlite::TransactionInterface
+{
+public:
+ MOCK_METHOD(void, deferredBegin, (), (override));
+ MOCK_METHOD(void, immediateBegin, (), (override));
+ MOCK_METHOD(void, exclusiveBegin, (), (override));
+ MOCK_METHOD(void, commit, (), (override));
+ MOCK_METHOD(void, rollback, (), (override));
+ MOCK_METHOD(void, lock, (), (override));
+ MOCK_METHOD(void, unlock, (), (override));
+ MOCK_METHOD(void, immediateSessionBegin, (), (override));
+ MOCK_METHOD(void, sessionCommit, (), (override));
+ MOCK_METHOD(void, sessionRollback, (), (override));
+};
diff --git a/tests/unit/unittest/sqlitewritestatementmock.cpp b/tests/unit/unittest/sqlitewritestatementmock.cpp
new file mode 100644
index 0000000000..a3612833b2
--- /dev/null
+++ b/tests/unit/unittest/sqlitewritestatementmock.cpp
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "sqlitewritestatementmock.h"
+
+#include "sqlitedatabasemock.h"
+
+SqliteWriteStatementMock::SqliteWriteStatementMock(Utils::SmallStringView sqlStatement,
+ SqliteDatabaseMock &database)
+ : sqlStatement(sqlStatement)
+{
+ database.prepare(sqlStatement);
+}
diff --git a/tests/unit/unittest/sqlitewritestatementmock.h b/tests/unit/unittest/sqlitewritestatementmock.h
new file mode 100644
index 0000000000..3a8d159329
--- /dev/null
+++ b/tests/unit/unittest/sqlitewritestatementmock.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include "googletest.h"
+
+#include <sqliteblob.h>
+#include <sqlitevalue.h>
+
+class SqliteDatabaseMock;
+
+class SqliteWriteStatementMock
+{
+public:
+ SqliteWriteStatementMock() = default;
+ SqliteWriteStatementMock(Utils::SmallStringView sqlStatement, SqliteDatabaseMock &database);
+
+ MOCK_METHOD(void, execute, (), ());
+
+ MOCK_METHOD(void, write, (Utils::SmallStringView), ());
+ MOCK_METHOD(void, write, (long long), ());
+ MOCK_METHOD(void, write, (Utils::SmallStringView, Utils::SmallStringView), ());
+ MOCK_METHOD(void, write, (long long, Utils::SmallStringView), ());
+ MOCK_METHOD(void,
+ write,
+ (Utils::SmallStringView, Utils::SmallStringView, Utils::SmallStringView),
+ ());
+ MOCK_METHOD(void, write, (Utils::SmallStringView, Utils::SmallStringView, long long), ());
+ MOCK_METHOD(void, write, (Utils::SmallStringView, Utils::SmallStringView, double), ());
+ MOCK_METHOD(void, write, (long long, Utils::SmallStringView, Utils::SmallStringView), ());
+ MOCK_METHOD(void, write, (long long, Utils::SmallStringView, const Sqlite::Value &), ());
+ MOCK_METHOD(void, write, (Utils::SmallStringView, long long, Sqlite::BlobView, Sqlite::BlobView), ());
+ MOCK_METHOD(void,
+ write,
+ (Utils::SmallStringView, long long, Sqlite::NullValue, Sqlite::NullValue),
+ ());
+ MOCK_METHOD(void,
+ write,
+ (Utils::SmallStringView,
+ Utils::SmallStringView,
+ Utils::SmallStringView,
+ Utils::SmallStringView),
+ ());
+ MOCK_METHOD(void,
+ write,
+ (long long, Utils::SmallStringView, Utils::SmallStringView, Utils::SmallStringView),
+ ());
+ MOCK_METHOD(void, write, (long long, long long, Utils::SmallStringView, Utils::SmallStringView), ());
+ MOCK_METHOD(void,
+ write,
+ (Utils::SmallStringView,
+ Utils::SmallStringView,
+ Utils::SmallStringView,
+ Utils::SmallStringView,
+ Utils::SmallStringView),
+ ());
+
+ MOCK_METHOD(void, write, (void *, long long), ());
+
+ Utils::SmallString sqlStatement;
+};
diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro
index 967463bbdc..6200a24d7f 100644
--- a/tests/unit/unittest/unittest.pro
+++ b/tests/unit/unittest/unittest.pro
@@ -66,6 +66,9 @@ SOURCES += \
filepathview-test.cpp \
gtest-creator-printing.cpp \
gtest-qt-printing.cpp \
+ imagecache-test.cpp \
+ imagecachegenerator-test.cpp \
+ imagecachestorage-test.cpp \
lastchangedrowid-test.cpp \
lineprefixer-test.cpp \
listmodeleditor-test.cpp \
@@ -134,7 +137,9 @@ SOURCES += \
sqlitestatement-test.cpp \
sqlitetable-test.cpp \
sqlstatementbuilder-test.cpp \
- createtablesqlstatementbuilder-test.cpp
+ createtablesqlstatementbuilder-test.cpp \
+ sqlitereadstatementmock.cpp \
+ sqlitewritestatementmock.cpp
!isEmpty(QTC_UNITTEST_BUILD_CPP_PARSER):SOURCES += matchingtext-test.cpp
@@ -240,12 +245,15 @@ HEADERS += \
gtest-llvm-printing.h \
gtest-qt-printing.h \
gtest-std-printing.h \
+ imagecachecollectormock.h \
mimedatabase-utilities.h \
mockclangcodemodelclient.h \
mockclangcodemodelserver.h \
mockclangpathwatcher.h \
mockclangpathwatchernotifier.h \
mockfilesystem.h \
+ mockimagecachegenerator.h \
+ mockimagecachestorage.h \
mocklistmodeleditorview.h \
mockpchcreator.h \
mockpchmanagerclient.h \
@@ -258,6 +266,8 @@ HEADERS += \
mocksearchhandle.h \
mocksearchresult.h \
mocksyntaxhighligher.h \
+ mocktimestampprovider.h \
+ notification.h \
processevents-utilities.h \
sourcerangecontainer-matcher.h \
spydummy.h \
@@ -301,7 +311,12 @@ HEADERS += \
mockpchtaskgenerator.h \
../mockup/qmldesigner/designercore/include/nodeinstanceview.h \
../mockup/qmldesigner/designercore/include/rewriterview.h \
- ../mockup/qmldesigner/designercore/include/itemlibraryitem.h
+ ../mockup/qmldesigner/designercore/include/itemlibraryitem.h\
+ sqlitedatabasemock.h \
+ sqlitereadstatementmock.h \
+ sqlitestatementmock.h \
+ sqlitetransactionbackendmock.h \
+ sqlitewritestatementmock.h
!isEmpty(LIBCLANG_LIBS) {
diff --git a/tests/unit/unittest/unittest.qbs b/tests/unit/unittest/unittest.qbs
index 5ceb723b22..ac7eb08b82 100644
--- a/tests/unit/unittest/unittest.qbs
+++ b/tests/unit/unittest/unittest.qbs
@@ -333,6 +333,19 @@ Project {
"unittests-main.cpp",
"usedmacrofilter-test.cpp",
"utf8-test.cpp",
+ "imagecache-test.cpp",
+ "imagecachegenerator-test.cpp",
+ "imagecachestorage-test.cpp",
+ "sqlitedatabasemock.h",
+ "sqlitereadstatementmock.h",
+ "sqlitestatementmock.h",
+ "sqlitetransactionbackendmock.h",
+ "sqlitewritestatementmock.h",
+ "notification.h",
+ "mocktimestampprovider.h",
+ "imagecachecollectormock.h",
+ "mockimagecachegenerator.h",
+ "mockimagecachestorage.h",
]
Group {