QmlDesigner: Add ProjectStorageUpdater

Adding a skeleton for the ProjectStorageUpdater.

Task-number: QDS-4819
Task-number: QDS-4793
Change-Id: I230d68f71480d360d71019883510ef22dd276802
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Marco Bubke
2021-09-16 17:19:56 +02:00
parent cb5eaf4a63
commit a570d53db2
24 changed files with 1350 additions and 526 deletions
+10 -2
View File
@@ -33,7 +33,7 @@ add_qtc_test(unittest GTEST
DEPENDS
Qt5::Core Qt5::Network Qt5::Widgets
Qt5::Xml Qt5::Concurrent Qt5::Qml Qt5::Gui
Qt6Core5Compat
Qt6Core5Compat QmlJS
Googletest
DEFINES
QT_NO_CAST_TO_ASCII
@@ -342,6 +342,8 @@ extend_qtc_test(unittest
projectstorage/filestatus.h
projectstorage/filestatuscache.cpp projectstorage/filestatuscache.h
projectstorage/nonlockingmutex.h
projectstorage/projectmanagerinterface.h
projectstorage/projectstorageinterface.h
projectstorage/projectstorage.h
projectstorage/projectstoragepathwatcher.h
projectstorage/projectstoragepathwatcherinterface.h
@@ -351,6 +353,7 @@ extend_qtc_test(unittest
projectstorage/projectstoragepathwatcher.h
projectstorage/projectstoragepathwatchertypes.h
projectstorage/projectstoragetypes.h
projectstorage/projectstorageupdater.cpp projectstorage/projectstorageupdater.h
projectstorage/sourcepath.h
projectstorage/sourcepathcache.h
projectstorage/sourcepathcache.h
@@ -359,6 +362,8 @@ extend_qtc_test(unittest
projectstorage/storagecache.h
projectstorage/storagecacheentry.h
projectstorage/storagecachefwd.h
projectstorage/qmldocumentparserinterface.h
projectstorage/qmltypesparserinterface.h
rewritertransaction.cpp
rewritertransaction.h
EXPLICIT_MOC
@@ -373,7 +378,9 @@ extend_qtc_test(unittest
filesystemmock.h
filestatuscache-test.cpp
listmodeleditor-test.cpp
projectmanagermock.h
projectstorage-test.cpp
projectstorageupdater-test.cpp
projectstoragesqlitefunctionregistry-test.cpp
projectstoragepathwatchermock.h
projectstoragepathwatchernotifiermock.h
@@ -383,7 +390,8 @@ extend_qtc_test(unittest
sourcepathcachemock.h
sourcepathview-test.cpp
storagecache-test.cpp
qmldocumentparsermock.h
qmltypesparsermock.h
)
# QmlDesigner tests END
+1
View File
@@ -40,4 +40,5 @@ public:
MOCK_METHOD(long long, lastModified, (QmlDesigner::SourceId sourceId), (const, override));
MOCK_METHOD(QmlDesigner::FileStatus, fileStatus, (QmlDesigner::SourceId sourceId), (const, override));
MOCK_METHOD(void, remove, (const QmlDesigner::SourceIds &sourceIds), (override));
MOCK_METHOD(QString, contentAsQString, (const QString &filePath), (const, override));
};
+36
View File
@@ -0,0 +1,36 @@
/****************************************************************************
**
** Copyright (C) 2021 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 <projectstorage/projectmanagerinterface.h>
class ProjectManagerMock : public QmlDesigner::ProjectManagerInterface
{
public:
MOCK_METHOD(QStringList, qtQmlDirs, (), (const));
};
File diff suppressed because it is too large Load Diff
+43 -24
View File
@@ -29,36 +29,55 @@
#include "sqlitedatabasemock.h"
#include <projectstorage/projectstoragetypes.h>
#include <projectstorage/filestatus.h>
#include <projectstorage/projectstorageinterface.h>
#include <projectstorage/sourcepathcache.h>
#include <projectstorageids.h>
class ProjectStorageMock
class ProjectStorageMock : public QmlDesigner::ProjectStorageInterface
{
public:
ProjectStorageMock(SqliteDatabaseMock &databaseMock)
: databaseMock{databaseMock}
{}
MOCK_METHOD(void,
synchronize,
(QmlDesigner::Storage::ImportDependencies importDependencies,
QmlDesigner::Storage::Documents documents,
QmlDesigner::Storage::Types types,
QmlDesigner::SourceIds sourceIds,
QmlDesigner::FileStatuses fileStatuses),
(override));
MOCK_METHOD1(fetchSourceContextId,
QmlDesigner::SourceContextId(Utils::SmallStringView SourceContextPath));
MOCK_METHOD2(fetchSourceId,
QmlDesigner::SourceId(QmlDesigner::SourceContextId SourceContextId,
Utils::SmallStringView sourceName));
MOCK_METHOD1(fetchSourceContextIdUnguarded,
QmlDesigner::SourceContextId(Utils::SmallStringView SourceContextPath));
MOCK_METHOD2(fetchSourceIdUnguarded,
QmlDesigner::SourceId(QmlDesigner::SourceContextId SourceContextId,
Utils::SmallStringView sourceName));
MOCK_METHOD1(fetchSourceContextPath,
Utils::PathString(QmlDesigner::SourceContextId sourceContextId));
MOCK_METHOD1(fetchSourceNameAndSourceContextId,
QmlDesigner::Cache::SourceNameAndSourceContextId(QmlDesigner::SourceId sourceId));
MOCK_METHOD0(fetchAllSourceContexts, std::vector<QmlDesigner::Cache::SourceContext>());
MOCK_METHOD0(fetchAllSources, std::vector<QmlDesigner::Cache::Source>());
MOCK_METHOD(QmlDesigner::FileStatus,
fetchFileStatus,
(QmlDesigner::SourceId sourceId),
(const, override));
SqliteDatabaseMock &database() { return databaseMock; }
MOCK_METHOD(QmlDesigner::SourceIds,
fetchSourceDependencieIds,
(QmlDesigner::SourceId sourceId),
(const, override));
SqliteDatabaseMock &databaseMock;
MOCK_METHOD(QmlDesigner::SourceContextId,
fetchSourceContextId,
(Utils::SmallStringView SourceContextPath),
());
MOCK_METHOD(QmlDesigner::SourceId,
fetchSourceId,
(QmlDesigner::SourceContextId SourceContextId, Utils::SmallStringView sourceName),
());
MOCK_METHOD(QmlDesigner::SourceContextId,
fetchSourceContextIdUnguarded,
(Utils::SmallStringView SourceContextPath),
());
MOCK_METHOD(QmlDesigner::SourceId,
fetchSourceIdUnguarded,
(QmlDesigner::SourceContextId SourceContextId, Utils::SmallStringView sourceName),
());
MOCK_METHOD(Utils::PathString,
fetchSourceContextPath,
(QmlDesigner::SourceContextId sourceContextId));
MOCK_METHOD(QmlDesigner::Cache::SourceNameAndSourceContextId,
fetchSourceNameAndSourceContextId,
(QmlDesigner::SourceId sourceId));
MOCK_METHOD(std::vector<QmlDesigner::Cache::SourceContext>, fetchAllSourceContexts, (), ());
MOCK_METHOD(std::vector<QmlDesigner::Cache::Source>, fetchAllSources, (), ());
};
@@ -41,6 +41,7 @@ namespace {
using Watcher = QmlDesigner::ProjectStoragePathWatcher<NiceMock<MockQFileSytemWatcher>,
NiceMock<MockTimer>,
NiceMock<SourcePathCacheMock>>;
using QmlDesigner::FileStatus;
using QmlDesigner::IdPaths;
using QmlDesigner::ProjectChunkId;
using QmlDesigner::ProjectChunkIds;
@@ -81,7 +82,9 @@ protected:
.WillByDefault(Return(sourceContextIds[1]));
ON_CALL(sourcePathCacheMock, sourceContextId(TypedEq<SourceId>(pathIds[4])))
.WillByDefault(Return(sourceContextIds[2]));
ON_CALL(mockFileSystem, lastModified(_)).WillByDefault(Return(1));
ON_CALL(mockFileSystem, fileStatus(_)).WillByDefault([](auto sourceId) {
return FileStatus{sourceId, 1, 1};
});
ON_CALL(sourcePathCacheMock,
sourceContextId(TypedEq<Utils::SmallStringView>(sourceContextPathString)))
.WillByDefault(Return(sourceContextIds[0]));
@@ -359,9 +362,12 @@ TEST_F(ProjectStoragePathWatcher, TwoNotifyFileChanges)
watcher.updateIdPaths({{id1, {pathIds[0], pathIds[1], pathIds[2]}},
{id2, {pathIds[0], pathIds[1], pathIds[2], pathIds[3], pathIds[4]}},
{id3, {pathIds[4]}}});
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[0]))).WillByDefault(Return(2));
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[1]))).WillByDefault(Return(2));
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[3]))).WillByDefault(Return(2));
ON_CALL(mockFileSystem, fileStatus(Eq(pathIds[0])))
.WillByDefault(Return(FileStatus{pathIds[0], 1, 2}));
ON_CALL(mockFileSystem, fileStatus(Eq(pathIds[1])))
.WillByDefault(Return(FileStatus{pathIds[1], 1, 2}));
ON_CALL(mockFileSystem, fileStatus(Eq(pathIds[3])))
.WillByDefault(Return(FileStatus{pathIds[3], 1, 2}));
EXPECT_CALL(notifier,
pathsWithIdsChanged(
@@ -376,8 +382,11 @@ TEST_F(ProjectStoragePathWatcher, NotifyForPathChanges)
{
watcher.updateIdPaths(
{{id1, {pathIds[0], pathIds[1], pathIds[2]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}});
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[0]))).WillByDefault(Return(2));
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[3]))).WillByDefault(Return(2));
ON_CALL(mockFileSystem, fileStatus(Eq(pathIds[0])))
.WillByDefault(Return(FileStatus{pathIds[0], 1, 2}));
ON_CALL(mockFileSystem, fileStatus(Eq(pathIds[3])))
.WillByDefault(Return(FileStatus{pathIds[3], 1, 2}));
EXPECT_CALL(notifier, pathsChanged(ElementsAre(pathIds[0])));
@@ -397,7 +406,8 @@ TEST_F(ProjectStoragePathWatcher, NoDuplicatePathChanges)
{
watcher.updateIdPaths(
{{id1, {pathIds[0], pathIds[1], pathIds[2]}}, {id2, {pathIds[0], pathIds[1], pathIds[3]}}});
ON_CALL(mockFileSystem, lastModified(Eq(pathIds[0]))).WillByDefault(Return(2));
ON_CALL(mockFileSystem, fileStatus(Eq(pathIds[0])))
.WillByDefault(Return(FileStatus{pathIds[0], 1, 2}));
EXPECT_CALL(notifier, pathsChanged(ElementsAre(pathIds[0])));
@@ -0,0 +1,368 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "filesystemmock.h"
#include "projectmanagermock.h"
#include "projectstoragemock.h"
#include "qmldocumentparsermock.h"
#include "qmltypesparsermock.h"
#include <projectstorage/filestatuscache.h>
#include <projectstorage/projectstorage.h>
#include <projectstorage/projectstorageupdater.h>
#include <projectstorage/sourcepathcache.h>
#include <sqlitedatabase.h>
namespace {
namespace Storage = QmlDesigner::Storage;
using QmlDesigner::FileStatus;
using QmlDesigner::SourceId;
using QmlDesigner::Storage::TypeAccessSemantics;
MATCHER_P5(IsStorageType,
import,
typeName,
prototype,
accessSemantics,
sourceId,
std::string(negation ? "isn't " : "is ")
+ PrintToString(Storage::Type{import, typeName, prototype, accessSemantics, sourceId}))
{
const Storage::Type &type = arg;
return type.import == import && type.typeName == typeName
&& type.accessSemantics == accessSemantics && type.sourceId == sourceId
&& Storage::TypeName{prototype} == type.prototype;
}
MATCHER_P3(IsPropertyDeclaration,
name,
typeName,
traits,
std::string(negation ? "isn't " : "is ")
+ PrintToString(Storage::PropertyDeclaration{name, typeName, traits}))
{
const Storage::PropertyDeclaration &propertyDeclaration = arg;
return propertyDeclaration.name == name
&& Storage::TypeName{typeName} == propertyDeclaration.typeName
&& propertyDeclaration.traits == traits;
}
MATCHER_P(IsExportedType,
name,
std::string(negation ? "isn't " : "is ") + PrintToString(Storage::ExportedType{name}))
{
const Storage::ExportedType &type = arg;
return type.name == name;
}
class ProjectStorageUpdater : public testing::Test
{
public:
ProjectStorageUpdater()
{
ON_CALL(fileSystemMock, fileStatus(Eq(qmltypesPathSourceId)))
.WillByDefault(Return(FileStatus{qmltypesPathSourceId, 21, 421}));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmltypesPathSourceId)))
.WillByDefault(Return(FileStatus{qmltypesPathSourceId, 2, 421}));
ON_CALL(fileSystemMock, fileStatus(Eq(qmltypes2PathSourceId)))
.WillByDefault(Return(FileStatus{qmltypes2PathSourceId, 21, 421}));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmltypes2PathSourceId)))
.WillByDefault(Return(FileStatus{qmltypes2PathSourceId, 2, 421}));
ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId)))
.WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 421}));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDirPathSourceId)))
.WillByDefault(Return(FileStatus{qmlDirPathSourceId, 2, 421}));
ON_CALL(projectStorageMock, fetchSourceDependencieIds(Eq(qmlDirPathSourceId)))
.WillByDefault(Return(QmlDesigner::SourceIds{qmltypesPathSourceId, qmltypes2PathSourceId}));
QString qmldir{"module Example\ntypeinfo example.qmltypes\n"};
ON_CALL(projectManagerMock, qtQmlDirs()).WillByDefault(Return(QStringList{"/path/qmldir"}));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir"))))
.WillByDefault(Return(qmldir));
}
protected:
NiceMock<ProjectManagerMock> projectManagerMock;
NiceMock<FileSystemMock> fileSystemMock;
NiceMock<ProjectStorageMock> projectStorageMock;
NiceMock<QmlTypesParserMock> qmlTypesParserMock;
NiceMock<QmlDocumentParserMock> qmlDocumentParserMock;
QmlDesigner::FileStatusCache fileStatusCache{fileSystemMock};
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
QmlDesigner::ProjectStorage<Sqlite::Database> storage{database, database.isInitialized()};
QmlDesigner::SourcePathCache<QmlDesigner::ProjectStorage<Sqlite::Database>> sourcePathCache{
storage};
QmlDesigner::ProjectUpdater updater{projectManagerMock,
fileSystemMock,
projectStorageMock,
fileStatusCache,
sourcePathCache,
qmlDocumentParserMock,
qmlTypesParserMock};
SourceId objectTypeSourceId{sourcePathCache.sourceId("/path/Object")};
Storage::Type objectType{Storage::Import{"Qml", 2},
"QObject",
Storage::NativeType{},
Storage::TypeAccessSemantics::Reference,
objectTypeSourceId,
{Storage::ExportedType{"Object"}, Storage::ExportedType{"Obj"}}};
SourceId qmltypesPathSourceId = sourcePathCache.sourceId("/path/example.qmltypes");
SourceId qmltypes2PathSourceId = sourcePathCache.sourceId("/path/example2.qmltypes");
SourceId qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir");
};
TEST_F(ProjectStorageUpdater, GetContentForQmlDirPathsIfFileStatusIsDifferent)
{
SourceId qmlDir1PathSourceId = sourcePathCache.sourceId("/path/one/qmldir");
SourceId qmlDir2PathSourceId = sourcePathCache.sourceId("/path/two/qmldir");
SourceId qmlDir3PathSourceId = sourcePathCache.sourceId("/path/three/qmldir");
ON_CALL(projectManagerMock, qtQmlDirs())
.WillByDefault(
Return(QStringList{"/path/one/qmldir", "/path/two/qmldir", "/path/three/qmldir"}));
ON_CALL(fileSystemMock, fileStatus(_)).WillByDefault([](auto sourceId) {
return FileStatus{sourceId, 21, 421};
});
ON_CALL(projectStorageMock, fetchFileStatus(_)).WillByDefault([](auto sourceId) {
return FileStatus{sourceId, 2, 421};
});
ON_CALL(fileSystemMock, fileStatus(Eq(qmlDir3PathSourceId)))
.WillByDefault(Return(FileStatus{qmlDir3PathSourceId, 21, 421}));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDir3PathSourceId)))
.WillByDefault(Return(FileStatus{qmlDir3PathSourceId, 21, 421}));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/one/qmldir"))));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/two/qmldir"))));
updater.update();
}
TEST_F(ProjectStorageUpdater, RequestFileStatusFromFileSystem)
{
EXPECT_CALL(fileSystemMock, fileStatus(Ne(qmlDirPathSourceId))).Times(AnyNumber());
EXPECT_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId)));
updater.update();
}
TEST_F(ProjectStorageUpdater, GetContentForQmlTypes)
{
QString qmldir{"module Example\ntypeinfo example.qmltypes\n"};
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir"))))
.WillRepeatedly(Return(qmldir));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))));
updater.update();
}
TEST_F(ProjectStorageUpdater, GetContentForQmlTypesIfProjectStorageFileStatusIsInvalid)
{
QString qmldir{"module Example\ntypeinfo example.qmltypes\n"};
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir"))))
.WillRepeatedly(Return(qmldir));
ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmltypesPathSourceId)))
.WillByDefault(Return(FileStatus{}));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))));
updater.update();
}
TEST_F(ProjectStorageUpdater, DontGetContentForQmlTypesIfFileSystemFileStatusIsInvalid)
{
QString qmldir{"module Example\ntypeinfo example.qmltypes\n"};
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir"))))
.WillRepeatedly(Return(qmldir));
ON_CALL(fileSystemMock, fileStatus(Eq(qmltypesPathSourceId))).WillByDefault(Return(FileStatus{}));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))).Times(0);
updater.update();
}
TEST_F(ProjectStorageUpdater, ParseQmlTypes)
{
QString qmldir{"module Example\ntypeinfo example.qmltypes\ntypeinfo example2.qmltypes\n"};
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
QString qmltypes{"Module {\ndependencies: []}"};
QString qmltypes2{"Module {\ndependencies: [foo]}"};
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))))
.WillByDefault(Return(qmltypes));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example2.qmltypes"))))
.WillByDefault(Return(qmltypes2));
EXPECT_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _));
EXPECT_CALL(qmlTypesParserMock, parse(qmltypes2, _, _, _));
updater.update();
}
TEST_F(ProjectStorageUpdater, DISABLED_SynchronizeIsEmptyForNoChange)
{
EXPECT_CALL(projectStorageMock,
synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));
updater.update();
}
TEST_F(ProjectStorageUpdater, SynchronizeQmlTypes)
{
auto qmlDirPathSourceId = sourcePathCache.sourceId("/path/qmldir");
auto qmltypesPathSourceId = sourcePathCache.sourceId("/path/example.qmltypes");
QString qmltypes{"Module {\ndependencies: []}"};
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))))
.WillByDefault(Return(qmltypes));
ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _))
.WillByDefault([&](auto, auto &importDependencies, auto &types, auto &sourceIds) {
types.push_back(objectType);
});
EXPECT_CALL(projectStorageMock,
synchronize(_,
_,
ElementsAre(Eq(objectType)),
UnorderedElementsAre(qmlDirPathSourceId, qmltypesPathSourceId),
_));
updater.update();
}
TEST_F(ProjectStorageUpdater, SynchronizeQmlTypesAreEmptyIfFileDoesNotChanged)
{
QString qmltypes{"Module {\ndependencies: []}"};
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes"))))
.WillByDefault(Return(qmltypes));
ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _))
.WillByDefault([&](auto, auto &importDependencies, auto &types, auto &sourceIds) {
types.push_back(objectType);
});
ON_CALL(fileSystemMock, fileStatus(Eq(qmltypesPathSourceId)))
.WillByDefault(Return(FileStatus{qmltypesPathSourceId, 2, 421}));
ON_CALL(fileSystemMock, fileStatus(Eq(qmltypes2PathSourceId)))
.WillByDefault(Return(FileStatus{qmltypes2PathSourceId, 2, 421}));
ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId)))
.WillByDefault(Return(FileStatus{qmlDirPathSourceId, 2, 421}));
EXPECT_CALL(projectStorageMock,
synchronize(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));
updater.update();
}
TEST_F(ProjectStorageUpdater, GetContentForQmlDocuments)
{
QString qmldir{"module Example\nFirstType 1.0 First.qml\nFirstTypeV2 2.2 "
"First.2.qml\nSecondType 2.1 OldSecond.qml\nSecondType 2.2 Second.qml\n"};
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir"))))
.WillRepeatedly(Return(qmldir));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml"))));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.2.qml"))));
EXPECT_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml"))));
updater.update();
}
TEST_F(ProjectStorageUpdater, ParseQmlDocuments)
{
QString qmldir{"module Example\nFirstType 1.0 First.qml\nFirstTypeV2 2.2 "
"First.2.qml\nSecondType 2.1 OldSecond.qml\nSecondType 2.2 Second.qml\n"};
QString qmlDocument1{"First{}"};
QString qmlDocument2{"Second{}"};
QString qmlDocument3{"Third{}"};
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml"))))
.WillByDefault(Return(qmlDocument1));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.2.qml"))))
.WillByDefault(Return(qmlDocument2));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml"))))
.WillByDefault(Return(qmlDocument3));
EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument1));
EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument2));
EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument3));
updater.update();
}
TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments)
{
QString qmldir{"module Example\nFirstType 1.0 First.qml\nFirstTypeV2 2.2 "
"First.2.qml\nSecondType 2.1 OldSecond.qml\nSecondType 2.2 Second.qml\n"};
QString qmlDocument1{"First{}"};
QString qmlDocument2{"Second{}"};
QString qmlDocument3{"Third{}"};
auto qmlDocumentSourceId1 = sourcePathCache.sourceId("/path/First.qml");
auto qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First.2.qml");
auto qmlDocumentSourceId3 = sourcePathCache.sourceId("/path/Second.qml");
Storage::Type firstType;
firstType.prototype = Storage::ExportedType{"Object"};
Storage::Type secondType;
secondType.prototype = Storage::ExportedType{"Object2"};
Storage::Type thirdType;
thirdType.prototype = Storage::ExportedType{"Object3"};
auto firstQmlDocumentSourceId = sourcePathCache.sourceId("/path/First.qml");
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.qml"))))
.WillByDefault(Return(qmlDocument1));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/First.2.qml"))))
.WillByDefault(Return(qmlDocument2));
ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/Second.qml"))))
.WillByDefault(Return(qmlDocument3));
ON_CALL(qmlDocumentParserMock, parse(qmlDocument1)).WillByDefault(Return(firstType));
ON_CALL(qmlDocumentParserMock, parse(qmlDocument2)).WillByDefault(Return(secondType));
ON_CALL(qmlDocumentParserMock, parse(qmlDocument3)).WillByDefault(Return(thirdType));
EXPECT_CALL(projectStorageMock,
synchronize(_,
_,
Contains(AllOf(IsStorageType(Storage::Import{"Example", 1},
"First.qml",
Storage::ExportedType{"Object"},
TypeAccessSemantics::Reference,
firstQmlDocumentSourceId),
Field(&Storage::Type::exportedTypes,
ElementsAre(IsExportedType("FirstType"))))),
UnorderedElementsAre(qmlDirPathSourceId,
qmlDocumentSourceId1,
qmlDocumentSourceId2,
qmlDocumentSourceId3),
_));
updater.update();
}
} // namespace
@@ -0,0 +1,36 @@
/****************************************************************************
**
** Copyright (C) 2021 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 <projectstorage/qmldocumentparserinterface.h>
class QmlDocumentParserMock : public QmlDesigner::QmlDocumentParserInterface
{
public:
MOCK_METHOD(QmlDesigner::Storage::Type, parse, (const QString &), (override));
};
+42
View File
@@ -0,0 +1,42 @@
/****************************************************************************
**
** Copyright (C) 2021 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 <projectstorage/qmltypesparserinterface.h>
class QmlTypesParserMock : public QmlDesigner::QmlTypesParserInterface
{
public:
MOCK_METHOD(void,
parse,
(const QString &sourceContent,
QmlDesigner::Storage::ImportDependencies &importDependencies,
QmlDesigner::Storage::Types &types,
QmlDesigner::SourceIds &sourceIds),
(override));
};
+11 -3
View File
@@ -76,10 +76,9 @@ protected:
}
protected:
NiceMock<SqliteDatabaseMock> databaseMock;
NiceMock<ProjectStorageMock> storageMock{databaseMock};
NiceMock<ProjectStorageMock> storageMock;
Cache cache{storageMock};
NiceMock<ProjectStorageMock> storageMockFilled{databaseMock};
NiceMock<ProjectStorageMock> storageMockFilled;
Cache cacheNotFilled{storageMockFilled};
};
@@ -104,6 +103,15 @@ TEST_F(SourcePathCache, SourceIdOfSourceIdWithOutAnyEntry)
ASSERT_THAT(sourceId, SourceId{42});
}
TEST_F(SourcePathCache, SourceIdWithSourceContextIdAndSourceName)
{
auto sourceContextId = cache.sourceContextId("/path/to"_sv);
auto sourceId = cache.sourceId(sourceContextId, "file.cpp"_sv);
ASSERT_THAT(sourceId, SourceId{42});
}
TEST_F(SourcePathCache, IfEntryExistsDontCallInStrorage)
{
cache.sourceId(SourcePathView("/path/to/file.cpp"));
@@ -27,7 +27,7 @@
#include "googletest.h"
#include <cppeditor/usages.h>
#include <projectstorage/filestatus.h>
#include <projectstorage/projectstoragetypes.h>
#include <projectstorage/sourcepathcachetypes.h>
#include <projectstorageids.h>
@@ -60,10 +60,6 @@ public:
(Utils::SmallStringView, long long),
());
MOCK_METHOD(CppEditor::Usages, valuesReturnSourceUsages, (std::size_t, int, int, int), ());
MOCK_METHOD(CppEditor::Usages, valuesReturnSourceUsages, (std::size_t, int, int, int, int), ());
MOCK_METHOD(Utils::optional<int>, valueReturnInt32, (Utils::SmallStringView), ());
MOCK_METHOD(Utils::optional<int>, valueReturnInt32, (int, Utils::SmallStringView), ());
@@ -78,7 +74,7 @@ public:
MOCK_METHOD(Utils::optional<Utils::SmallString>, valueReturnSmallString, (int), ());
MOCK_METHOD(QmlDesigner::TypeId, valueReturnsTypeId, (Utils::SmallStringView name), ());
MOCK_METHOD(QmlDesigner::TypeId, valueReturnsTypeId, (long long, Utils::SmallStringView name), ());
MOCK_METHOD(QmlDesigner::TypeId, valueWithTransactionReturnsTypeId, (long long, long long), ());
MOCK_METHOD(QmlDesigner::PropertyDeclarationId,
valueWithTransactionReturnsPropertyDeclarationId,
@@ -151,6 +147,8 @@ public:
(std::size_t, long long),
());
MOCK_METHOD(QmlDesigner::FileStatuses, rangesReturnsFileStatuses, (Utils::span<const int>), ());
template<typename ResultType, typename... QueryTypes>
auto optionalValue(const QueryTypes &...queryValues)
{
@@ -221,8 +219,6 @@ public:
return valuesReturnStringVector(reserveSize);
else if constexpr (std::is_same_v<ResultType, long long>)
return valuesReturnRowIds(reserveSize);
else if constexpr (std::is_same_v<ResultType, CppEditor::Usage>)
return valuesReturnSourceUsages(reserveSize, queryValues...);
else if constexpr (std::is_same_v<ResultType, QmlDesigner::Cache::SourceContext>)
return valuesReturnCacheSourceContexts(reserveSize);
else if constexpr (std::is_same_v<ResultType, QmlDesigner::Cache::Source>)
@@ -255,6 +251,8 @@ public:
return rangeReturnStorageSignalDeclarationViews(queryValues...);
else if constexpr (std::is_same_v<ResultType, QmlDesigner::Storage::EnumerationDeclarationView>)
return rangeReturnStorageEnumerationDeclarationViews(queryValues...);
else if constexpr (std::is_same_v<ResultType, QmlDesigner::FileStatus>)
return rangesReturnsFileStatuses(queryValues...);
else
static_assert(!std::is_same_v<ResultType, ResultType>,
"SqliteReadStatementMock::values does not handle result type!");
@@ -44,6 +44,7 @@ public:
MOCK_METHOD(void, write, (long long), ());
MOCK_METHOD(void, write, (long long, long long), ());
MOCK_METHOD(void, write, (long long, long long, int), ());
MOCK_METHOD(void, write, (long long, long long, long long), ());
MOCK_METHOD(void, write, (long long, unsigned int), ());
MOCK_METHOD(void, write, (Utils::SmallStringView, long long), ());
MOCK_METHOD(void, write, (Utils::SmallStringView, Utils::SmallStringView), ());
@@ -95,6 +96,7 @@ public:
MOCK_METHOD(void, write, (void *, long long), ());
MOCK_METHOD(void, write, (int), ());
MOCK_METHOD(void, write, (int, long long), ());
MOCK_METHOD(void, write, (int, long long, long long), ());
MOCK_METHOD(void, write, (int, int), ());
MOCK_METHOD(void, write, (uint, uint, uint), ());
MOCK_METHOD(void, write, (int, off_t, time_t), ());
@@ -109,6 +111,7 @@ public:
MOCK_METHOD(void, write, (uint, Utils::SmallStringView), ());
MOCK_METHOD(void, write, (int, Utils::SmallStringView), ());
MOCK_METHOD(void, write, (int, Utils::SmallStringView, long long), ());
MOCK_METHOD(void, write, (long long, Sqlite::NullValue, Sqlite::NullValue), ());
MOCK_METHOD(void, write, (Utils::span<int>, Utils::span<long long>), ());
MOCK_METHOD(void, write, (Utils::span<long long>), ());
+1 -2
View File
@@ -101,8 +101,7 @@ protected:
}
protected:
NiceMock<SqliteDatabaseMock> databaseMock;
NiceMock<ProjectStorageMock> mockStorage{databaseMock};
NiceMock<ProjectStorageMock> mockStorage;
StorageAdapter storageAdapter{mockStorage};
Cache cache{storageAdapter};
typename Cache::MutexType &mockMutex = cache.mutex();