1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "googletest.h"
27
28 #include "sqlitedatabasemock.h"
29
30 #include <modelnode.h>
31 #include <projectstorage/projectstorage.h>
32 #include <projectstorage/sourcepathcache.h>
33 #include <sqlitedatabase.h>
34 #include <sqlitereadstatement.h>
35 #include <sqlitewritestatement.h>
36
37 namespace {
38
39 using QmlDesigner::ImportId;
40 using QmlDesigner::PropertyDeclarationId;
41 using QmlDesigner::SourceContextId;
42 using QmlDesigner::SourceId;
43 using QmlDesigner::TypeId;
44 using QmlDesigner::Cache::Source;
45 using QmlDesigner::Cache::SourceContext;
46 using QmlDesigner::Storage::TypeAccessSemantics;
47
48 namespace Storage = QmlDesigner::Storage;
49
50 MATCHER_P2(IsSourceContext,
51 id,
52 value,
53 std::string(negation ? "isn't " : "is ") + PrintToString(SourceContext{value, id}))
54 {
55 const SourceContext &sourceContext = arg;
56
57 return sourceContext.id == id && sourceContext.value == value;
58 }
59
60 MATCHER_P2(IsSourceNameAndSourceContextId,
61 name,
62 id,
63 std::string(negation ? "isn't " : "is ")
64 + PrintToString(QmlDesigner::Cache::SourceNameAndSourceContextId{name, id}))
65 {
66 const QmlDesigner::Cache::SourceNameAndSourceContextId &sourceNameAndSourceContextId = arg;
67
68 return sourceNameAndSourceContextId.sourceName == name
69 && sourceNameAndSourceContextId.sourceContextId == id;
70 }
71
72 MATCHER_P5(IsStorageType,
73 importId,
74 typeName,
75 prototype,
76 accessSemantics,
77 sourceId,
78 std::string(negation ? "isn't " : "is ")
79 + PrintToString(Storage::Type{importId, typeName, prototype, accessSemantics, sourceId}))
80 {
81 const Storage::Type &type = arg;
82
83 return type.importId == importId && type.typeName == typeName
84 && type.accessSemantics == accessSemantics && type.sourceId == sourceId
__anon2a96ed8e0202(auto &&v) 85 && Utils::visit([&](auto &&v) -> bool { return v.name == prototype.name; }, type.prototype);
86 }
87
88 MATCHER_P4(IsStorageTypeWithInvalidSourceId,
89 importId,
90 typeName,
91 prototype,
92 accessSemantics,
93 std::string(negation ? "isn't " : "is ")
94 + PrintToString(Storage::Type{importId, typeName, prototype, accessSemantics, SourceId{}}))
95 {
96 const Storage::Type &type = arg;
97
98 return type.importId == importId && type.typeName == typeName && type.prototype == prototype
99 && type.accessSemantics == accessSemantics && !type.sourceId.isValid();
100 }
101
102 MATCHER_P(IsExportedType,
103 name,
104 std::string(negation ? "isn't " : "is ") + PrintToString(Storage::ExportedType{name}))
105 {
106 const Storage::ExportedType &type = arg;
107
108 return type.name == name;
109 }
110
111 MATCHER_P3(IsPropertyDeclaration,
112 name,
113 typeName,
114 traits,
115 std::string(negation ? "isn't " : "is ")
116 + PrintToString(Storage::PropertyDeclaration{name, typeName, traits}))
117 {
118 const Storage::PropertyDeclaration &propertyDeclaration = arg;
119
120 return propertyDeclaration.name == name
__anon2a96ed8e0302(auto &&v) 121 && Utils::visit([&](auto &&v) -> bool { return v.name == typeName.name; },
122 propertyDeclaration.typeName)
123 && propertyDeclaration.traits == traits;
124 }
125
126 MATCHER_P2(IsBasicImport,
127 name,
128 version,
129 std::string(negation ? "isn't " : "is ") + PrintToString(Storage::Import{name, version}))
130 {
131 const Storage::BasicImport &import = arg;
132
133 return import.name == name && import.version == version;
134 }
135
136 MATCHER_P3(IsImport,
137 name,
138 version,
139 sourceId,
140 std::string(negation ? "isn't " : "is ")
141 + PrintToString(Storage::Import{name, version, sourceId}))
142 {
143 const Storage::Import &import = arg;
144
145 return import.name == name && import.version == version && &import.sourceId == &sourceId;
146 }
147
148 class ProjectStorage : public testing::Test
149 {
150 public:
ProjectStorage()151 ProjectStorage()
152 {
153 ON_CALL(selectSourceContextIdFromSourceContextsBySourceContextPathStatement,
154 valueReturnsSourceContextId(A<Utils::SmallStringView>()))
155 .WillByDefault(Return(SourceContextId()));
156 ON_CALL(selectSourceContextIdFromSourceContextsBySourceContextPathStatement,
157 valueReturnsSourceContextId(Utils::SmallStringView("")))
158 .WillByDefault(Return(SourceContextId(0)));
159 ON_CALL(selectSourceContextIdFromSourceContextsBySourceContextPathStatement,
160 valueReturnsSourceContextId(Utils::SmallStringView("/path/to")))
161 .WillByDefault(Return(SourceContextId(5)));
162 ON_CALL(databaseMock, lastInsertedRowId()).WillByDefault(Return(12));
163 ON_CALL(selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatment,
164 valueReturnInt32(_, _))
165 .WillByDefault(Return(Utils::optional<int>()));
166 ON_CALL(selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatment,
167 valueReturnInt32(0, Utils::SmallStringView("")))
168 .WillByDefault(Return(Utils::optional<int>(0)));
169 ON_CALL(selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatment,
170 valueReturnInt32(5, Utils::SmallStringView("file.h")))
171 .WillByDefault(Return(Utils::optional<int>(42)));
172 ON_CALL(selectAllSourcesStatement, valuesReturnCacheSources(_))
173 .WillByDefault(Return(std::vector<Source>{{"file.h", SourceContextId{1}, SourceId{1}},
174 {"file.cpp", SourceContextId{2}, SourceId{4}}}));
175 ON_CALL(selectSourceContextPathFromSourceContextsBySourceContextIdStatement,
176 valueReturnPathString(5))
177 .WillByDefault(Return(Utils::optional<Utils::PathString>("/path/to")));
178 ON_CALL(selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement,
179 valueReturnCacheSourceNameAndSourceContextId(42))
180 .WillByDefault(Return(QmlDesigner::Cache::SourceNameAndSourceContextId{"file.cpp", 5}));
181 ON_CALL(selectSourceContextIdFromSourcesBySourceIdStatement,
182 valueReturnInt32(TypedEq<int>(42)))
183 .WillByDefault(Return(Utils::optional<int>(5)));
184 }
185
186 protected:
187 using ProjectStorageMock = QmlDesigner::ProjectStorage<SqliteDatabaseMock>;
188 template<int ResultCount>
189 using ReadStatement = ProjectStorageMock::ReadStatement<ResultCount>;
190 using WriteStatement = ProjectStorageMock::WriteStatement;
191 template<int ResultCount>
192 using ReadWriteStatement = ProjectStorageMock::ReadWriteStatement<ResultCount>;
193
194 NiceMock<SqliteDatabaseMock> databaseMock;
195 ProjectStorageMock storage{databaseMock, true};
196 ReadWriteStatement<1> &upsertTypeStatement = storage.upsertTypeStatement;
197 ReadStatement<1> &selectTypeIdByExportedNameStatement = storage.selectTypeIdByExportedNameStatement;
198 WriteStatement &upsertExportedTypesStatement = storage.upsertExportedTypesStatement;
199 ReadStatement<1> &selectSourceContextIdFromSourceContextsBySourceContextPathStatement
200 = storage.selectSourceContextIdFromSourceContextsBySourceContextPathStatement;
201 ReadStatement<1> &selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatment
202 = storage.selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatement;
203 ReadStatement<1> &selectSourceContextPathFromSourceContextsBySourceContextIdStatement
204 = storage.selectSourceContextPathFromSourceContextsBySourceContextIdStatement;
205 ReadStatement<2> &selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement
206 = storage.selectSourceNameAndSourceContextIdFromSourcesBySourceIdStatement;
207 ReadStatement<2> &selectAllSourceContextsStatement = storage.selectAllSourceContextsStatement;
208 WriteStatement &insertIntoSourceContexts = storage.insertIntoSourceContextsStatement;
209 WriteStatement &insertIntoSourcesStatement = storage.insertIntoSourcesStatement;
210 ReadStatement<3> &selectAllSourcesStatement = storage.selectAllSourcesStatement;
211 ReadStatement<1> &selectSourceContextIdFromSourcesBySourceIdStatement = storage.selectSourceContextIdFromSourcesBySourceIdStatement;
212 ReadStatement<5> &selectTypeByTypeIdStatement = storage.selectTypeByTypeIdStatement;
213 ReadStatement<1> &selectExportedTypesByTypeIdStatement = storage.selectExportedTypesByTypeIdStatement;
214 ReadStatement<6> &selectTypesStatement = storage.selectTypesStatement;
215 };
216
TEST_F(ProjectStorage,SelectForFetchingSourceContextIdForKnownPathCalls)217 TEST_F(ProjectStorage, SelectForFetchingSourceContextIdForKnownPathCalls)
218 {
219 InSequence s;
220
221 EXPECT_CALL(databaseMock, deferredBegin());
222 EXPECT_CALL(selectSourceContextIdFromSourceContextsBySourceContextPathStatement,
223 valueReturnsSourceContextId(TypedEq<Utils::SmallStringView>("/path/to")));
224 EXPECT_CALL(databaseMock, commit());
225
226 storage.fetchSourceContextId("/path/to");
227 }
228
TEST_F(ProjectStorage,SelectForFetchingSourceIdForKnownPathCalls)229 TEST_F(ProjectStorage, SelectForFetchingSourceIdForKnownPathCalls)
230 {
231 InSequence s;
232
233 EXPECT_CALL(databaseMock, deferredBegin());
234 EXPECT_CALL(selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatment,
235 valueReturnsSourceId(5, Eq("file.h")));
236 EXPECT_CALL(databaseMock, commit());
237
238 storage.fetchSourceId(SourceContextId{5}, "file.h");
239 }
240
TEST_F(ProjectStorage,NotWriteForFetchingSourceContextIdForKnownPathCalls)241 TEST_F(ProjectStorage, NotWriteForFetchingSourceContextIdForKnownPathCalls)
242 {
243 EXPECT_CALL(insertIntoSourceContexts, write(An<Utils::SmallStringView>())).Times(0);
244
245 storage.fetchSourceContextId("/path/to");
246 }
247
TEST_F(ProjectStorage,NotWriteForFetchingSoureIdForKnownEntryCalls)248 TEST_F(ProjectStorage, NotWriteForFetchingSoureIdForKnownEntryCalls)
249 {
250 EXPECT_CALL(insertIntoSourcesStatement, write(An<uint>(), An<Utils::SmallStringView>())).Times(0);
251
252 storage.fetchSourceId(SourceContextId{5}, "file.h");
253 }
254
TEST_F(ProjectStorage,SelectAndWriteForFetchingSourceContextIdForUnknownPathCalls)255 TEST_F(ProjectStorage, SelectAndWriteForFetchingSourceContextIdForUnknownPathCalls)
256 {
257 InSequence s;
258
259 EXPECT_CALL(databaseMock, deferredBegin());
260 EXPECT_CALL(selectSourceContextIdFromSourceContextsBySourceContextPathStatement,
261 valueReturnsSourceContextId(
262 TypedEq<Utils::SmallStringView>("/some/not/known/path")));
263 EXPECT_CALL(insertIntoSourceContexts,
264 write(TypedEq<Utils::SmallStringView>("/some/not/known/path")));
265 EXPECT_CALL(databaseMock, commit());
266
267 storage.fetchSourceContextId("/some/not/known/path");
268 }
269
TEST_F(ProjectStorage,SelectAndWriteForFetchingSourceIdForUnknownEntryCalls)270 TEST_F(ProjectStorage, SelectAndWriteForFetchingSourceIdForUnknownEntryCalls)
271 {
272 InSequence s;
273
274 EXPECT_CALL(databaseMock, deferredBegin());
275 EXPECT_CALL(selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatment,
276 valueReturnsSourceId(5, Eq("unknownfile.h")));
277 EXPECT_CALL(insertIntoSourcesStatement,
278 write(TypedEq<int>(5), TypedEq<Utils::SmallStringView>("unknownfile.h")));
279 EXPECT_CALL(databaseMock, commit());
280
281 storage.fetchSourceId(SourceContextId{5}, "unknownfile.h");
282 }
283
TEST_F(ProjectStorage,ValueForFetchSourceContextForIdCalls)284 TEST_F(ProjectStorage, ValueForFetchSourceContextForIdCalls)
285 {
286 EXPECT_CALL(databaseMock, deferredBegin());
287 EXPECT_CALL(selectSourceContextPathFromSourceContextsBySourceContextIdStatement,
288 valueReturnPathString(5));
289 EXPECT_CALL(databaseMock, commit());
290
291 storage.fetchSourceContextPath(SourceContextId{5});
292 }
293
TEST_F(ProjectStorage,FetchSourceContextForId)294 TEST_F(ProjectStorage, FetchSourceContextForId)
295 {
296 auto path = storage.fetchSourceContextPath(SourceContextId{5});
297
298 ASSERT_THAT(path, Eq("/path/to"));
299 }
300
TEST_F(ProjectStorage,ThrowAsFetchingSourceContextPathForNonExistingId)301 TEST_F(ProjectStorage, ThrowAsFetchingSourceContextPathForNonExistingId)
302 {
303 ASSERT_THROW(storage.fetchSourceContextPath(SourceContextId{12}),
304 QmlDesigner::SourceContextIdDoesNotExists);
305 }
306
TEST_F(ProjectStorage,FetchSourceContextIdForUnknownSourceId)307 TEST_F(ProjectStorage, FetchSourceContextIdForUnknownSourceId)
308 {
309 ASSERT_THROW(storage.fetchSourceContextId(SourceId{1111}), QmlDesigner::SourceIdDoesNotExists);
310 }
311
TEST_F(ProjectStorage,FetchSourceContextIdThrows)312 TEST_F(ProjectStorage, FetchSourceContextIdThrows)
313 {
314 ASSERT_THROW(storage.fetchSourceContextId(SourceId{41}), QmlDesigner::SourceIdDoesNotExists);
315 }
316
TEST_F(ProjectStorage,GetTheSourceContextIdBackAfterFetchingANewEntryFromSourceContextsUnguarded)317 TEST_F(ProjectStorage, GetTheSourceContextIdBackAfterFetchingANewEntryFromSourceContextsUnguarded)
318 {
319 auto sourceContextId = storage.fetchSourceContextIdUnguarded("/some/not/known/path");
320
321 ASSERT_THAT(sourceContextId, SourceContextId{12});
322 }
323
TEST_F(ProjectStorage,GetTheSourceIdBackAfterFetchingANewEntryFromSourcesUnguarded)324 TEST_F(ProjectStorage, GetTheSourceIdBackAfterFetchingANewEntryFromSourcesUnguarded)
325 {
326 auto sourceId = storage.fetchSourceIdUnguarded(SourceContextId{5}, "unknownfile.h");
327
328 ASSERT_THAT(sourceId, SourceId{12});
329 }
330
TEST_F(ProjectStorage,SelectForFetchingSourceContextIdForKnownPathUnguardedCalls)331 TEST_F(ProjectStorage, SelectForFetchingSourceContextIdForKnownPathUnguardedCalls)
332 {
333 InSequence s;
334
335 EXPECT_CALL(selectSourceContextIdFromSourceContextsBySourceContextPathStatement,
336 valueReturnsSourceContextId(TypedEq<Utils::SmallStringView>("/path/to")));
337
338 storage.fetchSourceContextIdUnguarded("/path/to");
339 }
340
TEST_F(ProjectStorage,SelectForFetchingSourceIdForKnownPathUnguardedCalls)341 TEST_F(ProjectStorage, SelectForFetchingSourceIdForKnownPathUnguardedCalls)
342 {
343 EXPECT_CALL(selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatment,
344 valueReturnsSourceId(5, Eq("file.h")));
345
346 storage.fetchSourceIdUnguarded(SourceContextId{5}, "file.h");
347 }
348
TEST_F(ProjectStorage,NotWriteForFetchingSourceContextIdForKnownPathUnguardedCalls)349 TEST_F(ProjectStorage, NotWriteForFetchingSourceContextIdForKnownPathUnguardedCalls)
350 {
351 EXPECT_CALL(insertIntoSourceContexts, write(An<Utils::SmallStringView>())).Times(0);
352
353 storage.fetchSourceContextIdUnguarded("/path/to");
354 }
355
TEST_F(ProjectStorage,NotWriteForFetchingSoureIdForKnownEntryUnguardedCalls)356 TEST_F(ProjectStorage, NotWriteForFetchingSoureIdForKnownEntryUnguardedCalls)
357 {
358 EXPECT_CALL(insertIntoSourcesStatement, write(An<uint>(), An<Utils::SmallStringView>())).Times(0);
359
360 storage.fetchSourceIdUnguarded(SourceContextId{5}, "file.h");
361 }
362
TEST_F(ProjectStorage,SelectAndWriteForFetchingSourceContextIdForUnknownPathUnguardedCalls)363 TEST_F(ProjectStorage, SelectAndWriteForFetchingSourceContextIdForUnknownPathUnguardedCalls)
364 {
365 InSequence s;
366
367 EXPECT_CALL(selectSourceContextIdFromSourceContextsBySourceContextPathStatement,
368 valueReturnsSourceContextId(
369 TypedEq<Utils::SmallStringView>("/some/not/known/path")));
370 EXPECT_CALL(insertIntoSourceContexts,
371 write(TypedEq<Utils::SmallStringView>("/some/not/known/path")));
372
373 storage.fetchSourceContextIdUnguarded("/some/not/known/path");
374 }
375
TEST_F(ProjectStorage,SelectAndWriteForFetchingSourceIdForUnknownEntryUnguardedCalls)376 TEST_F(ProjectStorage, SelectAndWriteForFetchingSourceIdForUnknownEntryUnguardedCalls)
377 {
378 InSequence s;
379
380 EXPECT_CALL(selectSourceIdFromSourcesBySourceContextIdAndSourceNameStatment,
381 valueReturnsSourceId(5, Eq("unknownfile.h")));
382 EXPECT_CALL(insertIntoSourcesStatement,
383 write(TypedEq<int>(5), TypedEq<Utils::SmallStringView>("unknownfile.h")));
384
385 storage.fetchSourceIdUnguarded(SourceContextId{5}, "unknownfile.h");
386 }
387
TEST_F(ProjectStorage,SelectAndWriteForFetchingSourceContextIdTwoTimesIfTheIndexIsConstraintBecauseTheEntryExistsAlreadyCalls)388 TEST_F(ProjectStorage,
389 SelectAndWriteForFetchingSourceContextIdTwoTimesIfTheIndexIsConstraintBecauseTheEntryExistsAlreadyCalls)
390 {
391 InSequence s;
392
393 EXPECT_CALL(databaseMock, deferredBegin());
394 EXPECT_CALL(selectSourceContextIdFromSourceContextsBySourceContextPathStatement,
395 valueReturnsSourceContextId(TypedEq<Utils::SmallStringView>("/other/unknow/path")));
396 EXPECT_CALL(insertIntoSourceContexts, write(TypedEq<Utils::SmallStringView>("/other/unknow/path")))
397 .WillOnce(Throw(Sqlite::ConstraintPreventsModification("busy")));
398 EXPECT_CALL(databaseMock, rollback());
399 EXPECT_CALL(databaseMock, deferredBegin());
400 EXPECT_CALL(selectSourceContextIdFromSourceContextsBySourceContextPathStatement,
401 valueReturnsSourceContextId(TypedEq<Utils::SmallStringView>("/other/unknow/path")));
402 EXPECT_CALL(insertIntoSourceContexts,
403 write(TypedEq<Utils::SmallStringView>("/other/unknow/path")));
404 EXPECT_CALL(databaseMock, commit());
405
406 storage.fetchSourceContextId("/other/unknow/path");
407 }
408
TEST_F(ProjectStorage,FetchTypeByTypeIdCalls)409 TEST_F(ProjectStorage, FetchTypeByTypeIdCalls)
410 {
411 InSequence s;
412
413 EXPECT_CALL(databaseMock, deferredBegin());
414 EXPECT_CALL(selectTypeByTypeIdStatement, valueReturnsStorageType(Eq(21)));
415 EXPECT_CALL(selectExportedTypesByTypeIdStatement, valuesReturnsStorageExportedTypes(_, Eq(21)));
416 EXPECT_CALL(databaseMock, commit());
417
418 storage.fetchTypeByTypeId(TypeId{21});
419 }
420
TEST_F(ProjectStorage,FetchTypesCalls)421 TEST_F(ProjectStorage, FetchTypesCalls)
422 {
423 InSequence s;
424 Storage::Type type{ImportId{}, {}, {}, {}, SourceId{}, {}, {}, {}, {}, {}, {}, {}, TypeId{55}};
425 Storage::Types types{type};
426
427 EXPECT_CALL(databaseMock, deferredBegin());
428 EXPECT_CALL(selectTypesStatement, valuesReturnsStorageTypes(_)).WillOnce(Return(types));
429 EXPECT_CALL(selectExportedTypesByTypeIdStatement, valuesReturnsStorageExportedTypes(_, Eq(55)));
430 EXPECT_CALL(databaseMock, commit());
431
432 storage.fetchTypes();
433 }
434
435 class ProjectStorageSlowTest : public testing::Test
436 {
437 protected:
438 template<typename Range>
toValues(Range && range)439 static auto toValues(Range &&range)
440 {
441 using Type = typename std::decay_t<Range>;
442
443 return std::vector<typename Type::value_type>{range.begin(), range.end()};
444 }
445
addSomeDummyData()446 void addSomeDummyData()
447 {
448 auto sourceContextId1 = storage.fetchSourceContextId("/path/dummy");
449 auto sourceContextId2 = storage.fetchSourceContextId("/path/dummy2");
450 auto sourceContextId3 = storage.fetchSourceContextId("/path/");
451
452 storage.fetchSourceId(sourceContextId1, "foo");
453 storage.fetchSourceId(sourceContextId1, "dummy");
454 storage.fetchSourceId(sourceContextId2, "foo");
455 storage.fetchSourceId(sourceContextId2, "bar");
456 storage.fetchSourceId(sourceContextId3, "foo");
457 storage.fetchSourceId(sourceContextId3, "bar");
458 storage.fetchSourceId(sourceContextId1, "bar");
459 storage.fetchSourceId(sourceContextId3, "bar");
460 }
461
createTypes()462 auto createTypes()
463 {
464 setUpImports();
465
466 sourceId1 = sourcePathCache.sourceId(path1);
467 sourceId2 = sourcePathCache.sourceId(path2);
468 sourceId3 = sourcePathCache.sourceId(path3);
469 sourceId4 = sourcePathCache.sourceId(path4);
470
471 return Storage::Types{
472 Storage::Type{
473 importId2,
474 "QQuickItem",
475 Storage::NativeType{"QObject"},
476 TypeAccessSemantics::Reference,
477 sourceId1,
478 importIds,
479 {Storage::ExportedType{"Item"}},
480 {Storage::PropertyDeclaration{"data",
481 Storage::NativeType{"QObject"},
482 Storage::PropertyDeclarationTraits::IsList},
483 Storage::PropertyDeclaration{"children",
484 Storage::ExportedType{"Item"},
485 Storage::PropertyDeclarationTraits::IsList
486 | Storage::PropertyDeclarationTraits::IsReadOnly}},
487 {Storage::FunctionDeclaration{"execute", "", {Storage::ParameterDeclaration{"arg", ""}}},
488 Storage::FunctionDeclaration{
489 "values",
490 "Vector3D",
491 {Storage::ParameterDeclaration{"arg1", "int"},
492 Storage::ParameterDeclaration{"arg2",
493 "QObject",
494 Storage::PropertyDeclarationTraits::IsPointer},
495 Storage::ParameterDeclaration{"arg3", "string"}}}},
496 {Storage::SignalDeclaration{"execute", {Storage::ParameterDeclaration{"arg", ""}}},
497 Storage::SignalDeclaration{
498 "values",
499 {Storage::ParameterDeclaration{"arg1", "int"},
500 Storage::ParameterDeclaration{"arg2",
501 "QObject",
502 Storage::PropertyDeclarationTraits::IsPointer},
503 Storage::ParameterDeclaration{"arg3", "string"}}}},
504 {Storage::EnumerationDeclaration{"Enum",
505 {Storage::EnumeratorDeclaration{"Foo"},
506 Storage::EnumeratorDeclaration{"Bar", 32}}},
507 Storage::EnumerationDeclaration{"Type",
508 {Storage::EnumeratorDeclaration{"Foo"},
509 Storage::EnumeratorDeclaration{"Poo", 12}}}}},
510 Storage::Type{importId1,
511 "QObject",
512 Storage::NativeType{},
513 TypeAccessSemantics::Reference,
514 sourceId2,
515 importIds,
516 {Storage::ExportedType{"Object"}, Storage::ExportedType{"Obj"}}}};
517 }
518
createTypesWithAliases()519 auto createTypesWithAliases()
520 {
521 auto types = createTypes();
522
523 types[1].propertyDeclarations.push_back(
524 Storage::PropertyDeclaration{"objects",
525 Storage::NativeType{"QObject"},
526 Storage::PropertyDeclarationTraits::IsList});
527
528 types.push_back(Storage::Type{importId2,
529 "QAliasItem",
530 Storage::NativeType{"QQuickItem"},
531 TypeAccessSemantics::Reference,
532 sourceId3,
533 importIds,
534 {Storage::ExportedType{"AliasItem"}}});
535 types.back().propertyDeclarations.push_back(
536 Storage::PropertyDeclaration{"data",
537 Storage::NativeType{"QObject"},
538 Storage::PropertyDeclarationTraits::IsList});
539 types.back().aliasDeclarations.push_back(
540 Storage::AliasPropertyDeclaration{"items", Storage::NativeType{"QQuickItem"}, "children"});
541 types.back().aliasDeclarations.push_back(
542 Storage::AliasPropertyDeclaration{"objects", Storage::NativeType{"QQuickItem"}, "objects"});
543
544 types.push_back(
545 Storage::Type{importId3,
546 "QObject2",
547 Storage::NativeType{},
548 TypeAccessSemantics::Reference,
549 sourceId4,
550 importIds,
551 {Storage::ExportedType{"Object2"}, Storage::ExportedType{"Obj2"}}});
552 types[3].propertyDeclarations.push_back(
553 Storage::PropertyDeclaration{"objects",
554 Storage::NativeType{"QObject"},
555 Storage::PropertyDeclarationTraits::IsList});
556
557 return types;
558 }
559
createImports()560 auto createImports()
561 {
562 importSourceId1 = sourcePathCache.sourceId(importPath1);
563 importSourceId2 = sourcePathCache.sourceId(importPath2);
564 importSourceId3 = sourcePathCache.sourceId(importPath3);
565
566 return Storage::Imports{Storage::Import{"Qml", Storage::VersionNumber{2}, importSourceId1, {}},
567 Storage::Import{"QtQuick",
568 Storage::VersionNumber{},
569 importSourceId2,
570 {Storage::Import{"Qml", Storage::VersionNumber{2}}}},
571 Storage::Import{"/path/to",
572 Storage::VersionNumber{},
573 SourceId{},
574 {Storage::Import{"QtQuick"},
575 Storage::Import{"Qml", Storage::VersionNumber{2}}}}};
576 }
577
setUpImports()578 void setUpImports()
579 {
580 auto imports = createImports();
581 storage.synchronizeImports(imports);
582 importIds = storage.fetchImportIds(imports);
583 importId1 = importIds[0];
584 importId2 = importIds[1];
585 importId3 = importIds[2];
586 }
587
588 protected:
589 using ProjectStorage = QmlDesigner::ProjectStorage<Sqlite::Database>;
590 Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
591 ProjectStorage storage{database, database.isInitialized()};
592 QmlDesigner::SourcePathCache<ProjectStorage> sourcePathCache{storage};
593 QmlDesigner::SourcePathView path1{"/path1/to"};
594 QmlDesigner::SourcePathView path2{"/path2/to"};
595 QmlDesigner::SourcePathView path3{"/path3/to"};
596 QmlDesigner::SourcePathView path4{"/path4/to"};
597 SourceId sourceId1;
598 SourceId sourceId2;
599 SourceId sourceId3;
600 SourceId sourceId4;
601 QmlDesigner::SourcePathView importPath1{"/import/path1/to"};
602 QmlDesigner::SourcePathView importPath2{"/import/path2/to"};
603 QmlDesigner::SourcePathView importPath3{"/import/aaaa/to"};
604 SourceId importSourceId1;
605 SourceId importSourceId2;
606 SourceId importSourceId3;
607 ImportId importId1;
608 ImportId importId2;
609 ImportId importId3;
610 QmlDesigner::ImportIds importIds;
611 };
612
TEST_F(ProjectStorageSlowTest,FetchSourceContextIdReturnsAlwaysTheSameIdForTheSamePath)613 TEST_F(ProjectStorageSlowTest, FetchSourceContextIdReturnsAlwaysTheSameIdForTheSamePath)
614 {
615 auto sourceContextId = storage.fetchSourceContextId("/path/to");
616
617 auto newSourceContextId = storage.fetchSourceContextId("/path/to");
618
619 ASSERT_THAT(newSourceContextId, Eq(sourceContextId));
620 }
621
TEST_F(ProjectStorageSlowTest,FetchSourceContextIdReturnsNotTheSameIdForDifferentPath)622 TEST_F(ProjectStorageSlowTest, FetchSourceContextIdReturnsNotTheSameIdForDifferentPath)
623 {
624 auto sourceContextId = storage.fetchSourceContextId("/path/to");
625
626 auto newSourceContextId = storage.fetchSourceContextId("/path/to2");
627
628 ASSERT_THAT(newSourceContextId, Ne(sourceContextId));
629 }
630
TEST_F(ProjectStorageSlowTest,FetchSourceContextPath)631 TEST_F(ProjectStorageSlowTest, FetchSourceContextPath)
632 {
633 auto sourceContextId = storage.fetchSourceContextId("/path/to");
634
635 auto path = storage.fetchSourceContextPath(sourceContextId);
636
637 ASSERT_THAT(path, Eq("/path/to"));
638 }
639
TEST_F(ProjectStorageSlowTest,FetchUnknownSourceContextPathThrows)640 TEST_F(ProjectStorageSlowTest, FetchUnknownSourceContextPathThrows)
641 {
642 ASSERT_THROW(storage.fetchSourceContextPath(SourceContextId{323}),
643 QmlDesigner::SourceContextIdDoesNotExists);
644 }
645
TEST_F(ProjectStorageSlowTest,FetchAllSourceContextsAreEmptyIfNoSourceContextsExists)646 TEST_F(ProjectStorageSlowTest, FetchAllSourceContextsAreEmptyIfNoSourceContextsExists)
647 {
648 auto sourceContexts = storage.fetchAllSourceContexts();
649
650 ASSERT_THAT(toValues(sourceContexts), IsEmpty());
651 }
652
TEST_F(ProjectStorageSlowTest,FetchAllSourceContexts)653 TEST_F(ProjectStorageSlowTest, FetchAllSourceContexts)
654 {
655 auto sourceContextId = storage.fetchSourceContextId("/path/to");
656 auto sourceContextId2 = storage.fetchSourceContextId("/path/to2");
657
658 auto sourceContexts = storage.fetchAllSourceContexts();
659
660 ASSERT_THAT(toValues(sourceContexts),
661 UnorderedElementsAre(IsSourceContext(sourceContextId, "/path/to"),
662 IsSourceContext(sourceContextId2, "/path/to2")));
663 }
664
TEST_F(ProjectStorageSlowTest,FetchSourceIdFirstTime)665 TEST_F(ProjectStorageSlowTest, FetchSourceIdFirstTime)
666 {
667 addSomeDummyData();
668 auto sourceContextId = storage.fetchSourceContextId("/path/to");
669
670 auto sourceId = storage.fetchSourceId(sourceContextId, "foo");
671
672 ASSERT_TRUE(sourceId.isValid());
673 }
674
TEST_F(ProjectStorageSlowTest,FetchExistingSourceId)675 TEST_F(ProjectStorageSlowTest, FetchExistingSourceId)
676 {
677 addSomeDummyData();
678 auto sourceContextId = storage.fetchSourceContextId("/path/to");
679 auto createdSourceId = storage.fetchSourceId(sourceContextId, "foo");
680
681 auto sourceId = storage.fetchSourceId(sourceContextId, "foo");
682
683 ASSERT_THAT(sourceId, createdSourceId);
684 }
685
TEST_F(ProjectStorageSlowTest,FetchSourceIdWithDifferentContextIdAreNotEqual)686 TEST_F(ProjectStorageSlowTest, FetchSourceIdWithDifferentContextIdAreNotEqual)
687 {
688 addSomeDummyData();
689 auto sourceContextId = storage.fetchSourceContextId("/path/to");
690 auto sourceContextId2 = storage.fetchSourceContextId("/path/to2");
691 auto sourceId2 = storage.fetchSourceId(sourceContextId2, "foo");
692
693 auto sourceId = storage.fetchSourceId(sourceContextId, "foo");
694
695 ASSERT_THAT(sourceId, Ne(sourceId2));
696 }
697
TEST_F(ProjectStorageSlowTest,FetchSourceIdWithDifferentNameAreNotEqual)698 TEST_F(ProjectStorageSlowTest, FetchSourceIdWithDifferentNameAreNotEqual)
699 {
700 addSomeDummyData();
701 auto sourceContextId = storage.fetchSourceContextId("/path/to");
702 auto sourceId2 = storage.fetchSourceId(sourceContextId, "foo");
703
704 auto sourceId = storage.fetchSourceId(sourceContextId, "foo2");
705
706 ASSERT_THAT(sourceId, Ne(sourceId2));
707 }
708
TEST_F(ProjectStorageSlowTest,FetchSourceIdWithNonExistingSourceContextIdThrows)709 TEST_F(ProjectStorageSlowTest, FetchSourceIdWithNonExistingSourceContextIdThrows)
710 {
711 ASSERT_THROW(storage.fetchSourceId(SourceContextId{42}, "foo"),
712 Sqlite::ConstraintPreventsModification);
713 }
714
TEST_F(ProjectStorageSlowTest,FetchSourceNameAndSourceContextIdForNonExistingSourceId)715 TEST_F(ProjectStorageSlowTest, FetchSourceNameAndSourceContextIdForNonExistingSourceId)
716 {
717 ASSERT_THROW(storage.fetchSourceNameAndSourceContextId(SourceId{212}),
718 QmlDesigner::SourceIdDoesNotExists);
719 }
720
TEST_F(ProjectStorageSlowTest,FetchSourceNameAndSourceContextIdForNonExistingEntry)721 TEST_F(ProjectStorageSlowTest, FetchSourceNameAndSourceContextIdForNonExistingEntry)
722 {
723 addSomeDummyData();
724 auto sourceContextId = storage.fetchSourceContextId("/path/to");
725 auto sourceId = storage.fetchSourceId(sourceContextId, "foo");
726
727 auto sourceNameAndSourceContextId = storage.fetchSourceNameAndSourceContextId(sourceId);
728
729 ASSERT_THAT(sourceNameAndSourceContextId, IsSourceNameAndSourceContextId("foo", sourceContextId));
730 }
731
TEST_F(ProjectStorageSlowTest,FetchSourceContextIdForNonExistingSourceId)732 TEST_F(ProjectStorageSlowTest, FetchSourceContextIdForNonExistingSourceId)
733 {
734 ASSERT_THROW(storage.fetchSourceContextId(SourceId{212}), QmlDesigner::SourceIdDoesNotExists);
735 }
736
TEST_F(ProjectStorageSlowTest,FetchSourceContextIdForExistingSourceId)737 TEST_F(ProjectStorageSlowTest, FetchSourceContextIdForExistingSourceId)
738 {
739 addSomeDummyData();
740 auto originalSourceContextId = storage.fetchSourceContextId("/path/to3");
741 auto sourceId = storage.fetchSourceId(originalSourceContextId, "foo");
742
743 auto sourceContextId = storage.fetchSourceContextId(sourceId);
744
745 ASSERT_THAT(sourceContextId, Eq(originalSourceContextId));
746 }
747
TEST_F(ProjectStorageSlowTest,FetchAllSources)748 TEST_F(ProjectStorageSlowTest, FetchAllSources)
749 {
750 auto sources = storage.fetchAllSources();
751
752 ASSERT_THAT(toValues(sources), IsEmpty());
753 }
754
TEST_F(ProjectStorageSlowTest,FetchSourceIdUnguardedFirstTime)755 TEST_F(ProjectStorageSlowTest, FetchSourceIdUnguardedFirstTime)
756 {
757 addSomeDummyData();
758 auto sourceContextId = storage.fetchSourceContextId("/path/to");
759 std::lock_guard lock{database};
760
761 auto sourceId = storage.fetchSourceIdUnguarded(sourceContextId, "foo");
762
763 ASSERT_TRUE(sourceId.isValid());
764 }
765
TEST_F(ProjectStorageSlowTest,FetchExistingSourceIdUnguarded)766 TEST_F(ProjectStorageSlowTest, FetchExistingSourceIdUnguarded)
767 {
768 addSomeDummyData();
769 auto sourceContextId = storage.fetchSourceContextId("/path/to");
770 std::lock_guard lock{database};
771 auto createdSourceId = storage.fetchSourceIdUnguarded(sourceContextId, "foo");
772
773 auto sourceId = storage.fetchSourceIdUnguarded(sourceContextId, "foo");
774
775 ASSERT_THAT(sourceId, createdSourceId);
776 }
777
TEST_F(ProjectStorageSlowTest,FetchSourceIdUnguardedWithDifferentContextIdAreNotEqual)778 TEST_F(ProjectStorageSlowTest, FetchSourceIdUnguardedWithDifferentContextIdAreNotEqual)
779 {
780 addSomeDummyData();
781 auto sourceContextId = storage.fetchSourceContextId("/path/to");
782 auto sourceContextId2 = storage.fetchSourceContextId("/path/to2");
783 std::lock_guard lock{database};
784 auto sourceId2 = storage.fetchSourceIdUnguarded(sourceContextId2, "foo");
785
786 auto sourceId = storage.fetchSourceIdUnguarded(sourceContextId, "foo");
787
788 ASSERT_THAT(sourceId, Ne(sourceId2));
789 }
790
TEST_F(ProjectStorageSlowTest,FetchSourceIdUnguardedWithDifferentNameAreNotEqual)791 TEST_F(ProjectStorageSlowTest, FetchSourceIdUnguardedWithDifferentNameAreNotEqual)
792 {
793 addSomeDummyData();
794 auto sourceContextId = storage.fetchSourceContextId("/path/to");
795 std::lock_guard lock{database};
796 auto sourceId2 = storage.fetchSourceIdUnguarded(sourceContextId, "foo");
797
798 auto sourceId = storage.fetchSourceIdUnguarded(sourceContextId, "foo2");
799
800 ASSERT_THAT(sourceId, Ne(sourceId2));
801 }
802
TEST_F(ProjectStorageSlowTest,FetchSourceIdUnguardedWithNonExistingSourceContextIdThrows)803 TEST_F(ProjectStorageSlowTest, FetchSourceIdUnguardedWithNonExistingSourceContextIdThrows)
804 {
805 std::lock_guard lock{database};
806
807 ASSERT_THROW(storage.fetchSourceIdUnguarded(SourceContextId{42}, "foo"),
808 Sqlite::ConstraintPreventsModification);
809 }
810
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddsNewTypes)811 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddsNewTypes)
812 {
813 Storage::Types types{createTypes()};
814
815 storage.synchronizeTypes(types, {sourceId1, sourceId2});
816
817 ASSERT_THAT(storage.fetchTypes(),
818 UnorderedElementsAre(AllOf(IsStorageType(importId1,
819 "QObject",
820 Storage::NativeType{},
821 TypeAccessSemantics::Reference,
822 sourceId2),
823 Field(&Storage::Type::exportedTypes,
824 UnorderedElementsAre(IsExportedType("Object"),
825 IsExportedType("Obj")))),
826 AllOf(IsStorageType(importId2,
827 "QQuickItem",
828 Storage::NativeType{"QObject"},
829 TypeAccessSemantics::Reference,
830 sourceId1),
831 Field(&Storage::Type::exportedTypes,
832 UnorderedElementsAre(IsExportedType("Item"))))));
833 }
834
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddsNewTypesWithExportedPrototypeName)835 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddsNewTypesWithExportedPrototypeName)
836 {
837 Storage::Types types{createTypes()};
838 types[0].prototype = Storage::ExportedType{"Object"};
839
840 storage.synchronizeTypes(types, {sourceId1, sourceId2});
841
842 ASSERT_THAT(storage.fetchTypes(),
843 UnorderedElementsAre(AllOf(IsStorageType(importId1,
844 "QObject",
845 Storage::NativeType{},
846 TypeAccessSemantics::Reference,
847 sourceId2),
848 Field(&Storage::Type::exportedTypes,
849 UnorderedElementsAre(IsExportedType("Object"),
850 IsExportedType("Obj")))),
851 AllOf(IsStorageType(importId2,
852 "QQuickItem",
853 Storage::NativeType{"QObject"},
854 TypeAccessSemantics::Reference,
855 sourceId1),
856 Field(&Storage::Type::exportedTypes,
857 UnorderedElementsAre(IsExportedType("Item"))))));
858 }
859
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddsNewTypesThrowsWithWrongExportedPrototypeName)860 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddsNewTypesThrowsWithWrongExportedPrototypeName)
861 {
862 Storage::Types types{createTypes()};
863 types[0].prototype = Storage::ExportedType{"Objec"};
864
865 ASSERT_THROW(storage.synchronizeTypes(types, {sourceId1, sourceId2}),
866 QmlDesigner::TypeNameDoesNotExists);
867 }
868
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddsNewTypesWithMissingImportAndExportedPrototypeName)869 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddsNewTypesWithMissingImportAndExportedPrototypeName)
870 {
871 Storage::Types types{createTypes()};
872 types[0].importIds = {importId1};
873 types[1].prototype = Storage::ExportedType{"Object"};
874
875 ASSERT_THROW(storage.synchronizeTypes(types, {sourceId1, sourceId2}),
876 QmlDesigner::TypeNameDoesNotExists);
877 }
878
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddsNewTypesWithMissingImport)879 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddsNewTypesWithMissingImport)
880 {
881 Storage::Types types{createTypes()};
882 types[0].importIds = {importId1};
883
884 ASSERT_THROW(storage.synchronizeTypes(types, {sourceId1, sourceId2}),
885 QmlDesigner::TypeNameDoesNotExists);
886 }
887
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddsNewTypesReverseOrder)888 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddsNewTypesReverseOrder)
889 {
890 Storage::Types types{createTypes()};
891 std::reverse(types.begin(), types.end());
892
893 storage.synchronizeTypes(types, {sourceId1, sourceId2});
894
895 ASSERT_THAT(storage.fetchTypes(),
896 UnorderedElementsAre(AllOf(IsStorageType(importId1,
897 "QObject",
898 Storage::NativeType{},
899 TypeAccessSemantics::Reference,
900 sourceId2),
901 Field(&Storage::Type::exportedTypes,
902 UnorderedElementsAre(IsExportedType("Object"),
903 IsExportedType("Obj")))),
904 AllOf(IsStorageType(importId2,
905 "QQuickItem",
906 Storage::NativeType{"QObject"},
907 TypeAccessSemantics::Reference,
908 sourceId1),
909 Field(&Storage::Type::exportedTypes,
910 UnorderedElementsAre(IsExportedType("Item"))))));
911 }
912
TEST_F(ProjectStorageSlowTest,SynchronizeTypesOverwritesTypeAccessSemantics)913 TEST_F(ProjectStorageSlowTest, SynchronizeTypesOverwritesTypeAccessSemantics)
914 {
915 Storage::Types types{createTypes()};
916 storage.synchronizeTypes(types, {sourceId1, sourceId2});
917 types[0].accessSemantics = TypeAccessSemantics::Value;
918 types[1].accessSemantics = TypeAccessSemantics::Value;
919
920 storage.synchronizeTypes(types, {sourceId1, sourceId2});
921
922 ASSERT_THAT(storage.fetchTypes(),
923 UnorderedElementsAre(AllOf(IsStorageType(importId1,
924 "QObject",
925 Storage::NativeType{},
926 TypeAccessSemantics::Value,
927 sourceId2),
928 Field(&Storage::Type::exportedTypes,
929 UnorderedElementsAre(IsExportedType("Object"),
930 IsExportedType("Obj")))),
931 AllOf(IsStorageType(importId2,
932 "QQuickItem",
933 Storage::NativeType{"QObject"},
934 TypeAccessSemantics::Value,
935 sourceId1),
936 Field(&Storage::Type::exportedTypes,
937 UnorderedElementsAre(IsExportedType("Item"))))));
938 }
939
TEST_F(ProjectStorageSlowTest,SynchronizeTypesOverwritesSources)940 TEST_F(ProjectStorageSlowTest, SynchronizeTypesOverwritesSources)
941 {
942 Storage::Types types{createTypes()};
943 storage.synchronizeTypes(types, {sourceId1, sourceId2});
944 types[0].sourceId = sourceId3;
945 types[1].sourceId = sourceId4;
946
947 storage.synchronizeTypes(types, {sourceId1, sourceId2});
948
949 ASSERT_THAT(storage.fetchTypes(),
950 UnorderedElementsAre(AllOf(IsStorageType(importId1,
951 "QObject",
952 Storage::NativeType{},
953 TypeAccessSemantics::Reference,
954 sourceId4),
955 Field(&Storage::Type::exportedTypes,
956 UnorderedElementsAre(IsExportedType("Object"),
957 IsExportedType("Obj")))),
958 AllOf(IsStorageType(importId2,
959 "QQuickItem",
960 Storage::NativeType{"QObject"},
961 TypeAccessSemantics::Reference,
962 sourceId3),
963 Field(&Storage::Type::exportedTypes,
964 UnorderedElementsAre(IsExportedType("Item"))))));
965 }
966
TEST_F(ProjectStorageSlowTest,SynchronizeTypesInsertTypeIntoPrototypeChain)967 TEST_F(ProjectStorageSlowTest, SynchronizeTypesInsertTypeIntoPrototypeChain)
968 {
969 Storage::Types types{createTypes()};
970 storage.synchronizeTypes(types, {sourceId1, sourceId2});
971 types[0].prototype = Storage::NativeType{"QQuickObject"};
972 types.push_back(Storage::Type{importId2,
973 "QQuickObject",
974 Storage::NativeType{"QObject"},
975 TypeAccessSemantics::Reference,
976 sourceId1,
977 importIds,
978 {Storage::ExportedType{"Object"}}});
979
980 storage.synchronizeTypes(types, {sourceId1, sourceId2});
981
982 ASSERT_THAT(storage.fetchTypes(),
983 UnorderedElementsAre(AllOf(IsStorageType(importId1,
984 "QObject",
985 Storage::NativeType{},
986 TypeAccessSemantics::Reference,
987 sourceId2),
988 Field(&Storage::Type::exportedTypes,
989 UnorderedElementsAre(IsExportedType("Object"),
990 IsExportedType("Obj")))),
991 AllOf(IsStorageType(importId2,
992 "QQuickObject",
993 Storage::NativeType{"QObject"},
994 TypeAccessSemantics::Reference,
995 sourceId1),
996 Field(&Storage::Type::exportedTypes,
997 UnorderedElementsAre(IsExportedType("Object")))),
998 AllOf(IsStorageType(importId2,
999 "QQuickItem",
1000 Storage::NativeType{"QQuickObject"},
1001 TypeAccessSemantics::Reference,
1002 sourceId1),
1003 Field(&Storage::Type::exportedTypes,
1004 UnorderedElementsAre(IsExportedType("Item"))))));
1005 }
1006
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddExplicitPrototype)1007 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddExplicitPrototype)
1008 {
1009 Storage::Types types{createTypes()};
1010 types[0].prototype = Storage::ExplicitExportedType{"Object", importId2};
1011 types.push_back(Storage::Type{importId2,
1012 "QQuickObject",
1013 Storage::NativeType{"QObject"},
1014 TypeAccessSemantics::Reference,
1015 sourceId1,
1016 importIds,
1017 {Storage::ExportedType{"Object"}}});
1018
1019 storage.synchronizeTypes(types, {sourceId1, sourceId2});
1020
1021 ASSERT_THAT(storage.fetchTypes(),
1022 UnorderedElementsAre(AllOf(IsStorageType(importId1,
1023 "QObject",
1024 Storage::NativeType{},
1025 TypeAccessSemantics::Reference,
1026 sourceId2),
1027 Field(&Storage::Type::exportedTypes,
1028 UnorderedElementsAre(IsExportedType("Object"),
1029 IsExportedType("Obj")))),
1030 AllOf(IsStorageType(importId2,
1031 "QQuickObject",
1032 Storage::NativeType{"QObject"},
1033 TypeAccessSemantics::Reference,
1034 sourceId1),
1035 Field(&Storage::Type::exportedTypes,
1036 UnorderedElementsAre(IsExportedType("Object")))),
1037 AllOf(IsStorageType(importId2,
1038 "QQuickItem",
1039 Storage::NativeType{"QQuickObject"},
1040 TypeAccessSemantics::Reference,
1041 sourceId1),
1042 Field(&Storage::Type::exportedTypes,
1043 UnorderedElementsAre(IsExportedType("Item"))))));
1044 }
1045
TEST_F(ProjectStorageSlowTest,SynchronizeTypesThrowsForMissingPrototype)1046 TEST_F(ProjectStorageSlowTest, SynchronizeTypesThrowsForMissingPrototype)
1047 {
1048 sourceId1 = sourcePathCache.sourceId(path1);
1049 Storage::Types types{Storage::Type{importId2,
1050 "QQuickItem",
1051 Storage::NativeType{"QObject"},
1052 TypeAccessSemantics::Reference,
1053 sourceId1,
1054 importIds,
1055 {Storage::ExportedType{"Item"}}}};
1056
1057 ASSERT_THROW(storage.synchronizeTypes(types, {sourceId1}), QmlDesigner::TypeNameDoesNotExists);
1058 }
1059
TEST_F(ProjectStorageSlowTest,TypeWithInvalidSourceIdThrows)1060 TEST_F(ProjectStorageSlowTest, TypeWithInvalidSourceIdThrows)
1061 {
1062 Storage::Types types{Storage::Type{importId2,
1063 "QQuickItem",
1064 Storage::NativeType{""},
1065 TypeAccessSemantics::Reference,
1066 SourceId{},
1067 importIds,
1068 {Storage::ExportedType{"Item"}}}};
1069
1070 ASSERT_THROW(storage.synchronizeTypes(types, {}), QmlDesigner::TypeHasInvalidSourceId);
1071 }
1072
TEST_F(ProjectStorageSlowTest,DeleteTypeIfSourceIdIsSynchronized)1073 TEST_F(ProjectStorageSlowTest, DeleteTypeIfSourceIdIsSynchronized)
1074 {
1075 Storage::Types types{createTypes()};
1076 storage.synchronizeTypes(types, {sourceId1, sourceId2});
1077 types.erase(types.begin());
1078
1079 storage.synchronizeTypes(types, {sourceId1, sourceId2});
1080
1081 ASSERT_THAT(storage.fetchTypes(),
1082 UnorderedElementsAre(AllOf(IsStorageType(importId1,
1083 "QObject",
1084 Storage::NativeType{},
1085 TypeAccessSemantics::Reference,
1086 sourceId2),
1087 Field(&Storage::Type::exportedTypes,
1088 UnorderedElementsAre(IsExportedType("Object"),
1089 IsExportedType("Obj"))))));
1090 }
1091
TEST_F(ProjectStorageSlowTest,DontDeleteTypeIfSourceIdIsNotSynchronized)1092 TEST_F(ProjectStorageSlowTest, DontDeleteTypeIfSourceIdIsNotSynchronized)
1093 {
1094 Storage::Types types{createTypes()};
1095 storage.synchronizeTypes(types, {sourceId1, sourceId2});
1096 types.pop_back();
1097
1098 storage.synchronizeTypes(types, {sourceId1});
1099
1100 ASSERT_THAT(storage.fetchTypes(),
1101 UnorderedElementsAre(AllOf(IsStorageType(importId1,
1102 "QObject",
1103 Storage::NativeType{},
1104 TypeAccessSemantics::Reference,
1105 sourceId2),
1106 Field(&Storage::Type::exportedTypes,
1107 UnorderedElementsAre(IsExportedType("Object"),
1108 IsExportedType("Obj")))),
1109 AllOf(IsStorageType(importId2,
1110 "QQuickItem",
1111 Storage::NativeType{"QObject"},
1112 TypeAccessSemantics::Reference,
1113 sourceId1),
1114 Field(&Storage::Type::exportedTypes,
1115 UnorderedElementsAre(IsExportedType("Item"))))));
1116 }
1117
TEST_F(ProjectStorageSlowTest,BreakingPrototypeChainByDeletingBaseComponentThrows)1118 TEST_F(ProjectStorageSlowTest, BreakingPrototypeChainByDeletingBaseComponentThrows)
1119 {
1120 Storage::Types types{createTypes()};
1121 storage.synchronizeTypes(types, {sourceId1, sourceId2});
1122 types.pop_back();
1123
1124 ASSERT_THROW(storage.synchronizeTypes(types, {sourceId1, sourceId2}),
1125 Sqlite::ConstraintPreventsModification);
1126 }
1127
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddPropertyDeclarations)1128 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddPropertyDeclarations)
1129 {
1130 Storage::Types types{createTypes()};
1131
1132 storage.synchronizeTypes(types, {});
1133
1134 ASSERT_THAT(storage.fetchTypes(),
1135 Contains(
1136 AllOf(IsStorageType(importId2,
1137 "QQuickItem",
1138 Storage::NativeType{"QObject"},
1139 TypeAccessSemantics::Reference,
1140 sourceId1),
1141 Field(&Storage::Type::propertyDeclarations,
1142 UnorderedElementsAre(
1143 IsPropertyDeclaration("data",
1144 Storage::NativeType{"QObject"},
1145 Storage::PropertyDeclarationTraits::IsList),
1146 IsPropertyDeclaration(
1147 "children",
1148 Storage::NativeType{"QQuickItem"},
1149 Storage::PropertyDeclarationTraits::IsList
1150 | Storage::PropertyDeclarationTraits::IsReadOnly))))));
1151 }
1152
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddPropertyDeclarationsWithMissingImportIdsForNativeTypes)1153 TEST_F(ProjectStorageSlowTest,
1154 SynchronizeTypesAddPropertyDeclarationsWithMissingImportIdsForNativeTypes)
1155 {
1156 Storage::Types types{createTypes()};
1157 types[0].importIds = {importId2};
1158 types[0].propertyDeclarations.pop_back();
1159
1160 ASSERT_THROW(storage.synchronizeTypes(types, {}), QmlDesigner::TypeNameDoesNotExists);
1161 }
1162
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddPropertyDeclarationsWithMissingImportIdsForExportedTypes)1163 TEST_F(ProjectStorageSlowTest,
1164 SynchronizeTypesAddPropertyDeclarationsWithMissingImportIdsForExportedTypes)
1165 {
1166 Storage::Types types{createTypes()};
1167 types[0].importIds = {importId1};
1168 types[0].propertyDeclarations[0].typeName = Storage::ExportedType{"Obj"};
1169
1170 ASSERT_THROW(storage.synchronizeTypes(types, {}), QmlDesigner::TypeNameDoesNotExists);
1171 }
1172
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddPropertyDeclarationExplicitType)1173 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddPropertyDeclarationExplicitType)
1174 {
1175 Storage::Types types{createTypes()};
1176 types[0].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"Object", importId2};
1177 types.push_back(Storage::Type{importId2,
1178 "QQuickObject",
1179 Storage::NativeType{"QObject"},
1180 TypeAccessSemantics::Reference,
1181 sourceId1,
1182 importIds,
1183 {Storage::ExportedType{"Object"}}});
1184
1185 storage.synchronizeTypes(types, {});
1186
1187 ASSERT_THAT(storage.fetchTypes(),
1188 Contains(
1189 AllOf(IsStorageType(importId2,
1190 "QQuickItem",
1191 Storage::NativeType{"QObject"},
1192 TypeAccessSemantics::Reference,
1193 sourceId1),
1194 Field(&Storage::Type::propertyDeclarations,
1195 UnorderedElementsAre(
1196 IsPropertyDeclaration("data",
1197 Storage::NativeType{"QQuickObject"},
1198 Storage::PropertyDeclarationTraits::IsList),
1199 IsPropertyDeclaration(
1200 "children",
1201 Storage::NativeType{"QQuickItem"},
1202 Storage::PropertyDeclarationTraits::IsList
1203 | Storage::PropertyDeclarationTraits::IsReadOnly))))));
1204 }
1205
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesPropertyDeclarationType)1206 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesPropertyDeclarationType)
1207 {
1208 Storage::Types types{createTypes()};
1209 storage.synchronizeTypes(types, {});
1210 types[0].propertyDeclarations[0].typeName = Storage::NativeType{"QQuickItem"};
1211
1212 storage.synchronizeTypes(types, {});
1213
1214 ASSERT_THAT(storage.fetchTypes(),
1215 Contains(
1216 AllOf(IsStorageType(importId2,
1217 "QQuickItem",
1218 Storage::NativeType{"QObject"},
1219 TypeAccessSemantics::Reference,
1220 sourceId1),
1221 Field(&Storage::Type::propertyDeclarations,
1222 UnorderedElementsAre(
1223 IsPropertyDeclaration("data",
1224 Storage::NativeType{"QQuickItem"},
1225 Storage::PropertyDeclarationTraits::IsList),
1226 IsPropertyDeclaration(
1227 "children",
1228 Storage::NativeType{"QQuickItem"},
1229 Storage::PropertyDeclarationTraits::IsList
1230 | Storage::PropertyDeclarationTraits::IsReadOnly))))));
1231 }
1232
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesDeclarationTraits)1233 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesDeclarationTraits)
1234 {
1235 Storage::Types types{createTypes()};
1236 storage.synchronizeTypes(types, {});
1237 types[0].propertyDeclarations[0].traits = Storage::PropertyDeclarationTraits::IsPointer;
1238
1239 storage.synchronizeTypes(types, {});
1240
1241 ASSERT_THAT(storage.fetchTypes(),
1242 Contains(
1243 AllOf(IsStorageType(importId2,
1244 "QQuickItem",
1245 Storage::NativeType{"QObject"},
1246 TypeAccessSemantics::Reference,
1247 sourceId1),
1248 Field(&Storage::Type::propertyDeclarations,
1249 UnorderedElementsAre(
1250 IsPropertyDeclaration("data",
1251 Storage::NativeType{"QObject"},
1252 Storage::PropertyDeclarationTraits::IsPointer),
1253 IsPropertyDeclaration(
1254 "children",
1255 Storage::NativeType{"QQuickItem"},
1256 Storage::PropertyDeclarationTraits::IsList
1257 | Storage::PropertyDeclarationTraits::IsReadOnly))))));
1258 }
1259
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesDeclarationTraitsAndType)1260 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesDeclarationTraitsAndType)
1261 {
1262 Storage::Types types{createTypes()};
1263 storage.synchronizeTypes(types, {});
1264 types[0].propertyDeclarations[0].traits = Storage::PropertyDeclarationTraits::IsPointer;
1265 types[0].propertyDeclarations[0].typeName = Storage::NativeType{"QQuickItem"};
1266
1267 storage.synchronizeTypes(types, {});
1268
1269 ASSERT_THAT(storage.fetchTypes(),
1270 Contains(
1271 AllOf(IsStorageType(importId2,
1272 "QQuickItem",
1273 Storage::NativeType{"QObject"},
1274 TypeAccessSemantics::Reference,
1275 sourceId1),
1276 Field(&Storage::Type::propertyDeclarations,
1277 UnorderedElementsAre(
1278 IsPropertyDeclaration("data",
1279 Storage::NativeType{"QQuickItem"},
1280 Storage::PropertyDeclarationTraits::IsPointer),
1281 IsPropertyDeclaration(
1282 "children",
1283 Storage::NativeType{"QQuickItem"},
1284 Storage::PropertyDeclarationTraits::IsList
1285 | Storage::PropertyDeclarationTraits::IsReadOnly))))));
1286 }
1287
TEST_F(ProjectStorageSlowTest,SynchronizeTypesRemovesAPropertyDeclaration)1288 TEST_F(ProjectStorageSlowTest, SynchronizeTypesRemovesAPropertyDeclaration)
1289 {
1290 Storage::Types types{createTypes()};
1291 storage.synchronizeTypes(types, {});
1292 types[0].propertyDeclarations.pop_back();
1293
1294 storage.synchronizeTypes(types, {});
1295
1296 ASSERT_THAT(storage.fetchTypes(),
1297 Contains(AllOf(IsStorageType(importId2,
1298 "QQuickItem",
1299 Storage::NativeType{"QObject"},
1300 TypeAccessSemantics::Reference,
1301 sourceId1),
1302 Field(&Storage::Type::propertyDeclarations,
1303 UnorderedElementsAre(IsPropertyDeclaration(
1304 "data",
1305 Storage::NativeType{"QObject"},
1306 Storage::PropertyDeclarationTraits::IsList))))));
1307 }
1308
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddsAPropertyDeclaration)1309 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddsAPropertyDeclaration)
1310 {
1311 Storage::Types types{createTypes()};
1312 storage.synchronizeTypes(types, {});
1313 types[0].propertyDeclarations.push_back(
1314 Storage::PropertyDeclaration{"object",
1315 Storage::NativeType{"QObject"},
1316 Storage::PropertyDeclarationTraits::IsPointer});
1317
1318 storage.synchronizeTypes(types, {});
1319
1320 ASSERT_THAT(
1321 storage.fetchTypes(),
1322 Contains(AllOf(
1323 IsStorageType(importId2,
1324 "QQuickItem",
1325 Storage::NativeType{"QObject"},
1326 TypeAccessSemantics::Reference,
1327 sourceId1),
1328 Field(&Storage::Type::propertyDeclarations,
1329 UnorderedElementsAre(
1330 IsPropertyDeclaration("object",
1331 Storage::NativeType{"QObject"},
1332 Storage::PropertyDeclarationTraits::IsPointer),
1333 IsPropertyDeclaration("data",
1334 Storage::NativeType{"QObject"},
1335 Storage::PropertyDeclarationTraits::IsList),
1336 IsPropertyDeclaration("children",
1337 Storage::NativeType{"QQuickItem"},
1338 Storage::PropertyDeclarationTraits::IsList
1339 | Storage::PropertyDeclarationTraits::IsReadOnly))))));
1340 }
1341
TEST_F(ProjectStorageSlowTest,SynchronizeTypesRenameAPropertyDeclaration)1342 TEST_F(ProjectStorageSlowTest, SynchronizeTypesRenameAPropertyDeclaration)
1343 {
1344 Storage::Types types{createTypes()};
1345 storage.synchronizeTypes(types, {});
1346 types[0].propertyDeclarations[1].name = "objects";
1347
1348 storage.synchronizeTypes(types, {});
1349
1350 ASSERT_THAT(storage.fetchTypes(),
1351 Contains(
1352 AllOf(IsStorageType(importId2,
1353 "QQuickItem",
1354 Storage::NativeType{"QObject"},
1355 TypeAccessSemantics::Reference,
1356 sourceId1),
1357 Field(&Storage::Type::propertyDeclarations,
1358 UnorderedElementsAre(
1359 IsPropertyDeclaration("data",
1360 Storage::NativeType{"QObject"},
1361 Storage::PropertyDeclarationTraits::IsList),
1362 IsPropertyDeclaration(
1363 "objects",
1364 Storage::NativeType{"QQuickItem"},
1365 Storage::PropertyDeclarationTraits::IsList
1366 | Storage::PropertyDeclarationTraits::IsReadOnly))))));
1367 }
1368
TEST_F(ProjectStorageSlowTest,UsingNonExistingNativePropertyTypeThrows)1369 TEST_F(ProjectStorageSlowTest, UsingNonExistingNativePropertyTypeThrows)
1370 {
1371 Storage::Types types{createTypes()};
1372 types[0].propertyDeclarations[0].typeName = Storage::NativeType{"QObject2"};
1373 types.pop_back();
1374
1375 ASSERT_THROW(storage.synchronizeTypes(types, {sourceId1, sourceId2}),
1376 QmlDesigner::TypeNameDoesNotExists);
1377 }
1378
TEST_F(ProjectStorageSlowTest,UsingNonExistingExportedPropertyTypeThrows)1379 TEST_F(ProjectStorageSlowTest, UsingNonExistingExportedPropertyTypeThrows)
1380 {
1381 Storage::Types types{createTypes()};
1382 types[0].propertyDeclarations[0].typeName = Storage::ExportedType{"QObject2"};
1383 types.pop_back();
1384
1385 ASSERT_THROW(storage.synchronizeTypes(types, {sourceId1, sourceId2}),
1386 QmlDesigner::TypeNameDoesNotExists);
1387 }
1388
TEST_F(ProjectStorageSlowTest,UsingNonExistingExplicitExportedPropertyTypeWithWrongNAMEThrows)1389 TEST_F(ProjectStorageSlowTest, UsingNonExistingExplicitExportedPropertyTypeWithWrongNAMEThrows)
1390 {
1391 Storage::Types types{createTypes()};
1392 types[0].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"QObject2", importId1};
1393 types.pop_back();
1394
1395 ASSERT_THROW(storage.synchronizeTypes(types, {sourceId1, sourceId2}),
1396 QmlDesigner::TypeNameDoesNotExists);
1397 }
1398
TEST_F(ProjectStorageSlowTest,UsingNonExistingExplicitExportedPropertyTypeWithWrongImportThrows)1399 TEST_F(ProjectStorageSlowTest, UsingNonExistingExplicitExportedPropertyTypeWithWrongImportThrows)
1400 {
1401 Storage::Types types{createTypes()};
1402 types[0].propertyDeclarations[0].typeName = Storage::ExplicitExportedType{"QObject", importId2};
1403 types.pop_back();
1404
1405 ASSERT_THROW(storage.synchronizeTypes(types, {sourceId1, sourceId2}),
1406 QmlDesigner::TypeNameDoesNotExists);
1407 }
1408
TEST_F(ProjectStorageSlowTest,BreakingPropertyDeclarationTypeDependencyByDeletingTypeThrows)1409 TEST_F(ProjectStorageSlowTest, BreakingPropertyDeclarationTypeDependencyByDeletingTypeThrows)
1410 {
1411 Storage::Types types{createTypes()};
1412 storage.synchronizeTypes(types, {sourceId1, sourceId2});
1413 types[0].prototype = Storage::NativeType{};
1414 types.pop_back();
1415
1416 ASSERT_THROW(storage.synchronizeTypes(types, {sourceId1, sourceId2}),
1417 Sqlite::ConstraintPreventsModification);
1418 }
1419
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddFunctionDeclarations)1420 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddFunctionDeclarations)
1421 {
1422 Storage::Types types{createTypes()};
1423
1424 storage.synchronizeTypes(types, {sourceId1, sourceId2});
1425
1426 ASSERT_THAT(storage.fetchTypes(),
1427 Contains(AllOf(IsStorageType(importId2,
1428 "QQuickItem",
1429 Storage::NativeType{"QObject"},
1430 TypeAccessSemantics::Reference,
1431 sourceId1),
1432 Field(&Storage::Type::functionDeclarations,
1433 UnorderedElementsAre(Eq(types[0].functionDeclarations[0]),
1434 Eq(types[0].functionDeclarations[1]))))));
1435 }
1436
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesFunctionDeclarationReturnType)1437 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesFunctionDeclarationReturnType)
1438 {
1439 Storage::Types types{createTypes()};
1440 storage.synchronizeTypes(types, {});
1441 types[0].functionDeclarations[1].returnTypeName = "item";
1442
1443 storage.synchronizeTypes(types, {});
1444
1445 ASSERT_THAT(storage.fetchTypes(),
1446 Contains(AllOf(IsStorageType(importId2,
1447 "QQuickItem",
1448 Storage::NativeType{"QObject"},
1449 TypeAccessSemantics::Reference,
1450 sourceId1),
1451 Field(&Storage::Type::functionDeclarations,
1452 UnorderedElementsAre(Eq(types[0].functionDeclarations[0]),
1453 Eq(types[0].functionDeclarations[1]))))));
1454 }
1455
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesFunctionDeclarationName)1456 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesFunctionDeclarationName)
1457 {
1458 Storage::Types types{createTypes()};
1459 storage.synchronizeTypes(types, {});
1460 types[0].functionDeclarations[1].name = "name";
1461
1462 storage.synchronizeTypes(types, {});
1463
1464 ASSERT_THAT(storage.fetchTypes(),
1465 Contains(AllOf(IsStorageType(importId2,
1466 "QQuickItem",
1467 Storage::NativeType{"QObject"},
1468 TypeAccessSemantics::Reference,
1469 sourceId1),
1470 Field(&Storage::Type::functionDeclarations,
1471 UnorderedElementsAre(Eq(types[0].functionDeclarations[0]),
1472 Eq(types[0].functionDeclarations[1]))))));
1473 }
1474
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesFunctionDeclarationPopParameters)1475 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesFunctionDeclarationPopParameters)
1476 {
1477 Storage::Types types{createTypes()};
1478 storage.synchronizeTypes(types, {});
1479 types[0].functionDeclarations[1].parameters.pop_back();
1480
1481 storage.synchronizeTypes(types, {});
1482
1483 ASSERT_THAT(storage.fetchTypes(),
1484 Contains(AllOf(IsStorageType(importId2,
1485 "QQuickItem",
1486 Storage::NativeType{"QObject"},
1487 TypeAccessSemantics::Reference,
1488 sourceId1),
1489 Field(&Storage::Type::functionDeclarations,
1490 UnorderedElementsAre(Eq(types[0].functionDeclarations[0]),
1491 Eq(types[0].functionDeclarations[1]))))));
1492 }
1493
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesFunctionDeclarationAppendParameters)1494 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesFunctionDeclarationAppendParameters)
1495 {
1496 Storage::Types types{createTypes()};
1497 storage.synchronizeTypes(types, {});
1498 types[0].functionDeclarations[1].parameters.push_back(Storage::ParameterDeclaration{"arg4", "int"});
1499
1500 storage.synchronizeTypes(types, {});
1501
1502 ASSERT_THAT(storage.fetchTypes(),
1503 Contains(AllOf(IsStorageType(importId2,
1504 "QQuickItem",
1505 Storage::NativeType{"QObject"},
1506 TypeAccessSemantics::Reference,
1507 sourceId1),
1508 Field(&Storage::Type::functionDeclarations,
1509 UnorderedElementsAre(Eq(types[0].functionDeclarations[0]),
1510 Eq(types[0].functionDeclarations[1]))))));
1511 }
1512
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesFunctionDeclarationChangeParameterName)1513 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesFunctionDeclarationChangeParameterName)
1514 {
1515 Storage::Types types{createTypes()};
1516 storage.synchronizeTypes(types, {});
1517 types[0].functionDeclarations[1].parameters[0].name = "other";
1518
1519 storage.synchronizeTypes(types, {});
1520
1521 ASSERT_THAT(storage.fetchTypes(),
1522 Contains(AllOf(IsStorageType(importId2,
1523 "QQuickItem",
1524 Storage::NativeType{"QObject"},
1525 TypeAccessSemantics::Reference,
1526 sourceId1),
1527 Field(&Storage::Type::functionDeclarations,
1528 UnorderedElementsAre(Eq(types[0].functionDeclarations[0]),
1529 Eq(types[0].functionDeclarations[1]))))));
1530 }
1531
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesFunctionDeclarationChangeParameterTypeName)1532 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesFunctionDeclarationChangeParameterTypeName)
1533 {
1534 Storage::Types types{createTypes()};
1535 storage.synchronizeTypes(types, {});
1536 types[0].functionDeclarations[1].parameters[0].name = "long long";
1537
1538 storage.synchronizeTypes(types, {});
1539
1540 ASSERT_THAT(storage.fetchTypes(),
1541 Contains(AllOf(IsStorageType(importId2,
1542 "QQuickItem",
1543 Storage::NativeType{"QObject"},
1544 TypeAccessSemantics::Reference,
1545 sourceId1),
1546 Field(&Storage::Type::functionDeclarations,
1547 UnorderedElementsAre(Eq(types[0].functionDeclarations[0]),
1548 Eq(types[0].functionDeclarations[1]))))));
1549 }
1550
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesFunctionDeclarationChangeParameterTraits)1551 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesFunctionDeclarationChangeParameterTraits)
1552 {
1553 Storage::Types types{createTypes()};
1554 storage.synchronizeTypes(types, {});
1555 types[0].functionDeclarations[1].parameters[0].traits = QmlDesigner::Storage::PropertyDeclarationTraits::IsList;
1556
1557 storage.synchronizeTypes(types, {});
1558
1559 ASSERT_THAT(storage.fetchTypes(),
1560 Contains(AllOf(IsStorageType(importId2,
1561 "QQuickItem",
1562 Storage::NativeType{"QObject"},
1563 TypeAccessSemantics::Reference,
1564 sourceId1),
1565 Field(&Storage::Type::functionDeclarations,
1566 UnorderedElementsAre(Eq(types[0].functionDeclarations[0]),
1567 Eq(types[0].functionDeclarations[1]))))));
1568 }
1569
TEST_F(ProjectStorageSlowTest,SynchronizeTypesRemovesFunctionDeclaration)1570 TEST_F(ProjectStorageSlowTest, SynchronizeTypesRemovesFunctionDeclaration)
1571 {
1572 Storage::Types types{createTypes()};
1573 storage.synchronizeTypes(types, {});
1574 types[0].functionDeclarations.pop_back();
1575
1576 storage.synchronizeTypes(types, {});
1577
1578 ASSERT_THAT(storage.fetchTypes(),
1579 Contains(AllOf(IsStorageType(importId2,
1580 "QQuickItem",
1581 Storage::NativeType{"QObject"},
1582 TypeAccessSemantics::Reference,
1583 sourceId1),
1584 Field(&Storage::Type::functionDeclarations,
1585 UnorderedElementsAre(Eq(types[0].functionDeclarations[0]))))));
1586 }
1587
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddFunctionDeclaration)1588 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddFunctionDeclaration)
1589 {
1590 Storage::Types types{createTypes()};
1591 storage.synchronizeTypes(types, {});
1592 types[0].functionDeclarations.push_back(
1593 Storage::FunctionDeclaration{"name", "string", {Storage::ParameterDeclaration{"arg", "int"}}});
1594
1595 storage.synchronizeTypes(types, {});
1596
1597 ASSERT_THAT(storage.fetchTypes(),
1598 Contains(AllOf(IsStorageType(importId2,
1599 "QQuickItem",
1600 Storage::NativeType{"QObject"},
1601 TypeAccessSemantics::Reference,
1602 sourceId1),
1603 Field(&Storage::Type::functionDeclarations,
1604 UnorderedElementsAre(Eq(types[0].functionDeclarations[0]),
1605 Eq(types[0].functionDeclarations[1]),
1606 Eq(types[0].functionDeclarations[2]))))));
1607 }
1608
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddSignalDeclarations)1609 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddSignalDeclarations)
1610 {
1611 Storage::Types types{createTypes()};
1612
1613 storage.synchronizeTypes(types, {});
1614
1615 ASSERT_THAT(storage.fetchTypes(),
1616 Contains(AllOf(IsStorageType(importId2,
1617 "QQuickItem",
1618 Storage::NativeType{"QObject"},
1619 TypeAccessSemantics::Reference,
1620 sourceId1),
1621 Field(&Storage::Type::signalDeclarations,
1622 UnorderedElementsAre(Eq(types[0].signalDeclarations[0]),
1623 Eq(types[0].signalDeclarations[1]))))));
1624 }
1625
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesSignalDeclarationName)1626 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesSignalDeclarationName)
1627 {
1628 Storage::Types types{createTypes()};
1629 storage.synchronizeTypes(types, {});
1630 types[0].signalDeclarations[1].name = "name";
1631
1632 storage.synchronizeTypes(types, {});
1633
1634 ASSERT_THAT(storage.fetchTypes(),
1635 Contains(AllOf(IsStorageType(importId2,
1636 "QQuickItem",
1637 Storage::NativeType{"QObject"},
1638 TypeAccessSemantics::Reference,
1639 sourceId1),
1640 Field(&Storage::Type::signalDeclarations,
1641 UnorderedElementsAre(Eq(types[0].signalDeclarations[0]),
1642 Eq(types[0].signalDeclarations[1]))))));
1643 }
1644
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesSignalDeclarationPopParameters)1645 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesSignalDeclarationPopParameters)
1646 {
1647 Storage::Types types{createTypes()};
1648 storage.synchronizeTypes(types, {});
1649 types[0].signalDeclarations[1].parameters.pop_back();
1650
1651 storage.synchronizeTypes(types, {});
1652
1653 ASSERT_THAT(storage.fetchTypes(),
1654 Contains(AllOf(IsStorageType(importId2,
1655 "QQuickItem",
1656 Storage::NativeType{"QObject"},
1657 TypeAccessSemantics::Reference,
1658 sourceId1),
1659 Field(&Storage::Type::signalDeclarations,
1660 UnorderedElementsAre(Eq(types[0].signalDeclarations[0]),
1661 Eq(types[0].signalDeclarations[1]))))));
1662 }
1663
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesSignalDeclarationAppendParameters)1664 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesSignalDeclarationAppendParameters)
1665 {
1666 Storage::Types types{createTypes()};
1667 storage.synchronizeTypes(types, {});
1668 types[0].signalDeclarations[1].parameters.push_back(Storage::ParameterDeclaration{"arg4", "int"});
1669
1670 storage.synchronizeTypes(types, {});
1671
1672 ASSERT_THAT(storage.fetchTypes(),
1673 Contains(AllOf(IsStorageType(importId2,
1674 "QQuickItem",
1675 Storage::NativeType{"QObject"},
1676 TypeAccessSemantics::Reference,
1677 sourceId1),
1678 Field(&Storage::Type::signalDeclarations,
1679 UnorderedElementsAre(Eq(types[0].signalDeclarations[0]),
1680 Eq(types[0].signalDeclarations[1]))))));
1681 }
1682
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesSignalDeclarationChangeParameterName)1683 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesSignalDeclarationChangeParameterName)
1684 {
1685 Storage::Types types{createTypes()};
1686 storage.synchronizeTypes(types, {});
1687 types[0].signalDeclarations[1].parameters[0].name = "other";
1688
1689 storage.synchronizeTypes(types, {});
1690
1691 ASSERT_THAT(storage.fetchTypes(),
1692 Contains(AllOf(IsStorageType(importId2,
1693 "QQuickItem",
1694 Storage::NativeType{"QObject"},
1695 TypeAccessSemantics::Reference,
1696 sourceId1),
1697 Field(&Storage::Type::signalDeclarations,
1698 UnorderedElementsAre(Eq(types[0].signalDeclarations[0]),
1699 Eq(types[0].signalDeclarations[1]))))));
1700 }
1701
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesSignalDeclarationChangeParameterTypeName)1702 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesSignalDeclarationChangeParameterTypeName)
1703 {
1704 Storage::Types types{createTypes()};
1705 storage.synchronizeTypes(types, {});
1706 types[0].signalDeclarations[1].parameters[0].typeName = "long long";
1707
1708 storage.synchronizeTypes(types, {});
1709
1710 ASSERT_THAT(storage.fetchTypes(),
1711 Contains(AllOf(IsStorageType(importId2,
1712 "QQuickItem",
1713 Storage::NativeType{"QObject"},
1714 TypeAccessSemantics::Reference,
1715 sourceId1),
1716 Field(&Storage::Type::signalDeclarations,
1717 UnorderedElementsAre(Eq(types[0].signalDeclarations[0]),
1718 Eq(types[0].signalDeclarations[1]))))));
1719 }
1720
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesSignalDeclarationChangeParameterTraits)1721 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesSignalDeclarationChangeParameterTraits)
1722 {
1723 Storage::Types types{createTypes()};
1724 storage.synchronizeTypes(types, {});
1725 types[0].signalDeclarations[1].parameters[0].traits = QmlDesigner::Storage::PropertyDeclarationTraits::IsList;
1726
1727 storage.synchronizeTypes(types, {});
1728
1729 ASSERT_THAT(storage.fetchTypes(),
1730 Contains(AllOf(IsStorageType(importId2,
1731 "QQuickItem",
1732 Storage::NativeType{"QObject"},
1733 TypeAccessSemantics::Reference,
1734 sourceId1),
1735 Field(&Storage::Type::signalDeclarations,
1736 UnorderedElementsAre(Eq(types[0].signalDeclarations[0]),
1737 Eq(types[0].signalDeclarations[1]))))));
1738 }
1739
TEST_F(ProjectStorageSlowTest,SynchronizeTypesRemovesSignalDeclaration)1740 TEST_F(ProjectStorageSlowTest, SynchronizeTypesRemovesSignalDeclaration)
1741 {
1742 Storage::Types types{createTypes()};
1743 storage.synchronizeTypes(types, {});
1744 types[0].signalDeclarations.pop_back();
1745
1746 storage.synchronizeTypes(types, {});
1747
1748 ASSERT_THAT(storage.fetchTypes(),
1749 Contains(AllOf(IsStorageType(importId2,
1750 "QQuickItem",
1751 Storage::NativeType{"QObject"},
1752 TypeAccessSemantics::Reference,
1753 sourceId1),
1754 Field(&Storage::Type::signalDeclarations,
1755 UnorderedElementsAre(Eq(types[0].signalDeclarations[0]))))));
1756 }
1757
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddSignalDeclaration)1758 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddSignalDeclaration)
1759 {
1760 Storage::Types types{createTypes()};
1761 storage.synchronizeTypes(types, {});
1762 types[0].signalDeclarations.push_back(
1763 Storage::SignalDeclaration{"name", {Storage::ParameterDeclaration{"arg", "int"}}});
1764
1765 storage.synchronizeTypes(types, {});
1766
1767 ASSERT_THAT(storage.fetchTypes(),
1768 Contains(AllOf(IsStorageType(importId2,
1769 "QQuickItem",
1770 Storage::NativeType{"QObject"},
1771 TypeAccessSemantics::Reference,
1772 sourceId1),
1773 Field(&Storage::Type::signalDeclarations,
1774 UnorderedElementsAre(Eq(types[0].signalDeclarations[0]),
1775 Eq(types[0].signalDeclarations[1]),
1776 Eq(types[0].signalDeclarations[2]))))));
1777 }
1778
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddEnumerationDeclarations)1779 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddEnumerationDeclarations)
1780 {
1781 Storage::Types types{createTypes()};
1782
1783 storage.synchronizeTypes(types, {});
1784
1785 ASSERT_THAT(storage.fetchTypes(),
1786 Contains(AllOf(IsStorageType(importId2,
1787 "QQuickItem",
1788 Storage::NativeType{"QObject"},
1789 TypeAccessSemantics::Reference,
1790 sourceId1),
1791 Field(&Storage::Type::enumerationDeclarations,
1792 UnorderedElementsAre(Eq(types[0].enumerationDeclarations[0]),
1793 Eq(types[0].enumerationDeclarations[1]))))));
1794 }
1795
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesEnumerationDeclarationName)1796 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesEnumerationDeclarationName)
1797 {
1798 Storage::Types types{createTypes()};
1799 storage.synchronizeTypes(types, {});
1800 types[0].enumerationDeclarations[1].name = "Name";
1801
1802 storage.synchronizeTypes(types, {});
1803
1804 ASSERT_THAT(storage.fetchTypes(),
1805 Contains(AllOf(IsStorageType(importId2,
1806 "QQuickItem",
1807 Storage::NativeType{"QObject"},
1808 TypeAccessSemantics::Reference,
1809 sourceId1),
1810 Field(&Storage::Type::enumerationDeclarations,
1811 UnorderedElementsAre(Eq(types[0].enumerationDeclarations[0]),
1812 Eq(types[0].enumerationDeclarations[1]))))));
1813 }
1814
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesEnumerationDeclarationPopEnumeratorDeclaration)1815 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesEnumerationDeclarationPopEnumeratorDeclaration)
1816 {
1817 Storage::Types types{createTypes()};
1818 storage.synchronizeTypes(types, {});
1819 types[0].enumerationDeclarations[1].enumeratorDeclarations.pop_back();
1820
1821 storage.synchronizeTypes(types, {});
1822
1823 ASSERT_THAT(storage.fetchTypes(),
1824 Contains(AllOf(IsStorageType(importId2,
1825 "QQuickItem",
1826 Storage::NativeType{"QObject"},
1827 TypeAccessSemantics::Reference,
1828 sourceId1),
1829 Field(&Storage::Type::enumerationDeclarations,
1830 UnorderedElementsAre(Eq(types[0].enumerationDeclarations[0]),
1831 Eq(types[0].enumerationDeclarations[1]))))));
1832 }
1833
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesEnumerationDeclarationAppendEnumeratorDeclaration)1834 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangesEnumerationDeclarationAppendEnumeratorDeclaration)
1835 {
1836 Storage::Types types{createTypes()};
1837 storage.synchronizeTypes(types, {});
1838 types[0].enumerationDeclarations[1].enumeratorDeclarations.push_back(
1839 Storage::EnumeratorDeclaration{"Haa", 54});
1840
1841 storage.synchronizeTypes(types, {});
1842
1843 ASSERT_THAT(storage.fetchTypes(),
1844 Contains(AllOf(IsStorageType(importId2,
1845 "QQuickItem",
1846 Storage::NativeType{"QObject"},
1847 TypeAccessSemantics::Reference,
1848 sourceId1),
1849 Field(&Storage::Type::enumerationDeclarations,
1850 UnorderedElementsAre(Eq(types[0].enumerationDeclarations[0]),
1851 Eq(types[0].enumerationDeclarations[1]))))));
1852 }
1853
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesEnumerationDeclarationChangeEnumeratorDeclarationName)1854 TEST_F(ProjectStorageSlowTest,
1855 SynchronizeTypesChangesEnumerationDeclarationChangeEnumeratorDeclarationName)
1856 {
1857 Storage::Types types{createTypes()};
1858 storage.synchronizeTypes(types, {});
1859 types[0].enumerationDeclarations[1].enumeratorDeclarations[0].name = "Hoo";
1860
1861 storage.synchronizeTypes(types, {});
1862
1863 ASSERT_THAT(storage.fetchTypes(),
1864 Contains(AllOf(IsStorageType(importId2,
1865 "QQuickItem",
1866 Storage::NativeType{"QObject"},
1867 TypeAccessSemantics::Reference,
1868 sourceId1),
1869 Field(&Storage::Type::enumerationDeclarations,
1870 UnorderedElementsAre(Eq(types[0].enumerationDeclarations[0]),
1871 Eq(types[0].enumerationDeclarations[1]))))));
1872 }
1873
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesEnumerationDeclarationChangeEnumeratorDeclarationValue)1874 TEST_F(ProjectStorageSlowTest,
1875 SynchronizeTypesChangesEnumerationDeclarationChangeEnumeratorDeclarationValue)
1876 {
1877 Storage::Types types{createTypes()};
1878 storage.synchronizeTypes(types, {});
1879 types[0].enumerationDeclarations[1].enumeratorDeclarations[1].value = 11;
1880
1881 storage.synchronizeTypes(types, {});
1882
1883 ASSERT_THAT(storage.fetchTypes(),
1884 Contains(AllOf(IsStorageType(importId2,
1885 "QQuickItem",
1886 Storage::NativeType{"QObject"},
1887 TypeAccessSemantics::Reference,
1888 sourceId1),
1889 Field(&Storage::Type::enumerationDeclarations,
1890 UnorderedElementsAre(Eq(types[0].enumerationDeclarations[0]),
1891 Eq(types[0].enumerationDeclarations[1]))))));
1892 }
1893
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesEnumerationDeclarationAddThatEnumeratorDeclarationHasValue)1894 TEST_F(ProjectStorageSlowTest,
1895 SynchronizeTypesChangesEnumerationDeclarationAddThatEnumeratorDeclarationHasValue)
1896 {
1897 Storage::Types types{createTypes()};
1898 storage.synchronizeTypes(types, {});
1899 types[0].enumerationDeclarations[1].enumeratorDeclarations[0].value = 11;
1900 types[0].enumerationDeclarations[1].enumeratorDeclarations[0].hasValue = true;
1901
1902 storage.synchronizeTypes(types, {});
1903
1904 ASSERT_THAT(storage.fetchTypes(),
1905 Contains(AllOf(IsStorageType(importId2,
1906 "QQuickItem",
1907 Storage::NativeType{"QObject"},
1908 TypeAccessSemantics::Reference,
1909 sourceId1),
1910 Field(&Storage::Type::enumerationDeclarations,
1911 UnorderedElementsAre(Eq(types[0].enumerationDeclarations[0]),
1912 Eq(types[0].enumerationDeclarations[1]))))));
1913 }
1914
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangesEnumerationDeclarationRemoveThatEnumeratorDeclarationHasValue)1915 TEST_F(ProjectStorageSlowTest,
1916 SynchronizeTypesChangesEnumerationDeclarationRemoveThatEnumeratorDeclarationHasValue)
1917 {
1918 Storage::Types types{createTypes()};
1919 storage.synchronizeTypes(types, {});
1920 types[0].enumerationDeclarations[1].enumeratorDeclarations[0].hasValue = false;
1921
1922 storage.synchronizeTypes(types, {});
1923
1924 ASSERT_THAT(storage.fetchTypes(),
1925 Contains(AllOf(IsStorageType(importId2,
1926 "QQuickItem",
1927 Storage::NativeType{"QObject"},
1928 TypeAccessSemantics::Reference,
1929 sourceId1),
1930 Field(&Storage::Type::enumerationDeclarations,
1931 UnorderedElementsAre(Eq(types[0].enumerationDeclarations[0]),
1932 Eq(types[0].enumerationDeclarations[1]))))));
1933 }
1934
TEST_F(ProjectStorageSlowTest,SynchronizeTypesRemovesEnumerationDeclaration)1935 TEST_F(ProjectStorageSlowTest, SynchronizeTypesRemovesEnumerationDeclaration)
1936 {
1937 Storage::Types types{createTypes()};
1938 storage.synchronizeTypes(types, {});
1939 types[0].enumerationDeclarations.pop_back();
1940
1941 storage.synchronizeTypes(types, {});
1942
1943 ASSERT_THAT(storage.fetchTypes(),
1944 Contains(AllOf(IsStorageType(importId2,
1945 "QQuickItem",
1946 Storage::NativeType{"QObject"},
1947 TypeAccessSemantics::Reference,
1948 sourceId1),
1949 Field(&Storage::Type::enumerationDeclarations,
1950 UnorderedElementsAre(Eq(types[0].enumerationDeclarations[0]))))));
1951 }
1952
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddEnumerationDeclaration)1953 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddEnumerationDeclaration)
1954 {
1955 Storage::Types types{createTypes()};
1956 storage.synchronizeTypes(types, {});
1957 types[0].enumerationDeclarations.push_back(
1958 Storage::EnumerationDeclaration{"name", {Storage::EnumeratorDeclaration{"Foo", 98, true}}});
1959
1960 storage.synchronizeTypes(types, {});
1961
1962 ASSERT_THAT(storage.fetchTypes(),
1963 Contains(AllOf(IsStorageType(importId2,
1964 "QQuickItem",
1965 Storage::NativeType{"QObject"},
1966 TypeAccessSemantics::Reference,
1967 sourceId1),
1968 Field(&Storage::Type::enumerationDeclarations,
1969 UnorderedElementsAre(Eq(types[0].enumerationDeclarations[0]),
1970 Eq(types[0].enumerationDeclarations[1]),
1971 Eq(types[0].enumerationDeclarations[2]))))));
1972 }
1973
TEST_F(ProjectStorageSlowTest,SynchronizeImportsAddImports)1974 TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddImports)
1975 {
1976 Storage::Imports imports{createImports()};
1977
1978 storage.synchronizeImports(imports);
1979
1980 ASSERT_THAT(storage.fetchAllImports(),
1981 UnorderedElementsAre(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
1982 IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
1983 IsImport("/path/to", Storage::VersionNumber{}, SourceId{})));
1984 }
1985
TEST_F(ProjectStorageSlowTest,SynchronizeImportsAddImportsAgain)1986 TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddImportsAgain)
1987 {
1988 Storage::Imports imports{createImports()};
1989 storage.synchronizeImports(imports);
1990
1991 storage.synchronizeImports(imports);
1992
1993 ASSERT_THAT(storage.fetchAllImports(),
1994 UnorderedElementsAre(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
1995 IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
1996 IsImport("/path/to", Storage::VersionNumber{}, SourceId{})));
1997 }
1998
TEST_F(ProjectStorageSlowTest,SynchronizeImportsAddMoreImports)1999 TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddMoreImports)
2000 {
2001 Storage::Imports imports{createImports()};
2002 storage.synchronizeImports(imports);
2003 imports.push_back(Storage::Import{"QtQuick.Foo", Storage::VersionNumber{1}, importSourceId3});
2004
2005 storage.synchronizeImports(imports);
2006
2007 ASSERT_THAT(storage.fetchAllImports(),
2008 UnorderedElementsAre(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
2009 IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
2010 IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
2011 IsImport("QtQuick.Foo", Storage::VersionNumber{1}, importSourceId3)));
2012 }
2013
TEST_F(ProjectStorageSlowTest,SynchronizeImportsAddSameImportNameButDifferentVersion)2014 TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddSameImportNameButDifferentVersion)
2015 {
2016 Storage::Imports imports{createImports()};
2017 imports.push_back(Storage::Import{"Qml", Storage::VersionNumber{4}, importSourceId3});
2018 storage.synchronizeImports(imports);
2019 imports.pop_back();
2020 imports.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}, importSourceId3});
2021
2022 storage.synchronizeImports(imports);
2023
2024 ASSERT_THAT(storage.fetchAllImports(),
2025 UnorderedElementsAre(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
2026 IsImport("Qml", Storage::VersionNumber{3}, importSourceId3),
2027 IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
2028 IsImport("/path/to", Storage::VersionNumber{}, SourceId{})));
2029 }
2030
TEST_F(ProjectStorageSlowTest,SynchronizeImportsRemoveImport)2031 TEST_F(ProjectStorageSlowTest, SynchronizeImportsRemoveImport)
2032 {
2033 Storage::Imports imports{createImports()};
2034 storage.synchronizeImports(imports);
2035 imports.pop_back();
2036
2037 storage.synchronizeImports(imports);
2038
2039 ASSERT_THAT(storage.fetchAllImports(),
2040 UnorderedElementsAre(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
2041 IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2)));
2042 }
2043
TEST_F(ProjectStorageSlowTest,SynchronizeImportsUpdateImport)2044 TEST_F(ProjectStorageSlowTest, SynchronizeImportsUpdateImport)
2045 {
2046 Storage::Imports imports{createImports()};
2047 storage.synchronizeImports(imports);
2048 imports[1].sourceId = importSourceId3;
2049
2050 storage.synchronizeImports(imports);
2051
2052 ASSERT_THAT(storage.fetchAllImports(),
2053 UnorderedElementsAre(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
2054 IsImport("QtQuick", Storage::VersionNumber{}, importSourceId3),
2055 IsImport("/path/to", Storage::VersionNumber{}, SourceId{})));
2056 }
2057
TEST_F(ProjectStorageSlowTest,SynchronizeImportsAddImportDependecies)2058 TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddImportDependecies)
2059 {
2060 Storage::Imports imports{createImports()};
2061
2062 storage.synchronizeImports(imports);
2063
2064 ASSERT_THAT(storage.fetchAllImports(),
2065 UnorderedElementsAre(
2066 AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
2067 Field(&Storage::Import::importDependencies, IsEmpty())),
2068 AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
2069 Field(&Storage::Import::importDependencies,
2070 ElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2})))),
2071 AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
2072 Field(&Storage::Import::importDependencies,
2073 UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
2074 IsBasicImport("QtQuick",
2075 Storage::VersionNumber{}))))));
2076 }
2077
TEST_F(ProjectStorageSlowTest,SynchronizeImportsAddImportDependeciesWhichDoesNotExitsThrows)2078 TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddImportDependeciesWhichDoesNotExitsThrows)
2079 {
2080 Storage::Imports imports{createImports()};
2081 imports[1].importDependencies.push_back(Storage::Import{"QmlBase", Storage::VersionNumber{2}});
2082
2083 ASSERT_THROW(storage.synchronizeImports(imports), QmlDesigner::ImportDoesNotExists);
2084 }
2085
TEST_F(ProjectStorageSlowTest,SynchronizeImportsRemovesDependeciesForRemovedImports)2086 TEST_F(ProjectStorageSlowTest, SynchronizeImportsRemovesDependeciesForRemovedImports)
2087 {
2088 Storage::Imports imports{createImports()};
2089 storage.synchronizeImports(imports);
2090 auto last = imports.back();
2091 imports.pop_back();
2092
2093 storage.synchronizeImports(imports);
2094
2095 last.importDependencies.pop_back();
2096 imports.push_back(last);
2097 storage.synchronizeImports(imports);
2098 ASSERT_THAT(storage.fetchAllImports(),
2099 UnorderedElementsAre(
2100 AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
2101 Field(&Storage::Import::importDependencies, IsEmpty())),
2102 AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
2103 Field(&Storage::Import::importDependencies,
2104 ElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2})))),
2105 AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
2106 Field(&Storage::Import::importDependencies,
2107 UnorderedElementsAre(
2108 IsBasicImport("QtQuick", Storage::VersionNumber{}))))));
2109 }
2110
TEST_F(ProjectStorageSlowTest,SynchronizeImportsAddMoreImportDependecies)2111 TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddMoreImportDependecies)
2112 {
2113 Storage::Imports imports{createImports()};
2114 storage.synchronizeImports(imports);
2115 imports.push_back(Storage::Import{"QmlBase", Storage::VersionNumber{2}, importSourceId1, {}});
2116 imports[1].importDependencies.push_back(Storage::Import{"QmlBase", Storage::VersionNumber{2}});
2117
2118 storage.synchronizeImports(imports);
2119
2120 ASSERT_THAT(
2121 storage.fetchAllImports(),
2122 UnorderedElementsAre(
2123 AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
2124 Field(&Storage::Import::importDependencies, IsEmpty())),
2125 AllOf(IsImport("QmlBase", Storage::VersionNumber{2}, importSourceId1),
2126 Field(&Storage::Import::importDependencies, IsEmpty())),
2127 AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
2128 Field(&Storage::Import::importDependencies,
2129 UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
2130 IsBasicImport("QmlBase", Storage::VersionNumber{2})))),
2131 AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
2132 Field(&Storage::Import::importDependencies,
2133 UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
2134 IsBasicImport("QtQuick", Storage::VersionNumber{}))))));
2135 }
2136
TEST_F(ProjectStorageSlowTest,SynchronizeImportsAddMoreImportDependeciesWithDifferentVersionNumber)2137 TEST_F(ProjectStorageSlowTest, SynchronizeImportsAddMoreImportDependeciesWithDifferentVersionNumber)
2138 {
2139 Storage::Imports imports{createImports()};
2140 storage.synchronizeImports(imports);
2141 imports.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}, importSourceId1, {}});
2142 imports[1].importDependencies.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}});
2143
2144 storage.synchronizeImports(imports);
2145
2146 ASSERT_THAT(
2147 storage.fetchAllImports(),
2148 UnorderedElementsAre(
2149 AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
2150 Field(&Storage::Import::importDependencies, IsEmpty())),
2151 AllOf(IsImport("Qml", Storage::VersionNumber{3}, importSourceId1),
2152 Field(&Storage::Import::importDependencies, IsEmpty())),
2153 AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
2154 Field(&Storage::Import::importDependencies,
2155 UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
2156 IsBasicImport("Qml", Storage::VersionNumber{3})))),
2157 AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
2158 Field(&Storage::Import::importDependencies,
2159 UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
2160 IsBasicImport("QtQuick", Storage::VersionNumber{}))))));
2161 }
2162
TEST_F(ProjectStorageSlowTest,SynchronizeImportsDependencyGetsHighestVersionIfNoVersionIsSupplied)2163 TEST_F(ProjectStorageSlowTest, SynchronizeImportsDependencyGetsHighestVersionIfNoVersionIsSupplied)
2164 {
2165 Storage::Imports imports{createImports()};
2166 storage.synchronizeImports(imports);
2167 imports.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}, importSourceId1, {}});
2168 imports[1].importDependencies.push_back(Storage::Import{"Qml"});
2169
2170 storage.synchronizeImports(imports);
2171
2172 ASSERT_THAT(
2173 storage.fetchAllImports(),
2174 UnorderedElementsAre(
2175 AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
2176 Field(&Storage::Import::importDependencies, IsEmpty())),
2177 AllOf(IsImport("Qml", Storage::VersionNumber{3}, importSourceId1),
2178 Field(&Storage::Import::importDependencies, IsEmpty())),
2179 AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
2180 Field(&Storage::Import::importDependencies,
2181 UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
2182 IsBasicImport("Qml", Storage::VersionNumber{3})))),
2183 AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
2184 Field(&Storage::Import::importDependencies,
2185 UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
2186 IsBasicImport("QtQuick", Storage::VersionNumber{}))))));
2187 }
2188
TEST_F(ProjectStorageSlowTest,SynchronizeImportsDependencyGetsOnlyTheHighestDependency)2189 TEST_F(ProjectStorageSlowTest, SynchronizeImportsDependencyGetsOnlyTheHighestDependency)
2190 {
2191 Storage::Imports imports{createImports()};
2192 storage.synchronizeImports(imports);
2193 imports.push_back(Storage::Import{"Qml", Storage::VersionNumber{1}, importSourceId1, {}});
2194 imports[1].importDependencies.push_back(Storage::Import{"Qml"});
2195
2196 storage.synchronizeImports(imports);
2197
2198 ASSERT_THAT(
2199 storage.fetchAllImports(),
2200 UnorderedElementsAre(
2201 AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
2202 Field(&Storage::Import::importDependencies, IsEmpty())),
2203 AllOf(IsImport("Qml", Storage::VersionNumber{1}, importSourceId1),
2204 Field(&Storage::Import::importDependencies, IsEmpty())),
2205 AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
2206 Field(&Storage::Import::importDependencies,
2207 UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2})))),
2208 AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
2209 Field(&Storage::Import::importDependencies,
2210 UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
2211 IsBasicImport("QtQuick", Storage::VersionNumber{}))))));
2212 }
2213
TEST_F(ProjectStorageSlowTest,SynchronizeImportsDependencyRemoveDuplicateDependencies)2214 TEST_F(ProjectStorageSlowTest, SynchronizeImportsDependencyRemoveDuplicateDependencies)
2215 {
2216 Storage::Imports imports{createImports()};
2217 storage.synchronizeImports(imports);
2218 imports.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}, importSourceId1, {}});
2219 imports[2].importDependencies.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}});
2220 imports[2].importDependencies.push_back(Storage::Import{"Qml", Storage::VersionNumber{2}});
2221 imports[2].importDependencies.push_back(Storage::Import{"Qml", Storage::VersionNumber{3}});
2222 imports[2].importDependencies.push_back(Storage::Import{"Qml", Storage::VersionNumber{2}});
2223
2224 storage.synchronizeImports(imports);
2225
2226 ASSERT_THAT(
2227 storage.fetchAllImports(),
2228 UnorderedElementsAre(
2229 AllOf(IsImport("Qml", Storage::VersionNumber{2}, importSourceId1),
2230 Field(&Storage::Import::importDependencies, IsEmpty())),
2231 AllOf(IsImport("Qml", Storage::VersionNumber{3}, importSourceId1),
2232 Field(&Storage::Import::importDependencies, IsEmpty())),
2233 AllOf(IsImport("QtQuick", Storage::VersionNumber{}, importSourceId2),
2234 Field(&Storage::Import::importDependencies,
2235 UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2})))),
2236 AllOf(IsImport("/path/to", Storage::VersionNumber{}, SourceId{}),
2237 Field(&Storage::Import::importDependencies,
2238 UnorderedElementsAre(IsBasicImport("Qml", Storage::VersionNumber{2}),
2239 IsBasicImport("Qml", Storage::VersionNumber{3}),
2240 IsBasicImport("QtQuick", Storage::VersionNumber{}))))));
2241 }
2242
TEST_F(ProjectStorageSlowTest,RemovingImportRemovesDependentTypesToo)2243 TEST_F(ProjectStorageSlowTest, RemovingImportRemovesDependentTypesToo)
2244 {
2245 Storage::Types types{createTypes()};
2246 storage.synchronizeTypes(types, {sourceId1, sourceId2});
2247 Storage::Imports imports{createImports()};
2248 imports.pop_back();
2249 imports.pop_back();
2250 storage.synchronizeImports(imports);
2251
2252 ASSERT_THAT(storage.fetchTypes(),
2253 UnorderedElementsAre(AllOf(IsStorageType(importId1,
2254 "QObject",
2255 Storage::NativeType{},
2256 TypeAccessSemantics::Reference,
2257 sourceId2),
2258 Field(&Storage::Type::exportedTypes,
2259 UnorderedElementsAre(IsExportedType("Object"),
2260 IsExportedType("Obj"))))));
2261 }
2262
TEST_F(ProjectStorageSlowTest,FetchTypeIdByImportIdAndName)2263 TEST_F(ProjectStorageSlowTest, FetchTypeIdByImportIdAndName)
2264 {
2265 Storage::Types types{createTypes()};
2266 storage.synchronizeTypes(types, {sourceId1, sourceId2});
2267
2268 auto typeId = storage.fetchTypeIdByName(importId1, "QObject");
2269
2270 ASSERT_THAT(storage.fetchTypeIdByExportedName("Object"), Eq(typeId));
2271 }
2272
TEST_F(ProjectStorageSlowTest,FetchTypeIdByExportedName)2273 TEST_F(ProjectStorageSlowTest, FetchTypeIdByExportedName)
2274 {
2275 Storage::Types types{createTypes()};
2276 storage.synchronizeTypes(types, {sourceId1, sourceId2});
2277
2278 auto typeId = storage.fetchTypeIdByExportedName("Object");
2279
2280 ASSERT_THAT(storage.fetchTypeIdByName(importId1, "QObject"), Eq(typeId));
2281 }
2282
TEST_F(ProjectStorageSlowTest,FetchTypeIdByImporIdsAndExportedName)2283 TEST_F(ProjectStorageSlowTest, FetchTypeIdByImporIdsAndExportedName)
2284 {
2285 Storage::Types types{createTypes()};
2286 storage.synchronizeTypes(types, {sourceId1, sourceId2});
2287
2288 auto typeId = storage.fetchTypeIdByImportIdsAndExportedName({importId1, importId2}, "Object");
2289
2290 ASSERT_THAT(storage.fetchTypeIdByName(importId1, "QObject"), Eq(typeId));
2291 }
2292
TEST_F(ProjectStorageSlowTest,FetchInvalidTypeIdByImporIdsAndExportedNameIfImportIdsAreEmpty)2293 TEST_F(ProjectStorageSlowTest, FetchInvalidTypeIdByImporIdsAndExportedNameIfImportIdsAreEmpty)
2294 {
2295 Storage::Types types{createTypes()};
2296 storage.synchronizeTypes(types, {sourceId1, sourceId2});
2297
2298 auto typeId = storage.fetchTypeIdByImportIdsAndExportedName({}, "Object");
2299
2300 ASSERT_FALSE(typeId.isValid());
2301 }
2302
TEST_F(ProjectStorageSlowTest,FetchInvalidTypeIdByImporIdsAndExportedNameIfImportIdsAreInvalid)2303 TEST_F(ProjectStorageSlowTest, FetchInvalidTypeIdByImporIdsAndExportedNameIfImportIdsAreInvalid)
2304 {
2305 Storage::Types types{createTypes()};
2306 storage.synchronizeTypes(types, {sourceId1, sourceId2});
2307
2308 auto typeId = storage.fetchTypeIdByImportIdsAndExportedName({ImportId{}}, "Object");
2309
2310 ASSERT_FALSE(typeId.isValid());
2311 }
2312
TEST_F(ProjectStorageSlowTest,FetchInvalidTypeIdByImporIdsAndExportedNameIfNotInImport)2313 TEST_F(ProjectStorageSlowTest, FetchInvalidTypeIdByImporIdsAndExportedNameIfNotInImport)
2314 {
2315 Storage::Types types{createTypes()};
2316 storage.synchronizeTypes(types, {sourceId1, sourceId2});
2317
2318 auto typeId = storage.fetchTypeIdByImportIdsAndExportedName({importId2, importId3}, "Object");
2319
2320 ASSERT_FALSE(typeId.isValid());
2321 }
2322
TEST_F(ProjectStorageSlowTest,FetchImportDepencencyIds)2323 TEST_F(ProjectStorageSlowTest, FetchImportDepencencyIds)
2324 {
2325 Storage::Types types{createTypes()};
2326 storage.synchronizeTypes(types, {sourceId1, sourceId2});
2327
2328 auto importIds = storage.fetchImportDependencyIds({importId3});
2329
2330 ASSERT_THAT(importIds, UnorderedElementsAre(importId1, importId2, importId3));
2331 }
2332
TEST_F(ProjectStorageSlowTest,FetchImportDepencencyIdsForRootDepencency)2333 TEST_F(ProjectStorageSlowTest, FetchImportDepencencyIdsForRootDepencency)
2334 {
2335 Storage::Types types{createTypes()};
2336 storage.synchronizeTypes(types, {sourceId1, sourceId2});
2337
2338 auto importIds = storage.fetchImportDependencyIds({importId1});
2339
2340 ASSERT_THAT(importIds, ElementsAre(importId1));
2341 }
2342
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddAliasDeclarations)2343 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddAliasDeclarations)
2344 {
2345 Storage::Types types{createTypesWithAliases()};
2346
2347 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2348
2349 ASSERT_THAT(storage.fetchTypes(),
2350 Contains(AllOf(
2351 IsStorageType(importId2,
2352 "QAliasItem",
2353 Storage::NativeType{"QQuickItem"},
2354 TypeAccessSemantics::Reference,
2355 sourceId3),
2356 Field(&Storage::Type::propertyDeclarations,
2357 UnorderedElementsAre(
2358 IsPropertyDeclaration("items",
2359 Storage::NativeType{"QQuickItem"},
2360 Storage::PropertyDeclarationTraits::IsList
2361 | Storage::PropertyDeclarationTraits::IsReadOnly),
2362 IsPropertyDeclaration("objects",
2363 Storage::NativeType{"QObject"},
2364 Storage::PropertyDeclarationTraits::IsList),
2365 IsPropertyDeclaration("data",
2366 Storage::NativeType{"QObject"},
2367 Storage::PropertyDeclarationTraits::IsList))))));
2368 }
2369
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddAliasDeclarationsAgain)2370 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddAliasDeclarationsAgain)
2371 {
2372 Storage::Types types{createTypesWithAliases()};
2373 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2374
2375 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2376
2377 ASSERT_THAT(storage.fetchTypes(),
2378 Contains(AllOf(
2379 IsStorageType(importId2,
2380 "QAliasItem",
2381 Storage::NativeType{"QQuickItem"},
2382 TypeAccessSemantics::Reference,
2383 sourceId3),
2384 Field(&Storage::Type::propertyDeclarations,
2385 UnorderedElementsAre(
2386 IsPropertyDeclaration("items",
2387 Storage::NativeType{"QQuickItem"},
2388 Storage::PropertyDeclarationTraits::IsList
2389 | Storage::PropertyDeclarationTraits::IsReadOnly),
2390 IsPropertyDeclaration("objects",
2391 Storage::NativeType{"QObject"},
2392 Storage::PropertyDeclarationTraits::IsList),
2393 IsPropertyDeclaration("data",
2394 Storage::NativeType{"QObject"},
2395 Storage::PropertyDeclarationTraits::IsList))))));
2396 }
2397
TEST_F(ProjectStorageSlowTest,SynchronizeTypesRemoveAliasDeclarations)2398 TEST_F(ProjectStorageSlowTest, SynchronizeTypesRemoveAliasDeclarations)
2399 {
2400 Storage::Types types{createTypesWithAliases()};
2401 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2402 types[2].aliasDeclarations.pop_back();
2403
2404 storage.synchronizeTypes({types[2]}, {sourceId3});
2405
2406 ASSERT_THAT(storage.fetchTypes(),
2407 Contains(AllOf(
2408 IsStorageType(importId2,
2409 "QAliasItem",
2410 Storage::NativeType{"QQuickItem"},
2411 TypeAccessSemantics::Reference,
2412 sourceId3),
2413 Field(&Storage::Type::propertyDeclarations,
2414 UnorderedElementsAre(
2415 IsPropertyDeclaration("items",
2416 Storage::NativeType{"QQuickItem"},
2417 Storage::PropertyDeclarationTraits::IsList
2418 | Storage::PropertyDeclarationTraits::IsReadOnly),
2419 IsPropertyDeclaration("data",
2420 Storage::NativeType{"QObject"},
2421 Storage::PropertyDeclarationTraits::IsList))))));
2422 }
2423
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddAliasDeclarationsThrowsForWrongTypeName)2424 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddAliasDeclarationsThrowsForWrongTypeName)
2425 {
2426 Storage::Types types{createTypesWithAliases()};
2427 types[2].aliasDeclarations[0].aliasTypeName = Storage::NativeType{"QQuickItemWrong"};
2428
2429 ASSERT_THROW(storage.synchronizeTypes({types[2]}, {sourceId4}),
2430 QmlDesigner::TypeNameDoesNotExists);
2431 }
TEST_F(ProjectStorageSlowTest,SynchronizeTypesAddAliasDeclarationsThrowsForWrongPropertyName)2432 TEST_F(ProjectStorageSlowTest, SynchronizeTypesAddAliasDeclarationsThrowsForWrongPropertyName)
2433 {
2434 Storage::Types types{createTypesWithAliases()};
2435 types[2].aliasDeclarations[0].aliasPropertyName = "childrenWrong";
2436
2437 ASSERT_THROW(storage.synchronizeTypes(types, {sourceId4}), QmlDesigner::PropertyNameDoesNotExists);
2438 }
2439
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangeAliasDeclarationsTypeName)2440 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangeAliasDeclarationsTypeName)
2441 {
2442 Storage::Types types{createTypesWithAliases()};
2443 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2444 types[2].aliasDeclarations[1].aliasTypeName = Storage::ExportedType{"Obj2"};
2445
2446 storage.synchronizeTypes({types[2]}, {sourceId3});
2447
2448 ASSERT_THAT(storage.fetchTypes(),
2449 Contains(AllOf(
2450 IsStorageType(importId2,
2451 "QAliasItem",
2452 Storage::NativeType{"QQuickItem"},
2453 TypeAccessSemantics::Reference,
2454 sourceId3),
2455 Field(&Storage::Type::propertyDeclarations,
2456 UnorderedElementsAre(
2457 IsPropertyDeclaration("items",
2458 Storage::NativeType{"QQuickItem"},
2459 Storage::PropertyDeclarationTraits::IsList
2460 | Storage::PropertyDeclarationTraits::IsReadOnly),
2461 IsPropertyDeclaration("objects",
2462 Storage::NativeType{"QObject"},
2463 Storage::PropertyDeclarationTraits::IsList),
2464 IsPropertyDeclaration("data",
2465 Storage::NativeType{"QObject"},
2466 Storage::PropertyDeclarationTraits::IsList))))));
2467 }
2468
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangeAliasDeclarationsPropertyName)2469 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangeAliasDeclarationsPropertyName)
2470 {
2471 Storage::Types types{createTypesWithAliases()};
2472 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2473 types[2].aliasDeclarations[1].aliasPropertyName = "children";
2474
2475 storage.synchronizeTypes({types[2]}, {sourceId3});
2476
2477 ASSERT_THAT(
2478 storage.fetchTypes(),
2479 Contains(
2480 AllOf(IsStorageType(importId2,
2481 "QAliasItem",
2482 Storage::NativeType{"QQuickItem"},
2483 TypeAccessSemantics::Reference,
2484 sourceId3),
2485 Field(&Storage::Type::propertyDeclarations,
2486 UnorderedElementsAre(
2487 IsPropertyDeclaration("items",
2488 Storage::NativeType{"QQuickItem"},
2489 Storage::PropertyDeclarationTraits::IsList
2490 | Storage::PropertyDeclarationTraits::IsReadOnly),
2491 IsPropertyDeclaration("objects",
2492 Storage::NativeType{"QQuickItem"},
2493 Storage::PropertyDeclarationTraits::IsList
2494 | Storage::PropertyDeclarationTraits::IsReadOnly),
2495 IsPropertyDeclaration("data",
2496 Storage::NativeType{"QObject"},
2497 Storage::PropertyDeclarationTraits::IsList))))));
2498 }
2499
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangeAliasDeclarationsToPropertyDeclaration)2500 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangeAliasDeclarationsToPropertyDeclaration)
2501 {
2502 Storage::Types types{createTypesWithAliases()};
2503 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2504 types[2].aliasDeclarations.pop_back();
2505 types[2].propertyDeclarations.push_back(
2506 Storage::PropertyDeclaration{"objects",
2507 Storage::NativeType{"QQuickItem"},
2508 Storage::PropertyDeclarationTraits::IsList
2509 | Storage::PropertyDeclarationTraits::IsReadOnly});
2510
2511 storage.synchronizeTypes({types[2]}, {sourceId3});
2512
2513 ASSERT_THAT(
2514 storage.fetchTypes(),
2515 Contains(
2516 AllOf(IsStorageType(importId2,
2517 "QAliasItem",
2518 Storage::NativeType{"QQuickItem"},
2519 TypeAccessSemantics::Reference,
2520 sourceId3),
2521 Field(&Storage::Type::propertyDeclarations,
2522 UnorderedElementsAre(
2523 IsPropertyDeclaration("items",
2524 Storage::NativeType{"QQuickItem"},
2525 Storage::PropertyDeclarationTraits::IsList
2526 | Storage::PropertyDeclarationTraits::IsReadOnly),
2527 IsPropertyDeclaration("objects",
2528 Storage::NativeType{"QQuickItem"},
2529 Storage::PropertyDeclarationTraits::IsList
2530 | Storage::PropertyDeclarationTraits::IsReadOnly),
2531 IsPropertyDeclaration("data",
2532 Storage::NativeType{"QObject"},
2533 Storage::PropertyDeclarationTraits::IsList))))));
2534 }
2535
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangePropertyDeclarationsToAliasDeclaration)2536 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangePropertyDeclarationsToAliasDeclaration)
2537 {
2538 Storage::Types types{createTypesWithAliases()};
2539 auto typesChanged = types;
2540 typesChanged[2].aliasDeclarations.pop_back();
2541 typesChanged[2].propertyDeclarations.push_back(
2542 Storage::PropertyDeclaration{"objects",
2543 Storage::NativeType{"QQuickItem"},
2544 Storage::PropertyDeclarationTraits::IsList
2545 | Storage::PropertyDeclarationTraits::IsReadOnly});
2546 storage.synchronizeTypes(typesChanged, {sourceId1, sourceId2, sourceId3, sourceId4});
2547
2548 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2549
2550 ASSERT_THAT(storage.fetchTypes(),
2551 Contains(AllOf(
2552 IsStorageType(importId2,
2553 "QAliasItem",
2554 Storage::NativeType{"QQuickItem"},
2555 TypeAccessSemantics::Reference,
2556 sourceId3),
2557 Field(&Storage::Type::propertyDeclarations,
2558 UnorderedElementsAre(
2559 IsPropertyDeclaration("items",
2560 Storage::NativeType{"QQuickItem"},
2561 Storage::PropertyDeclarationTraits::IsList
2562 | Storage::PropertyDeclarationTraits::IsReadOnly),
2563 IsPropertyDeclaration("objects",
2564 Storage::NativeType{"QObject"},
2565 Storage::PropertyDeclarationTraits::IsList),
2566 IsPropertyDeclaration("data",
2567 Storage::NativeType{"QObject"},
2568 Storage::PropertyDeclarationTraits::IsList))))));
2569 }
2570
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangeAliasTargetPropertyDeclarationTraits)2571 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangeAliasTargetPropertyDeclarationTraits)
2572 {
2573 Storage::Types types{createTypesWithAliases()};
2574 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2575 types[1].propertyDeclarations[0].traits = Storage::PropertyDeclarationTraits::IsList
2576 | Storage::PropertyDeclarationTraits::IsReadOnly;
2577
2578 storage.synchronizeTypes({types[1]}, {sourceId2});
2579
2580 ASSERT_THAT(
2581 storage.fetchTypes(),
2582 Contains(
2583 AllOf(IsStorageType(importId2,
2584 "QAliasItem",
2585 Storage::NativeType{"QQuickItem"},
2586 TypeAccessSemantics::Reference,
2587 sourceId3),
2588 Field(&Storage::Type::propertyDeclarations,
2589 UnorderedElementsAre(
2590 IsPropertyDeclaration("items",
2591 Storage::NativeType{"QQuickItem"},
2592 Storage::PropertyDeclarationTraits::IsList
2593 | Storage::PropertyDeclarationTraits::IsReadOnly),
2594 IsPropertyDeclaration("objects",
2595 Storage::NativeType{"QObject"},
2596 Storage::PropertyDeclarationTraits::IsList
2597 | Storage::PropertyDeclarationTraits::IsReadOnly),
2598 IsPropertyDeclaration("data",
2599 Storage::NativeType{"QObject"},
2600 Storage::PropertyDeclarationTraits::IsList))))));
2601 }
2602
TEST_F(ProjectStorageSlowTest,SynchronizeTypesChangeAliasTargetPropertyDeclarationTypeName)2603 TEST_F(ProjectStorageSlowTest, SynchronizeTypesChangeAliasTargetPropertyDeclarationTypeName)
2604 {
2605 Storage::Types types{createTypesWithAliases()};
2606 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2607 types[1].propertyDeclarations[0].typeName = Storage::ExportedType{"Item"};
2608
2609 storage.synchronizeTypes({types[1]}, {sourceId2});
2610
2611 ASSERT_THAT(storage.fetchTypes(),
2612 Contains(AllOf(
2613 IsStorageType(importId2,
2614 "QAliasItem",
2615 Storage::NativeType{"QQuickItem"},
2616 TypeAccessSemantics::Reference,
2617 sourceId3),
2618 Field(&Storage::Type::propertyDeclarations,
2619 UnorderedElementsAre(
2620 IsPropertyDeclaration("items",
2621 Storage::NativeType{"QQuickItem"},
2622 Storage::PropertyDeclarationTraits::IsList
2623 | Storage::PropertyDeclarationTraits::IsReadOnly),
2624 IsPropertyDeclaration("objects",
2625 Storage::NativeType{"QQuickItem"},
2626 Storage::PropertyDeclarationTraits::IsList),
2627 IsPropertyDeclaration("data",
2628 Storage::NativeType{"QObject"},
2629 Storage::PropertyDeclarationTraits::IsList))))));
2630 }
2631
TEST_F(ProjectStorageSlowTest,SynchronizeTypesRemovePropertyDeclarationWithAnAliasThrows)2632 TEST_F(ProjectStorageSlowTest, SynchronizeTypesRemovePropertyDeclarationWithAnAliasThrows)
2633 {
2634 Storage::Types types{createTypesWithAliases()};
2635 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2636 types[1].propertyDeclarations.pop_back();
2637
2638 ASSERT_THROW(storage.synchronizeTypes({types[1]}, {sourceId2}),
2639 Sqlite::ConstraintPreventsModification);
2640 }
2641
TEST_F(ProjectStorageSlowTest,SynchronizeTypesRemovePropertyDeclarationAndAlias)2642 TEST_F(ProjectStorageSlowTest, SynchronizeTypesRemovePropertyDeclarationAndAlias)
2643 {
2644 Storage::Types types{createTypesWithAliases()};
2645 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2646 types[1].propertyDeclarations.pop_back();
2647 types[2].aliasDeclarations.pop_back();
2648
2649 storage.synchronizeTypes({types[1], types[2]}, {sourceId2, sourceId3});
2650
2651 ASSERT_THAT(storage.fetchTypes(),
2652 Contains(AllOf(
2653 IsStorageType(importId2,
2654 "QAliasItem",
2655 Storage::NativeType{"QQuickItem"},
2656 TypeAccessSemantics::Reference,
2657 sourceId3),
2658 Field(&Storage::Type::propertyDeclarations,
2659 UnorderedElementsAre(
2660 IsPropertyDeclaration("items",
2661 Storage::NativeType{"QQuickItem"},
2662 Storage::PropertyDeclarationTraits::IsList
2663 | Storage::PropertyDeclarationTraits::IsReadOnly),
2664 IsPropertyDeclaration("data",
2665 Storage::NativeType{"QObject"},
2666 Storage::PropertyDeclarationTraits::IsList))))));
2667 }
2668
TEST_F(ProjectStorageSlowTest,SynchronizeTypesRemoveTypeWithAliasTargetPropertyDeclarationThrows)2669 TEST_F(ProjectStorageSlowTest, SynchronizeTypesRemoveTypeWithAliasTargetPropertyDeclarationThrows)
2670 {
2671 Storage::Types types{createTypesWithAliases()};
2672 types[2].aliasDeclarations[1].aliasTypeName = Storage::ExportedType{"Object2"};
2673 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2674
2675 ASSERT_THROW(storage.synchronizeTypes({}, {sourceId4}), Sqlite::ConstraintPreventsModification);
2676 }
2677
TEST_F(ProjectStorageSlowTest,SynchronizeTypesRemoveTypeAndAliasPropertyDeclaration)2678 TEST_F(ProjectStorageSlowTest, SynchronizeTypesRemoveTypeAndAliasPropertyDeclaration)
2679 {
2680 Storage::Types types{createTypesWithAliases()};
2681 types[2].aliasDeclarations[1].aliasTypeName = Storage::ExportedType{"Object2"};
2682 storage.synchronizeTypes(types, {sourceId1, sourceId2, sourceId3, sourceId4});
2683 types[2].aliasDeclarations.pop_back();
2684
2685 storage.synchronizeTypes({types[0], types[2]}, {sourceId1, sourceId3});
2686
2687 ASSERT_THAT(storage.fetchTypes(),
2688 Contains(AllOf(
2689 IsStorageType(importId2,
2690 "QAliasItem",
2691 Storage::NativeType{"QQuickItem"},
2692 TypeAccessSemantics::Reference,
2693 sourceId3),
2694 Field(&Storage::Type::propertyDeclarations,
2695 UnorderedElementsAre(
2696 IsPropertyDeclaration("items",
2697 Storage::NativeType{"QQuickItem"},
2698 Storage::PropertyDeclarationTraits::IsList
2699 | Storage::PropertyDeclarationTraits::IsReadOnly),
2700 IsPropertyDeclaration("data",
2701 Storage::NativeType{"QObject"},
2702 Storage::PropertyDeclarationTraits::IsList))))));
2703 }
2704
2705 } // namespace
2706