1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qbs.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #undef QT_NO_CAST_FROM_ASCII // I am qmake, and I approve this hack.
41
42 #include "tst_tools.h"
43
44 #include "../shared.h"
45
46 #include <tools/buildoptions.h>
47 #include <tools/error.h>
48 #include <tools/fileinfo.h>
49 #include <tools/filesaver.h>
50 #include <tools/hostosinfo.h>
51 #include <tools/processutils.h>
52 #include <tools/profile.h>
53 #include <tools/set.h>
54 #include <tools/settings.h>
55 #include <tools/setupprojectparameters.h>
56 #include <tools/stringutils.h>
57 #include <tools/version.h>
58
59 #include <QtCore/qdir.h>
60 #include <QtCore/qfile.h>
61 #include <QtCore/qfileinfo.h>
62 #include <QtCore/qsettings.h>
63 #include <QtCore/qtemporarydir.h>
64 #include <QtCore/qtemporaryfile.h>
65
66 #include <QtTest/qtest.h>
67
68 using namespace qbs;
69 using namespace qbs::Internal;
70
71 namespace std {
72 template<typename T> struct hash<std::vector<T>>
73 {
operator ()std::hash74 std::size_t operator()(const std::vector<T> &v) const noexcept
75 {
76 return hashRange(v);
77 }
78 };
79 } // namespace std
80
TestTools(Settings * settings)81 TestTools::TestTools(Settings *settings)
82 : m_settings(settings), testDataDir(testWorkDir("tools"))
83 {
84 }
85
~TestTools()86 TestTools::~TestTools()
87 {
88 qDeleteAll(m_tmpDirs);
89 }
90
initTestCase()91 void TestTools::initTestCase()
92 {
93 QDir().mkpath(testDataDir);
94 }
95
fileSaver()96 void TestTools::fileSaver()
97 {
98 QVERIFY(QDir::setCurrent(testDataDir));
99
100 static const char *fn = "foo.txt";
101 const auto run = [](const std::function<void()> &func) {
102 if (QFile::exists(fn))
103 QVERIFY(QFile::remove(fn));
104 func();
105 if (QFile::exists(fn))
106 QVERIFY(QFile::remove(fn));
107 };
108
109 // failing to open the file means nothing works
110 run([] {
111 Internal::FileSaver fs(fn);
112 QVERIFY(!fs.device());
113 QVERIFY(!fs.write("hello"));
114 QVERIFY(!fs.commit());
115 QVERIFY(!QFile::exists(fn));
116 });
117
118 // verify that correct usage creates a file with the right contents
119 run([] {
120 Internal::FileSaver fs(fn);
121 QVERIFY(fs.open());
122 QVERIFY(fs.device());
123 QVERIFY(fs.write("hello"));
124 QVERIFY(fs.commit());
125 QVERIFY(QFile::exists(fn));
126 QFile f(fn);
127 QVERIFY(f.open(QIODevice::ReadOnly));
128 QCOMPARE(f.readAll(), QByteArrayLiteral("hello"));
129 });
130
131 // failing to commit writes nothing
132 run([] {
133 Internal::FileSaver fs(fn);
134 QVERIFY(fs.open());
135 QVERIFY(fs.device());
136 QVERIFY(fs.write("hello"));
137 QVERIFY(!QFile::exists(fn));
138 });
139
140 // verify that correct usage creates a file with the right contents and does not overwrite
141 run([] {
142 {
143 Internal::FileSaver fs(fn);
144 QVERIFY(fs.open());
145 QVERIFY(fs.device());
146 QVERIFY(fs.write("hello"));
147 QVERIFY(fs.commit());
148 QVERIFY(QFile::exists(fn));
149 QFile f(fn);
150 QVERIFY(f.open(QIODevice::ReadOnly));
151 QCOMPARE(f.readAll(), QByteArrayLiteral("hello"));
152 }
153
154 const auto lm = QFileInfo(fn).lastModified();
155 QVERIFY(lm.isValid());
156
157 waitForNewTimestamp(".");
158
159 {
160 Internal::FileSaver fs(fn);
161 QVERIFY(fs.open());
162 QVERIFY(fs.device());
163 QVERIFY(fs.write("hello"));
164 QVERIFY(fs.commit());
165 QVERIFY(QFile::exists(fn));
166 }
167
168 const auto lm2 = QFileInfo(fn).lastModified();
169 QVERIFY(lm2.isValid());
170
171 QCOMPARE(lm, lm2); // timestamps should be the same since content did not change
172
173 waitForNewTimestamp(".");
174
175 {
176 Internal::FileSaver fs(fn);
177 QVERIFY(fs.open());
178 QVERIFY(fs.device());
179 QVERIFY(fs.write("hello2"));
180 QVERIFY(fs.commit());
181 QVERIFY(QFile::exists(fn));
182 QFile f(fn);
183 QVERIFY(f.open(QIODevice::ReadOnly));
184 QCOMPARE(f.readAll(), QByteArrayLiteral("hello2"));
185 }
186
187 const auto lm3 = QFileInfo(fn).lastModified();
188 QVERIFY(lm3.isValid());
189
190 QVERIFY(lm != lm3); // timestamps should differ since the content changed
191
192 waitForNewTimestamp(".");
193
194 {
195 // Test overwriteIfUnchanged
196 Internal::FileSaver fs(fn, true);
197 QVERIFY(fs.open());
198 QVERIFY(fs.device());
199 QVERIFY(fs.write("hello2"));
200 QVERIFY(fs.commit());
201 QVERIFY(QFile::exists(fn));
202 QFile f(fn);
203 QVERIFY(f.open(QIODevice::ReadOnly));
204 QCOMPARE(f.readAll(), QByteArrayLiteral("hello2"));
205 }
206
207 const auto lm4 = QFileInfo(fn).lastModified();
208 QVERIFY(lm4.isValid());
209
210 QVERIFY(lm3 != lm4); // timestamps should differ since we always overwrite
211 });
212 }
213
testFileInfo()214 void TestTools::testFileInfo()
215 {
216 QCOMPARE(FileInfo::fileName("C:/waffl/copter.exe"), QString("copter.exe"));
217 QCOMPARE(FileInfo::baseName("C:/waffl/copter.exe.lib"), QString("copter"));
218 QCOMPARE(FileInfo::completeBaseName("C:/waffl/copter.exe.lib"), QString("copter.exe"));
219 QCOMPARE(FileInfo::suffix("C:/waffl/copter.exe.lib"), QString("lib"));
220 QCOMPARE(FileInfo::completeSuffix("C:/waffl/copter.exe.lib"), QString("exe.lib"));
221 QCOMPARE(FileInfo::path("abc"), QString("."));
222 QCOMPARE(FileInfo::path("/abc/lol"), QString("/abc"));
223 QCOMPARE(FileInfo::path("/fileInRoot"), QString(QLatin1Char('/')));
224 if (HostOsInfo::isWindowsHost())
225 QCOMPARE(FileInfo::path("C:/fileInDriveRoot"), QString("C:/"));
226 QVERIFY(!FileInfo::isAbsolute("bla/lol"));
227 QVERIFY(FileInfo::isAbsolute("/bla/lol"));
228 if (HostOsInfo::isWindowsHost()) {
229 QVERIFY(FileInfo::isAbsolute("C:\\bla\\lol"));
230 QVERIFY(FileInfo::isAbsolute("C:\\"));
231 QVERIFY(FileInfo::isAbsolute("C:/"));
232 QVERIFY(!FileInfo::isAbsolute("C:"));
233 }
234 QCOMPARE(FileInfo::resolvePath("/abc/lol", "waffl"), QString("/abc/lol/waffl"));
235 QCOMPARE(FileInfo::resolvePath("/abc/def/ghi/jkl/", "../foo/bar"), QString("/abc/def/ghi/foo/bar"));
236 QCOMPARE(FileInfo::resolvePath("/abc/def/ghi/jkl/", "../../foo/bar"), QString("/abc/def/foo/bar"));
237 QCOMPARE(FileInfo::resolvePath("/abc", "../../../foo/bar"), QString("/foo/bar"));
238 if (HostOsInfo::isWindowsHost()) {
239 QCOMPARE(FileInfo::resolvePath("C:/share", ".."), QString("C:/"));
240 QCOMPARE(FileInfo::resolvePath("C:/share", "D:/"), QString("D:/"));
241 QCOMPARE(FileInfo::resolvePath("C:/share", "D:"), QString()); // should soft-assert
242 }
243 QCOMPARE(FileInfo("/does/not/exist").lastModified(), FileTime());
244 }
245
fileCaseCheck()246 void TestTools::fileCaseCheck()
247 {
248 QTemporaryFile tempFile(QDir::tempPath() + QLatin1String("/CamelCase"));
249 QVERIFY2(tempFile.open(), qPrintable(tempFile.errorString()));
250 QFileInfo tempFileInfo(tempFile.fileName());
251 const QString lowerFilePath = tempFileInfo.absolutePath() + QLatin1Char('/')
252 + tempFileInfo.fileName().toLower();
253 const QString upperFilePath = tempFileInfo.absolutePath() + QLatin1Char('/')
254 + tempFileInfo.fileName().toUpper();
255 QVERIFY(FileInfo::isFileCaseCorrect(tempFileInfo.absoluteFilePath()));
256 if (QFile::exists(lowerFilePath))
257 QVERIFY(!FileInfo::isFileCaseCorrect(lowerFilePath));
258 if (QFile::exists(upperFilePath))
259 QVERIFY(!FileInfo::isFileCaseCorrect(upperFilePath));
260 }
261
testProfiles()262 void TestTools::testProfiles()
263 {
264 TemporaryProfile tpp("parent", m_settings);
265 Profile parentProfile = tpp.p;
266 TemporaryProfile tpc("child", m_settings);
267 Profile childProfile = tpc.p;
268 parentProfile.removeBaseProfile();
269 parentProfile.remove("testKey");
270 QCOMPARE(parentProfile.value("testKey", "none").toString(), QLatin1String("none"));
271 parentProfile.setValue("testKey", "testValue");
272 QCOMPARE(parentProfile.value("testKey").toString(), QLatin1String("testValue"));
273
274 childProfile.remove("testKey");
275 childProfile.removeBaseProfile();
276 QCOMPARE(childProfile.value("testKey", "none").toString(), QLatin1String("none"));
277 childProfile.setBaseProfile("parent");
278 QCOMPARE(childProfile.value("testKey").toString(), QLatin1String("testValue"));
279
280 // Change base profile and check if the inherited value also changes.
281 TemporaryProfile tpf("foo", m_settings);
282 Profile fooProfile = tpf.p;
283 fooProfile.setValue("testKey", "gnampf");
284 childProfile.setBaseProfile("foo");
285 QCOMPARE(childProfile.value("testKey", "none").toString(), QLatin1String("gnampf"));
286
287 ErrorInfo errorInfo;
288 childProfile.setBaseProfile("SmurfAlongWithMe");
289 childProfile.value("blubb", QString(), &errorInfo);
290 QVERIFY(errorInfo.hasError());
291
292 errorInfo.clear();
293 childProfile.setBaseProfile("parent");
294 parentProfile.setBaseProfile("child");
295 QVERIFY(!childProfile.value("blubb", QString(), &errorInfo).isValid());
296 QVERIFY(errorInfo.hasError());
297
298 QVERIFY(!childProfile.allKeys(Profile::KeySelectionNonRecursive).empty());
299
300 errorInfo.clear();
301 QVERIFY(childProfile.allKeys(Profile::KeySelectionRecursive, &errorInfo).empty());
302 QVERIFY(errorInfo.hasError());
303 }
304
testSettingsMigration()305 void TestTools::testSettingsMigration()
306 {
307 QFETCH(QString, baseDir);
308 QFETCH(bool, hasOldSettings);
309 Settings settings(baseDir);
310 if (hasOldSettings) {
311 // checks that we do not copy old "profiles/" dir anymore
312 QVERIFY(!QFileInfo(settings.baseDirectory() + "/qbs/" QBS_VERSION "/profiles/right.txt")
313 .exists());
314 QVERIFY(!settings.value("key", Settings::UserScope).toString().isEmpty());
315 } else {
316 QVERIFY(!QFileInfo(settings.baseDirectory() + "/qbs/" QBS_VERSION "/profiles").exists());
317 QVERIFY(settings.allKeys(Settings::UserScope).empty());
318 }
319 }
320
testSettingsMigration_data()321 void TestTools::testSettingsMigration_data()
322 {
323 QTest::addColumn<QString>("baseDir");
324 QTest::addColumn<bool>("hasOldSettings");
325 QTest::newRow("settings dir with lots of versions") << setupSettingsDir1() << true;
326 QTest::newRow("settings dir with only a fallback") << setupSettingsDir2() << true;
327 QTest::newRow("no previous settings") << setupSettingsDir3() << false;
328 }
329
setupSettingsDir1()330 QString TestTools::setupSettingsDir1()
331 {
332 const auto baseDir = new QTemporaryDir;
333 m_tmpDirs.push_back(baseDir);
334
335 const Version thisVersion = Version::fromString(QBS_VERSION);
336 Version predecessor;
337 if (thisVersion.patchLevel() > 0) {
338 predecessor.setMajorVersion(thisVersion.majorVersion());
339 predecessor.setMinorVersion(thisVersion.minorVersion());
340 predecessor.setPatchLevel(thisVersion.patchLevel() - 1);
341 } else if (thisVersion.minorVersion() > 0) {
342 predecessor.setMajorVersion(thisVersion.majorVersion());
343 predecessor.setMinorVersion(thisVersion.minorVersion() - 1);
344 predecessor.setPatchLevel(99);
345 } else {
346 predecessor.setMajorVersion(thisVersion.majorVersion() - 1);
347 predecessor.setMajorVersion(99);
348 predecessor.setPatchLevel(99);
349 }
350 const auto versions = QList<Version>() << Version(0, 1, 0) << Version(1, 0, 5) << predecessor
351 << Version(thisVersion.majorVersion() + 1, thisVersion.minorVersion(),
352 thisVersion.patchLevel())
353 << Version(thisVersion.majorVersion(), thisVersion.minorVersion() + 1,
354 thisVersion.patchLevel())
355 << Version(thisVersion.majorVersion(), thisVersion.minorVersion(),
356 thisVersion.patchLevel() + 1)
357 << Version(99, 99, 99);
358 for (const Version &v : versions) {
359 const QString settingsDir = baseDir->path() + "/qbs/" + v.toString();
360 QSettings s(settingsDir + "/qbs.conf",
361 HostOsInfo::isWindowsHost() ? QSettings::IniFormat : QSettings::NativeFormat);
362 const QString profilesDir = settingsDir + "/profiles";
363 QDir::root().mkpath(profilesDir);
364 const QString magicString = v == predecessor ? "right" : "wrong";
365 QFile f(profilesDir + '/' + magicString + ".txt");
366 f.open(QIODevice::WriteOnly);
367 s.setValue("org/qt-project/qbs/key", profilesDir + magicString);
368 }
369
370 return baseDir->path();
371 }
372
setupSettingsDir2()373 QString TestTools::setupSettingsDir2()
374 {
375 const auto baseDir = new QTemporaryDir;
376 m_tmpDirs.push_back(baseDir);
377 const QString settingsDir = baseDir->path();
378 QSettings s(settingsDir + QLatin1String("/qbs.conf"),
379 HostOsInfo::isWindowsHost() ? QSettings::IniFormat : QSettings::NativeFormat);
380 const QString profilesDir = settingsDir + QLatin1String("/qbs/profiles");
381 QDir::root().mkpath(profilesDir);
382 QFile f(profilesDir + "/right.txt");
383 f.open(QIODevice::WriteOnly);
384 s.setValue("org/qt-project/qbs/key", profilesDir + "right");
385
386 return baseDir->path();
387 }
388
setupSettingsDir3()389 QString TestTools::setupSettingsDir3()
390 {
391 const auto baseDir = new QTemporaryDir;
392 m_tmpDirs.push_back(baseDir);
393 return baseDir->path();
394 }
395
testBuildConfigMerging()396 void TestTools::testBuildConfigMerging()
397 {
398 TemporaryProfile tp(QLatin1String("tst_tools_profile"), m_settings);
399 Profile profile = tp.p;
400 profile.setValue(QStringLiteral("topLevelKey"), QStringLiteral("topLevelValue"));
401 profile.setValue(QStringLiteral("qbs.toolchain"), QStringLiteral("gcc"));
402 profile.setValue(QStringLiteral("qbs.architecture"),
403 QStringLiteral("Jean-Claude Pillemann"));
404 profile.setValue(QStringLiteral("cpp.treatWarningsAsErrors"), true);
405 QVariantMap overrideMap;
406 overrideMap.insert(QStringLiteral("qbs.toolchain"), QStringLiteral("clang"));
407 overrideMap.insert(QStringLiteral("qbs.installRoot"), QStringLiteral("/blubb"));
408 SetupProjectParameters params;
409 params.setSettingsDirectory(m_settings->baseDirectory());
410 params.setTopLevelProfile(profile.name());
411 params.setConfigurationName(QStringLiteral("debug"));
412 params.setOverriddenValues(overrideMap);
413 const ErrorInfo error = params.expandBuildConfiguration();
414 QVERIFY2(!error.hasError(), qPrintable(error.toString()));
415 const QVariantMap finalMap = params.finalBuildConfigurationTree();
416 QCOMPARE(finalMap.size(), 3);
417 QCOMPARE(finalMap.value(QStringLiteral("topLevelKey")).toString(),
418 QStringLiteral("topLevelValue"));
419 const QVariantMap finalQbsMap = finalMap.value(QStringLiteral("qbs")).toMap();
420 QCOMPARE(finalQbsMap.size(), 4);
421 QCOMPARE(finalQbsMap.value(QStringLiteral("toolchain")).toString(),
422 QStringLiteral("clang"));
423 QCOMPARE(finalQbsMap.value(QStringLiteral("configurationName")).toString(),
424 QStringLiteral("debug"));
425 QCOMPARE(finalQbsMap.value(QStringLiteral("architecture")).toString(),
426 QStringLiteral("Jean-Claude Pillemann"));
427 QCOMPARE(finalQbsMap.value(QStringLiteral("installRoot")).toString(), QLatin1String("/blubb"));
428 const QVariantMap finalCppMap = finalMap.value(QStringLiteral("cpp")).toMap();
429 QCOMPARE(finalCppMap.size(), 1);
430 QCOMPARE(finalCppMap.value(QStringLiteral("treatWarningsAsErrors")).toBool(), true);
431 }
432
testProcessNameByPid()433 void TestTools::testProcessNameByPid()
434 {
435 QCOMPARE(qAppName(), processNameByPid(QCoreApplication::applicationPid()));
436 }
437
438
toNumber(const QString & str)439 int toNumber(const QString &str)
440 {
441 int res = 0;
442 for (const QChar &c : str)
443 res = (res * 10) + c.digitValue();
444 return res;
445 }
446
set_operator_eq()447 void TestTools::set_operator_eq()
448 {
449 {
450 Set<int> set1, set2;
451 QVERIFY(set1 == set2);
452 QVERIFY(!(set1 != set2));
453
454 set1.insert(1);
455 QVERIFY(set1 != set2);
456 QVERIFY(!(set1 == set2));
457
458 set2.insert(1);
459 QVERIFY(set1 == set2);
460 QVERIFY(!(set1 != set2));
461
462 set2.insert(1);
463 QVERIFY(set1 == set2);
464 QVERIFY(!(set1 != set2));
465
466 set1.insert(2);
467 QVERIFY(set1 != set2);
468 QVERIFY(!(set1 == set2));
469 }
470
471 {
472 Set<QString> set1, set2;
473 QVERIFY(set1 == set2);
474 QVERIFY(!(set1 != set2));
475
476 set1.insert("one");
477 QVERIFY(set1 != set2);
478 QVERIFY(!(set1 == set2));
479
480 set2.insert("one");
481 QVERIFY(set1 == set2);
482 QVERIFY(!(set1 != set2));
483
484 set2.insert("one");
485 QVERIFY(set1 == set2);
486 QVERIFY(!(set1 != set2));
487
488 set1.insert("two");
489 QVERIFY(set1 != set2);
490 QVERIFY(!(set1 == set2));
491 }
492
493 {
494 Set<QString> a;
495 Set<QString> b;
496
497 a += "otto";
498 b += "willy";
499
500 QVERIFY(a != b);
501 QVERIFY(!(a == b));
502 }
503
504 {
505 Set<int> s1, s2;
506 s1.reserve(100);
507 s2.reserve(4);
508 QVERIFY(s1 == s2);
509 s1 << 100 << 200 << 300 << 400;
510 s2 << 400 << 300 << 200 << 100;
511 QVERIFY(s1 == s2);
512 }
513 }
514
set_swap()515 void TestTools::set_swap()
516 {
517 Set<int> s1, s2;
518 s1.insert(1);
519 s2.insert(2);
520 s1.swap(s2);
521 QCOMPARE(*s1.begin(),2);
522 QCOMPARE(*s2.begin(),1);
523 }
524
set_size()525 void TestTools::set_size()
526 {
527 Set<int> set;
528 QVERIFY(set.size() == 0);
529 QVERIFY(set.empty());
530 QVERIFY(set.size() == set.size());
531
532 set.insert(1);
533 QVERIFY(set.size() == 1);
534 QVERIFY(!set.empty());
535 QVERIFY(set.size() == set.size());
536
537 set.insert(1);
538 QVERIFY(set.size() == 1);
539 QVERIFY(!set.empty());
540 QVERIFY(set.size() == set.size());
541
542 set.insert(2);
543 QVERIFY(set.size() == 2);
544 QVERIFY(!set.empty());
545 QVERIFY(set.size() == set.size());
546
547 set.remove(1);
548 QVERIFY(set.size() == 1);
549 QVERIFY(!set.empty());
550 QVERIFY(set.size() == set.size());
551
552 set.remove(1);
553 QVERIFY(set.size() == 1);
554 QVERIFY(!set.empty());
555 QVERIFY(set.size() == set.size());
556
557 set.remove(2);
558 QVERIFY(set.size() == 0);
559 QVERIFY(set.empty());
560 QVERIFY(set.size() == set.size());
561 }
562
set_capacity()563 void TestTools::set_capacity()
564 {
565 Set<int> set;
566 size_t n = set.capacity();
567 QVERIFY(n == 0);
568
569 for (int i = 0; i < 1000; ++i) {
570 set.insert(i);
571 QVERIFY(set.capacity() >= set.size());
572 }
573 }
574
set_reserve()575 void TestTools::set_reserve()
576 {
577 Set<int> set;
578
579 set.reserve(1000);
580 QVERIFY(set.capacity() >= 1000);
581
582 for (int i = 0; i < 500; ++i)
583 set.insert(i);
584
585 QVERIFY(set.capacity() >= 1000);
586
587 for (int j = 0; j < 500; ++j)
588 set.remove(j);
589
590 QVERIFY(set.capacity() >= 1000);
591 }
592
set_clear()593 void TestTools::set_clear()
594 {
595 Set<QString> set1, set2;
596 QVERIFY(set1.size() == 0);
597
598 set1.clear();
599 QVERIFY(set1.size() == 0);
600
601 set1.insert("foo");
602 QVERIFY(set1.size() != 0);
603
604 set2 = set1;
605
606 set1.clear();
607 QVERIFY(set1.size() == 0);
608 QVERIFY(set2.size() != 0);
609
610 set2.clear();
611 QVERIFY(set1.size() == 0);
612 QVERIFY(set2.size() == 0);
613 }
614
set_remove()615 void TestTools::set_remove()
616 {
617 Set<QString> set1;
618
619 const size_t max = 500;
620
621 for (size_t i = 0; i < max; ++i)
622 set1.insert(QString::number(i));
623
624 QCOMPARE(set1.size(), max);
625
626 for (size_t j = 0; j < max; ++j) {
627 set1.remove(QString::number((j * 17) % max));
628 QCOMPARE(set1.size(), max - j - 1);
629 }
630 }
631
set_contains()632 void TestTools::set_contains()
633 {
634 Set<QString> set1;
635
636 for (int i = 0; i < 500; ++i) {
637 QVERIFY(!set1.contains(QString::number(i)));
638 set1.insert(QString::number(i));
639 QVERIFY(set1.contains(QString::number(i)));
640 }
641
642 QCOMPARE(set1.size(), size_t { 500 });
643
644 for (int j = 0; j < 500; ++j) {
645 int i = (j * 17) % 500;
646 QVERIFY(set1.contains(QString::number(i)));
647 set1.remove(QString::number(i));
648 QVERIFY(!set1.contains(QString::number(i)));
649 }
650 }
651
set_containsSet()652 void TestTools::set_containsSet()
653 {
654 Set<QString> set1;
655 Set<QString> set2;
656
657 // empty set contains the empty set
658 QVERIFY(set1.contains(set2));
659
660 for (int i = 0; i < 500; ++i) {
661 set1.insert(QString::number(i));
662 set2.insert(QString::number(i));
663 }
664 QVERIFY(set1.contains(set2));
665
666 set2.remove(QString::number(19));
667 set2.remove(QString::number(82));
668 set2.remove(QString::number(7));
669 QVERIFY(set1.contains(set2));
670
671 set1.remove(QString::number(23));
672 QVERIFY(!set1.contains(set2));
673
674 // filled set contains the empty set as well
675 Set<QString> set3;
676 QVERIFY(set1.contains(set3));
677
678 // the empty set doesn't contain a filled set
679 QVERIFY(!set3.contains(set1));
680
681 // verify const signature
682 const Set<QString> set4;
683 QVERIFY(set3.contains(set4));
684 }
685
set_find()686 void TestTools::set_find()
687 {
688 Set<QString> set1;
689
690 for (int i = 0; i < 500; ++i) {
691 QVERIFY(set1.find(QString::number(i)) == set1.end());
692 set1.insert(QString::number(i));
693 const auto it = set1.find(QString::number(i));
694 QVERIFY(it != set1.end());
695 QVERIFY(*it == QString::number(i));
696 }
697
698 QCOMPARE(set1.size(), size_t { 500 });
699
700 for (int j = 0; j < 500; ++j) {
701 int i = (j * 17) % 500;
702 const auto it = set1.find(QString::number(i));
703 QVERIFY(it != set1.end());
704 QVERIFY(*it == QString::number(i));
705 set1.remove(QString::number(i));
706 QVERIFY(set1.find(QString::number(i)) == set1.end());
707 }
708 }
709
set_begin()710 void TestTools::set_begin()
711 {
712 Set<int> set1;
713 Set<int> set2 = set1;
714
715 {
716 const auto i = set1.constBegin();
717 const auto j = set1.cbegin();
718 const auto k = set2.constBegin();
719 const auto ell = set2.cbegin();
720
721 QVERIFY(i == j);
722 QVERIFY(k == ell);
723 }
724
725 set1.insert(44);
726
727 {
728 const auto i = set1.constBegin();
729 const auto j = set1.cbegin();
730 const auto k = set2.constBegin();
731 const auto ell = set2.cbegin();
732
733 QVERIFY(i == j);
734 QVERIFY(k == ell);
735 }
736
737 set2 = set1;
738
739 {
740 const auto i = set1.constBegin();
741 const auto j = set1.cbegin();
742 const auto k = set2.constBegin();
743 const auto ell = set2.cbegin();
744
745 QVERIFY(i == j);
746 QVERIFY(k == ell);
747 }
748 }
749
set_end()750 void TestTools::set_end()
751 {
752 Set<int> set1;
753 Set<int> set2 = set1;
754
755 {
756 const auto i = set1.constEnd();
757 const auto j = set1.cend();
758 const auto k = set2.constEnd();
759 const auto ell = set2.cend();
760
761 QVERIFY(i == j);
762 QVERIFY(k == ell);
763
764 QVERIFY(set1.constBegin() == set1.constEnd());
765 QVERIFY(set2.constBegin() == set2.constEnd());
766 }
767
768 set1.insert(44);
769
770 {
771 const auto i = set1.constEnd();
772 const auto j = set1.cend();
773 const auto k = set2.constEnd();
774 const auto ell = set2.cend();
775
776 QVERIFY(i == j);
777 QVERIFY(k == ell);
778
779 QVERIFY(set1.constBegin() != set1.constEnd());
780 QVERIFY(set2.constBegin() == set2.constEnd());
781 }
782
783 set2 = set1;
784
785 {
786 const auto i = set1.constEnd();
787 const auto j = set1.cend();
788 const auto k = set2.constEnd();
789 const auto ell = set2.cend();
790
791 QVERIFY(i == j);
792 QVERIFY(k == ell);
793
794 QVERIFY(set1.constBegin() != set1.constEnd());
795 QVERIFY(set2.constBegin() != set2.constEnd());
796 }
797
798 set1.clear();
799 set2.clear();
800 QVERIFY(set1.constBegin() == set1.constEnd());
801 QVERIFY(set2.constBegin() == set2.constEnd());
802 }
803
804 struct IdentityTracker {
805 int value, id;
806 };
operator ==(IdentityTracker lhs,IdentityTracker rhs)807 inline bool operator==(IdentityTracker lhs, IdentityTracker rhs) { return lhs.value == rhs.value; }
operator <(IdentityTracker lhs,IdentityTracker rhs)808 inline bool operator<(IdentityTracker lhs, IdentityTracker rhs) { return lhs.value < rhs.value; }
809
set_insert()810 void TestTools::set_insert()
811 {
812 {
813 Set<int> set1;
814 QVERIFY(set1.size() == 0);
815 set1.insert(1);
816 QVERIFY(set1.size() == 1);
817 set1.insert(2);
818 QVERIFY(set1.size() == 2);
819 set1.insert(2);
820 QVERIFY(set1.size() == 2);
821 QVERIFY(set1.contains(2));
822 set1.remove(2);
823 QVERIFY(set1.size() == 1);
824 QVERIFY(!set1.contains(2));
825 set1.insert(2);
826 QVERIFY(set1.size() == 2);
827 QVERIFY(set1.contains(2));
828 }
829
830 {
831 Set<int> set1;
832 QVERIFY(set1.size() == 0);
833 set1 << 1;
834 QVERIFY(set1.size() == 1);
835 set1 << 2;
836 QVERIFY(set1.size() == 2);
837 set1 << 2;
838 QVERIFY(set1.size() == 2);
839 QVERIFY(set1.contains(2));
840 set1.remove(2);
841 QVERIFY(set1.size() == 1);
842 QVERIFY(!set1.contains(2));
843 set1 << 2;
844 QVERIFY(set1.size() == 2);
845 QVERIFY(set1.contains(2));
846 }
847
848 {
849 Set<IdentityTracker> set;
850 QCOMPARE(set.size(), size_t { 0 });
851 const int dummy = -1;
852 IdentityTracker id00 = {0, 0}, id01 = {0, 1}, searchKey = {0, dummy};
853 QCOMPARE(set.insert(id00).first->id, id00.id);
854 QCOMPARE(set.size(), size_t { 1 });
855 QCOMPARE(set.insert(id01).first->id, id00.id); // first inserted is kept
856 QCOMPARE(set.size(), size_t { 1 });
857 QCOMPARE(set.find(searchKey)->id, id00.id);
858 }
859 }
860
set_reverseIterators()861 void TestTools::set_reverseIterators()
862 {
863 Set<int> s;
864 s << 1 << 17 << 61 << 127 << 911;
865 std::vector<int> v(s.begin(), s.end());
866 std::reverse(v.begin(), v.end());
867 const Set<int> &cs = s;
868 QVERIFY(std::equal(v.begin(), v.end(), s.rbegin()));
869 QVERIFY(std::equal(v.begin(), v.end(), s.crbegin()));
870 QVERIFY(std::equal(v.begin(), v.end(), cs.rbegin()));
871 QVERIFY(std::equal(s.rbegin(), s.rend(), v.begin()));
872 QVERIFY(std::equal(s.crbegin(), s.crend(), v.begin()));
873 QVERIFY(std::equal(cs.rbegin(), cs.rend(), v.begin()));
874 }
875
set_stlIterator()876 void TestTools::set_stlIterator()
877 {
878 Set<QString> set1;
879 for (int i = 0; i < 25000; ++i)
880 set1.insert(QString::number(i));
881
882 {
883 int sum = 0;
884 auto i = set1.cbegin();
885 while (i != set1.end()) {
886 sum += toNumber(*i);
887 ++i;
888 }
889 QVERIFY(sum == 24999 * 25000 / 2);
890 }
891
892 {
893 int sum = 0;
894 auto i = set1.cend();
895 while (i != set1.begin()) {
896 --i;
897 sum += toNumber(*i);
898 }
899 QVERIFY(sum == 24999 * 25000 / 2);
900 }
901 }
902
set_stlMutableIterator()903 void TestTools::set_stlMutableIterator()
904 {
905 Set<QString> set1;
906 for (int i = 0; i < 25000; ++i)
907 set1.insert(QString::number(i));
908
909 {
910 int sum = 0;
911 auto i = set1.begin();
912 while (i != set1.end()) {
913 sum += toNumber(*i);
914 ++i;
915 }
916 QVERIFY(sum == 24999 * 25000 / 2);
917 }
918
919 {
920 int sum = 0;
921 auto i = set1.end();
922 while (i != set1.begin()) {
923 --i;
924 sum += toNumber(*i);
925 }
926 QVERIFY(sum == 24999 * 25000 / 2);
927 }
928
929 {
930 Set<QString> set2 = set1;
931 Set<QString> set3 = set2;
932
933 auto i = set2.begin();
934 auto j = set3.begin();
935
936 while (i != set2.end()) {
937 i = set2.erase(i);
938 }
939 QVERIFY(set2.empty());
940 QVERIFY(!set3.empty());
941
942 j = set3.end();
943 while (j != set3.begin()) {
944 j--;
945 if (j + 1 != set3.end())
946 set3.erase(j + 1);
947 }
948 if (set3.begin() != set3.end())
949 set3.erase(set3.begin());
950
951 QVERIFY(set2.empty());
952 QVERIFY(set3.empty());
953
954 i = set2.insert("foo").first;
955 QCOMPARE(*i, QLatin1String("foo"));
956 }
957 }
958
set_setOperations()959 void TestTools::set_setOperations()
960 {
961 Set<QString> set1, set2;
962 set1 << "alpha" << "beta" << "gamma" << "delta" << "zeta" << "omega";
963 set2 << "beta" << "gamma" << "delta" << "epsilon" << "iota" << "omega";
964
965 Set<QString> set3 = set1;
966 set3.unite(set2);
967 QVERIFY(set3.size() == 8);
968 QVERIFY(set3.contains("alpha"));
969 QVERIFY(set3.contains("beta"));
970 QVERIFY(set3.contains("gamma"));
971 QVERIFY(set3.contains("delta"));
972 QVERIFY(set3.contains("epsilon"));
973 QVERIFY(set3.contains("zeta"));
974 QVERIFY(set3.contains("iota"));
975 QVERIFY(set3.contains("omega"));
976
977 Set<QString> set4 = set2;
978 set4.unite(set1);
979 QVERIFY(set4.size() == 8);
980 QVERIFY(set4.contains("alpha"));
981 QVERIFY(set4.contains("beta"));
982 QVERIFY(set4.contains("gamma"));
983 QVERIFY(set4.contains("delta"));
984 QVERIFY(set4.contains("epsilon"));
985 QVERIFY(set4.contains("zeta"));
986 QVERIFY(set4.contains("iota"));
987 QVERIFY(set4.contains("omega"));
988
989 QVERIFY(set3 == set4);
990
991 Set<QString> set5 = set1;
992 set5.intersect(set2);
993 QVERIFY(set5.size() == 4);
994 QVERIFY(set5.contains("beta"));
995 QVERIFY(set5.contains("gamma"));
996 QVERIFY(set5.contains("delta"));
997 QVERIFY(set5.contains("omega"));
998
999 Set<QString> set6 = set2;
1000 set6.intersect(set1);
1001 QVERIFY(set6.size() == 4);
1002 QVERIFY(set6.contains("beta"));
1003 QVERIFY(set6.contains("gamma"));
1004 QVERIFY(set6.contains("delta"));
1005 QVERIFY(set6.contains("omega"));
1006
1007 QVERIFY(set5 == set6);
1008
1009 Set<QString> set7 = set1;
1010 set7.subtract(set2);
1011 QVERIFY(set7.size() == 2);
1012 QVERIFY(set7.contains("alpha"));
1013 QVERIFY(set7.contains("zeta"));
1014
1015 Set<QString> set8 = set2;
1016 set8.subtract(set1);
1017 QVERIFY(set8.size() == 2);
1018 QVERIFY(set8.contains("epsilon"));
1019 QVERIFY(set8.contains("iota"));
1020
1021 Set<QString> set9 = set1 | set2;
1022 QVERIFY(set9 == set3);
1023
1024 Set<QString> set10 = set1 & set2;
1025 QVERIFY(set10 == set5);
1026
1027 Set<QString> set11 = set1 + set2;
1028 QVERIFY(set11 == set3);
1029
1030 Set<QString> set12 = set1 - set2;
1031 QVERIFY(set12 == set7);
1032
1033 Set<QString> set13 = set2 - set1;
1034 QVERIFY(set13 == set8);
1035
1036 Set<QString> set14 = set1;
1037 set14 |= set2;
1038 QVERIFY(set14 == set3);
1039
1040 Set<QString> set15 = set1;
1041 set15 &= set2;
1042 QVERIFY(set15 == set5);
1043
1044 Set<QString> set16 = set1;
1045 set16 += set2;
1046 QVERIFY(set16 == set3);
1047
1048 Set<QString> set17 = set1;
1049 set17 -= set2;
1050 QVERIFY(set17 == set7);
1051
1052 Set<QString> set18 = set2;
1053 set18 -= set1;
1054 QVERIFY(set18 == set8);
1055 }
1056
set_makeSureTheComfortFunctionsCompile()1057 void TestTools::set_makeSureTheComfortFunctionsCompile()
1058 {
1059 Set<int> set1, set2, set3;
1060 set1 << 5;
1061 set1 |= set2;
1062 set1 |= 5;
1063 set1 &= set2;
1064 set1 &= 5;
1065 set1 += set2;
1066 set1 += 5;
1067 set1 -= set2;
1068 set1 -= 5;
1069 set1 = set2 | set3;
1070 set1 = set2 & set3;
1071 set1 = set2 + set3;
1072 set1 = set2 - set3;
1073 }
1074
set_initializerList()1075 void TestTools::set_initializerList()
1076 {
1077 Set<int> set = {1, 1, 2, 3, 4, 5};
1078 QCOMPARE(set.size(), size_t { 5 });
1079 QVERIFY(set.contains(1));
1080 QVERIFY(set.contains(2));
1081 QVERIFY(set.contains(3));
1082 QVERIFY(set.contains(4));
1083 QVERIFY(set.contains(5));
1084
1085 // check _which_ of the equal elements gets inserted (in the QHash/QMap case, it's the last):
1086 const Set<IdentityTracker> set2 = {{1, 0}, {1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
1087 QCOMPARE(set2.size(), size_t { 5 });
1088 const int dummy = -1;
1089 const IdentityTracker searchKey = {1, dummy};
1090 QCOMPARE(set2.find(searchKey)->id, 0);
1091
1092 Set<int> emptySet{};
1093 QVERIFY(emptySet.empty());
1094
1095 Set<int> set3{{}, {}, {}};
1096 QVERIFY(!set3.empty());
1097 }
1098
set_intersects()1099 void TestTools::set_intersects()
1100 {
1101 Set<int> s1;
1102 Set<int> s2;
1103
1104 QVERIFY(!s1.intersects(s1));
1105 QVERIFY(!s1.intersects(s2));
1106
1107 s1 << 100;
1108 QVERIFY(s1.intersects(s1));
1109 QVERIFY(!s1.intersects(s2));
1110
1111 s2 << 200;
1112 QVERIFY(!s1.intersects(s2));
1113
1114 s1 << 200;
1115 QVERIFY(s1.intersects(s2));
1116
1117 Set<int> s3;
1118 s3 << 500;
1119 QVERIFY(!s1.intersects(s3));
1120 s3 << 200;
1121 QVERIFY(s1.intersects(s3));
1122 }
1123
stringutils_join()1124 void TestTools::stringutils_join()
1125 {
1126 QFETCH(std::vector<std::string>, input);
1127 QFETCH(std::string, separator);
1128 QFETCH(std::string, expectedResult);
1129
1130 QCOMPARE(join(input, separator), expectedResult);
1131 }
1132
stringutils_join_data()1133 void TestTools::stringutils_join_data()
1134 {
1135 QTest::addColumn<std::vector<std::string>>("input");
1136 QTest::addColumn<std::string>("separator");
1137 QTest::addColumn<std::string>("expectedResult");
1138
1139 QTest::newRow("data1")
1140 << std::vector<std::string>()
1141 << std::string()
1142 << std::string();
1143
1144 QTest::newRow("data2")
1145 << std::vector<std::string>()
1146 << std::string("separator")
1147 << std::string();
1148
1149 QTest::newRow("data3")
1150 << std::vector<std::string>({"one"})
1151 << std::string("separator")
1152 << std::string("one");
1153
1154 QTest::newRow("data4")
1155 << std::vector<std::string>({"one"})
1156 << std::string("separator")
1157 << std::string("one");
1158
1159
1160 QTest::newRow("data5")
1161 << std::vector<std::string>({"a", "b"})
1162 << std::string(" ")
1163 << std::string("a b");
1164
1165 QTest::newRow("data6")
1166 << std::vector<std::string>({"a", "b", "c"})
1167 << std::string(" ")
1168 << std::string("a b c");
1169 }
1170
stringutils_join_empty()1171 void TestTools::stringutils_join_empty()
1172 {
1173 std::vector<std::string> list;
1174 std::string string = join(list, std::string());
1175
1176 QVERIFY(string.empty());
1177 }
1178
stringutils_join_char()1179 void TestTools::stringutils_join_char()
1180 {
1181 QFETCH(std::vector<std::string>, input);
1182 QFETCH(char, separator);
1183 QFETCH(std::string, expectedResult);
1184
1185 QCOMPARE(join(input, separator), expectedResult);
1186 }
1187
stringutils_join_char_data()1188 void TestTools::stringutils_join_char_data()
1189 {
1190 QTest::addColumn<std::vector<std::string>>("input");
1191 QTest::addColumn<char>("separator");
1192 QTest::addColumn<std::string>("expectedResult");
1193
1194 QTest::newRow("data1")
1195 << std::vector<std::string>()
1196 << ' '
1197 << std::string();
1198
1199 QTest::newRow("data5")
1200 << std::vector<std::string>({"a", "b"})
1201 << ' '
1202 << std::string("a b");
1203
1204 QTest::newRow("data6")
1205 << std::vector<std::string>({"a", "b", "c"})
1206 << ' '
1207 << std::string("a b c");
1208 }
1209
stringutils_startsWith()1210 void TestTools::stringutils_startsWith()
1211 {
1212 std::string a;
1213 a = "AB";
1214 QVERIFY( startsWith(a, "A") );
1215 QVERIFY( startsWith(a, "AB") );
1216 QVERIFY( !startsWith(a, "C") );
1217 QVERIFY( !startsWith(a, "ABCDEF") );
1218 QVERIFY( startsWith(a, "") );
1219 QVERIFY( startsWith(a, 'A') );
1220 QVERIFY( !startsWith(a, 'C') );
1221 QVERIFY( !startsWith(a, char()) );
1222
1223 QVERIFY( startsWith(a, "A") );
1224 QVERIFY( startsWith(a, "AB") );
1225 QVERIFY( !startsWith(a, "C") );
1226 QVERIFY( !startsWith(a, "ABCDEF") );
1227 QVERIFY( startsWith(a, "") );
1228
1229 a = "";
1230 QVERIFY( startsWith(a, "") );
1231 QVERIFY( !startsWith(a, "ABC") );
1232
1233 QVERIFY( startsWith(a, "") );
1234 QVERIFY( !startsWith(a, "ABC") );
1235
1236 QVERIFY( !startsWith(a, 'x') );
1237 QVERIFY( !startsWith(a, char()) );
1238
1239 a = std::string();
1240 QVERIFY( startsWith(a, "") ); // different from QString::startsWith
1241 QVERIFY( !startsWith(a, "ABC") );
1242
1243 QVERIFY( !startsWith(a, 'x') );
1244 QVERIFY( !startsWith(a, char()) );
1245
1246 a = u8"\xc3\xa9";
1247 QVERIFY( startsWith(a, u8"\xc3\xa9") );
1248 QVERIFY( !startsWith(a, u8"\xc3\xa1") );
1249 }
1250
stringutils_endsWith()1251 void TestTools::stringutils_endsWith()
1252 {
1253 std::string a;
1254 a = "AB";
1255 QVERIFY( endsWith(a, "B") );
1256 QVERIFY( endsWith(a, "AB") );
1257 QVERIFY( !endsWith(a, "C") );
1258 QVERIFY( !endsWith(a, "ABCDEF") );
1259 QVERIFY( endsWith(a, "") );
1260 QVERIFY( endsWith(a, 'B') );
1261 QVERIFY( !endsWith(a, 'C') );
1262 QVERIFY( !endsWith(a, char()) );
1263
1264 QVERIFY( endsWith(a, "B") );
1265 QVERIFY( endsWith(a, "AB") );
1266 QVERIFY( !endsWith(a, "C") );
1267 QVERIFY( !endsWith(a, "ABCDEF") );
1268 QVERIFY( endsWith(a, "") );
1269
1270 a = "";
1271 QVERIFY( endsWith(a, "") );
1272 QVERIFY( !endsWith(a, "ABC") );
1273 QVERIFY( !endsWith(a, 'x') );
1274 QVERIFY( !endsWith(a, char()) );
1275
1276 QVERIFY( endsWith(a, "") );
1277 QVERIFY( !endsWith(a, "ABC") );
1278
1279 a = std::string();
1280 QVERIFY( endsWith(a, "") ); // different from QString::endsWith
1281 QVERIFY( !endsWith(a, "ABC") );
1282
1283 QVERIFY( !endsWith(a, 'x') );
1284 QVERIFY( !endsWith(a, char()) );
1285
1286 a = u8"\xc3\xa9";
1287 QVERIFY( endsWith(a, u8"\xc3\xa9") );
1288 QVERIFY( !endsWith(a, u8"\xc3\xa1") );
1289 }
1290
stringutils_trimmed()1291 void TestTools::stringutils_trimmed()
1292 {
1293 std::string a;
1294 a = "Text";
1295 QCOMPARE(a, std::string("Text"));
1296 QCOMPARE(trimmed(a), std::string("Text"));
1297 QCOMPARE(a, std::string("Text"));
1298 a = " ";
1299 QCOMPARE(trimmed(a), std::string(""));
1300 QCOMPARE(a, std::string(" "));
1301 a = " a ";
1302 QCOMPARE(trimmed(a), std::string("a"));
1303
1304 a = "Text";
1305 QCOMPARE(trimmed(std::move(a)), std::string("Text"));
1306 a = " ";
1307 QCOMPARE(trimmed(std::move(a)), std::string(""));
1308 a = " a ";
1309 QCOMPARE(trimmed(std::move(a)), std::string("a"));
1310 }
1311
hash_tuple()1312 void TestTools::hash_tuple()
1313 {
1314 using Key = std::tuple<int, int>;
1315
1316 Key key0{0, 5};
1317 Key key1{10, 20};
1318 Key key2{30, 40};
1319
1320 std::unordered_map<Key, int> map;
1321 map.insert({key1, 1});
1322 map.insert({key2, 2});
1323
1324 QCOMPARE(map[key0], 0);
1325 QCOMPARE(map[key1], 1);
1326 QCOMPARE(map[key2], 2);
1327 }
1328
hash_range()1329 void TestTools::hash_range()
1330 {
1331 using Key = std::vector<int>;
1332
1333 Key key0;
1334 Key key1{1};
1335 Key key2{1, 2};
1336
1337 std::unordered_map<Key, int> map;
1338 map.insert({key1, 1});
1339 map.insert({key2, 2});
1340
1341 QCOMPARE(map[key0], 0);
1342 QCOMPARE(map[key1], 1);
1343 QCOMPARE(map[key2], 2);
1344 }
1345
main(int argc,char * argv[])1346 int main(int argc, char *argv[])
1347 {
1348 QCoreApplication app(argc, argv);
1349 const SettingsPtr s = settings();
1350 TestTools tt(s.get());
1351 return QTest::qExec(&tt, argc, argv);
1352 }
1353