| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  | /****************************************************************************
 | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** 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; | 
					
						
							| 
									
										
										
										
											2021-08-24 11:53:15 +02:00
										 |  |  | namespace Storage = QmlDesigner::Storage; | 
					
						
							| 
									
										
										
										
											2021-09-22 16:21:31 +02:00
										 |  |  | using QmlDesigner::IdPaths; | 
					
						
							| 
									
										
										
										
											2021-08-24 16:49:42 +02:00
										 |  |  | using QmlDesigner::Storage::Version; | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | MATCHER_P5(IsStorageType, | 
					
						
							| 
									
										
										
										
											2021-08-24 11:53:15 +02:00
										 |  |  |            module, | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  |            typeName, | 
					
						
							|  |  |  |            prototype, | 
					
						
							|  |  |  |            accessSemantics, | 
					
						
							|  |  |  |            sourceId, | 
					
						
							|  |  |  |            std::string(negation ? "isn't " : "is ") | 
					
						
							| 
									
										
										
										
											2021-08-24 11:53:15 +02:00
										 |  |  |                + PrintToString(Storage::Type{module, typeName, prototype, accessSemantics, sourceId})) | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     const Storage::Type &type = arg; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-24 11:53:15 +02:00
										 |  |  |     return type.module == module && type.typeName == typeName | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  |            && type.accessSemantics == accessSemantics && type.sourceId == sourceId | 
					
						
							| 
									
										
										
										
											2021-08-24 16:49:42 +02:00
										 |  |  |            && Storage::ImportedTypeName{prototype} == type.prototype; | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							| 
									
										
										
										
											2021-08-24 16:49:42 +02:00
										 |  |  |            && Storage::ImportedTypeName{typeName} == propertyDeclaration.typeName | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  |            && propertyDeclaration.traits == traits; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  | MATCHER_P3(IsExportedType, | 
					
						
							|  |  |  |            name, | 
					
						
							|  |  |  |            majorVersion, | 
					
						
							|  |  |  |            minorVersion, | 
					
						
							|  |  |  |            std::string(negation ? "isn't " : "is ") | 
					
						
							|  |  |  |                + PrintToString(Storage::ExportedType{name, | 
					
						
							|  |  |  |                                                      Storage::Version{majorVersion, minorVersion}})) | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     const Storage::ExportedType &type = arg; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  |     return type.name == name && type.version == Storage::Version{majorVersion, minorVersion}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MATCHER_P2(IsModule, | 
					
						
							|  |  |  |            name, | 
					
						
							|  |  |  |            sourceId, | 
					
						
							|  |  |  |            std::string(negation ? "isn't " : "is ") + PrintToString(Storage::Module{name, sourceId})) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const Storage::Module &module = arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return module.name == name && module.sourceId == sourceId; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MATCHER_P3(IsFileStatus, | 
					
						
							|  |  |  |            sourceId, | 
					
						
							|  |  |  |            size, | 
					
						
							|  |  |  |            lastModified, | 
					
						
							|  |  |  |            std::string(negation ? "isn't " : "is ") | 
					
						
							|  |  |  |                + PrintToString(FileStatus{sourceId, size, lastModified})) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const FileStatus &fileStatus = arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return fileStatus.sourceId == sourceId && fileStatus.size == size | 
					
						
							|  |  |  |            && fileStatus.lastModified == lastModified; | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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)); | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId1))) | 
					
						
							|  |  |  |             .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 12})); | 
					
						
							|  |  |  |         ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId1))) | 
					
						
							|  |  |  |             .WillByDefault(Return(FileStatus{qmlDocumentSourceId1, 22, 2})); | 
					
						
							|  |  |  |         ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId2))) | 
					
						
							|  |  |  |             .WillByDefault(Return(FileStatus{qmlDocumentSourceId2, 22, 13})); | 
					
						
							|  |  |  |         ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId2))) | 
					
						
							|  |  |  |             .WillByDefault(Return(FileStatus{qmlDocumentSourceId2, 22, 2})); | 
					
						
							|  |  |  |         ON_CALL(fileSystemMock, fileStatus(Eq(qmlDocumentSourceId3))) | 
					
						
							|  |  |  |             .WillByDefault(Return(FileStatus{qmlDocumentSourceId3, 22, 14})); | 
					
						
							|  |  |  |         ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId3))) | 
					
						
							|  |  |  |             .WillByDefault(Return(FileStatus{qmlDocumentSourceId3, 22, 2})); | 
					
						
							| 
									
										
										
										
											2021-09-22 16:21:31 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         firstType.prototype = Storage::ImportedType{"Object"}; | 
					
						
							|  |  |  |         secondType.prototype = Storage::ImportedType{"Object2"}; | 
					
						
							|  |  |  |         thirdType.prototype = Storage::ImportedType{"Object3"}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         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([&](auto, auto &imports) { | 
					
						
							|  |  |  |             imports.push_back(import1); | 
					
						
							|  |  |  |             return firstType; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         ON_CALL(qmlDocumentParserMock, parse(qmlDocument2, _)).WillByDefault([&](auto, auto &imports) { | 
					
						
							|  |  |  |             imports.push_back(import2); | 
					
						
							|  |  |  |             return secondType; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         ON_CALL(qmlDocumentParserMock, parse(qmlDocument3, _)).WillByDefault([&](auto, auto &imports) { | 
					
						
							|  |  |  |             imports.push_back(import3); | 
					
						
							|  |  |  |             return thirdType; | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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")}; | 
					
						
							| 
									
										
										
										
											2021-08-24 16:49:42 +02:00
										 |  |  |     Storage::Type objectType{Storage::Module{"Qml"}, | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  |                              "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"); | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  |     SourceId qmlDocumentSourceId1 = sourcePathCache.sourceId("/path/First.qml"); | 
					
						
							|  |  |  |     SourceId qmlDocumentSourceId2 = sourcePathCache.sourceId("/path/First.2.qml"); | 
					
						
							|  |  |  |     SourceId qmlDocumentSourceId3 = sourcePathCache.sourceId("/path/Second.qml"); | 
					
						
							| 
									
										
										
										
											2021-09-22 16:21:31 +02:00
										 |  |  |     QString qmlDocument1{"First{}"}; | 
					
						
							|  |  |  |     QString qmlDocument2{"Second{}"}; | 
					
						
							|  |  |  |     QString qmlDocument3{"Third{}"}; | 
					
						
							|  |  |  |     Storage::Type firstType; | 
					
						
							|  |  |  |     Storage::Type secondType; | 
					
						
							|  |  |  |     Storage::Type thirdType; | 
					
						
							|  |  |  |     Storage::Import import1{"Qml", Storage::Version{2, 3}, qmlDocumentSourceId1}; | 
					
						
							|  |  |  |     Storage::Import import2{"Qml", Storage::Version{}, qmlDocumentSourceId2}; | 
					
						
							|  |  |  |     Storage::Import import3{"Qml", Storage::Version{2}, qmlDocumentSourceId3}; | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  | TEST_F(ProjectStorageUpdater, SynchronizeIsEmptyForNoChange) | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  |     ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmltypesPathSourceId))) | 
					
						
							|  |  |  |         .WillByDefault(Return(FileStatus{qmltypesPathSourceId, 21, 421})); | 
					
						
							|  |  |  |     ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmltypes2PathSourceId))) | 
					
						
							|  |  |  |         .WillByDefault(Return(FileStatus{qmltypes2PathSourceId, 21, 421})); | 
					
						
							|  |  |  |     ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDirPathSourceId))) | 
					
						
							|  |  |  |         .WillByDefault(Return(FileStatus{qmlDirPathSourceId, 21, 421})); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  |     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"); | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  |     Storage::Import import{"Qml", Storage::Version{2, 3}, qmltypesPathSourceId}; | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  |     QString qmltypes{"Module {\ndependencies: []}"}; | 
					
						
							|  |  |  |     ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/example.qmltypes")))) | 
					
						
							|  |  |  |         .WillByDefault(Return(qmltypes)); | 
					
						
							|  |  |  |     ON_CALL(qmlTypesParserMock, parse(qmltypes, _, _, _)) | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  |         .WillByDefault([&](auto, auto &imports, auto &types, auto &sourceIds) { | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  |             types.push_back(objectType); | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  |             imports.push_back(import); | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     EXPECT_CALL(projectStorageMock, | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  |                 synchronize(ElementsAre(IsModule("Example", qmlDirPathSourceId)), | 
					
						
							|  |  |  |                             ElementsAre(import), | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  |                             ElementsAre(Eq(objectType)), | 
					
						
							|  |  |  |                             UnorderedElementsAre(qmlDirPathSourceId, qmltypesPathSourceId), | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  |                             UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), | 
					
						
							|  |  |  |                                                  IsFileStatus(qmltypesPathSourceId, 21, 421)))); | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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, _, _, _)) | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  |         .WillByDefault([&](auto, auto &imports, auto &types, auto &sourceIds) { | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  |             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)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  |     EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument1, _)); | 
					
						
							|  |  |  |     EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument2, _)); | 
					
						
							|  |  |  |     EXPECT_CALL(qmlDocumentParserMock, parse(qmlDocument3, _)); | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     updater.update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST_F(ProjectStorageUpdater, SynchronizeQmlDocuments) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  |     QString qmldir{"module Example\nFirstType 1.0 First.qml\nFirstType 2.2 " | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  |                    "First.2.qml\nSecondType 2.1 OldSecond.qml\nSecondType 2.2 Second.qml\n"}; | 
					
						
							|  |  |  |     ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     EXPECT_CALL(projectStorageMock, | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  |                 synchronize(ElementsAre(IsModule("Example", qmlDirPathSourceId)), | 
					
						
							|  |  |  |                             UnorderedElementsAre(import1, import2, import3), | 
					
						
							|  |  |  |                             UnorderedElementsAre( | 
					
						
							|  |  |  |                                 AllOf(IsStorageType(Storage::Module{"Example"}, | 
					
						
							|  |  |  |                                                     "First.qml", | 
					
						
							|  |  |  |                                                     Storage::ImportedType{"Object"}, | 
					
						
							|  |  |  |                                                     TypeAccessSemantics::Reference, | 
					
						
							|  |  |  |                                                     qmlDocumentSourceId1), | 
					
						
							|  |  |  |                                       Field(&Storage::Type::exportedTypes, | 
					
						
							|  |  |  |                                             ElementsAre(IsExportedType("FirstType", 1, 0)))), | 
					
						
							|  |  |  |                                 AllOf(IsStorageType(Storage::Module{"Example"}, | 
					
						
							|  |  |  |                                                     "First.2.qml", | 
					
						
							|  |  |  |                                                     Storage::ImportedType{"Object2"}, | 
					
						
							|  |  |  |                                                     TypeAccessSemantics::Reference, | 
					
						
							|  |  |  |                                                     qmlDocumentSourceId2), | 
					
						
							|  |  |  |                                       Field(&Storage::Type::exportedTypes, | 
					
						
							|  |  |  |                                             ElementsAre(IsExportedType("FirstType", 2, 2)))), | 
					
						
							|  |  |  |                                 AllOf(IsStorageType(Storage::Module{"Example"}, | 
					
						
							|  |  |  |                                                     "Second.qml", | 
					
						
							|  |  |  |                                                     Storage::ImportedType{"Object3"}, | 
					
						
							|  |  |  |                                                     TypeAccessSemantics::Reference, | 
					
						
							|  |  |  |                                                     qmlDocumentSourceId3), | 
					
						
							|  |  |  |                                       Field(&Storage::Type::exportedTypes, | 
					
						
							|  |  |  |                                             ElementsAre(IsExportedType("SecondType", 2, 2))))), | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  |                             UnorderedElementsAre(qmlDirPathSourceId, | 
					
						
							|  |  |  |                                                  qmlDocumentSourceId1, | 
					
						
							|  |  |  |                                                  qmlDocumentSourceId2, | 
					
						
							|  |  |  |                                                  qmlDocumentSourceId3), | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  |                             UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), | 
					
						
							|  |  |  |                                                  IsFileStatus(qmlDocumentSourceId1, 22, 12), | 
					
						
							|  |  |  |                                                  IsFileStatus(qmlDocumentSourceId2, 22, 13), | 
					
						
							|  |  |  |                                                  IsFileStatus(qmlDocumentSourceId3, 22, 14)))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     updater.update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 16:21:31 +02:00
										 |  |  | TEST_F(ProjectStorageUpdater, SynchronizeQmlDocumentsDontUpdateIfUpToDate) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString qmldir{"module Example\nFirstType 1.0 First.qml\nFirstType 2.2 " | 
					
						
							|  |  |  |                    "First.2.qml\nSecondType 2.1 OldSecond.qml\nSecondType 2.2 Second.qml\n"}; | 
					
						
							|  |  |  |     ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path/qmldir")))).WillByDefault(Return(qmldir)); | 
					
						
							|  |  |  |     ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDocumentSourceId3))) | 
					
						
							|  |  |  |         .WillByDefault(Return(FileStatus{qmlDocumentSourceId3, 22, 14})); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     EXPECT_CALL( | 
					
						
							|  |  |  |         projectStorageMock, | 
					
						
							|  |  |  |         synchronize(ElementsAre(IsModule("Example", qmlDirPathSourceId)), | 
					
						
							|  |  |  |                     UnorderedElementsAre(import1, import2), | 
					
						
							|  |  |  |                     UnorderedElementsAre(AllOf(IsStorageType(Storage::Module{"Example"}, | 
					
						
							|  |  |  |                                                              "First.qml", | 
					
						
							|  |  |  |                                                              Storage::ImportedType{"Object"}, | 
					
						
							|  |  |  |                                                              TypeAccessSemantics::Reference, | 
					
						
							|  |  |  |                                                              qmlDocumentSourceId1), | 
					
						
							|  |  |  |                                                Field(&Storage::Type::exportedTypes, | 
					
						
							|  |  |  |                                                      ElementsAre(IsExportedType("FirstType", 1, 0)))), | 
					
						
							|  |  |  |                                          AllOf(IsStorageType(Storage::Module{"Example"}, | 
					
						
							|  |  |  |                                                              "First.2.qml", | 
					
						
							|  |  |  |                                                              Storage::ImportedType{"Object2"}, | 
					
						
							|  |  |  |                                                              TypeAccessSemantics::Reference, | 
					
						
							|  |  |  |                                                              qmlDocumentSourceId2), | 
					
						
							|  |  |  |                                                Field(&Storage::Type::exportedTypes, | 
					
						
							|  |  |  |                                                      ElementsAre(IsExportedType("FirstType", 2, 2))))), | 
					
						
							|  |  |  |                     UnorderedElementsAre(qmlDirPathSourceId, qmlDocumentSourceId1, qmlDocumentSourceId2), | 
					
						
							|  |  |  |                     UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), | 
					
						
							|  |  |  |                                          IsFileStatus(qmlDocumentSourceId1, 22, 12), | 
					
						
							|  |  |  |                                          IsFileStatus(qmlDocumentSourceId2, 22, 13)))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     updater.update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-20 14:12:57 +02:00
										 |  |  | TEST_F(ProjectStorageUpdater, SynchronizeModules) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     SourceId qmlDirPathSourceId2 = sourcePathCache.sourceId("/path2/qmldir"); | 
					
						
							|  |  |  |     ON_CALL(fileSystemMock, fileStatus(Eq(qmlDirPathSourceId2))) | 
					
						
							|  |  |  |         .WillByDefault(Return(FileStatus{qmlDirPathSourceId2, 22, 423})); | 
					
						
							|  |  |  |     ON_CALL(projectStorageMock, fetchFileStatus(Eq(qmlDirPathSourceId2))) | 
					
						
							|  |  |  |         .WillByDefault(Return(FileStatus{qmlDirPathSourceId2, 2, 421})); | 
					
						
							|  |  |  |     QString qmldir2{"module Example2\n"}; | 
					
						
							|  |  |  |     ON_CALL(projectManagerMock, qtQmlDirs()) | 
					
						
							|  |  |  |         .WillByDefault(Return(QStringList{"/path/qmldir", "/path2/qmldir"})); | 
					
						
							|  |  |  |     ON_CALL(fileSystemMock, contentAsQString(Eq(QString("/path2/qmldir")))).WillByDefault(Return(qmldir2)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     EXPECT_CALL(projectStorageMock, | 
					
						
							|  |  |  |                 synchronize(UnorderedElementsAre(IsModule("Example", qmlDirPathSourceId), | 
					
						
							|  |  |  |                                                  IsModule("Example2", qmlDirPathSourceId2)), | 
					
						
							|  |  |  |                             _, | 
					
						
							|  |  |  |                             _, | 
					
						
							|  |  |  |                             _, | 
					
						
							|  |  |  |                             UnorderedElementsAre(IsFileStatus(qmlDirPathSourceId, 21, 421), | 
					
						
							|  |  |  |                                                  IsFileStatus(qmltypesPathSourceId, 21, 421), | 
					
						
							|  |  |  |                                                  IsFileStatus(qmlDirPathSourceId2, 22, 423)))); | 
					
						
							| 
									
										
										
										
											2021-09-16 17:19:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     updater.update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace
 |