aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/api/testdata/multiplexing/multiplexing.qbs7
-rw-r--r--tests/auto/api/testdata/process-result/process-result.qbs1
-rw-r--r--tests/auto/api/tst_api.cpp195
-rw-r--r--tests/auto/api/tst_api.h2
-rw-r--r--tests/auto/blackbox/find/find-android.qbs49
-rw-r--r--tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c1
-rw-r--r--tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xml2
-rw-r--r--tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xml2
-rw-r--r--tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xml2
-rw-r--r--tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml2
-rw-r--r--tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbs2
-rw-r--r--tests/auto/blackbox/testdata-apple/overrideInfoPlist/Override-Info.plist10
-rw-r--r--tests/auto/blackbox/testdata-apple/overrideInfoPlist/main.c1
-rw-r--r--tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs16
-rw-r--r--tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs7
-rw-r--r--tests/auto/blackbox/testdata-qt/metatypes/metatypes.qbs28
-rw-r--r--tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.cpp3
-rw-r--r--tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.h8
-rw-r--r--tests/auto/blackbox/testdata-qt/metatypes/mocableclass2.cpp10
-rw-r--r--tests/auto/blackbox/testdata-qt/metatypes/unmocableclass.cpp7
-rw-r--r--tests/auto/blackbox/testdata-qt/qmltyperegistrar/example.qml58
-rw-r--r--tests/auto/blackbox/testdata-qt/qmltyperegistrar/main.cpp71
-rw-r--r--tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.cpp78
-rw-r--r--tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.h78
-rw-r--r--tests/auto/blackbox/testdata-qt/qmltyperegistrar/qmltyperegistrar.qbs33
-rw-r--r--tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs22
-rw-r--r--tests/auto/blackbox/testdata/build-variant-defaults/build-variant-defaults.qbs16
-rw-r--r--tests/auto/blackbox/testdata/build-variant-defaults/main.cpp1
-rw-r--r--tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile-probe-project.qbs22
-rw-r--r--tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile.py25
-rw-r--r--tests/auto/blackbox/testdata/conanfile-probe/testlib/conanfile.py25
-rw-r--r--tests/auto/blackbox/testdata/dependency-profile-mismatch/dependency-profile-mismatch.qbs12
-rw-r--r--tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs34
-rw-r--r--tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp1
-rw-r--r--tests/auto/blackbox/testdata/empty-profile/empty-profile.qbs3
-rw-r--r--tests/auto/blackbox/testdata/empty-profile/main.cpp1
-rw-r--r--tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs25
-rw-r--r--tests/auto/blackbox/testdata/freedesktop/main.cpp4
-rw-r--r--tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml15
-rw-r--r--tests/auto/blackbox/testdata/freedesktop/myapp.desktop4
-rw-r--r--tests/auto/blackbox/testdata/freedesktop/myapp.png0
-rw-r--r--tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs3
-rw-r--r--tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs1
-rw-r--r--tests/auto/blackbox/testdata/host-os-properties/host-os-properties.qbs8
-rw-r--r--tests/auto/blackbox/testdata/host-os-properties/main.cpp7
-rw-r--r--tests/auto/blackbox/testdata/install-locations/install-locations.qbs12
-rw-r--r--tests/auto/blackbox/testdata/install-locations/theplugin.cpp3
-rw-r--r--tests/auto/blackbox/testdata/last-module-candidate-broken/last-module-candidate-broken.qbs5
-rw-r--r--tests/auto/blackbox/testdata/last-module-candidate-broken/main.cpp1
-rw-r--r--tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo1.qbs3
-rw-r--r--tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo2.qbs2
-rw-r--r--tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs4
-rw-r--r--tests/auto/blackbox/testdata/list-property-order/product.qbs1
-rw-r--r--tests/auto/blackbox/testdata/path-probe/BaseApp.qbs64
-rw-r--r--tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs3
-rw-r--r--tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs3
-rw-r--r--tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs3
-rw-r--r--tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs1
-rw-r--r--tests/auto/blackbox/testdata/path-probe/mult-files.qbs1
-rw-r--r--tests/auto/blackbox/testdata/path-probe/name-filter.qbs1
-rw-r--r--tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs1
-rw-r--r--tests/auto/blackbox/testdata/path-probe/non-existent.qbs1
-rw-r--r--tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs1
-rw-r--r--tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs1
-rw-r--r--tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs1
-rw-r--r--tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs3
-rw-r--r--tests/auto/blackbox/testdata/path-probe/single-file.qbs1
-rw-r--r--tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs51
-rw-r--r--tests/auto/blackbox/testdata/property-evaluation-context/modules/base/base.qbs4
-rw-r--r--tests/auto/blackbox/testdata/property-evaluation-context/modules/top/top.qbs6
-rw-r--r--tests/auto/blackbox/testdata/property-evaluation-context/property-evaluation-context.qbs34
-rw-r--r--tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs1
-rw-r--r--tests/auto/blackbox/testdata/protobuf/import.qbs1
-rw-r--r--tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs1
-rw-r--r--tests/auto/blackbox/testdata/response-files/response-files.qbs3
-rw-r--r--tests/auto/blackbox/testdata/sanitizer/sanitizer.cpp4
-rw-r--r--tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs30
-rw-r--r--tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.h1
-rw-r--r--tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.qbs4
-rw-r--r--tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/main.cpp3
-rw-r--r--tests/auto/blackbox/testdata/scan-result-in-non-dependency/lib/lib.h3
-rw-r--r--tests/auto/blackbox/testdata/scan-result-in-non-dependency/other/other.qbs24
-rw-r--r--tests/auto/blackbox/testdata/scan-result-in-non-dependency/p.qbs6
-rw-r--r--tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.h1
-rw-r--r--tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.qbs4
-rw-r--r--tests/auto/blackbox/testdata/scan-result-in-other-product/app/main.cpp3
-rw-r--r--tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.h3
-rw-r--r--tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.qbs7
-rw-r--r--tests/auto/blackbox/testdata/scan-result-in-other-product/other/other.qbs24
-rw-r--r--tests/auto/blackbox/testdata/scan-result-in-other-product/p.qbs7
-rw-r--r--tests/auto/blackbox/testdata/undefined-target-platform/undefined-target-platform.qbs13
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp557
-rw-r--r--tests/auto/blackbox/tst_blackbox.h15
-rw-r--r--tests/auto/blackbox/tst_blackboxandroid.cpp257
-rw-r--r--tests/auto/blackbox/tst_blackboxapple.cpp163
-rw-r--r--tests/auto/blackbox/tst_blackboxapple.h1
-rw-r--r--tests/auto/blackbox/tst_blackboxbase.cpp20
-rw-r--r--tests/auto/blackbox/tst_blackboxbase.h9
-rw-r--r--tests/auto/blackbox/tst_blackboxjava.cpp3
-rw-r--r--tests/auto/blackbox/tst_blackboxqt.cpp76
-rw-r--r--tests/auto/blackbox/tst_blackboxqt.h4
-rw-r--r--tests/auto/blackbox/tst_clangdb.cpp4
-rw-r--r--tests/auto/buildgraph/tst_buildgraph.cpp10
-rw-r--r--tests/auto/language/testdata/erroneous/ambiguous-multiplex-dependency.qbs14
-rw-r--r--tests/auto/language/testdata/erroneous/dependency-profile-mismatch-2.qbs17
-rw-r--r--tests/auto/language/testdata/erroneous/dependency-profile-mismatch.qbs14
-rw-r--r--tests/auto/language/tst_language.cpp31
-rw-r--r--tests/auto/shared.h45
-rw-r--r--tests/benchmarker/benchmarker.cpp13
-rw-r--r--tests/benchmarker/benchmarker.h4
-rw-r--r--tests/benchmarker/commandlineparser.cpp8
-rw-r--r--tests/benchmarker/exception.h4
-rw-r--r--tests/benchmarker/valgrindrunner.cpp4
-rw-r--r--tests/benchmarker/valgrindrunner.h2
-rw-r--r--tests/fuzzy-test/commandlineparser.cpp4
-rw-r--r--tests/fuzzy-test/commandlineparser.h4
-rw-r--r--tests/fuzzy-test/fuzzytester.cpp3
-rw-r--r--tests/fuzzy-test/fuzzytester.h4
118 files changed, 2110 insertions, 436 deletions
diff --git a/tests/auto/api/testdata/multiplexing/multiplexing.qbs b/tests/auto/api/testdata/multiplexing/multiplexing.qbs
index 243c73d46..75958ed60 100644
--- a/tests/auto/api/testdata/multiplexing/multiplexing.qbs
+++ b/tests/auto/api/testdata/multiplexing/multiplexing.qbs
@@ -74,6 +74,13 @@ Project {
qbs.architectures: ["TRS-80", "C64"]
qbs.buildVariants: ["debug", "release"]
}
+ Product {
+ name: "multiplex-without-aggregator-4-depends-2"
+ multiplexByQbsProperties: ["architectures", "buildVariants"]
+ qbs.architectures: ["TRS-80", "C64"]
+ qbs.buildVariants: ["debug", "release"]
+ Depends { name: "multiplex-without-aggregator-2" }
+ }
}
Product {
diff --git a/tests/auto/api/testdata/process-result/process-result.qbs b/tests/auto/api/testdata/process-result/process-result.qbs
index 52eb1a3ec..5b71ecaaa 100644
--- a/tests/auto/api/testdata/process-result/process-result.qbs
+++ b/tests/auto/api/testdata/process-result/process-result.qbs
@@ -1,6 +1,7 @@
Project {
CppApplication {
name: "app"
+ consoleApplication: true
files: ["main.cpp"]
}
Product {
diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp
index 34f5090d7..151690c63 100644
--- a/tests/auto/api/tst_api.cpp
+++ b/tests/auto/api/tst_api.cpp
@@ -144,7 +144,7 @@ static bool waitForFinished(qbs::AbstractJob *job, int timeout = 0)
TestApi::TestApi()
: m_logSink(new LogSink)
- , m_sourceDataDir(QDir::cleanPath(SRCDIR "/testdata"))
+ , m_sourceDataDir(testDataSourceDir(SRCDIR "/testdata"))
, m_workingDataDir(testWorkDir(QStringLiteral("api")))
{
}
@@ -502,6 +502,8 @@ void TestApi::canonicalToolchainList()
QStringList({"xcode", "clang", "llvm", "gcc"}));
QCOMPARE(qbs::canonicalToolchain(QStringList({"clang", "llvm", "gcc"})),
QStringList({"clang", "llvm", "gcc"}));
+ QCOMPARE(qbs::canonicalToolchain(QStringList({"clang-cl", "msvc"})),
+ QStringList({"clang-cl", "msvc"}));
QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm", "gcc"})),
QStringList({"llvm", "gcc"}));
QCOMPARE(qbs::canonicalToolchain(QStringList({"mingw", "gcc"})),
@@ -516,6 +518,8 @@ void TestApi::canonicalToolchainList()
QStringList({"xcode", "clang", "llvm", "gcc"}));
QCOMPARE(qbs::canonicalToolchain(QStringList({"clang"})),
QStringList({"clang", "llvm", "gcc"}));
+ QCOMPARE(qbs::canonicalToolchain(QStringList({"clang-cl"})),
+ QStringList({"clang-cl", "msvc"}));
QCOMPARE(qbs::canonicalToolchain(QStringList({"llvm"})),
QStringList({"llvm", "gcc"}));
QCOMPARE(qbs::canonicalToolchain(QStringList({"mingw"})),
@@ -623,30 +627,24 @@ static qbs::Project::ProductSelection defaultProducts()
return qbs::Project::ProductSelectionDefaultOnly;
}
-static void printProjectData(const qbs::ProjectData &project)
-{
- const auto products = project.products();
- for (const qbs::ProductData &p : products) {
- qDebug(" Product '%s' at %s", qPrintable(p.name()), qPrintable(p.location().toString()));
- const auto groups = p.groups();
- for (const qbs::GroupData &g : groups) {
- qDebug(" Group '%s' at %s", qPrintable(g.name()), qPrintable(g.location().toString()));
- qDebug(" Files: %s", qPrintable(g.allFilePaths().join(QLatin1String(", "))));
- }
- }
-}
-
void TestApi::changeContent()
{
qbs::SetupProjectParameters setupParams = defaultSetupParameters("project-editing");
- std::unique_ptr<qbs::SetupProjectJob> job(qbs::Project().setupProject(setupParams,
- m_logSink, 0));
- waitForFinished(job.get());
- QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
- qbs::Project project = job->project();
- qbs::ProjectData projectData = project.projectData();
- QCOMPARE(projectData.allProducts().size(), 1);
- qbs::ProductData product = projectData.allProducts().front();
+ std::unique_ptr<qbs::SetupProjectJob> job;
+ qbs::Project project;
+ qbs::ProjectData projectData;
+ qbs::ProductData product;
+
+ const auto resolve = [&] {
+ job.reset(project.setupProject(setupParams, m_logSink, 0));
+ waitForFinished(job.get());
+ QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
+ project = job->project();
+ projectData = project.projectData();
+ QCOMPARE(projectData.allProducts().size(), 1);
+ product = projectData.allProducts().front();
+ };
+ resolve();
QVERIFY(product.groups().size() >= 8);
// Error handling: Invalid product.
@@ -659,12 +657,16 @@ void TestApi::changeContent()
QVERIFY(errorInfo.hasError());
QVERIFY(errorInfo.toString().contains("empty"));
+ WAIT_FOR_NEW_TIMESTAMP();
errorInfo = project.addGroup(product, "New Group 1");
VERIFY_NO_ERROR(errorInfo);
errorInfo = project.addGroup(product, "New Group 2");
VERIFY_NO_ERROR(errorInfo);
+ resolve();
+ QVERIFY(product.groups().size() >= 10);
+
// Error handling: Group already inserted.
errorInfo = project.addGroup(product, "New Group 1");
QVERIFY(errorInfo.hasError());
@@ -677,20 +679,14 @@ void TestApi::changeContent()
QVERIFY2(errorInfo.toString().contains("more than once"), qPrintable(errorInfo.toString()));
// Add files to empty array literal.
- projectData = project.projectData();
- QVERIFY(projectData.products().size() == 1);
- product = projectData.products().front();
- QVERIFY(product.groups().size() >= 10);
+ WAIT_FOR_NEW_TIMESTAMP();
qbs::GroupData group = findGroup(product, "New Group 1");
QVERIFY(group.isValid());
errorInfo = project.addFiles(product, group, QStringList() << "file.h" << "file.cpp");
VERIFY_NO_ERROR(errorInfo);
// Error handling: Add the same file again.
- projectData = project.projectData();
- QVERIFY(projectData.products().size() == 1);
- product = projectData.products().front();
- QVERIFY(product.groups().size() >= 10);
+ resolve();
group = findGroup(product, "New Group 1");
QVERIFY(group.isValid());
errorInfo = project.addFiles(product, group, QStringList() << "file.cpp");
@@ -698,14 +694,12 @@ void TestApi::changeContent()
QVERIFY2(errorInfo.toString().contains("already"), qPrintable(errorInfo.toString()));
// Remove one of the newly added files again.
+ WAIT_FOR_NEW_TIMESTAMP();
errorInfo = project.removeFiles(product, group, QStringList("file.h"));
VERIFY_NO_ERROR(errorInfo);
// Error handling: Try to remove the same file again.
- projectData = project.projectData();
- QVERIFY(projectData.products().size() == 1);
- product = projectData.products().front();
- QVERIFY(product.groups().size() >= 10);
+ resolve();
group = findGroup(product, "New Group 1");
QVERIFY(group.isValid());
errorInfo = project.removeFiles(product, group, QStringList() << "file.h");
@@ -720,38 +714,34 @@ void TestApi::changeContent()
QVERIFY2(errorInfo.toString().contains("complex"), qPrintable(errorInfo.toString()));
// Remove file from product's 'files' binding.
+ WAIT_FOR_NEW_TIMESTAMP();
errorInfo = project.removeFiles(product, qbs::GroupData(), QStringList("main.cpp"));
VERIFY_NO_ERROR(errorInfo);
+ resolve();
// Add file to non-empty array literal.
- projectData = project.projectData();
- QVERIFY(projectData.products().size() == 1);
- product = projectData.products().front();
+ WAIT_FOR_NEW_TIMESTAMP();
group = findGroup(product, "Existing Group 1");
QVERIFY(group.isValid());
errorInfo = project.addFiles(product, group, QStringList() << "newfile1.txt");
VERIFY_NO_ERROR(errorInfo);
+ resolve();
// Add files to list represented as a single string.
- projectData = project.projectData();
- QVERIFY(projectData.products().size() == 1);
- product = projectData.products().front();
+ WAIT_FOR_NEW_TIMESTAMP();
errorInfo = project.addFiles(product, qbs::GroupData(), QStringList() << "newfile2.txt");
VERIFY_NO_ERROR(errorInfo);
+ resolve();
// Add files to list represented as an identifier.
- projectData = project.projectData();
- QVERIFY(projectData.products().size() == 1);
- product = projectData.products().front();
+ WAIT_FOR_NEW_TIMESTAMP();
group = findGroup(product, "Existing Group 2");
QVERIFY(group.isValid());
errorInfo = project.addFiles(product, group, QStringList() << "newfile3.txt");
VERIFY_NO_ERROR(errorInfo);
+ resolve();
// Add files to list represented as a block of code (not yet implemented).
- projectData = project.projectData();
- QVERIFY(projectData.products().size() == 1);
- product = projectData.products().front();
group = findGroup(product, "Existing Group 3");
QVERIFY(group.isValid());
errorInfo = project.addFiles(product, group, QStringList() << "newfile4.txt");
@@ -759,18 +749,14 @@ void TestApi::changeContent()
QVERIFY2(errorInfo.toString().contains("complex"), qPrintable(errorInfo.toString()));
// Add file to group with directory prefix.
- projectData = project.projectData();
- QVERIFY(projectData.products().size() == 1);
- product = projectData.products().front();
+ WAIT_FOR_NEW_TIMESTAMP();
group = findGroup(product, "Existing Group 4");
QVERIFY(group.isValid());
errorInfo = project.addFiles(product, group, QStringList() << "file.txt");
VERIFY_NO_ERROR(errorInfo);
+ resolve();
// Error handling: Add file to group with non-directory prefix.
- projectData = project.projectData();
- QVERIFY(projectData.products().size() == 1);
- product = projectData.products().front();
group = findGroup(product, "Existing Group 5");
QVERIFY(group.isValid());
errorInfo = project.addFiles(product, group, QStringList() << "newfile1.txt");
@@ -778,16 +764,12 @@ void TestApi::changeContent()
QVERIFY2(errorInfo.toString().contains("prefix"), qPrintable(errorInfo.toString()));
// Remove group.
- projectData = project.projectData();
- QVERIFY(projectData.products().size() == 1);
- product = projectData.products().front();
+ WAIT_FOR_NEW_TIMESTAMP();
group = findGroup(product, "Existing Group 5");
QVERIFY(group.isValid());
errorInfo = project.removeGroup(product, group);
VERIFY_NO_ERROR(errorInfo);
- projectData = project.projectData();
- QVERIFY(projectData.products().size() == 1);
- QVERIFY(projectData.products().front().groups().size() >= 9);
+ resolve();
// Error handling: Try to remove the same group again.
errorInfo = project.removeGroup(product, group);
@@ -805,9 +787,7 @@ void TestApi::changeContent()
newFile.close();
errorInfo = project.addFiles(product, group, QStringList() << newFile.fileName());
VERIFY_NO_ERROR(errorInfo);
- projectData = project.projectData();
- QVERIFY(projectData.products().size() == 1);
- product = projectData.products().front();
+ resolve();
group = findGroup(product, "Group with wildcards");
QVERIFY(group.isValid());
QCOMPARE(group.sourceArtifactsFromWildcards().size(), 1);
@@ -838,46 +818,13 @@ void TestApi::changeContent()
QVERIFY(rcvr.descriptions.contains("compiling file.cpp"));
QVERIFY(!rcvr.descriptions.contains("compiling main.cpp"));
- // Now check whether the data updates were done correctly.
- projectData = project.projectData();
- job.reset(project.setupProject(setupParams, m_logSink, 0));
- waitForFinished(job.get());
- QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
- project = job->project();
- qbs::ProjectData newProjectData = project.projectData();
-
- // Can't use Project::operator== here, as the target artifacts will differ due to the build
- // not having run yet.
- bool projectDataMatches = newProjectData.products().size() == 1
- && projectData.products().size() == 1
- && newProjectData.products().front().groups() == projectData.products().front().groups();
- if (!projectDataMatches) {
- qDebug("This is the assumed project:");
- printProjectData(projectData);
- qDebug("This is the actual project:");
- printProjectData(newProjectData);
- }
- QVERIFY(projectDataMatches); // Will fail if e.g. code locations don't match.
-
- // Now try building again and check if the newly resolved product behaves the same way.
- buildJob.reset(project.buildAllProducts(buildOptions, defaultProducts(), this));
- connect(buildJob.get(), &qbs::BuildJob::reportCommandDescription,
- &rcvr, &BuildDescriptionReceiver::handleDescription);
- waitForFinished(buildJob.get());
- QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString()));
- QVERIFY(rcvr.descriptions.contains("compiling file.cpp"));
- QVERIFY(!rcvr.descriptions.contains("compiling main.cpp"));
-
- // Now, after the build, the project data must be entirely identical.
- QVERIFY(projectData == project.projectData());
-
// Error handling: Try to change the project during a build.
buildJob.reset(project.buildAllProducts(buildOptions, defaultProducts(), this));
- errorInfo = project.addGroup(newProjectData.products().front(), "blubb");
+ errorInfo = project.addGroup(projectData.products().front(), "blubb");
QVERIFY(errorInfo.hasError());
QVERIFY2(errorInfo.toString().contains("in progress"), qPrintable(errorInfo.toString()));
waitForFinished(buildJob.get());
- errorInfo = project.addGroup(newProjectData.products().front(), "blubb");
+ errorInfo = project.addGroup(projectData.products().front(), "blubb");
VERIFY_NO_ERROR(errorInfo);
project = qbs::Project();
@@ -888,16 +835,11 @@ void TestApi::changeContent()
setupParams.setProjectFilePath(QDir::cleanPath(m_workingDataDir +
"/project-editing/project-with-no-files.qbs"));
- job.reset(project.setupProject(setupParams, m_logSink, 0));
- waitForFinished(job.get());
- QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
- project = job->project();
- projectData = project.projectData();
- QCOMPARE(projectData.allProducts().size(), 1);
- product = projectData.allProducts().front();
+ resolve();
+ WAIT_FOR_NEW_TIMESTAMP();
errorInfo = project.addFiles(product, qbs::GroupData(), QStringList("main.cpp"));
VERIFY_NO_ERROR(errorInfo);
- projectData = project.projectData();
+ resolve();
rcvr.descriptions.clear();
buildJob.reset(project.buildAllProducts(buildOptions, defaultProducts(), this));
connect(buildJob.get(), &qbs::BuildJob::reportCommandDescription,
@@ -908,18 +850,6 @@ void TestApi::changeContent()
job.reset(project.setupProject(setupParams, m_logSink, 0));
waitForFinished(job.get());
QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
- // Can't use Project::operator== here, as the target artifacts will differ due to the build
- // not having run yet.
- newProjectData = job->project().projectData();
- projectDataMatches = newProjectData.products().size() == 1
- && projectData.products().size() == 1
- && newProjectData.products().front().groups() == projectData.products().front().groups();
- if (!projectDataMatches) {
- printProjectData(projectData);
- qDebug("\n====\n");
- printProjectData(newProjectData);
- }
- QVERIFY(projectDataMatches);
}
#endif // QBS_ENABLE_PROJECT_FILE_UPDATES
@@ -1129,7 +1059,7 @@ void TestApi::excludedInputs()
QCOMPARE(dummyCount, 3);
}
-static qbs::ErrorInfo forceRuleEvaluation(const qbs::Project project)
+static qbs::ErrorInfo forceRuleEvaluation(const qbs::Project &project)
{
qbs::BuildOptions buildOptions;
buildOptions.setDryRun(true);
@@ -1537,7 +1467,7 @@ void TestApi::linkDynamicAndStaticLibs()
// The dependent static libs should not appear in the link command for the executable.
const SettingsPtr s = settings();
const qbs::Profile buildProfile(profileName(), s.get());
- if (buildProfile.value("qbs.toolchain").toStringList().contains("gcc")) {
+ if (profileToolchain(buildProfile).contains("gcc")) {
static const std::regex appLinkCmdRex(" -o [^ ]*/HelloWorld" QBS_HOST_EXE_SUFFIX " ");
QString appLinkCmd;
for (const QString &line : qAsConst(bdr.descriptionLines)) {
@@ -1570,7 +1500,7 @@ void TestApi::linkStaticAndDynamicLibs()
// executable. The -rpath-link line for libdynamic1.so must be there.
const SettingsPtr s = settings();
const qbs::Profile buildProfile(profileName(), s.get());
- if (buildProfile.value("qbs.toolchain").toStringList().contains("gcc")) {
+ if (profileToolchain(buildProfile).contains("gcc")) {
static const std::regex appLinkCmdRex(" -o [^ ]*/HelloWorld" QBS_HOST_EXE_SUFFIX " ");
QString appLinkCmd;
for (const QString &line : qAsConst(bdr.descriptionLines)) {
@@ -2037,6 +1967,31 @@ void TestApi::multiplexing()
QVERIFY(product.dependencies().empty());
selector.clear();
+ selector.name = "multiplex-without-aggregator-4-depends-2";
+ selector.qbsProperties["architecture"] = "C64";
+ selector.qbsProperties["buildVariant"] = "debug";
+ product = takeMatchingProduct(products, selector);
+ QVERIFY(product.isValid());
+ QVERIFY(product.isMultiplexed());
+ QCOMPARE(product.dependencies().size(), 1);
+ selector.qbsProperties["buildVariant"] = "release";
+ product = takeMatchingProduct(products, selector);
+ QVERIFY(product.isValid());
+ QVERIFY(product.isMultiplexed());
+ QCOMPARE(product.dependencies().size(), 1);
+ selector.qbsProperties["architecture"] = "TRS-80";
+ selector.qbsProperties["buildVariant"] = "debug";
+ product = takeMatchingProduct(products, selector);
+ QVERIFY(product.isValid());
+ QVERIFY(product.isMultiplexed());
+ QCOMPARE(product.dependencies().size(), 1);
+ selector.qbsProperties["buildVariant"] = "release";
+ product = takeMatchingProduct(products, selector);
+ QVERIFY(product.isValid());
+ QVERIFY(product.isMultiplexed());
+ QCOMPARE(product.dependencies().size(), 1);
+
+ selector.clear();
selector.name = "multiplex-with-aggregator-2";
selector.qbsProperties["architecture"] = "C64";
product = takeMatchingProduct(products, selector);
@@ -3054,7 +3009,7 @@ void TestApi::uic()
qbs::ErrorInfo TestApi::doBuildProject(
const QString &projectFilePath, BuildDescriptionReceiver *buildDescriptionReceiver,
ProcessResultReceiver *procResultReceiver, TaskReceiver *taskReceiver,
- const qbs::BuildOptions &options, const QVariantMap overriddenValues)
+ const qbs::BuildOptions &options, const QVariantMap &overriddenValues)
{
qbs::SetupProjectParameters params = defaultSetupParameters(projectFilePath);
params.setOverriddenValues(overriddenValues);
diff --git a/tests/auto/api/tst_api.h b/tests/auto/api/tst_api.h
index aa00ddc99..39eada57a 100644
--- a/tests/auto/api/tst_api.h
+++ b/tests/auto/api/tst_api.h
@@ -161,7 +161,7 @@ private:
ProcessResultReceiver *procResultReceiver = 0,
TaskReceiver *taskReceiver = 0,
const qbs::BuildOptions &options = qbs::BuildOptions(),
- const QVariantMap overriddenValues = QVariantMap());
+ const QVariantMap &overriddenValues = QVariantMap());
LogSink * const m_logSink;
const QString m_sourceDataDir;
diff --git a/tests/auto/blackbox/find/find-android.qbs b/tests/auto/blackbox/find/find-android.qbs
index 26dedc60f..de5c78d10 100644
--- a/tests/auto/blackbox/find/find-android.qbs
+++ b/tests/auto/blackbox/find/find-android.qbs
@@ -3,12 +3,23 @@ import qbs.TextFile
Product {
property string packageName: ""
qbs.targetPlatform: "android"
+ multiplexByQbsProperties: ["architectures"]
+
+ Properties {
+ condition: qbs.architectures && qbs.architectures.length > 1
+ aggregate: true
+ multiplexedType: "json_arch"
+ }
Depends { name: "Android.sdk"; required: false }
Depends { name: "Android.ndk"; required: false }
type: ["json"]
+
Rule {
multiplex: true
+ property stringList inputTags: "json_arch"
+ inputsFromDependencies: inputTags
+ inputs: product.aggregate ? [] : inputTags
Artifact {
filePath: ["android.json"]
fileTags: ["json"]
@@ -18,17 +29,50 @@ Product {
cmd.description = output.filePath;
cmd.sourceCode = function() {
var tools = {};
+
+ for (var i in inputs["json_arch"]) {
+ var tf = new TextFile(inputs["json_arch"][i].filePath, TextFile.ReadOnly);
+ var json = JSON.parse(tf.readAll());
+ tools["ndk"] = json["ndk"];
+ tools["ndk-samples"] = json["ndk-samples"];
+ tf.close();
+ }
+
if (product.moduleProperty("Android.sdk", "present")) {
tools["sdk"] = product.moduleProperty("Android.sdk", "sdkDir");
tools["sdk-build-tools-dx"] = product.Android.sdk.dxFilePath;
}
+ if (product.java && product.java.present)
+ tools["jar"] = product.java.jarFilePath;
+
+ var tf;
+ try {
+ tf = new TextFile(output.filePath, TextFile.WriteOnly);
+ tf.writeLine(JSON.stringify(tools, undefined, 4));
+ } finally {
+ if (tf)
+ tf.close();
+ }
+ };
+ return cmd;
+ }
+ }
+ Rule {
+ multiplex: true
+ Artifact {
+ filePath: ["android_arch.json"]
+ fileTags: ["json_arch"]
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = output.filePath;
+ cmd.sourceCode = function() {
+ var tools = {};
if (product.moduleProperty("Android.ndk", "present")) {
tools["ndk"] = product.moduleProperty("Android.ndk", "ndkDir");
tools["ndk-samples"] = product.Android.ndk.ndkSamplesDir;
}
- if (product.java && product.java.present)
- tools["jar"] = product.java.jarFilePath;
var tf;
try {
@@ -43,3 +87,4 @@ Product {
}
}
}
+
diff --git a/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c b/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c
index 6b625858b..f49b4f90f 100644
--- a/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c
+++ b/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c
@@ -4,5 +4,6 @@
jstring
Java_minimalnative_MinimalNative_stringFromNative(JNIEnv* env, jobject thiz)
{
+ (void)thiz;
return (*env)->NewStringUTF(env, "This message comes from native code.");
}
diff --git a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xml
index 289969409..272fe55de 100644
--- a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xml
+++ b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.qt.dummy1" android:versionCode="1" android:versionName="1.0">
- <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="19"/>
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
<uses-feature android:glEsVersion="0x00020000"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:allowBackup="true" android:hasCode="true">
diff --git a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xml
index ef0fbe54f..871aadbe6 100644
--- a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xml
+++ b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.qt.dummy2" android:versionCode="1" android:versionName="1.0">
- <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="19"/>
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
<uses-feature android:glEsVersion="0x00020000"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:allowBackup="true" android:hasCode="true">
diff --git a/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xml
index 6694afc18..f184a8f1f 100644
--- a/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xml
+++ b/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.qt.dummy" android:versionCode="1" android:versionName="1.0">
- <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="19"/>
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
<uses-feature android:glEsVersion="0x00020000"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:allowBackup="true" android:hasCode="true">
diff --git a/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml
index 066ec0a63..542794825 100644
--- a/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml
+++ b/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml
@@ -67,7 +67,7 @@
</application>
- <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16"/>
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/>
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
diff --git a/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbs b/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbs
index e7c8867bd..a65dcd023 100644
--- a/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbs
+++ b/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbs
@@ -14,6 +14,7 @@ Project {
// This will generate 2 multiplex configs and an aggregate.
qbs.architectures: ["x86", "x86_64"]
qbs.buildVariant: "debug"
+ cpp.minimumMacosVersion: "10.8"
}
CppApplication {
@@ -30,6 +31,7 @@ Project {
qbs.architecture: "x86_64"
qbs.buildVariant: "debug"
+ cpp.minimumMacosVersion: "10.8"
multiplexByQbsProperties: []
}
}
diff --git a/tests/auto/blackbox/testdata-apple/overrideInfoPlist/Override-Info.plist b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/Override-Info.plist
new file mode 100644
index 000000000..f2621e983
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/Override-Info.plist
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>DefaultValue</key>
+ <string>The default value</string>
+ <key>OverriddenValue</key>
+ <string>The default value</string>
+</dict>
+</plist>
diff --git a/tests/auto/blackbox/testdata-apple/overrideInfoPlist/main.c b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/main.c
new file mode 100644
index 000000000..76e819701
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/main.c
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs
new file mode 100644
index 000000000..e70584ed8
--- /dev/null
+++ b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs
@@ -0,0 +1,16 @@
+CppApplication {
+ Depends { name: "bundle" }
+ cpp.minimumMacosVersion: "10.7"
+ files: ["main.c", "Override-Info.plist"]
+
+ Properties {
+ condition: qbs.targetOS.contains("darwin")
+ bundle.isBundle: true
+ bundle.identifierPrefix: "com.test"
+
+ bundle.infoPlist: ({
+ "CFBundleName": "My Bundle",
+ "OverriddenValue": "The overridden value",
+ })
+ }
+}
diff --git a/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs b/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs
index fbab6d0b1..fa4c67b96 100644
--- a/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs
+++ b/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs
@@ -43,8 +43,11 @@ Project {
}
for (var i = 0; i < a.length; ++i) {
- if (a[i] !== b[i]) {
- throw msg;
+ var version1 = a[i].split('.');
+ var version2 = b[i].split('.');
+ for (var j = 0; j < version1.length; ++j) {
+ if (version1[j] !== version2[j])
+ throw msg;
}
}
}
diff --git a/tests/auto/blackbox/testdata-qt/metatypes/metatypes.qbs b/tests/auto/blackbox/testdata-qt/metatypes/metatypes.qbs
new file mode 100644
index 000000000..bbc98c934
--- /dev/null
+++ b/tests/auto/blackbox/testdata-qt/metatypes/metatypes.qbs
@@ -0,0 +1,28 @@
+import qbs.Utilities
+
+StaticLibrary {
+ name: "mylib"
+
+ Depends { name: "Qt.core" }
+
+ qbs.installPrefix: "some-prefix"
+
+ Probe {
+ id: capabilitiesChecker
+ property string version: Qt.core.version
+ configure: {
+ if (Utilities.versionCompare(version, "5.15") >= 0)
+ console.info("can generate");
+ else
+ console.info("cannot generate");
+ found = true;
+ }
+ }
+
+ files: [
+ "mocableclass1.cpp",
+ "mocableclass1.h",
+ "mocableclass2.cpp",
+ "unmocableclass.cpp",
+ ]
+}
diff --git a/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.cpp b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.cpp
new file mode 100644
index 000000000..06adc8ca5
--- /dev/null
+++ b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.cpp
@@ -0,0 +1,3 @@
+#include "mocableclass1.h"
+
+MocableClass1::MocableClass1(QObject *parent) : QObject(parent) {}
diff --git a/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.h b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.h
new file mode 100644
index 000000000..020c15179
--- /dev/null
+++ b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.h
@@ -0,0 +1,8 @@
+#include <QObject>
+
+class MocableClass1 : public QObject
+{
+ Q_OBJECT
+public:
+ MocableClass1(QObject *parent = nullptr);
+};
diff --git a/tests/auto/blackbox/testdata-qt/metatypes/mocableclass2.cpp b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass2.cpp
new file mode 100644
index 000000000..bf538913a
--- /dev/null
+++ b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass2.cpp
@@ -0,0 +1,10 @@
+#include <QObject>
+
+class MocableClass2 : public QObject
+{
+ Q_OBJECT
+public:
+ MocableClass2(QObject *parent) : QObject(parent) {}
+};
+
+#include <mocableclass2.moc>
diff --git a/tests/auto/blackbox/testdata-qt/metatypes/unmocableclass.cpp b/tests/auto/blackbox/testdata-qt/metatypes/unmocableclass.cpp
new file mode 100644
index 000000000..34330d189
--- /dev/null
+++ b/tests/auto/blackbox/testdata-qt/metatypes/unmocableclass.cpp
@@ -0,0 +1,7 @@
+#include <QObject>
+
+class UnmocableClass : public QObject
+{
+public:
+ UnmocableClass(QObject *parent) : QObject(parent) {}
+};
diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/example.qml b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/example.qml
new file mode 100644
index 000000000..ef97df12d
--- /dev/null
+++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/example.qml
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// ![0]
+import People 1.0
+
+Person {
+ name: "Bob Jones"
+ shoeSize: 12
+}
+// ![0]
diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/main.cpp b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/main.cpp
new file mode 100644
index 000000000..6c3920f04
--- /dev/null
+++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/main.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QCoreApplication>
+#include <QQmlEngine>
+#include <QQmlComponent>
+#include <QDebug>
+#include "person.h"
+
+int main(int argc, char ** argv)
+{
+ QCoreApplication app(argc, argv);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl("qrc:example.qml"));
+ auto *person = qobject_cast<Person *>(component.create());
+ if (person) {
+ qWarning() << "The person's name is" << person->name();
+ qWarning() << "They wear a" << person->shoeSize() << "sized shoe";
+ } else {
+ qWarning() << component.errors();
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.cpp b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.cpp
new file mode 100644
index 000000000..de4a33dd0
--- /dev/null
+++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.cpp
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "person.h"
+
+// ![0]
+Person::Person(QObject *parent)
+: QObject(parent), m_shoeSize(0)
+{
+}
+
+QString Person::name() const
+{
+ return m_name;
+}
+
+void Person::setName(const QString &n)
+{
+ m_name = n;
+}
+
+int Person::shoeSize() const
+{
+ return m_shoeSize;
+}
+
+void Person::setShoeSize(int s)
+{
+ m_shoeSize = s;
+}
+
+// ![0]
diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.h b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.h
new file mode 100644
index 000000000..530c335de
--- /dev/null
+++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef PERSON_H
+#define PERSON_H
+
+#include <QObject>
+#include <QtQml/qqml.h>
+
+//![0]
+class Person : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString name READ name WRITE setName)
+ Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize)
+ QML_ELEMENT
+public:
+ Person(QObject *parent = nullptr);
+
+ QString name() const;
+ void setName(const QString &);
+
+ int shoeSize() const;
+ void setShoeSize(int);
+
+private:
+ QString m_name;
+ int m_shoeSize;
+};
+//![0]
+
+#endif // PERSON_H
diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/qmltyperegistrar.qbs b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/qmltyperegistrar.qbs
new file mode 100644
index 000000000..68dc83743
--- /dev/null
+++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/qmltyperegistrar.qbs
@@ -0,0 +1,33 @@
+import qbs.Utilities
+
+CppApplication {
+ name: "myapp"
+ Depends { name: "Qt.qml" }
+
+ Qt.qml.importVersion: "1"
+ cpp.includePaths: sourceDirectory
+ qbs.installPrefix: ""
+
+ files: [
+ "main.cpp",
+ "person.cpp",
+ "person.h",
+ ]
+
+ Group {
+ files: "example.qml"
+ fileTags: "qt.core.resource_data"
+ }
+
+ Probe {
+ id: versionProbe
+ property string version: Qt.core.version
+ configure: {
+ if (Utilities.versionCompare(version, "5.15") >= 0)
+ console.info("has registrar");
+ else
+ console.info("does not have registrar");
+ found = true;
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs b/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs
index 38ed5fac9..90b968ec9 100644
--- a/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs
+++ b/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs
@@ -39,18 +39,22 @@ Project {
prepare: {
var cmd = new Command(input.filePath);
cmd.description = "running " + input.filePath;
- var pathVar;
- var pathValue;
+
+ var envVars = {};
if (product.qbs.hostOS.contains("windows")) {
- pathVar = "PATH";
- pathValue = FileInfo.toWindowsSeparators(input["Qt.core"].binPath);
+ envVars["PATH"] = FileInfo.toWindowsSeparators(input["Qt.core"].binPath);
+ } else if (product.qbs.hostOS.contains("macos")) {
+ envVars["DYLD_LIBRARY_PATH"] = input["Qt.core"].libPath;
+ envVars["DYLD_FRAMEWORK_PATH"] = input["Qt.core"].libPath;
} else {
- pathVar = "LD_LIBRARY_PATH";
- pathValue = input["Qt.core"].libPath;
+ envVars["LD_LIBRARY_PATH"] = input["Qt.core"].libPath;
+ }
+ for (var varName in envVars) {
+ var oldValue = Environment.getEnv(varName) || "";
+ var newValue = envVars[varName] + product.qbs.pathListSeparator + oldValue;
+ cmd.environment.push(varName + '=' + newValue);
}
- var oldValue = Environment.getEnv(pathVar) || "";
- var newValue = pathValue + product.qbs.pathListSeparator + oldValue;
- cmd.environment = [pathVar + '=' + newValue];
+
return [cmd];
}
}
diff --git a/tests/auto/blackbox/testdata/build-variant-defaults/build-variant-defaults.qbs b/tests/auto/blackbox/testdata/build-variant-defaults/build-variant-defaults.qbs
new file mode 100644
index 000000000..4015817ca
--- /dev/null
+++ b/tests/auto/blackbox/testdata/build-variant-defaults/build-variant-defaults.qbs
@@ -0,0 +1,16 @@
+CppApplication {
+ property bool validate: {
+ var valid = true;
+ if (qbs.buildVariant === "release") {
+ valid = !qbs.enableDebugCode && !qbs.debugInformation && qbs.optimization === "fast";
+ } else if (qbs.buildVariant === "debug") {
+ valid = qbs.enableDebugCode && qbs.debugInformation && qbs.optimization === "none";
+ } else if (qbs.buildVariant === "profiling") {
+ valid = !qbs.enableDebugCode && qbs.debugInformation && qbs.optimization === "fast";
+ }
+
+ if (!valid)
+ throw "Invalid defaults";
+ return valid;
+ }
+}
diff --git a/tests/auto/blackbox/testdata/build-variant-defaults/main.cpp b/tests/auto/blackbox/testdata/build-variant-defaults/main.cpp
new file mode 100644
index 000000000..76e819701
--- /dev/null
+++ b/tests/auto/blackbox/testdata/build-variant-defaults/main.cpp
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile-probe-project.qbs b/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile-probe-project.qbs
new file mode 100644
index 000000000..ab1c68385
--- /dev/null
+++ b/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile-probe-project.qbs
@@ -0,0 +1,22 @@
+import qbs.Probes
+import qbs.TextFile
+
+Project {
+
+ Probes.ConanfileProbe {
+ id: conan
+ conanfilePath: path + "/conanfile.py"
+ options: ({opt: "True"})
+ settings: ({os: "AIX"})
+ }
+
+ property var check: {
+ tf = new TextFile(buildDirectory + "/results.json", TextFile.WriteOnly);
+ var o = {
+ json: conan.json.deps_env_info["ENV_VAR"],
+ dependencies: conan.dependencies["testlib"].libs,
+ generatedFilesPath: conan.generatedFilesPath
+ };
+ tf.write(JSON.stringify(o));
+ }
+}
diff --git a/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile.py b/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile.py
new file mode 100644
index 000000000..630cf0283
--- /dev/null
+++ b/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile.py
@@ -0,0 +1,25 @@
+from conans import ConanFile
+
+class TestApp(ConanFile):
+ name = "testapp"
+ description = "Our project package, to be inspected by the Qbs ConanfileProbe"
+ license = "none"
+ version = "6.6.6"
+
+ settings = "os"
+ options = {"opt": [True, False]}
+ default_options = {"opt": False}
+
+ requires = "testlib/1.2.3@qbs/testing"
+
+ def configure(self):
+ self.options["testlib"].opt = self.options.opt
+
+ def source(self):
+ pass
+
+ def build(self):
+ pass
+
+ def package(self):
+ pass
diff --git a/tests/auto/blackbox/testdata/conanfile-probe/testlib/conanfile.py b/tests/auto/blackbox/testdata/conanfile-probe/testlib/conanfile.py
new file mode 100644
index 000000000..983c22599
--- /dev/null
+++ b/tests/auto/blackbox/testdata/conanfile-probe/testlib/conanfile.py
@@ -0,0 +1,25 @@
+from conans import ConanFile
+
+class Testlib(ConanFile):
+ name = "testlib"
+ description = "Represents an arbitrary package, for instance on bintray"
+ license = "none"
+ version = "1.2.3"
+
+ settings = "os"
+ options = {"opt": [True, False]}
+ default_options = {"opt": False}
+
+ def source(self):
+ pass
+
+ def build(self):
+ pass
+
+ def package(self):
+ pass
+
+ def package_info(self):
+ self.cpp_info.libs = ["testlib1","testlib2"]
+ self.env_info.ENV_VAR = "TESTLIB_ENV_VAL"
+ self.user_info.user_var = "testlib_user_val"
diff --git a/tests/auto/blackbox/testdata/dependency-profile-mismatch/dependency-profile-mismatch.qbs b/tests/auto/blackbox/testdata/dependency-profile-mismatch/dependency-profile-mismatch.qbs
deleted file mode 100644
index 8a6f733c0..000000000
--- a/tests/auto/blackbox/testdata/dependency-profile-mismatch/dependency-profile-mismatch.qbs
+++ /dev/null
@@ -1,12 +0,0 @@
-Project {
- property string mainProfile
- property string depProfile
- Product {
- name: "dep"
- qbs.profiles: [project.depProfile]
- }
- Product {
- name: "main"
- Depends { name: "dep"; profiles: [project.mainProfile]; }
- }
-}
diff --git a/tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs b/tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs
new file mode 100644
index 000000000..ac8e7258c
--- /dev/null
+++ b/tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs
@@ -0,0 +1,34 @@
+import qbs.FileInfo
+import qbs.TextFile
+
+CppApplication {
+ name: "app"
+ cpp.includePaths: buildDirectory
+ Group {
+ files: "main.cpp"
+ fileTags: ["cpp", "custom.in"]
+ }
+ Rule {
+ inputs: "custom.in"
+ Artifact {
+ filePath: FileInfo.completeBaseName(input.filePath) + ".h"
+ fileTags: "hpp"
+ }
+ Artifact {
+ filePath: "custom.txt"
+ fileTags: "whatever"
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "generating " + outputs.hpp[0].fileName;
+ cmd.sourceCode = function() {
+ var f = new TextFile(outputs.hpp[0].filePath, TextFile.WriteOnly);
+ f.writeLine("int main() {}");
+ f.close();
+ f = new TextFile(outputs.whatever[0].filePath, TextFile.WriteOnly);
+ f.close();
+ }
+ return cmd;
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp b/tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp
new file mode 100644
index 000000000..5e8dda41b
--- /dev/null
+++ b/tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp
@@ -0,0 +1 @@
+#include <main.h>
diff --git a/tests/auto/blackbox/testdata/empty-profile/empty-profile.qbs b/tests/auto/blackbox/testdata/empty-profile/empty-profile.qbs
new file mode 100644
index 000000000..da7536315
--- /dev/null
+++ b/tests/auto/blackbox/testdata/empty-profile/empty-profile.qbs
@@ -0,0 +1,3 @@
+CppApplication {
+ files: ["main.cpp"]
+}
diff --git a/tests/auto/blackbox/testdata/empty-profile/main.cpp b/tests/auto/blackbox/testdata/empty-profile/main.cpp
new file mode 100644
index 000000000..76e819701
--- /dev/null
+++ b/tests/auto/blackbox/testdata/empty-profile/main.cpp
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs b/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs
new file mode 100644
index 000000000..60c3d304f
--- /dev/null
+++ b/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs
@@ -0,0 +1,25 @@
+import qbs 1.0
+
+Project {
+ CppApplication {
+ name: "main"
+ install: true
+ files: [
+ "main.cpp",
+ "myapp.desktop",
+ "myapp.appdata.xml",
+ ]
+
+ Depends { name: "freedesktop" }
+
+ freedesktop.name: "My App"
+ freedesktop.desktopKeys: ({
+ 'Icon': "myapp.png"
+ })
+
+ Group {
+ files: "myapp.png"
+ fileTags: "freedesktop.appIcon"
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/freedesktop/main.cpp b/tests/auto/blackbox/testdata/freedesktop/main.cpp
new file mode 100644
index 000000000..905869dfa
--- /dev/null
+++ b/tests/auto/blackbox/testdata/freedesktop/main.cpp
@@ -0,0 +1,4 @@
+int main()
+{
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml b/tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml
new file mode 100644
index 000000000..3cf0a5641
--- /dev/null
+++ b/tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<component type="desktop">
+ <id>myapp.desktop</id>
+ <metadata_license>CC0</metadata_license>
+ <name>MyApp</name>
+ <summary>The coolest app ever</summary>
+
+ <description>
+ <p>This is a cool application.</p>
+ </description>
+
+ <url type="homepage">https://software.house/myapp</url>
+ <project_license>GPL-2.0+</project_license>
+ <developer_name>Coding Wizard</developer_name>
+</component>
diff --git a/tests/auto/blackbox/testdata/freedesktop/myapp.desktop b/tests/auto/blackbox/testdata/freedesktop/myapp.desktop
new file mode 100644
index 000000000..dac3014c3
--- /dev/null
+++ b/tests/auto/blackbox/testdata/freedesktop/myapp.desktop
@@ -0,0 +1,4 @@
+[Desktop Entry]
+GenericName=Image Editor
+Comment=Create images and edit photographs
+Icon=overridden.png
diff --git a/tests/auto/blackbox/testdata/freedesktop/myapp.png b/tests/auto/blackbox/testdata/freedesktop/myapp.png
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/freedesktop/myapp.png
diff --git a/tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs b/tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs
index 815e64853..8c971a747 100644
--- a/tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs
+++ b/tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs
@@ -2,11 +2,14 @@ Project {
CppApplication {
name: "app-map"
files: ["main.cpp"]
+ // lld-link has different flag for map files, test it by switching to "lld" linkerVariant
+ Properties { condition: qbs.toolchain.contains("clang-cl"); cpp.linkerVariant: "lld" }
cpp.generateLinkerMapFile: true
}
CppApplication {
name: "app-nomap"
files: ["main.cpp"]
+ Properties { condition: qbs.toolchain.contains("clang-cl"); cpp.linkerVariant: "lld" }
cpp.generateLinkerMapFile: false
}
CppApplication {
diff --git a/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs b/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs
index 8ee3dd9c9..b7a594c13 100644
--- a/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs
+++ b/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs
@@ -7,6 +7,7 @@ CppApplication {
Depends { name: "cpp" }
cpp.cxxLanguageVersion: "c++11"
+ cpp.minimumMacosVersion: "10.8"
cpp.warningLevel: "none"
Depends { name: "protobuf.cpp"; required: false }
diff --git a/tests/auto/blackbox/testdata/host-os-properties/host-os-properties.qbs b/tests/auto/blackbox/testdata/host-os-properties/host-os-properties.qbs
new file mode 100644
index 000000000..b6b862d1c
--- /dev/null
+++ b/tests/auto/blackbox/testdata/host-os-properties/host-os-properties.qbs
@@ -0,0 +1,8 @@
+CppApplication {
+ consoleApplication: true
+ cpp.defines: [
+ 'HOST_ARCHITECTURE="' + qbs.hostArchitecture + '"',
+ 'HOST_PLATFORM="' + qbs.hostPlatform + '"'
+ ]
+ files: "main.cpp"
+}
diff --git a/tests/auto/blackbox/testdata/host-os-properties/main.cpp b/tests/auto/blackbox/testdata/host-os-properties/main.cpp
new file mode 100644
index 000000000..b0c239e20
--- /dev/null
+++ b/tests/auto/blackbox/testdata/host-os-properties/main.cpp
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main() {
+ printf("HOST_ARCHITECTURE = %s\n", HOST_ARCHITECTURE);
+ printf("HOST_PLATFORM = %s\n", HOST_PLATFORM);
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/install-locations/install-locations.qbs b/tests/auto/blackbox/testdata/install-locations/install-locations.qbs
index ed0e1810a..722b233c4 100644
--- a/tests/auto/blackbox/testdata/install-locations/install-locations.qbs
+++ b/tests/auto/blackbox/testdata/install-locations/install-locations.qbs
@@ -13,7 +13,9 @@ Project {
CppApplication {
name: "theapp"
install: true
+ installDebugInformation: true
files: "main.cpp"
+ cpp.separateDebugInformation: true
Group {
fileTagsFilter: "application"
fileTags: "some-tag"
@@ -23,7 +25,17 @@ Project {
name: "thelib"
install: true
installImportLib: true
+ installDebugInformation: true
Depends { name: "cpp" }
+ cpp.separateDebugInformation: true
files: "thelib.cpp"
}
+ LoadableModule {
+ name: "theplugin"
+ install: true
+ installDebugInformation: true
+ Depends { name: "cpp" }
+ cpp.separateDebugInformation: true
+ files: "theplugin.cpp"
+ }
}
diff --git a/tests/auto/blackbox/testdata/install-locations/theplugin.cpp b/tests/auto/blackbox/testdata/install-locations/theplugin.cpp
new file mode 100644
index 000000000..ac1ede090
--- /dev/null
+++ b/tests/auto/blackbox/testdata/install-locations/theplugin.cpp
@@ -0,0 +1,3 @@
+#include "../dllexport.h"
+
+DLL_EXPORT void pluginFunc() {}
diff --git a/tests/auto/blackbox/testdata/last-module-candidate-broken/last-module-candidate-broken.qbs b/tests/auto/blackbox/testdata/last-module-candidate-broken/last-module-candidate-broken.qbs
new file mode 100644
index 000000000..db7dc2265
--- /dev/null
+++ b/tests/auto/blackbox/testdata/last-module-candidate-broken/last-module-candidate-broken.qbs
@@ -0,0 +1,5 @@
+CppApplication {
+ qbsSearchPaths: "qbs"
+ Depends { name: "Foo" }
+ files: "main.cpp"
+}
diff --git a/tests/auto/blackbox/testdata/last-module-candidate-broken/main.cpp b/tests/auto/blackbox/testdata/last-module-candidate-broken/main.cpp
new file mode 100644
index 000000000..76e819701
--- /dev/null
+++ b/tests/auto/blackbox/testdata/last-module-candidate-broken/main.cpp
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo1.qbs b/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo1.qbs
new file mode 100644
index 000000000..ba08b862b
--- /dev/null
+++ b/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo1.qbs
@@ -0,0 +1,3 @@
+Module {
+ condition: false
+}
diff --git a/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo2.qbs b/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo2.qbs
new file mode 100644
index 000000000..0bc383b86
--- /dev/null
+++ b/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo2.qbs
@@ -0,0 +1,2 @@
+Group {
+}
diff --git a/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs b/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs
index c7462676d..c47a40aea 100644
--- a/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs
+++ b/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs
@@ -1,5 +1,5 @@
Module {
- property stringList listProp
+ property stringList listProp: [ "lower" ]
Rule {
inputs: ["intype"]
@@ -10,7 +10,7 @@ Module {
prepare: {
var cmd = new JavaScriptCommand();
cmd.sourceCode = function() {
- console.info("listProp = " + JSON.stringify(product.lower.listProp));
+ console.warn("listProp = " + JSON.stringify(product.lower.listProp));
};
cmd.silent = true;
return [cmd];
diff --git a/tests/auto/blackbox/testdata/list-property-order/product.qbs b/tests/auto/blackbox/testdata/list-property-order/product.qbs
index e92494693..bec122214 100644
--- a/tests/auto/blackbox/testdata/list-property-order/product.qbs
+++ b/tests/auto/blackbox/testdata/list-property-order/product.qbs
@@ -4,6 +4,7 @@ Product {
Depends { name: "higher1" }
Depends { name: "higher2" }
Depends { name: "higher3" }
+ lower.listProp: ["product"]
Group {
files: ["dummy.txt"]
fileTags: ["intype"]
diff --git a/tests/auto/blackbox/testdata/path-probe/BaseApp.qbs b/tests/auto/blackbox/testdata/path-probe/BaseApp.qbs
index 84c00c240..93172579f 100644
--- a/tests/auto/blackbox/testdata/path-probe/BaseApp.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/BaseApp.qbs
@@ -28,6 +28,7 @@
**
****************************************************************************/
+import qbs.FileInfo
import qbs.Probes
CppApplication {
@@ -40,6 +41,7 @@ CppApplication {
property var inputCandidateFilter
property stringList outputFilePaths
+ property var outputCandidatePaths
Probes.PathProbe {
id: probe
@@ -49,6 +51,7 @@ CppApplication {
nameFilter: inputNameFilter
candidateFilter: inputCandidateFilter
searchPaths: inputSearchPaths
+ platformSearchPaths: []
}
property bool validate: {
@@ -56,19 +59,72 @@ CppApplication {
if (lhs.length !== rhs.length)
return false;
for (var i = 0; i < lhs.length; ++i) {
- if (lhs[i] !== rhs[i])
+ if (Array.isArray(lhs[i]) && Array.isArray(rhs[i])) {
+ if (!compareArrays(lhs[i], rhs[i]))
+ return false;
+ } else if (lhs[i] !== rhs[i]) {
return false;
+ }
}
return true;
};
- if (!probe.found)
+ if (outputCandidatePaths) {
+ var actual = probe.allResults.map(function(file) { return file.candidatePaths; });
+ if (!compareArrays(actual, outputCandidatePaths)) {
+ throw "Invalid canndidatePaths: actual = " + JSON.stringify(actual)
+ + ", expected = " + JSON.stringify(outputCandidatePaths);
+ }
+ }
+
+ if (!probe.found) {
+ if (probe.filePath) {
+ throw "Invalid filePath: actual = " + JSON.stringify(probe.filePath)
+ + ", expected = 'undefined'";
+ }
+ if (probe.fileName) {
+ throw "Invalid fileName: actual = " + JSON.stringify(probe.fileName)
+ + ", expected = 'undefined'";
+ }
+ if (probe.path) {
+ throw "Invalid path: actual = " + JSON.stringify(probe.path)
+ + ", expected = 'undefined'";
+ }
+
throw "Probe failed to find files";
+ }
if (outputFilePaths) {
var actual = probe.allResults.map(function(file) { return file.filePath; });
- if (!compareArrays(actual, outputFilePaths))
- throw "Invalid filePaths: actual = " + actual + ", expected = " + outputFilePaths;
+ if (!compareArrays(actual, outputFilePaths)) {
+ throw "Invalid filePaths: actual = " + JSON.stringify(actual)
+ + ", expected = " + JSON.stringify(outputFilePaths);
+ }
+ }
+
+ if (probe.allResults.length !== 1)
+ return;
+
+ // check that single-file interface matches the first value in allResults
+ var expectedFilePath = probe.allResults[0].filePath;
+ if (probe.filePath !== expectedFilePath) {
+ throw "Invalid filePath: actual = " + probe.filePath
+ + ", expected = " + expectedFilePath;
+ }
+ var expectedFileName = probe.allResults[0].fileName;
+ if (probe.fileName !== expectedFileName) {
+ throw "Invalid fileName: actual = " + probe.fileName
+ + ", expected = " + expectedFileName;
+ }
+ var expectedPath = probe.allResults[0].path;
+ if (probe.path !== expectedPath) {
+ throw "Invalid path: actual = " + probe.path
+ + ", expected = " + expectedPath;
+ }
+ var expectedCandidatePaths = probe.allResults[0].candidatePaths;
+ if (!compareArrays(probe.candidatePaths, expectedCandidatePaths)) {
+ throw "Invalid candidatePaths: actual = " + JSON.stringify(probe.candidatePaths)
+ + ", expected = " + JSON.stringify(expectedCandidatePaths);
}
}
diff --git a/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs b/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs
index a65256a68..c40f22736 100644
--- a/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs
@@ -3,10 +3,11 @@ import qbs.FileInfo
BaseApp {
inputNames: ["tool.1", "tool.2"]
inputSearchPaths: "bin"
- outputFilePaths: ["bin/tool.2"]
inputCandidateFilter: {
return function(f) {
return FileInfo.fileName(f) == "tool.2";
}
}
+ outputFilePaths: ["bin/tool.2"]
+ outputCandidatePaths: [["bin/tool.1", "bin/tool.2"]]
}
diff --git a/tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs b/tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs
index b112db44d..33656d4e6 100644
--- a/tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs
@@ -1,8 +1,9 @@
BaseApp {
inputSelectors: [
- {names : "tool", nameSuffixes: [".1", ".2"]},
+ {names : "tool", nameSuffixes: [".0", ".1", ".2"]},
{names : "super-tool", nameSuffixes: [".1"]},
]
inputSearchPaths: "bin"
outputFilePaths: ["bin/tool.1", "bin/super-tool.1"]
+ outputCandidatePaths: [["bin/tool.0", "bin/tool.1"], ["bin/super-tool.1"]]
}
diff --git a/tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs b/tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs
index 60c56e6b4..dd0b58aa2 100644
--- a/tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs
@@ -1,9 +1,10 @@
BaseApp {
inputSelectors: [
"tool",
- ["tool.1", "tool.2"],
+ ["tool.0", "tool.1", "tool.2"],
{names : ["tool.3", "tool.4"]},
]
inputSearchPaths: "bin"
outputFilePaths: ["bin/tool", "bin/tool.1", "bin/tool.3"]
+ outputCandidatePaths: [["bin/tool"], ["bin/tool.0", "bin/tool.1"], ["bin/tool.3"]]
}
diff --git a/tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs b/tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs
index 5e4fc27ca..7ae78de24 100644
--- a/tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs
@@ -5,4 +5,5 @@ BaseApp {
]
inputSearchPaths: "bin"
outputFilePaths: ["bin/tool.2", "bin/super-tool.1"]
+ outputCandidatePaths: [["bin/tool.2"], ["bin/super-tool.1"]]
}
diff --git a/tests/auto/blackbox/testdata/path-probe/mult-files.qbs b/tests/auto/blackbox/testdata/path-probe/mult-files.qbs
index 08727ac01..aa08befc8 100644
--- a/tests/auto/blackbox/testdata/path-probe/mult-files.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/mult-files.qbs
@@ -7,4 +7,5 @@ BaseApp {
]
inputSearchPaths: "bin"
outputFilePaths: ["bin/tool.1", "bin/tool.2", "bin/tool.3", "bin/tool.4"]
+ outputCandidatePaths: [["bin/tool.1"], ["bin/tool.2"], ["bin/tool.3"], ["bin/tool.4"]]
}
diff --git a/tests/auto/blackbox/testdata/path-probe/name-filter.qbs b/tests/auto/blackbox/testdata/path-probe/name-filter.qbs
index 406988fed..b2840443b 100644
--- a/tests/auto/blackbox/testdata/path-probe/name-filter.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/name-filter.qbs
@@ -7,4 +7,5 @@ BaseApp {
};
}
outputFilePaths: ["bin/tool.2"]
+ outputCandidatePaths: [["bin/tool.2"]]
}
diff --git a/tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs b/tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs
index aaa27042c..aabb0fe7b 100644
--- a/tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs
@@ -5,4 +5,5 @@ BaseApp {
"tool.2",
]
inputSearchPaths: "bin"
+ outputCandidatePaths: [["bin/tool.1"], ["bin/nonexistent"], ["bin/tool.2"]]
}
diff --git a/tests/auto/blackbox/testdata/path-probe/non-existent.qbs b/tests/auto/blackbox/testdata/path-probe/non-existent.qbs
index f0c58fa6c..aad01c31b 100644
--- a/tests/auto/blackbox/testdata/path-probe/non-existent.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/non-existent.qbs
@@ -1,4 +1,5 @@
BaseApp {
inputNames: "nonexistent"
inputSearchPaths: "bin"
+ outputCandidatePaths: [["bin/nonexistent"]]
}
diff --git a/tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs b/tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs
index 992a0bea4..98f5b141a 100644
--- a/tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs
@@ -2,4 +2,5 @@ BaseApp {
inputNames: ["tool.1", "tool.2"]
inputSearchPaths: "bin"
outputFilePaths: ["bin/tool.1"]
+ outputCandidatePaths: [["bin/tool.1"]]
}
diff --git a/tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs b/tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs
index 697665242..292df4add 100644
--- a/tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs
@@ -2,4 +2,5 @@ BaseApp {
inputSelectors: ["tool"]
inputSearchPaths: "bin"
outputFilePaths: ["bin/tool"]
+ outputCandidatePaths: [["bin/tool"]]
}
diff --git a/tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs b/tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs
index d57700baf..cf7cfe436 100644
--- a/tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs
@@ -2,4 +2,5 @@ BaseApp {
inputSelectors: "tool"
inputSearchPaths: "bin"
outputFilePaths: ["bin/tool"]
+ outputCandidatePaths: [["bin/tool"]]
}
diff --git a/tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs b/tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs
index 4442e719a..3436a49c3 100644
--- a/tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs
@@ -1,6 +1,7 @@
BaseApp {
inputNames: "tool"
inputSearchPaths: "bin"
- inputNameSuffixes: [".1", ".2"]
+ inputNameSuffixes: [".0", ".1", ".2"]
outputFilePaths: ["bin/tool.1"]
+ outputCandidatePaths: [["bin/tool.0", "bin/tool.1"]]
}
diff --git a/tests/auto/blackbox/testdata/path-probe/single-file.qbs b/tests/auto/blackbox/testdata/path-probe/single-file.qbs
index 3590e7664..e22d7ba0d 100644
--- a/tests/auto/blackbox/testdata/path-probe/single-file.qbs
+++ b/tests/auto/blackbox/testdata/path-probe/single-file.qbs
@@ -2,4 +2,5 @@ BaseApp {
inputNames: "tool"
inputSearchPaths: "bin"
outputFilePaths: ["bin/tool"]
+ outputCandidatePaths: [["bin/tool"]]
}
diff --git a/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs b/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs
index 9846eacef..ce89d11f4 100644
--- a/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs
+++ b/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs
@@ -1,29 +1,40 @@
import qbs.Probes
-CppApplication {
- Probes.PathProbe {
- id: probe1
- names: ["bin/tool"]
- platformSearchPaths: [product.sourceDirectory]
- }
+Project {
- Probes.PathProbe {
- id: probe2
- names: ["tool"]
- platformSearchPaths: [product.sourceDirectory + "/bin"]
- }
+ CppApplication {
+ Probes.PathProbe {
+ id: probe1
+ names: ["bin/tool"]
+ platformSearchPaths: [product.sourceDirectory]
+ }
- targetName: {
- console.info("probe1.fileName=" + probe1.fileName);
- console.info("probe1.path=" + probe1.path);
- console.info("probe1.filePath=" + probe1.filePath);
+ Probes.PathProbe {
+ id: probe2
+ names: ["tool"]
+ platformSearchPaths: [product.sourceDirectory + "/bin"]
+ }
- console.info("probe2.fileName=" + probe2.fileName);
- console.info("probe2.path=" + probe2.path);
- console.info("probe2.filePath=" + probe2.filePath);
+ targetName: {
+ console.info("probe1.fileName=" + probe1.fileName);
+ console.info("probe1.path=" + probe1.path);
+ console.info("probe1.filePath=" + probe1.filePath);
- return name;
+ console.info("probe2.fileName=" + probe2.fileName);
+ console.info("probe2.path=" + probe2.path);
+ console.info("probe2.filePath=" + probe2.filePath);
+
+ console.info("probe3.fileName=" + probe3.fileName);
+ console.info("probe3.path=" + probe3.path);
+ console.info("probe3.filePath=" + probe3.filePath);
+ return name;
+ }
+ }
+
+ Probes.PathProbe {
+ id: probe3
+ names: ["tool"]
+ platformSearchPaths: [project.sourceDirectory + "/bin"]
}
- files: ["main.c"]
}
diff --git a/tests/auto/blackbox/testdata/property-evaluation-context/modules/base/base.qbs b/tests/auto/blackbox/testdata/property-evaluation-context/modules/base/base.qbs
new file mode 100644
index 000000000..a97538751
--- /dev/null
+++ b/tests/auto/blackbox/testdata/property-evaluation-context/modules/base/base.qbs
@@ -0,0 +1,4 @@
+Module {
+ property string productInBase: product.name
+ property string productInTop: ""
+}
diff --git a/tests/auto/blackbox/testdata/property-evaluation-context/modules/top/top.qbs b/tests/auto/blackbox/testdata/property-evaluation-context/modules/top/top.qbs
new file mode 100644
index 000000000..fa073ff78
--- /dev/null
+++ b/tests/auto/blackbox/testdata/property-evaluation-context/modules/top/top.qbs
@@ -0,0 +1,6 @@
+Module {
+ Depends { name: "base" }
+ base.productInTop: product.name
+ property string productInTop: product.name
+ property string productInExport: ""
+}
diff --git a/tests/auto/blackbox/testdata/property-evaluation-context/property-evaluation-context.qbs b/tests/auto/blackbox/testdata/property-evaluation-context/property-evaluation-context.qbs
new file mode 100644
index 000000000..28216c150
--- /dev/null
+++ b/tests/auto/blackbox/testdata/property-evaluation-context/property-evaluation-context.qbs
@@ -0,0 +1,34 @@
+Project {
+ qbsSearchPaths: [ path ]
+ Product {
+ name: "mylib"
+ Export {
+ Depends { name: "top" }
+ top.productInExport: product.name
+ }
+ }
+
+ Product {
+ type: "rule-output"
+ name: "myapp"
+ Depends { name: "mylib" }
+
+ Rule {
+ alwaysRun: true
+ multiplex: true
+ requiresInputs: false
+ outputFileTags: "rule-output"
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.silent = true;
+ cmd.sourceCode = function() {
+ console.info("base.productInBase evaluated in: " + product.base.productInBase);
+ console.info("base.productInTop evaluated in: " + product.base.productInTop);
+ console.info("top.productInExport evaluated in: " + product.top.productInExport);
+ console.info("top.productInTop evaluated in: " + product.top.productInTop);
+ }
+ return [cmd];
+ }
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs b/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs
index f09706b47..5e6ffc508 100644
--- a/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs
+++ b/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs
@@ -12,6 +12,7 @@ CppApplication {
Depends { name: "cpp" }
cpp.cxxLanguageVersion: "c++11"
+ cpp.minimumMacosVersion: "10.8"
Depends { name: "protobuf.cpp"; required: false }
property bool hasProtobuf: {
diff --git a/tests/auto/blackbox/testdata/protobuf/import.qbs b/tests/auto/blackbox/testdata/protobuf/import.qbs
index 59a094dce..ef4e80c1b 100644
--- a/tests/auto/blackbox/testdata/protobuf/import.qbs
+++ b/tests/auto/blackbox/testdata/protobuf/import.qbs
@@ -13,6 +13,7 @@ CppApplication {
protobuf.cpp.importPaths: [sourceDirectory]
cpp.cxxLanguageVersion: "c++11"
+ cpp.minimumMacosVersion: "10.8"
Depends { name: "protobuf.cpp"; required: false }
property bool hasProtobuf: {
diff --git a/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs b/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs
index 475c1c6c7..493632a0e 100644
--- a/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs
+++ b/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs
@@ -14,6 +14,7 @@ CppApplication {
protobuf.cpp.importPaths: (theImportDir ? [theImportDir] : []).concat([sourceDirectory])
cpp.cxxLanguageVersion: "c++11"
+ cpp.minimumMacosVersion: "10.8"
Depends { name: "protobuf.cpp"; required: false }
property bool hasProtobuf: {
diff --git a/tests/auto/blackbox/testdata/response-files/response-files.qbs b/tests/auto/blackbox/testdata/response-files/response-files.qbs
index efed1dc9f..168cdf66a 100644
--- a/tests/auto/blackbox/testdata/response-files/response-files.qbs
+++ b/tests/auto/blackbox/testdata/response-files/response-files.qbs
@@ -44,6 +44,9 @@ Project {
Product {
name: "lotsofobjects"
type: ["dynamiclibrary"]
+ // clang-cl does not use response file internally, thus linker complains that command is
+ // too long. This can be worked around by calling the linker directly
+ cpp.linkerMode: qbs.toolchain.contains("clang-cl") ? "manual" : original
Depends { name: "cpp" }
Rule {
multiplex: true
diff --git a/tests/auto/blackbox/testdata/sanitizer/sanitizer.cpp b/tests/auto/blackbox/testdata/sanitizer/sanitizer.cpp
new file mode 100644
index 000000000..4a7c3ee32
--- /dev/null
+++ b/tests/auto/blackbox/testdata/sanitizer/sanitizer.cpp
@@ -0,0 +1,4 @@
+int main(int argc, char *argv[])
+{
+ return 0;
+}
diff --git a/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs b/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs
new file mode 100644
index 000000000..7b5054316
--- /dev/null
+++ b/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs
@@ -0,0 +1,30 @@
+CppApplication {
+ property string sanitizer
+
+ property bool supportsSanitizer: {
+ if (qbs.toolchain.contains("clang-cl"))
+ // only these are supported
+ return sanitizer === "address" || sanitizer === "undefined";
+ if (!qbs.toolchain.contains("gcc"))
+ return false;
+ if (qbs.toolchain.contains("mingw"))
+ return false;
+ return true;
+ }
+
+ condition: {
+ if (!sanitizer)
+ return true;
+ if (!supportsSanitizer)
+ console.info("Compiler does not support sanitizer");
+ return supportsSanitizer;
+ }
+ qbs.buildVariant: "release"
+ cpp.cxxLanguageVersion: "c++11"
+ cpp.minimumMacosVersion: "10.8"
+ consoleApplication: true
+ cpp.runtimeLibrary: "static"
+ cpp.driverFlags: sanitizer ? ["-fsanitize=" + sanitizer] : []
+ cpp.debugInformation: true
+ files: "sanitizer.cpp"
+}
diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.h b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.h
new file mode 100644
index 000000000..a82b12fbd
--- /dev/null
+++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.h
@@ -0,0 +1 @@
+#include "lib.h"
diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.qbs b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.qbs
new file mode 100644
index 000000000..e931b853c
--- /dev/null
+++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.qbs
@@ -0,0 +1,4 @@
+CppApplication {
+ cpp.includePaths: project.sourceDirectory + "/lib"
+ files: "main.cpp"
+}
diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/main.cpp b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/main.cpp
new file mode 100644
index 000000000..2e7bedac8
--- /dev/null
+++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/main.cpp
@@ -0,0 +1,3 @@
+#include "app.h"
+
+int main() { }
diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/lib/lib.h b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/lib/lib.h
new file mode 100644
index 000000000..af6f627b7
--- /dev/null
+++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/lib/lib.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void lib1_foo(); \ No newline at end of file
diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/other/other.qbs b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/other/other.qbs
new file mode 100644
index 000000000..29682da1c
--- /dev/null
+++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/other/other.qbs
@@ -0,0 +1,24 @@
+import qbs.TextFile
+
+Product {
+ type: "testproduct"
+ files: "../lib/lib.h"
+
+ Rule {
+ multiplex: true
+ Artifact {
+ fileTags: ["testproduct"]
+ filePath: "fubar"
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "generating text file";
+ cmd.sourceCode = function() {
+ var tf = new TextFile(output.filePath, TextFile.WriteOnly);
+ tf.writeLine("blubb");
+ tf.close();
+ }
+ return cmd;
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/p.qbs b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/p.qbs
new file mode 100644
index 000000000..bcbd5ebce
--- /dev/null
+++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/p.qbs
@@ -0,0 +1,6 @@
+Project {
+ references: [
+ "app/app.qbs",
+ "other/other.qbs",
+ ]
+}
diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.h b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.h
new file mode 100644
index 000000000..a82b12fbd
--- /dev/null
+++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.h
@@ -0,0 +1 @@
+#include "lib.h"
diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.qbs b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.qbs
new file mode 100644
index 000000000..984e9aca9
--- /dev/null
+++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.qbs
@@ -0,0 +1,4 @@
+CppApplication {
+ Depends { name: "lib" }
+ files: "main.cpp"
+}
diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/app/main.cpp b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/main.cpp
new file mode 100644
index 000000000..2e7bedac8
--- /dev/null
+++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/main.cpp
@@ -0,0 +1,3 @@
+#include "app.h"
+
+int main() { }
diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.h b/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.h
new file mode 100644
index 000000000..af6f627b7
--- /dev/null
+++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void lib1_foo(); \ No newline at end of file
diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.qbs b/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.qbs
new file mode 100644
index 000000000..fe2916714
--- /dev/null
+++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.qbs
@@ -0,0 +1,7 @@
+Product {
+ files: "lib.h"
+ Export {
+ Depends { name: "cpp" }
+ cpp.includePaths: product.sourceDirectory
+ }
+}
diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/other/other.qbs b/tests/auto/blackbox/testdata/scan-result-in-other-product/other/other.qbs
new file mode 100644
index 000000000..29682da1c
--- /dev/null
+++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/other/other.qbs
@@ -0,0 +1,24 @@
+import qbs.TextFile
+
+Product {
+ type: "testproduct"
+ files: "../lib/lib.h"
+
+ Rule {
+ multiplex: true
+ Artifact {
+ fileTags: ["testproduct"]
+ filePath: "fubar"
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "generating text file";
+ cmd.sourceCode = function() {
+ var tf = new TextFile(output.filePath, TextFile.WriteOnly);
+ tf.writeLine("blubb");
+ tf.close();
+ }
+ return cmd;
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/p.qbs b/tests/auto/blackbox/testdata/scan-result-in-other-product/p.qbs
new file mode 100644
index 000000000..fedf84989
--- /dev/null
+++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/p.qbs
@@ -0,0 +1,7 @@
+Project {
+ references: [
+ "app/app.qbs",
+ "lib/lib.qbs",
+ "other/other.qbs",
+ ]
+}
diff --git a/tests/auto/blackbox/testdata/undefined-target-platform/undefined-target-platform.qbs b/tests/auto/blackbox/testdata/undefined-target-platform/undefined-target-platform.qbs
new file mode 100644
index 000000000..2b3724c26
--- /dev/null
+++ b/tests/auto/blackbox/testdata/undefined-target-platform/undefined-target-platform.qbs
@@ -0,0 +1,13 @@
+import qbs.File
+import qbs.FileInfo
+
+Product {
+ name: "undefined-target-platform"
+ qbs.targetPlatform: undefined
+
+ readonly property bool _validate: {
+ if (Array.isArray(qbs.targetOS) && qbs.targetOS.length === 0)
+ return true;
+ throw "Invalid qbs.targetOS value: " + qbs.targetOS;
+ }
+}
diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index 861790acd..25e36816c 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -713,6 +713,25 @@ void TestBlackbox::buildGraphVersions()
QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData());
}
+void TestBlackbox::buildVariantDefaults_data()
+{
+ QTest::addColumn<QString>("buildVariant");
+ QTest::newRow("default") << QString();
+ QTest::newRow("debug") << QStringLiteral("debug");
+ QTest::newRow("release") << QStringLiteral("release");
+ QTest::newRow("profiling") << QStringLiteral("profiling");
+}
+
+void TestBlackbox::buildVariantDefaults()
+{
+ QFETCH(QString, buildVariant);
+ QDir::setCurrent(testDataDir + "/build-variant-defaults");
+ QbsRunParameters params{QStringLiteral("resolve")};
+ if (!buildVariant.isEmpty())
+ params.arguments << ("modules.qbs.buildVariant:" + buildVariant);
+ QCOMPARE(runQbs(params), 0);
+}
+
void TestBlackbox::changedFiles_data()
{
QTest::addColumn<bool>("useChangedFilesForInitialBuild");
@@ -942,20 +961,11 @@ void TestBlackbox::dependenciesProperty()
QCOMPARE(product2_cpp_defines.first().toString(), QLatin1String("DIGEDAG"));
}
-void TestBlackbox::dependencyProfileMismatch()
+void TestBlackbox::dependencyScanningLoop()
{
- QDir::setCurrent(testDataDir + "/dependency-profile-mismatch");
- const SettingsPtr s = settings();
- qbs::Internal::TemporaryProfile depProfile("qbs_autotests_profileMismatch", s.get());
- depProfile.p.setValue("qbs.architecture", "x86"); // Profiles must not be empty...
- s->sync();
- QbsRunParameters params(QStringList() << ("project.mainProfile:" + profileName())
- << ("project.depProfile:" + depProfile.p.name()));
- params.expectFailure = true;
- QVERIFY2(runQbs(params) != 0, m_qbsStderr.constData());
- QVERIFY2(m_qbsStderr.contains(profileName().toLocal8Bit())
- && m_qbsStderr.contains("', which does not exist"),
- m_qbsStderr.constData());
+ QDir::setCurrent(testDataDir + "/dependency-scanning-loop");
+ QCOMPARE(runQbs(), 0);
+ QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData());
}
void TestBlackbox::deprecatedProperty()
@@ -1442,7 +1452,7 @@ void TestBlackbox::versionScript()
{
const SettingsPtr s = settings();
Profile buildProfile(profileName(), s.get());
- QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList();
+ QStringList toolchain = profileToolchain(buildProfile);
if (!toolchain.contains("gcc") || targetOs() != HostOsInfo::HostOsLinux)
QSKIP("version script test only applies to Linux");
QDir::setCurrent(testDataDir + "/versionscript");
@@ -1765,6 +1775,40 @@ void TestBlackbox::cxxLanguageVersion_data()
std::make_pair(QString("msvc-new"), QString("/std:"))});
}
+void TestBlackbox::conanfileProbe()
+{
+ QString executable = findExecutable({"conan"});
+ if (executable.isEmpty())
+ QSKIP("conan is not installed or not available in PATH.");
+
+ // We first build a dummy package testlib and use that as dependency
+ // in the testapp package.
+ QDir::setCurrent(testDataDir + "/conanfile-probe/testlib");
+ QStringList arguments { "create", "-o", "opt=True", "-s", "os=AIX", ".",
+ "testlib/1.2.3@qbs/testing" };
+ QProcess conan;
+ conan.start(executable, arguments);
+ QVERIFY(waitForProcessSuccess(conan));
+
+ QDir::setCurrent(testDataDir + "/conanfile-probe/testapp");
+ QCOMPARE(runQbs(QbsRunParameters("resolve", {"--force-probe-execution"})), 0);
+
+ QFile file(relativeBuildDir() + "/results.json");
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ QVariantMap actualResults = QJsonDocument::fromJson(file.readAll()).toVariant().toMap();
+ const auto generatedFilesPath = actualResults.take("generatedFilesPath").toString();
+ // We want to make sure that generatedFilesPath is under the project directory,
+ // but we don't care about the actual name.
+ QVERIFY(directoryExists(relativeBuildDir() + "/genconan/"
+ + QFileInfo(generatedFilesPath).baseName()));
+
+ const QVariantMap expectedResults = {
+ { "json", "TESTLIB_ENV_VAL" },
+ { "dependencies", QVariantList{"testlib1", "testlib2"} },
+ };
+ QCOMPARE(actualResults, expectedResults);
+}
+
void TestBlackbox::cpuFeatures()
{
QDir::setCurrent(testDataDir + "/cpu-features");
@@ -1832,7 +1876,7 @@ void TestBlackbox::separateDebugInfo()
const SettingsPtr s = settings();
Profile buildProfile(profileName(), s.get());
- QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList();
+ QStringList toolchain = profileToolchain(buildProfile);
if (isDarwin) {
QVERIFY(directoryExists(relativeProductBuildDir("app1") + "/app1.app.dSYM"));
QVERIFY(regularFileExists(relativeProductBuildDir("app1")
@@ -2035,7 +2079,7 @@ void TestBlackbox::trackExternalProductChanges()
rmDirR(relativeBuildDir());
const SettingsPtr s = settings();
const Profile profile(profileName(), s.get());
- const QStringList toolchainTypes = profile.value("qbs.toolchain").toStringList();
+ const QStringList toolchainTypes = profileToolchain(profile);
if (!toolchainTypes.contains("gcc"))
QSKIP("Need GCC-like compiler to run this test");
params.environment = QProcessEnvironment::systemEnvironment();
@@ -2332,9 +2376,11 @@ void TestBlackbox::reproducibleBuild()
{
const SettingsPtr s = settings();
const Profile profile(profileName(), s.get());
- const QStringList toolchains = profile.value("qbs.toolchain").toStringList();
- if (!toolchains.contains("gcc") || toolchains.contains("clang"))
+ const QStringList toolchains = profileToolchain(profile);
+ if (!toolchains.contains("gcc"))
QSKIP("reproducible builds only supported for gcc");
+ if (toolchains.contains("clang"))
+ QSKIP("reproducible builds are not supported for clang");
QFETCH(bool, reproducible);
@@ -2495,6 +2541,36 @@ void TestBlackbox::ruleWithNonRequiredInputs()
QVERIFY2(m_qbsStdout.contains("Generating"), m_qbsStdout.constData());
}
+void TestBlackbox::sanitizer_data()
+{
+ QTest::addColumn<QString>("sanitizer");
+ QTest::newRow("none") << QString();
+ QTest::newRow("address") << QStringLiteral("address");
+ QTest::newRow("undefined") << QStringLiteral("undefined");
+ QTest::newRow("thread") << QStringLiteral("thread");
+}
+
+void TestBlackbox::sanitizer()
+{
+ QFETCH(QString, sanitizer);
+ QDir::setCurrent(testDataDir + "/sanitizer");
+ rmDirR(relativeBuildDir());
+ QbsRunParameters params("build", {"--command-echo-mode", "command-line"});
+ if (!sanitizer.isEmpty()) {
+ params.arguments.append(
+ {QStringLiteral("products.sanitizer.sanitizer:\"") + sanitizer + "\""});
+ }
+ QCOMPARE(runQbs(params), 0);
+ if (m_qbsStdout.contains(QByteArrayLiteral("Compiler does not support sanitizer")))
+ QSKIP("Compiler does not support the specified sanitizer");
+ if (!sanitizer.isEmpty()) {
+ QVERIFY2(m_qbsStdout.contains(QByteArrayLiteral("-fsanitize=") + sanitizer.toLatin1()),
+ qPrintable(m_qbsStdout));
+ } else {
+ QVERIFY2(!m_qbsStdout.contains(QByteArrayLiteral("-fsanitize=")), qPrintable(m_qbsStdout));
+ }
+}
+
void TestBlackbox::scannerItem()
{
QDir::setCurrent(testDataDir + "/scanner-item");
@@ -2513,6 +2589,47 @@ void TestBlackbox::scannerItem()
QVERIFY2(m_qbsStdout.contains("handling file2.in"), m_qbsStdout.constData());
}
+void TestBlackbox::scanResultInOtherProduct()
+{
+ QDir::setCurrent(testDataDir + "/scan-result-in-other-product");
+ QCOMPARE(runQbs(QStringList("-vv")), 0);
+ QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStderr.contains("The file dependency might get lost during change tracking"),
+ m_qbsStderr.constData());
+ WAIT_FOR_NEW_TIMESTAMP();
+ REPLACE_IN_FILE("other/other.qbs", "blubb", "blubb2");
+ QCOMPARE(runQbs(), 0);
+ QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData());
+ WAIT_FOR_NEW_TIMESTAMP();
+ touch("lib/lib.h");
+ QCOMPARE(runQbs(), 0);
+ QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("generating text file"), m_qbsStdout.constData());
+}
+
+void TestBlackbox::scanResultInNonDependency()
+{
+ QDir::setCurrent(testDataDir + "/scan-result-in-non-dependency");
+ QCOMPARE(runQbs(QStringList("-vv")), 0);
+ QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStderr.contains("The file dependency might get lost during change tracking"),
+ m_qbsStderr.constData());
+ WAIT_FOR_NEW_TIMESTAMP();
+ REPLACE_IN_FILE("other/other.qbs", "blubb", "blubb2");
+ QCOMPARE(runQbs(), 0);
+ QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData());
+ WAIT_FOR_NEW_TIMESTAMP();
+ touch("lib/lib.h");
+ QCOMPARE(runQbs(), 0);
+ QEXPECT_FAIL("", "QBS-1532", Continue);
+ QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("generating text file"), m_qbsStdout.constData());
+}
+
void TestBlackbox::setupBuildEnvironment()
{
QDir::setCurrent(testDataDir + "/setup-build-environment");
@@ -2821,6 +2938,8 @@ void TestBlackbox::pathProbe()
QbsRunParameters buildParams("build", QStringList{"-f", projectFile});
buildParams.expectFailure = !successExpected;
QCOMPARE(runQbs(buildParams) == 0, successExpected);
+ if (!successExpected)
+ QVERIFY2(m_qbsStderr.contains("Probe failed to find files"), m_qbsStderr);
}
void TestBlackbox::pchChangeTracking()
@@ -3077,6 +3196,9 @@ void TestBlackbox::probeProperties()
QVERIFY2(m_qbsStdout.contains("probe2.fileName=tool"), m_qbsStdout.constData());
QVERIFY2(m_qbsStdout.contains("probe2.path=" + dir + "/bin"), m_qbsStdout.constData());
QVERIFY2(m_qbsStdout.contains("probe2.filePath=" + dir + "/bin/tool"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("probe3.fileName=tool"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("probe3.path=" + dir + "/bin"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("probe3.filePath=" + dir + "/bin/tool"), m_qbsStdout.constData());
}
void TestBlackbox::probesAndShadowProducts()
@@ -3099,7 +3221,7 @@ void TestBlackbox::probeInExportedModule()
<< QStringLiteral("probe-in-exported-module.qbs"))), 0);
QVERIFY2(m_qbsStdout.contains("found: true"), m_qbsStdout.constData());
QVERIFY2(m_qbsStdout.contains("prop: yes"), m_qbsStdout.constData());
- QVERIFY2(m_qbsStdout.contains("listProp: my,myother"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("listProp: myother,my"), m_qbsStdout.constData());
}
void TestBlackbox::probesAndArrayProperties()
@@ -3368,6 +3490,17 @@ void TestBlackbox::propertyChanges()
QVERIFY(m_qbsStdout.contains("Making output from other output"));
}
+void TestBlackbox::propertyEvaluationContext()
+{
+ const QString testDir = testDataDir + "/property-evaluation-context";
+ QDir::setCurrent(testDir);
+ QCOMPARE(runQbs(), 0);
+ QCOMPARE(m_qbsStdout.count("base.productInBase evaluated in: myapp"), 1);
+ QCOMPARE(m_qbsStdout.count("base.productInTop evaluated in: myapp"), 1);
+ QCOMPARE(m_qbsStdout.count("top.productInExport evaluated in: mylib"), 1);
+ QCOMPARE(m_qbsStdout.count("top.productInTop evaluated in: myapp"), 1);
+}
+
void TestBlackbox::qtBug51237()
{
const QString profileName = "profile-qtBug51237";
@@ -3452,6 +3585,42 @@ void TestBlackbox::dynamicRuleOutputs()
QVERIFY(!QFile::exists(sourceFile2));
}
+void TestBlackbox::emptyProfile()
+{
+ QDir::setCurrent(testDataDir + "/empty-profile");
+
+ const SettingsPtr s = settings();
+ const Profile buildProfile(profileName(), s.get());
+ bool isMsvc = false;
+ auto toolchainType = buildProfile.value(QStringLiteral("qbs.toolchainType")).toString();
+ QbsRunParameters params;
+ params.profile = "none";
+
+ if (toolchainType.isEmpty()) {
+ const auto toolchain = buildProfile.value(QStringLiteral("qbs.toolchain")).toStringList();
+ if (!toolchain.isEmpty())
+ toolchainType = toolchain.first();
+ }
+ if (!toolchainType.isEmpty()) {
+ params.arguments = QStringList{QStringLiteral("qbs.toolchainType:") + toolchainType};
+ isMsvc = toolchainType == "msvc" || toolchainType == "clang-cl";
+ }
+
+ if (!isMsvc) {
+ const auto tcPath =
+ QDir::toNativeSeparators(
+ buildProfile.value(QStringLiteral("cpp.toolchainInstallPath")).toString());
+ auto paths = params.environment.value(QStringLiteral("PATH"))
+ .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts);
+ if (!tcPath.isEmpty() && !paths.contains(tcPath)) {
+ paths.prepend(tcPath);
+ params.environment.insert(
+ QStringLiteral("PATH"), paths.join(HostOsInfo::pathListSeparator()));
+ }
+ }
+ QCOMPARE(runQbs(params), 0);
+}
+
void TestBlackbox::erroneousFiles_data()
{
QTest::addColumn<QString>("errorMessage");
@@ -3544,9 +3713,11 @@ void TestBlackbox::escapedLinkerFlags()
{
const SettingsPtr s = settings();
const Profile buildProfile(profileName(), s.get());
- const QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList();
- if (!toolchain.contains("gcc") || targetOs() == HostOsInfo::HostOsMacos)
+ const QStringList toolchain = profileToolchain(buildProfile);
+ if (!toolchain.contains("gcc"))
QSKIP("escaped linker flags test only applies with gcc and GNU ld");
+ if (targetOs() == HostOsInfo::HostOsMacos)
+ QSKIP("Does not apply on macOS");
QDir::setCurrent(testDataDir + "/escaped-linker-flags");
QbsRunParameters params(QStringList("products.app.escapeLinkerFlags:false"));
QCOMPARE(runQbs(params), 0);
@@ -3836,6 +4007,40 @@ void TestBlackbox::fileTagsFilterMerging()
QVERIFY2(QFile::exists(otherOutput), qPrintable(otherOutput));
}
+void TestBlackbox::freedesktop()
+{
+ if (!HostOsInfo::isAnyUnixHost())
+ QSKIP("only applies on Unix");
+ if (HostOsInfo::isMacosHost())
+ QSKIP("Does not apply on macOS");
+ QDir::setCurrent(testDataDir + "/freedesktop");
+ QCOMPARE(runQbs(), 0);
+
+ // Check desktop file
+ QString desktopFilePath =
+ defaultInstallRoot + "/usr/local/share/applications/myapp.desktop";
+ QVERIFY(QFile::exists(desktopFilePath));
+ QFile desktopFile(desktopFilePath);
+ QVERIFY2(desktopFile.open(QIODevice::ReadOnly), qPrintable(desktopFile.errorString()));
+ QByteArrayList lines = desktopFile.readAll().split('\n');
+ // Automatically filled line:
+ QVERIFY(lines.contains("Exec=main"));
+ // Name specified in `freedesktop.name` property
+ QVERIFY(lines.contains("Name=My App"));
+ // Overridden line:
+ QVERIFY(lines.contains("Icon=myapp.png"));
+ // Untouched line:
+ QVERIFY(lines.contains("Terminal=false"));
+
+ // Check AppStream file
+ QVERIFY(QFile::exists(defaultInstallRoot +
+ "/usr/local/share/metainfo/myapp.appdata.xml"));
+
+ // Check icon file
+ QVERIFY(QFile::exists(defaultInstallRoot +
+ "/usr/local/share/icons/hicolor/scalable/apps/myapp.png"));
+}
+
void TestBlackbox::installedTransformerOutput()
{
QDir::setCurrent(testDataDir + "/installed-transformer-output");
@@ -3849,8 +4054,16 @@ void TestBlackbox::installLocations_data()
QTest::addColumn<QString>("binDir");
QTest::addColumn<QString>("dllDir");
QTest::addColumn<QString>("libDir");
- QTest::newRow("explicit values") << QString("bindir") << QString("dlldir") << QString("libdir");
- QTest::newRow("default values") << QString() << QString() << QString();
+ QTest::addColumn<QString>("pluginDir");
+ QTest::addColumn<QString>("dsymDir");
+ QTest::newRow("explicit values")
+ << QString("bindir")
+ << QString("dlldir")
+ << QString("libdir")
+ << QString("pluginDir")
+ << QString("dsymDir");
+ QTest::newRow("default values")
+ << QString() << QString() << QString() << QString() << QString();
}
void TestBlackbox::installLocations()
@@ -3859,6 +4072,8 @@ void TestBlackbox::installLocations()
QFETCH(QString, binDir);
QFETCH(QString, dllDir);
QFETCH(QString, libDir);
+ QFETCH(QString, pluginDir);
+ QFETCH(QString, dsymDir);
QbsRunParameters params("resolve");
if (!binDir.isEmpty())
params.arguments.push_back("products.theapp.installDir:" + binDir);
@@ -3866,6 +4081,13 @@ void TestBlackbox::installLocations()
params.arguments.push_back("products.thelib.installDir:" + dllDir);
if (!libDir.isEmpty())
params.arguments.push_back("products.thelib.importLibInstallDir:" + libDir);
+ if (!pluginDir.isEmpty())
+ params.arguments.push_back("products.theplugin.installDir:" + pluginDir);
+ if (!dsymDir.isEmpty()) {
+ params.arguments.push_back("products.theapp.debugInformationInstallDir:" + dsymDir);
+ params.arguments.push_back("products.thelib.debugInformationInstallDir:" + dsymDir);
+ params.arguments.push_back("products.theplugin.debugInformationInstallDir:" + dsymDir);
+ }
QCOMPARE(runQbs(params), 0);
const bool isWindows = m_qbsStdout.contains("is windows");
const bool isDarwin = m_qbsStdout.contains("is darwin");
@@ -3873,33 +4095,77 @@ void TestBlackbox::installLocations()
const bool isUnix = m_qbsStdout.contains("is unix");
QVERIFY(isWindows || isDarwin || isUnix);
QCOMPARE(runQbs(QbsRunParameters(QStringList("--clean-install-root"))), 0);
- const QString dllFileName =
- isWindows ? "thelib.dll" : isDarwin ? "thelib" : "libthelib.so";
- const QString appFileName = isWindows ? "theapp.exe" : "theapp";
- if (binDir.isEmpty())
- binDir = isDarwin ? "/Applications" : "/bin";
- if (dllDir.isEmpty())
- dllDir = isDarwin ? "/Library/Frameworks" : isWindows ? "/bin" : "/lib";
- if (libDir.isEmpty())
- libDir = "/lib";
- if (isDarwin) {
- if (isMac)
- binDir += "/theapp.app/Contents/MacOS";
- else
- binDir += "/theapp.app/";
- dllDir += "/thelib.framework";
- }
+
+ struct BinaryInfo
+ {
+ QString fileName;
+ QString installDir;
+ QString subDir;
+
+ QString absolutePath(const QString &prefix) const
+ {
+ return QDir::cleanPath(prefix + '/' + installDir + '/' + subDir + '/' + fileName);
+ }
+ };
+
+ const BinaryInfo dll = {
+ isWindows ? "thelib.dll" : isDarwin ? "thelib" : "libthelib.so",
+ dllDir.isEmpty()
+ ? (isDarwin ? "/Library/Frameworks" : (isWindows ? "/bin" : "/lib"))
+ : dllDir,
+ isDarwin ? "thelib.framework" : ""
+ };
+ const BinaryInfo dllDsym = {
+ isWindows ? "thelib.pdb" : isDarwin ? "thelib.framework.dSYM" : "libthelib.so.debug",
+ dsymDir.isEmpty() ? dll.installDir : dsymDir,
+ {}
+ };
+ const BinaryInfo plugin = {
+ isWindows ? "theplugin.dll" : isDarwin ? "theplugin" : "libtheplugin.so",
+ pluginDir.isEmpty() ? dll.installDir : pluginDir,
+ isDarwin ? (isMac ? "theplugin.bundle/Contents/MacOS" : "theplugin.bundle") : ""
+ };
+ const BinaryInfo pluginDsym = {
+ isWindows ? "theplugin.pdb" : isDarwin ? "theplugin.bundle.dSYM" : "libtheplugin.so.debug",
+ dsymDir.isEmpty() ? plugin.installDir : dsymDir,
+ {}
+ };
+ const BinaryInfo app = {
+ isWindows ? "theapp.exe" : "theapp",
+ binDir.isEmpty() ? (isDarwin ? "/Applications" : "/bin") : binDir,
+ isDarwin ? (isMac ? "theapp.app/Contents/MacOS" : "theapp.app") : ""
+ };
+ const BinaryInfo appDsym = {
+ isWindows ? "theapp.pdb" : isDarwin ? "theapp.app.dSYM" : "theapp.debug",
+ dsymDir.isEmpty() ? app.installDir : dsymDir,
+ {}
+ };
+
const QString installRoot = QDir::currentPath() + "/default/install-root";
const QString installPrefix = isWindows ? QString() : "/usr/local";
const QString fullInstallPrefix = installRoot + '/' + installPrefix + '/';
- const QString appFilePath = fullInstallPrefix + binDir + '/' + appFileName;
+ const QString appFilePath = app.absolutePath(fullInstallPrefix);
QVERIFY2(QFile::exists(appFilePath), qPrintable(appFilePath));
- const QString dllFilePath = fullInstallPrefix + dllDir + '/' + dllFileName;
+ const QString dllFilePath = dll.absolutePath(fullInstallPrefix);
QVERIFY2(QFile::exists(dllFilePath), qPrintable(dllFilePath));
if (isWindows) {
- const QString libFilePath = fullInstallPrefix + libDir + "/thelib.lib";
+ const BinaryInfo lib = {
+ "thelib.lib",
+ libDir.isEmpty() ? "/lib" : libDir,
+ ""
+ };
+ const QString libFilePath = lib.absolutePath(fullInstallPrefix);
QVERIFY2(QFile::exists(libFilePath), qPrintable(libFilePath));
}
+ const QString pluginFilePath = plugin.absolutePath(fullInstallPrefix);
+ QVERIFY2(QFile::exists(pluginFilePath), qPrintable(pluginFilePath));
+
+ const QString appDsymFilePath = appDsym.absolutePath(fullInstallPrefix);
+ QVERIFY2(QFileInfo(appDsymFilePath).exists(), qPrintable(appDsymFilePath));
+ const QString dllDsymFilePath = dllDsym.absolutePath(fullInstallPrefix);
+ QVERIFY2(QFileInfo(dllDsymFilePath).exists(), qPrintable(dllDsymFilePath));
+ const QString pluginDsymFilePath = pluginDsym.absolutePath(fullInstallPrefix);
+ QVERIFY2(QFile::exists(pluginDsymFilePath), qPrintable(pluginDsymFilePath));
}
void TestBlackbox::inputsFromDependencies()
@@ -4080,7 +4346,7 @@ void TestBlackbox::cli()
const SettingsPtr s = settings();
Profile p("qbs_autotests-cli", s.get());
- const QStringList toolchain = p.value("qbs.toolchain").toStringList();
+ const QStringList toolchain = profileToolchain(p);
if (!p.exists() || !(toolchain.contains("dotnet") || toolchain.contains("mono")))
QSKIP("No suitable Common Language Infrastructure test profile");
@@ -4311,6 +4577,15 @@ void TestBlackbox::jsExtensionsBinaryFile()
QCOMPARE(data.at(7), char(0xFF));
}
+void TestBlackbox::lastModuleCandidateBroken()
+{
+ QDir::setCurrent(testDataDir + "/last-module-candidate-broken");
+ QbsRunParameters params;
+ params.expectFailure = true;
+ QVERIFY(runQbs(params) != 0);
+ QVERIFY2(m_qbsStderr.contains("Module Foo could not be loaded"), m_qbsStderr);
+}
+
void TestBlackbox::ld()
{
QDir::setCurrent(testDataDir + "/ld");
@@ -4549,7 +4824,7 @@ void TestBlackbox::linkerLibraryDuplicates()
{
const SettingsPtr s = settings();
Profile buildProfile(profileName(), s.get());
- QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList();
+ QStringList toolchain = profileToolchain(buildProfile);
if (!toolchain.contains("gcc"))
QSKIP("linkerLibraryDuplicates test only applies to GCC toolchain");
@@ -4629,7 +4904,7 @@ void TestBlackbox::linkerScripts()
{
const SettingsPtr s = settings();
Profile buildProfile(profileName(), s.get());
- QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList();
+ QStringList toolchain = profileToolchain(buildProfile);
if (!toolchain.contains("gcc") || targetOs() != HostOsInfo::HostOsLinux)
QSKIP("linker script test only applies to Linux ");
@@ -4743,9 +5018,10 @@ void TestBlackbox::listPropertiesWithOuter()
void TestBlackbox::listPropertyOrder()
{
QDir::setCurrent(testDataDir + "/list-property-order");
- const QbsRunParameters params(QStringList() << "-qq");
+ const QbsRunParameters params(QStringList() << "-q");
QCOMPARE(runQbs(params), 0);
const QByteArray firstOutput = m_qbsStderr;
+ QVERIFY(firstOutput.contains("listProp = [\"product\",\"higher3\",\"higher2\",\"higher1\",\"lower\"]"));
for (int i = 0; i < 25; ++i) {
rmDirR(relativeBuildDir());
QCOMPARE(runQbs(params), 0);
@@ -4987,6 +5263,8 @@ void TestBlackbox::propertyPrecedence()
// Case 1: [cmdline=0,prod=0,export=0,nonleaf=0,profile=0]
QCOMPARE(runQbs(params), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
+
QVERIFY2(m_qbsStdout.contains("scalar prop: leaf\n")
&& m_qbsStdout.contains("list prop: [\"leaf\"]\n"),
m_qbsStdout.constData());
@@ -4995,6 +5273,8 @@ void TestBlackbox::propertyPrecedence()
// Case 2: [cmdline=0,prod=0,export=0,nonleaf=0,profile=1]
switchProfileContents(profile.p, s.get(), true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
+
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: profile\n")
&& m_qbsStdout.contains("list prop: [\"profile\"]\n"),
@@ -5006,6 +5286,7 @@ void TestBlackbox::propertyPrecedence()
switchProfileContents(profile.p, s.get(), false);
switchFileContents(nonleafFile, true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: nonleaf\n")
&& m_qbsStdout.contains("list prop: [\"nonleaf\",\"leaf\"]\n"),
@@ -5014,6 +5295,7 @@ void TestBlackbox::propertyPrecedence()
// Case 4: [cmdline=0,prod=0,export=0,nonleaf=1,profile=1]
switchProfileContents(profile.p, s.get(), true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: nonleaf\n")
&& m_qbsStdout.contains("list prop: [\"nonleaf\",\"profile\"]\n"),
@@ -5026,6 +5308,7 @@ void TestBlackbox::propertyPrecedence()
switchFileContents(nonleafFile, false);
switchFileContents(depFile, true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: export\n")
&& m_qbsStdout.contains("list prop: [\"export\",\"leaf\"]\n"),
@@ -5034,15 +5317,21 @@ void TestBlackbox::propertyPrecedence()
// Case 6: [cmdline=0,prod=0,export=1,nonleaf=0,profile=1]
switchProfileContents(profile.p, s.get(), true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: export\n")
&& m_qbsStdout.contains("list prop: [\"export\",\"profile\"]\n"),
m_qbsStdout.constData());
+
// Case 7: [cmdline=0,prod=0,export=1,nonleaf=1,profile=0]
switchProfileContents(profile.p, s.get(), false);
switchFileContents(nonleafFile, true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.contains("WARNING: Conflicting scalar values at")
+ && m_qbsStderr.contains("nonleaf.qbs:4:22")
+ && m_qbsStderr.contains("dep.qbs:6:26"),
+ m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: export\n")
&& m_qbsStdout.contains("list prop: [\"export\",\"nonleaf\",\"leaf\"]\n"),
@@ -5051,6 +5340,10 @@ void TestBlackbox::propertyPrecedence()
// Case 8: [cmdline=0,prod=0,export=1,nonleaf=1,profile=1]
switchProfileContents(profile.p, s.get(), true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.contains("WARNING: Conflicting scalar values at")
+ && m_qbsStderr.contains("nonleaf.qbs:4:22")
+ && m_qbsStderr.contains("dep.qbs:6:26"),
+ m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: export\n")
&& m_qbsStdout.contains("list prop: [\"export\",\"nonleaf\",\"profile\"]\n"),
@@ -5064,6 +5357,7 @@ void TestBlackbox::propertyPrecedence()
switchFileContents(depFile, false);
switchFileContents(productFile, true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: product\n")
&& m_qbsStdout.contains("list prop: [\"product\",\"leaf\"]\n"),
@@ -5072,6 +5366,7 @@ void TestBlackbox::propertyPrecedence()
// Case 10: [cmdline=0,prod=1,export=0,nonleaf=0,profile=1]
switchProfileContents(profile.p, s.get(), true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: product\n")
&& m_qbsStdout.contains("list prop: [\"product\",\"profile\"]\n"),
@@ -5081,6 +5376,7 @@ void TestBlackbox::propertyPrecedence()
switchProfileContents(profile.p, s.get(), false);
switchFileContents(nonleafFile, true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: product\n")
&& m_qbsStdout.contains("list prop: [\"product\",\"nonleaf\",\"leaf\"]\n"),
@@ -5089,6 +5385,7 @@ void TestBlackbox::propertyPrecedence()
// Case 12: [cmdline=0,prod=1,export=0,nonleaf=1,profile=1]
switchProfileContents(profile.p, s.get(), true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: product\n")
&& m_qbsStdout.contains("list prop: [\"product\",\"nonleaf\",\"profile\"]\n"),
@@ -5099,6 +5396,7 @@ void TestBlackbox::propertyPrecedence()
switchFileContents(nonleafFile, false);
switchFileContents(depFile, true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: product\n")
&& m_qbsStdout.contains("list prop: [\"product\",\"export\",\"leaf\"]\n"),
@@ -5107,6 +5405,7 @@ void TestBlackbox::propertyPrecedence()
// Case 14: [cmdline=0,prod=1,export=1,nonleaf=0,profile=1]
switchProfileContents(profile.p, s.get(), true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: product\n")
&& m_qbsStdout.contains("list prop: [\"product\",\"export\",\"profile\"]\n"),
@@ -5116,6 +5415,7 @@ void TestBlackbox::propertyPrecedence()
switchProfileContents(profile.p, s.get(), false);
switchFileContents(nonleafFile, true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: product\n")
&& m_qbsStdout.contains("list prop: [\"product\",\"export\",\"nonleaf\",\"leaf\"]\n"),
@@ -5124,6 +5424,7 @@ void TestBlackbox::propertyPrecedence()
// Case 16: [cmdline=0,prod=1,export=1,nonleaf=1,profile=1]
switchProfileContents(profile.p, s.get(), true);
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: product\n")
&& m_qbsStdout.contains("list prop: [\"product\",\"export\",\"nonleaf\",\"profile\"]\n"),
@@ -5137,6 +5438,7 @@ void TestBlackbox::propertyPrecedence()
switchFileContents(productFile, false);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5146,6 +5448,7 @@ void TestBlackbox::propertyPrecedence()
switchProfileContents(profile.p, s.get(), true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5156,6 +5459,7 @@ void TestBlackbox::propertyPrecedence()
switchFileContents(nonleafFile, true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5165,6 +5469,7 @@ void TestBlackbox::propertyPrecedence()
switchProfileContents(profile.p, s.get(), true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5176,6 +5481,7 @@ void TestBlackbox::propertyPrecedence()
switchFileContents(depFile, true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5185,6 +5491,7 @@ void TestBlackbox::propertyPrecedence()
switchProfileContents(profile.p, s.get(), true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5195,6 +5502,7 @@ void TestBlackbox::propertyPrecedence()
switchFileContents(nonleafFile, true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5204,6 +5512,7 @@ void TestBlackbox::propertyPrecedence()
switchProfileContents(profile.p, s.get(), true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5216,6 +5525,7 @@ void TestBlackbox::propertyPrecedence()
switchFileContents(productFile, true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5225,6 +5535,7 @@ void TestBlackbox::propertyPrecedence()
switchProfileContents(profile.p, s.get(), true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5235,6 +5546,7 @@ void TestBlackbox::propertyPrecedence()
switchFileContents(nonleafFile, true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5244,6 +5556,7 @@ void TestBlackbox::propertyPrecedence()
switchProfileContents(profile.p, s.get(), true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5255,6 +5568,7 @@ void TestBlackbox::propertyPrecedence()
switchFileContents(depFile, true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5264,6 +5578,7 @@ void TestBlackbox::propertyPrecedence()
switchProfileContents(profile.p, s.get(), true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5274,6 +5589,7 @@ void TestBlackbox::propertyPrecedence()
switchFileContents(nonleafFile, true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5283,6 +5599,7 @@ void TestBlackbox::propertyPrecedence()
switchProfileContents(profile.p, s.get(), true);
resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline";
QCOMPARE(runQbs(resolveParams), 0);
+ QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData());
QCOMPARE(runQbs(params), 0);
QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n")
&& m_qbsStdout.contains("list prop: [\"cmdline\"]\n"),
@@ -5563,8 +5880,8 @@ void TestBlackbox::qbsSession()
// Wait for and verify hello packet.
QJsonObject receivedMessage = getNextSessionPacket(sessionProc, incomingData);
QCOMPARE(receivedMessage.value("type"), "hello");
- QCOMPARE(receivedMessage.value("api-level").toInt(), 1);
- QCOMPARE(receivedMessage.value("api-compat-level").toInt(), 1);
+ QCOMPARE(receivedMessage.value("api-level").toInt(), 2);
+ QCOMPARE(receivedMessage.value("api-compat-level").toInt(), 2);
// Resolve & verify structure
QJsonObject resolveMessage;
@@ -5622,7 +5939,7 @@ void TestBlackbox::qbsSession()
const QJsonObject group = v.toObject();
const QJsonArray sourceArtifacts
= group.value("source-artifacts").toArray();
- const auto findArtifact = [&sourceArtifacts](const QString fileName) {
+ const auto findArtifact = [&sourceArtifacts](const QString &fileName) {
for (const QJsonValue &v : sourceArtifacts) {
const QJsonObject artifact = v.toObject();
if (QFileInfo(artifact.value("file-path").toString()).fileName()
@@ -5892,34 +6209,51 @@ void TestBlackbox::qbsSession()
qDebug() << error;
}
QVERIFY(error.isEmpty());
- QJsonObject projectData = receivedMessage.value("project-data").toObject();
- QJsonArray products = projectData.value("products").toArray();
- bool file1 = false;
- bool file2 = false;
- for (const QJsonValue &v : products) {
- const QJsonObject product = v.toObject();
- const QString productName = product.value("full-display-name").toString();
- const QJsonArray groups = product.value("groups").toArray();
- for (const QJsonValue &v : groups) {
- const QJsonObject group = v.toObject();
- const QString groupName = group.value("name").toString();
- const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray();
- for (const QJsonValue &v : sourceArtifacts) {
- const QString filePath = v.toObject().value("file-path").toString();
- if (filePath.endsWith("file1.cpp")) {
- QCOMPARE(productName, QString("theLib"));
- QCOMPARE(groupName, QString("sources"));
- file1 = true;
- } else if (filePath.endsWith("file2.cpp")) {
- QCOMPARE(productName, QString("theLib"));
- QCOMPARE(groupName, QString("sources"));
- file2 = true;
+
+ receivedReply = false;
+ sendPacket(resolveMessage);
+ while (!receivedReply) {
+ receivedMessage = getNextSessionPacket(sessionProc, incomingData);
+ QVERIFY(!receivedMessage.isEmpty());
+ const QString msgType = receivedMessage.value("type").toString();
+ if (msgType == "project-resolved") {
+ receivedReply = true;
+ const QJsonObject error = receivedMessage.value("error").toObject();
+ if (!error.isEmpty())
+ qDebug() << error;
+ QVERIFY(error.isEmpty());
+ const QJsonObject projectData = receivedMessage.value("project-data").toObject();
+ QJsonArray products = projectData.value("products").toArray();
+ bool file1 = false;
+ bool file2 = false;
+ for (const QJsonValue &v : products) {
+ const QJsonObject product = v.toObject();
+ const QString productName = product.value("full-display-name").toString();
+ const QJsonArray groups = product.value("groups").toArray();
+ for (const QJsonValue &v : groups) {
+ const QJsonObject group = v.toObject();
+ const QString groupName = group.value("name").toString();
+ const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray();
+ for (const QJsonValue &v : sourceArtifacts) {
+ const QString filePath = v.toObject().value("file-path").toString();
+ if (filePath.endsWith("file1.cpp")) {
+ QCOMPARE(productName, QString("theLib"));
+ QCOMPARE(groupName, QString("sources"));
+ file1 = true;
+ } else if (filePath.endsWith("file2.cpp")) {
+ QCOMPARE(productName, QString("theLib"));
+ QCOMPARE(groupName, QString("sources"));
+ file2 = true;
+ }
+ }
}
}
+ QVERIFY(file1);
+ QVERIFY(file2);
}
}
- QVERIFY(file1);
- QVERIFY(file2);
+ QVERIFY(receivedReply);
+
receivedReply = false;
receivedProcessResult = false;
bool compiledFile1 = false;
@@ -5978,32 +6312,48 @@ void TestBlackbox::qbsSession()
if (!error.isEmpty())
qDebug() << error;
QVERIFY(error.isEmpty());
- projectData = receivedMessage.value("project-data").toObject();
- products = projectData.value("products").toArray();
- file1 = false;
- file2 = false;
- for (const QJsonValue &v : products) {
- const QJsonObject product = v.toObject();
- const QString productName = product.value("full-display-name").toString();
- const QJsonArray groups = product.value("groups").toArray();
- for (const QJsonValue &v : groups) {
- const QJsonObject group = v.toObject();
- const QString groupName = group.value("name").toString();
- const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray();
- for (const QJsonValue &v : sourceArtifacts) {
- const QString filePath = v.toObject().value("file-path").toString();
- if (filePath.endsWith("file1.cpp")) {
- file1 = true;
- } else if (filePath.endsWith("file2.cpp")) {
- QCOMPARE(productName, QString("theLib"));
- QCOMPARE(groupName, QString("sources"));
- file2 = true;
+ receivedReply = false;
+ sendPacket(resolveMessage);
+ while (!receivedReply) {
+ receivedMessage = getNextSessionPacket(sessionProc, incomingData);
+ QVERIFY(!receivedMessage.isEmpty());
+ const QString msgType = receivedMessage.value("type").toString();
+ if (msgType == "project-resolved") {
+ receivedReply = true;
+ const QJsonObject error = receivedMessage.value("error").toObject();
+ if (!error.isEmpty())
+ qDebug() << error;
+ QVERIFY(error.isEmpty());
+ const QJsonObject projectData = receivedMessage.value("project-data").toObject();
+ QJsonArray products = projectData.value("products").toArray();
+ bool file1 = false;
+ bool file2 = false;
+ for (const QJsonValue &v : products) {
+ const QJsonObject product = v.toObject();
+ const QString productName = product.value("full-display-name").toString();
+ const QJsonArray groups = product.value("groups").toArray();
+ for (const QJsonValue &v : groups) {
+ const QJsonObject group = v.toObject();
+ const QString groupName = group.value("name").toString();
+ const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray();
+ for (const QJsonValue &v : sourceArtifacts) {
+ const QString filePath = v.toObject().value("file-path").toString();
+ if (filePath.endsWith("file1.cpp")) {
+ file1 = true;
+ } else if (filePath.endsWith("file2.cpp")) {
+ QCOMPARE(productName, QString("theLib"));
+ QCOMPARE(groupName, QString("sources"));
+ file2 = true;
+ }
+ }
}
}
+ QVERIFY(!file1);
+ QVERIFY(file2);
}
}
- QVERIFY(!file1);
- QVERIFY(file2);
+ QVERIFY(receivedReply);
+
receivedReply = false;
receivedProcessResult = false;
compiledFile1 = false;
@@ -7012,6 +7362,12 @@ void TestBlackbox::typescript()
QVERIFY(regularFileExists(relativeProductBuildDir("animals") + "/main.js"));
}
+void TestBlackbox::undefinedTargetPlatform()
+{
+ QDir::setCurrent(testDataDir + "/undefined-target-platform");
+ QCOMPARE(runQbs(), 0);
+}
+
void TestBlackbox::importInPropertiesCondition()
{
QDir::setCurrent(testDataDir + "/import-in-properties-condition");
@@ -7776,6 +8132,17 @@ void TestBlackbox::grpc()
QCOMPARE(runQbs(runParams), 0);
}
+void TestBlackbox::hostOsProperties()
+{
+ QDir::setCurrent(testDataDir + "/host-os-properties");
+ QCOMPARE(runQbs(QStringLiteral("run")), 0);
+ QVERIFY2(m_qbsStdout.contains(
+ ("HOST_ARCHITECTURE = " + HostOsInfo::hostOSArchitecture()).data()),
+ m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains(("HOST_PLATFORM = " + HostOsInfo::hostOSIdentifier()).data()),
+ m_qbsStdout.constData());
+}
+
void TestBlackbox::ico()
{
QDir::setCurrent(testDataDir + "/ico");
diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h
index 4e2755724..757462b80 100644
--- a/tests/auto/blackbox/tst_blackbox.h
+++ b/tests/auto/blackbox/tst_blackbox.h
@@ -60,6 +60,8 @@ private slots:
void buildDirectories();
void buildEnvChange();
void buildGraphVersions();
+ void buildVariantDefaults_data();
+ void buildVariantDefaults();
void changedFiles_data();
void changedFiles();
void changedInputsFromDependencies();
@@ -83,9 +85,10 @@ private slots:
void conflictingArtifacts();
void cxxLanguageVersion();
void cxxLanguageVersion_data();
+ void conanfileProbe();
void cpuFeatures();
void dependenciesProperty();
- void dependencyProfileMismatch();
+ void dependencyScanningLoop();
void deprecatedProperty();
void disappearedProfile();
void discardUnusedData();
@@ -96,6 +99,7 @@ private slots:
void dynamicMultiplexRule();
void dynamicProject();
void dynamicRuleOutputs();
+ void emptyProfile();
void enableExceptions();
void enableExceptions_data();
void enableRtti();
@@ -118,6 +122,7 @@ private slots:
void externalLibs();
void fileDependencies();
void fileTagsFilterMerging();
+ void freedesktop();
void generatedArtifactAsInputToDynamicRule();
void generateLinkerMapFile();
void generator();
@@ -125,6 +130,7 @@ private slots:
void groupsInModules();
void grpc_data();
void grpc();
+ void hostOsProperties();
void ico();
void importAssignment();
void importChangeTracking();
@@ -164,6 +170,7 @@ private slots:
void jsExtensionsTemporaryDir();
void jsExtensionsTextFile();
void jsExtensionsBinaryFile();
+ void lastModuleCandidateBroken();
void ld();
void linkerMode();
void linkerVariant_data();
@@ -236,6 +243,7 @@ private slots:
void propertyAssignmentOnNonPresentModule();
void propertyAssignmentInFailedModule();
void propertyChanges();
+ void propertyEvaluationContext();
void propertyPrecedence();
void properQuoting();
void propertiesInExportItems();
@@ -265,7 +273,11 @@ private slots:
void ruleCycle();
void ruleWithNoInputs();
void ruleWithNonRequiredInputs();
+ void sanitizer_data();
+ void sanitizer();
void scannerItem();
+ void scanResultInOtherProduct();
+ void scanResultInNonDependency();
void setupBuildEnvironment();
void setupRunEnvironment();
void smartRelinking();
@@ -301,6 +313,7 @@ private slots:
void trackRemoveProduct();
void transitiveOptionalDependencies();
void typescript();
+ void undefinedTargetPlatform();
void usingsAsSoleInputsNonMultiplexed();
void variantSuffix();
void variantSuffix_data();
diff --git a/tests/auto/blackbox/tst_blackboxandroid.cpp b/tests/auto/blackbox/tst_blackboxandroid.cpp
index e312c4493..eb0303a07 100644
--- a/tests/auto/blackbox/tst_blackboxandroid.cpp
+++ b/tests/auto/blackbox/tst_blackboxandroid.cpp
@@ -79,7 +79,7 @@ void TestBlackboxAndroid::android()
QFETCH(QString, projectDir);
QFETCH(QStringList, productNames);
QFETCH(QList<QByteArrayList>, expectedFilesLists);
- QFETCH(QStringList, customProperties);
+ QFETCH(QStringList, qmlAppCustomProperties);
const SettingsPtr s = settings();
Profile p(theProfileName(projectDir == "qml-app"), s.get());
@@ -110,7 +110,7 @@ void TestBlackboxAndroid::android()
auto currentExpectedFilesLists = expectedFilesLists;
const QString configArgument = "config:" + configName;
QbsRunParameters resolveParams("resolve");
- resolveParams.arguments << configArgument << customProperties;
+ resolveParams.arguments << configArgument << qmlAppCustomProperties;
resolveParams.profile = p.name();
QCOMPARE(runQbs(resolveParams), 0);
QbsRunParameters buildParams(QStringList{"--command-echo-mode", "command-line",
@@ -206,14 +206,41 @@ void TestBlackboxAndroid::android_data()
.toString() == "clang";
return QByteArray("lib/${ARCH}/") + (usesClang ? "libc++_shared.so" : oldcxxLib);
};
- const QByteArrayList archsForQt = { pQt.value("qbs.architecture").toString().toUtf8() };
- QByteArrayList ndkArchsForQt = archsForQt;
- if (ndkArchsForQt.first() == "armv7a")
- ndkArchsForQt.first() = "armeabi-v7a";
- else if (ndkArchsForQt.first() == "armv5te")
- ndkArchsForQt.first() = "armeabi";
- else if (ndkArchsForQt.first() == "arm64")
- ndkArchsForQt.first() = "arm64-v8a";
+
+ bool usingOldQt = true;
+ QStringList qmakeFilePaths = pQt.value(QStringLiteral("moduleProviders.Qt.qmakeFilePaths")).
+ toStringList();
+ if (qmakeFilePaths.size() == 1) {
+ qbs::Version version = TestBlackboxBase::qmakeVersion(qmakeFilePaths[0]);
+ if (version.isValid() && version >= qbs::Version(5, 14))
+ usingOldQt = false;
+ }
+
+ QByteArrayList archsForQt;
+ if (usingOldQt) {
+ archsForQt = { pQt.value("qbs.architecture").toString().toUtf8() };
+ if (archsStringList.empty())
+ archsStringList << QStringLiteral("armv7a"); // must match default in common.qbs
+ } else {
+ QStringList archsForQtStringList = pQt.value(QStringLiteral("qbs.architectures"))
+ .toStringList();
+ if (archsForQtStringList.empty())
+ archsForQtStringList << pQt.value("qbs.architecture").toString();
+ std::transform(archsForQtStringList.begin(),
+ archsForQtStringList.end(),
+ std::back_inserter(archsForQt),
+ [] (const QString &s) {
+ return s.toUtf8();
+ });
+ }
+
+ QByteArrayList ndkArchsForQt;
+ std::transform(archsForQt.begin(), archsForQt.end(), std::back_inserter(ndkArchsForQt),
+ [] (const QString &s) {
+ return s.toUtf8().replace("armv7a", "armeabi-v7a")
+ .replace("armv5te", "armeabi")
+ .replace("arm64", "arm64-v8a");
+ });
auto expandArchs = [] (const QByteArrayList &archs, const QByteArrayList &lst) {
const QByteArray &archPlaceHolder = "${ARCH}";
@@ -237,7 +264,7 @@ void TestBlackboxAndroid::android_data()
QTest::addColumn<QString>("projectDir");
QTest::addColumn<QStringList>("productNames");
QTest::addColumn<QList<QByteArrayList>>("expectedFilesLists");
- QTest::addColumn<QStringList>("customProperties");
+ QTest::addColumn<QStringList>("qmlAppCustomProperties");
QTest::newRow("teapot")
<< "teapot" << QStringList("TeapotNativeActivity")
<< (QList<QByteArrayList>() << commonFiles + expandArchs(archs, {
@@ -257,9 +284,12 @@ void TestBlackboxAndroid::android_data()
"lib/${ARCH}/libdependency.so"}))
<< QStringList{"products.minimalnative.multiplexByQbsProperties:[]",
"modules.qbs.architecture:" + archsStringList.first()};
- QTest::newRow("qml app")
- << "qml-app" << QStringList("qmlapp")
- << (QList<QByteArrayList>() << commonFiles + expandArchs(ndkArchsForQt, {
+ QByteArrayList qmlAppExpectedFiles;
+ QByteArrayList qmlAppMinistroExpectedFiles;
+ QByteArrayList qmlAppCustomMetaDataExpectedFiles;
+ QStringList qmlAppCustomProperties;
+ if (usingOldQt) {
+ qmlAppExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, {
"resources.arsc",
"assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes",
"assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir",
@@ -298,64 +328,157 @@ void TestBlackboxAndroid::android_data()
"lib/${ARCH}/libQt5QuickParticles.so",
"lib/${ARCH}/libQt5Quick.so",
"lib/${ARCH}/libqmlapp.so",
- "res/layout/splash.xml"}))
- << QStringList{"modules.Android.sdk.automaticSources:false",
- "modules.qbs.architecture:" + archsForQt.first()};
- QTest::newRow("qml app using Ministro")
- << "qml-app" << QStringList("qmlapp")
- << (QList<QByteArrayList>() << commonFiles + expandArchs(ndkArchsForQt, {
+ "res/layout/splash.xml"});
+ qmlAppMinistroExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, {
+ "resources.arsc",
+ "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list",
+ "lib/${ARCH}/libgdbserver.so",
+ cxxLibPath("libgnustl_shared.so", true),
+ "lib/${ARCH}/libqmlapp.so",
+ "res/layout/splash.xml"});
+ qmlAppCustomMetaDataExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, {
+ "resources.arsc",
+ "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes",
+ "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir",
+ "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/plugins.qmltypes",
+ "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/qmldir",
+ "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list",
+ "assets/dummyasset.txt",
+ "lib/${ARCH}/libgdbserver.so",
+ cxxLibPath("libgnustl_shared.so", true),
+ "lib/${ARCH}/libplugins_bearer_libqandroidbearer.so",
+ "lib/${ARCH}/libplugins_imageformats_libqgif.so",
+ "lib/${ARCH}/libplugins_imageformats_libqicns.so",
+ "lib/${ARCH}/libplugins_imageformats_libqico.so",
+ "lib/${ARCH}/libplugins_imageformats_libqjpeg.so",
+ "lib/${ARCH}/libplugins_imageformats_libqtga.so",
+ "lib/${ARCH}/libplugins_imageformats_libqtiff.so",
+ "lib/${ARCH}/libplugins_imageformats_libqwbmp.so",
+ "lib/${ARCH}/libplugins_imageformats_libqwebp.so",
+ "lib/${ARCH}/libplugins_platforms_android_libqtforandroid.so",
+ "lib/${ARCH}/libplugins_qmltooling_libqmldbg_debugger.so",
+ "lib/${ARCH}/libplugins_qmltooling_libqmldbg_inspector.so",
+ "lib/${ARCH}/libplugins_qmltooling_libqmldbg_local.so",
+ "lib/${ARCH}/libplugins_qmltooling_libqmldbg_messages.so",
+ "lib/${ARCH}/libplugins_qmltooling_libqmldbg_native.so",
+ "lib/${ARCH}/libplugins_qmltooling_libqmldbg_nativedebugger.so",
+ "lib/${ARCH}/libplugins_qmltooling_libqmldbg_profiler.so",
+ "lib/${ARCH}/libplugins_qmltooling_libqmldbg_preview.so",
+ "lib/${ARCH}/libplugins_qmltooling_libqmldbg_quickprofiler.so",
+ "lib/${ARCH}/libplugins_qmltooling_libqmldbg_server.so",
+ "lib/${ARCH}/libplugins_qmltooling_libqmldbg_tcp.so",
+ "lib/${ARCH}/libqml_QtQuick.2_libqtquick2plugin.so",
+ "lib/${ARCH}/libqml_QtQuick_Window.2_libwindowplugin.so",
+ "lib/${ARCH}/libQt5Core.so",
+ "lib/${ARCH}/libQt5Gui.so",
+ "lib/${ARCH}/libQt5Network.so",
+ "lib/${ARCH}/libQt5Qml.so",
+ "lib/${ARCH}/libQt5QuickParticles.so",
+ "lib/${ARCH}/libQt5Quick.so",
+ "lib/${ARCH}/libqmlapp.so",
+ "res/layout/splash.xml"});
+ qmlAppCustomProperties = QStringList{"modules.Android.sdk.automaticSources:false",
+ "modules.qbs.architecture:" + archsForQt.first()};
+ } else {
+ qmlAppExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, {
"resources.arsc",
- "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list",
+ "assets/android_rcc_bundle.rcc",
"lib/${ARCH}/libgdbserver.so",
cxxLibPath("libgnustl_shared.so", true),
- "lib/${ARCH}/libqmlapp.so",
- "res/layout/splash.xml"}))
+ "lib/${ARCH}/libplugins_bearer_qandroidbearer_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qgif_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qicns_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qico_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qjpeg_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qtga_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qtiff_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qwbmp_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qwebp_${ARCH}.so",
+ "lib/${ARCH}/libplugins_platforms_qtforandroid_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_debugger_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_inspector_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_local_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_messages_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_native_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_nativedebugger_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_profiler_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_preview_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_quickprofiler_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_server_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_tcp_${ARCH}.so",
+ "lib/${ARCH}/libqml_QtQuick.2_qtquick2plugin_${ARCH}.so",
+ "lib/${ARCH}/libqml_QtQuick_Window.2_windowplugin_${ARCH}.so",
+ "lib/${ARCH}/libQt5Core_${ARCH}.so",
+ "lib/${ARCH}/libQt5Gui_${ARCH}.so",
+ "lib/${ARCH}/libQt5Network_${ARCH}.so",
+ "lib/${ARCH}/libQt5Qml_${ARCH}.so",
+ "lib/${ARCH}/libQt5QuickParticles_${ARCH}.so",
+ "lib/${ARCH}/libQt5Quick_${ARCH}.so",
+ "lib/${ARCH}/libQt5QmlModels_${ARCH}.so",
+ "lib/${ARCH}/libQt5QmlWorkerScript_${ARCH}.so",
+ "lib/${ARCH}/libqmlapp_${ARCH}.so",
+ "res/layout/splash.xml"});
+ qmlAppMinistroExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, {
+ "resources.arsc",
+ "assets/android_rcc_bundle.rcc",
+ "lib/${ARCH}/libgdbserver.so",
+ cxxLibPath("libgnustl_shared.so", true),
+ "lib/${ARCH}/libqmlapp_${ARCH}.so",
+ "res/layout/splash.xml"});
+ qmlAppCustomMetaDataExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, {
+ "resources.arsc",
+ "assets/android_rcc_bundle.rcc",
+ "assets/dummyasset.txt",
+ "lib/${ARCH}/libgdbserver.so",
+ cxxLibPath("libgnustl_shared.so", true),
+ "lib/${ARCH}/libplugins_bearer_qandroidbearer_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qgif_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qicns_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qico_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qjpeg_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qtga_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qtiff_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qwbmp_${ARCH}.so",
+ "lib/${ARCH}/libplugins_imageformats_qwebp_${ARCH}.so",
+ "lib/${ARCH}/libplugins_platforms_qtforandroid_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_debugger_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_inspector_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_local_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_messages_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_native_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_nativedebugger_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_profiler_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_preview_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_quickprofiler_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_server_${ARCH}.so",
+ "lib/${ARCH}/libplugins_qmltooling_qmldbg_tcp_${ARCH}.so",
+ "lib/${ARCH}/libqml_QtQuick.2_qtquick2plugin_${ARCH}.so",
+ "lib/${ARCH}/libqml_QtQuick_Window.2_windowplugin_${ARCH}.so",
+ "lib/${ARCH}/libQt5Core_${ARCH}.so",
+ "lib/${ARCH}/libQt5Gui_${ARCH}.so",
+ "lib/${ARCH}/libQt5Network_${ARCH}.so",
+ "lib/${ARCH}/libQt5Qml_${ARCH}.so",
+ "lib/${ARCH}/libQt5QuickParticles_${ARCH}.so",
+ "lib/${ARCH}/libQt5Quick_${ARCH}.so",
+ "lib/${ARCH}/libQt5QmlModels_${ARCH}.so",
+ "lib/${ARCH}/libQt5QmlWorkerScript_${ARCH}.so",
+ "lib/${ARCH}/libqmlapp_${ARCH}.so",
+ "res/layout/splash.xml"});
+ qmlAppCustomProperties = QStringList{"modules.Android.sdk.automaticSources:false"};
+ }
+ QTest::newRow("qml app")
+ << "qml-app" << QStringList("qmlapp")
+ << (QList<QByteArrayList>() << qmlAppExpectedFiles)
+ << qmlAppCustomProperties;
+ QTest::newRow("qml app using Ministro")
+ << "qml-app" << QStringList("qmlapp")
+ << (QList<QByteArrayList>() << qmlAppMinistroExpectedFiles)
<< QStringList{"modules.Qt.android_support.useMinistro:true",
"modules.Android.sdk.automaticSources:false"};
QTest::newRow("qml app with custom metadata")
<< "qml-app" << QStringList("qmlapp")
- << (QList<QByteArrayList>() << commonFiles + expandArchs(ndkArchsForQt, {
- "resources.arsc",
- "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes",
- "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir",
- "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/plugins.qmltypes",
- "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/qmldir",
- "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list",
- "assets/dummyasset.txt",
- "lib/${ARCH}/libgdbserver.so",
- cxxLibPath("libgnustl_shared.so", true),
- "lib/${ARCH}/libplugins_bearer_libqandroidbearer.so",
- "lib/${ARCH}/libplugins_imageformats_libqgif.so",
- "lib/${ARCH}/libplugins_imageformats_libqicns.so",
- "lib/${ARCH}/libplugins_imageformats_libqico.so",
- "lib/${ARCH}/libplugins_imageformats_libqjpeg.so",
- "lib/${ARCH}/libplugins_imageformats_libqtga.so",
- "lib/${ARCH}/libplugins_imageformats_libqtiff.so",
- "lib/${ARCH}/libplugins_imageformats_libqwbmp.so",
- "lib/${ARCH}/libplugins_imageformats_libqwebp.so",
- "lib/${ARCH}/libplugins_platforms_android_libqtforandroid.so",
- "lib/${ARCH}/libplugins_qmltooling_libqmldbg_debugger.so",
- "lib/${ARCH}/libplugins_qmltooling_libqmldbg_inspector.so",
- "lib/${ARCH}/libplugins_qmltooling_libqmldbg_local.so",
- "lib/${ARCH}/libplugins_qmltooling_libqmldbg_messages.so",
- "lib/${ARCH}/libplugins_qmltooling_libqmldbg_native.so",
- "lib/${ARCH}/libplugins_qmltooling_libqmldbg_nativedebugger.so",
- "lib/${ARCH}/libplugins_qmltooling_libqmldbg_profiler.so",
- "lib/${ARCH}/libplugins_qmltooling_libqmldbg_preview.so",
- "lib/${ARCH}/libplugins_qmltooling_libqmldbg_quickprofiler.so",
- "lib/${ARCH}/libplugins_qmltooling_libqmldbg_server.so",
- "lib/${ARCH}/libplugins_qmltooling_libqmldbg_tcp.so",
- "lib/${ARCH}/libqml_QtQuick.2_libqtquick2plugin.so",
- "lib/${ARCH}/libqml_QtQuick_Window.2_libwindowplugin.so",
- "lib/${ARCH}/libQt5Core.so",
- "lib/${ARCH}/libQt5Gui.so",
- "lib/${ARCH}/libQt5Network.so",
- "lib/${ARCH}/libQt5Qml.so",
- "lib/${ARCH}/libQt5QuickParticles.so",
- "lib/${ARCH}/libQt5Quick.so",
- "lib/${ARCH}/libqmlapp.so",
- "res/layout/splash.xml"}))
- << QStringList("modules.Android.sdk.automaticSources:true");
+ << (QList<QByteArrayList>() << qmlAppCustomMetaDataExpectedFiles)
+ << QStringList("modules.Android.sdk.automaticSources:true");
QTest::newRow("no native")
<< "no-native"
<< QStringList("com.example.android.basicmediadecoder")
@@ -390,7 +513,7 @@ void TestBlackboxAndroid::android_data()
"lib/${ARCH}/liblib2.so",
cxxLibPath("libstlport_shared.so", false)}))
<< QStringList();
- QByteArrayList expectedFiles1 = (commonFiles
+ QByteArrayList expectedFiles1 = qbs::toList(qbs::toSet(commonFiles
+ expandArchs(QByteArrayList{"armeabi-v7a", "x86"}, {
"resources.arsc",
"lib/${ARCH}/libgdbserver.so",
@@ -400,7 +523,7 @@ void TestBlackboxAndroid::android_data()
"resources.arsc",
"lib/${ARCH}/libgdbserver.so",
"lib/${ARCH}/libp1lib2.so",
- cxxLibPath("libstlport_shared.so", false)})).toSet().toList();
+ cxxLibPath("libstlport_shared.so", false)})));
QByteArrayList expectedFiles2 = commonFiles + expandArchs(archs, {
"lib/${ARCH}/libgdbserver.so",
"lib/${ARCH}/libp2lib1.so",
diff --git a/tests/auto/blackbox/tst_blackboxapple.cpp b/tests/auto/blackbox/tst_blackboxapple.cpp
index cde742f3c..3623dc51b 100644
--- a/tests/auto/blackbox/tst_blackboxapple.cpp
+++ b/tests/auto/blackbox/tst_blackboxapple.cpp
@@ -60,6 +60,65 @@ static QString getEmbeddedBinaryPlist(const QString &file)
return QString::fromUtf8(p.readAllStandardOutput()).trimmed();
}
+static QVariantMap readInfoPlistFile(const QString &infoPlistPath)
+{
+ if (!QFile::exists(infoPlistPath)) {
+ qWarning() << infoPlistPath << "doesn't exist";
+ return {};
+ }
+
+ QProcess plutil;
+ plutil.start("plutil", {
+ QStringLiteral("-convert"),
+ QStringLiteral("json"),
+ infoPlistPath
+ });
+ if (!plutil.waitForStarted()) {
+ qWarning() << plutil.errorString();
+ return {};
+ }
+ if (!plutil.waitForFinished()) {
+ qWarning() << plutil.errorString();
+ return {};
+ }
+ if (plutil.exitCode() != 0) {
+ qWarning() << plutil.readAllStandardError().constData();
+ return {};
+ }
+
+ QFile infoPlist(infoPlistPath);
+ if (!infoPlist.open(QIODevice::ReadOnly)) {
+ qWarning() << infoPlist.errorString();
+ return {};
+ }
+ QJsonParseError error;
+ const auto json = QJsonDocument::fromJson(infoPlist.readAll(), &error);
+ if (error.error != QJsonParseError::NoError) {
+ qWarning() << error.errorString();
+ return {};
+ }
+ return json.object().toVariantMap();
+}
+
+static QString getInfoPlistPath(const QString &bundlePath)
+{
+ QFileInfo contents(bundlePath + "/Contents");
+ if (contents.exists() && contents.isDir())
+ return contents.filePath() + "/Info.plist"; // macOS bundle
+ return bundlePath + "/Info.plist";
+}
+
+static bool testVariantListType(const QVariant &variant, QMetaType::Type type)
+{
+ if (variant.userType() != QMetaType::QVariantList)
+ return false;
+ for (const auto &value : variant.toList()) {
+ if (value.userType() != type)
+ return false;
+ }
+ return true;
+}
+
TestBlackboxApple::TestBlackboxApple()
: TestBlackboxBase (SRCDIR "/testdata-apple", "blackbox-apple")
{
@@ -190,8 +249,11 @@ void TestBlackboxApple::appleMultiConfig()
void TestBlackboxApple::aggregateDependencyLinking()
{
- if (HostOsInfo::hostOsVersion() > qbs::Version(10, 13, 4))
- QSKIP("32-bit arch build is no longer supported on macOS versions higher than 10.13.4.");
+ // XCode 11 produces warning about deprecation of 32-bit apps, so skip the test
+ // for future XCode versions as well
+ const auto xcodeVersion = findXcodeVersion();
+ if (xcodeVersion >= qbs::Version(11))
+ QSKIP("32-bit arch build is no longer supported on macOS higher than 10.13.4.");
QDir::setCurrent(testDataDir + "/aggregateDependencyLinking");
QCOMPARE(runQbs(QStringList{"-p", "multi_arch_lib"}), 0);
@@ -623,47 +685,47 @@ void TestBlackboxApple::deploymentTarget_data()
}
QTest::newRow("macos x86_64") << "macosx" << macos << "x86_64"
<< "-triple x86_64-apple-macosx10.6"
- << "-macosx_version_min 10.6";
+ << "10.6";
if (xcodeVersion >= qbs::Version(6))
QTest::newRow("macos x86_64h") << "macosx" << macos << "x86_64h"
<< "-triple x86_64h-apple-macosx10.12"
- << "-macosx_version_min 10.12";
+ << "10.12";
QTest::newRow("ios armv7a") << "iphoneos" << ios << "armv7a"
<< "-triple thumbv7-apple-ios6.0"
- << "-iphoneos_version_min 6.0";
+ << "6.0";
QTest::newRow("ios armv7s") << "iphoneos" <<ios << "armv7s"
<< "-triple thumbv7s-apple-ios7.0"
- << "-iphoneos_version_min 7.0";
+ << "7.0";
if (xcodeVersion >= qbs::Version(5))
QTest::newRow("ios arm64") << "iphoneos" <<ios << "arm64"
<< "-triple arm64-apple-ios7.0"
- << "-iphoneos_version_min 7.0";
+ << "7.0";
QTest::newRow("ios-simulator x86") << "iphonesimulator" << ios_sim << "x86"
<< "-triple i386-apple-ios6.0"
- << "-ios_simulator_version_min 6.0";
+ << "6.0";
if (xcodeVersion >= qbs::Version(5))
QTest::newRow("ios-simulator x86_64") << "iphonesimulator" << ios_sim << "x86_64"
<< "-triple x86_64-apple-ios7.0"
- << "-ios_simulator_version_min 7.0";
+ << "7.0";
if (xcodeVersion >= qbs::Version(7)) {
if (xcodeVersion >= qbs::Version(7, 1)) {
QTest::newRow("tvos arm64") << "appletvos" << tvos << "arm64"
<< "-triple arm64-apple-tvos9.0"
- << "-tvos_version_min 9.0";
+ << "9.0";
QTest::newRow("tvos-simulator x86_64") << "appletvsimulator" << tvos_sim << "x86_64"
<< "-triple x86_64-apple-tvos9.0"
- << "-tvos_simulator_version_min 9.0";
+ << "9.0";
}
QTest::newRow("watchos armv7k") << "watchos" << watchos << "armv7k"
<< "-triple thumbv7k-apple-watchos2.0"
- << "-watchos_version_min 2.0";
+ << "2.0";
QTest::newRow("watchos-simulator x86") << "watchsimulator" << watchos_sim << "x86"
<< "-triple i386-apple-watchos2.0"
- << "-watchos_simulator_version_min 2.0";
+ << "2.0";
}
}
@@ -772,37 +834,35 @@ void TestBlackboxApple::infoPlist()
params.arguments = QStringList() << "-f" << "infoplist.qbs";
QCOMPARE(runQbs(params), 0);
- auto infoplistPath = relativeProductBuildDir("infoplist")
- + "/infoplist.app/Contents/Info.plist";
- if (!QFile::exists(infoplistPath))
- infoplistPath = relativeProductBuildDir("infoplist") + "/infoplist.app/Info.plist";
- QVERIFY(QFile::exists(infoplistPath));
- QProcess plutil;
- plutil.start("plutil", {
- QStringLiteral("-convert"),
- QStringLiteral("json"),
- infoplistPath
- });
- QVERIFY2(plutil.waitForStarted(), qPrintable(plutil.errorString()));
- QVERIFY2(plutil.waitForFinished(), qPrintable(plutil.errorString()));
- QVERIFY2(plutil.exitCode() == 0, qPrintable(plutil.readAllStandardError().constData()));
+ const auto infoPlistPath = getInfoPlistPath(
+ relativeProductBuildDir("infoplist") + "/infoplist.app");
+ QVERIFY(QFile::exists(infoPlistPath));
+ const auto content = readInfoPlistFile(infoPlistPath);
+ QVERIFY(!content.isEmpty());
- QFile infoplist(infoplistPath);
- QVERIFY(infoplist.open(QIODevice::ReadOnly));
- QJsonParseError error;
- const auto json = QJsonDocument::fromJson(infoplist.readAll(), &error);
- QCOMPARE(error.error, QJsonParseError::NoError);
- QVERIFY(json.isObject());
// common values
- QCOMPARE(json.object().value(QStringLiteral("CFBundleIdentifier")),
+ QCOMPARE(content.value(QStringLiteral("CFBundleIdentifier")),
QStringLiteral("org.example.infoplist"));
- QCOMPARE(json.object().value(QStringLiteral("CFBundleName")), QStringLiteral("infoplist"));
- QCOMPARE(json.object().value(QStringLiteral("CFBundleExecutable")),
+ QCOMPARE(content.value(QStringLiteral("CFBundleName")), QStringLiteral("infoplist"));
+ QCOMPARE(content.value(QStringLiteral("CFBundleExecutable")),
QStringLiteral("infoplist"));
- if (!json.object().contains(QStringLiteral("SDKROOT"))) { // macOS-specific values
- QCOMPARE(json.object().value("LSMinimumSystemVersion"), QStringLiteral("10.7"));
- QVERIFY(json.object().contains("NSPrincipalClass"));
+ if (!content.contains(QStringLiteral("SDKROOT"))) { // macOS-specific values
+ QCOMPARE(content.value("LSMinimumSystemVersion"), QStringLiteral("10.7"));
+ QCOMPARE(content.value("NSPrincipalClass"), QStringLiteral("NSApplication"));
+ } else {
+ // QBS-1447: UIDeviceFamily was set to a string instead of an array
+ const auto family = content.value(QStringLiteral("UIDeviceFamily"));
+ if (family.isValid()) {
+ // int gets converted to a double when exporting plist as JSON
+ QVERIFY(testVariantListType(family, QMetaType::Double));
+ }
+ const auto caps = content.value(QStringLiteral("UIRequiredDeviceCapabilities"));
+ if (caps.isValid())
+ QVERIFY(testVariantListType(caps, QMetaType::QString));
+ const auto orientations = content.value(QStringLiteral("UIRequiredDeviceCapabilities"));
+ if (orientations.isValid())
+ QVERIFY(testVariantListType(orientations, QMetaType::QString));
}
}
@@ -813,6 +873,31 @@ void TestBlackboxApple::objcArc()
QCOMPARE(runQbs(), 0);
}
+void TestBlackboxApple::overrideInfoPlist()
+{
+ QDir::setCurrent(testDataDir + "/overrideInfoPlist");
+
+ QCOMPARE(runQbs(), 0);
+
+ const auto infoPlistPath = getInfoPlistPath(
+ relativeProductBuildDir("overrideInfoPlist") + "/overrideInfoPlist.app");
+ QVERIFY(QFile::exists(infoPlistPath));
+ const auto content = readInfoPlistFile(infoPlistPath);
+ QVERIFY(!content.isEmpty());
+
+ // test we do not override custom values by default
+ QCOMPARE(content.value(QStringLiteral("DefaultValue")),
+ QStringLiteral("The default value"));
+ // test we can override custom values
+ QCOMPARE(content.value(QStringLiteral("OverriddenValue")),
+ QStringLiteral("The overridden value"));
+ // test we do not override special values set by Qbs by default
+ QCOMPARE(content.value(QStringLiteral("CFBundleExecutable")),
+ QStringLiteral("overrideInfoPlist"));
+ // test we can override special values set by Qbs
+ QCOMPARE(content.value(QStringLiteral("CFBundleName")), QStringLiteral("My Bundle"));
+}
+
void TestBlackboxApple::xcode()
{
QProcess xcodeSelect;
diff --git a/tests/auto/blackbox/tst_blackboxapple.h b/tests/auto/blackbox/tst_blackboxapple.h
index 76711ddf5..be2e5c5b5 100644
--- a/tests/auto/blackbox/tst_blackboxapple.h
+++ b/tests/auto/blackbox/tst_blackboxapple.h
@@ -63,6 +63,7 @@ private slots:
void iconsetApp();
void infoPlist();
void objcArc();
+ void overrideInfoPlist();
void xcode();
private:
diff --git a/tests/auto/blackbox/tst_blackboxbase.cpp b/tests/auto/blackbox/tst_blackboxbase.cpp
index 61b0271f6..90afaabfc 100644
--- a/tests/auto/blackbox/tst_blackboxbase.cpp
+++ b/tests/auto/blackbox/tst_blackboxbase.cpp
@@ -64,7 +64,7 @@ static bool supportsSettingsDirOption(const QString &command) {
TestBlackboxBase::TestBlackboxBase(const QString &testDataSrcDir, const QString &testName)
: testDataDir(testWorkDir(testName)),
- testSourceDir(QDir::cleanPath(testDataSrcDir)),
+ testSourceDir(testDataSourceDir(testDataSrcDir)),
qbsExecutableFilePath(initQbsExecutableFilePath()),
defaultInstallRoot(relativeBuildDir() + QLatin1Char('/') + InstallOptions::defaultInstallRoot())
{
@@ -232,3 +232,21 @@ QMap<QString, QString> TestBlackboxBase::findJdkTools(int *status)
{"jar", QDir::fromNativeSeparators(tools["jar"].toString())}
};
}
+
+qbs::Version TestBlackboxBase::qmakeVersion(const QString &qmakeFilePath)
+{
+ QStringList arguments;
+ arguments << "-query" << "QT_VERSION";
+ QProcess qmakeProcess;
+ qmakeProcess.start(qmakeFilePath, arguments);
+ if (!qmakeProcess.waitForStarted() || !qmakeProcess.waitForFinished()
+ || qmakeProcess.exitStatus() != QProcess::NormalExit) {
+ qDebug() << "qmake '" << qmakeFilePath << "' could not be run.";
+ return qbs::Version();
+ }
+ QByteArray result = qmakeProcess.readAll().simplified();
+ qbs::Version version = qbs::Version::fromString(result);
+ if (!version.isValid())
+ qDebug() << "qmake '" << qmakeFilePath << "' version is not valid.";
+ return version;
+}
diff --git a/tests/auto/blackbox/tst_blackboxbase.h b/tests/auto/blackbox/tst_blackboxbase.h
index 251f3752d..518cc80d0 100644
--- a/tests/auto/blackbox/tst_blackboxbase.h
+++ b/tests/auto/blackbox/tst_blackboxbase.h
@@ -42,14 +42,14 @@ public:
init();
}
- QbsRunParameters(const QString &cmd, const QStringList &args = QStringList())
- : command(cmd), arguments(args)
+ QbsRunParameters(QString cmd, QStringList args = QStringList())
+ : command(std::move(cmd)), arguments(std::move(args))
{
init();
}
- QbsRunParameters(const QStringList &args)
- : arguments(args)
+ QbsRunParameters(QStringList args)
+ : arguments(std::move(args))
{
init();
}
@@ -92,6 +92,7 @@ protected:
static void ccp(const QString &sourceDirPath, const QString &targetDirPath);
static QString findExecutable(const QStringList &fileNames);
QMap<QString, QString> findJdkTools(int *status);
+ static qbs::Version qmakeVersion(const QString &qmakeFilePath);
const QString testDataDir;
const QString testSourceDir;
diff --git a/tests/auto/blackbox/tst_blackboxjava.cpp b/tests/auto/blackbox/tst_blackboxjava.cpp
index f7feb0612..a815a84ff 100644
--- a/tests/auto/blackbox/tst_blackboxjava.cpp
+++ b/tests/auto/blackbox/tst_blackboxjava.cpp
@@ -119,7 +119,7 @@ void TestBlackboxJava::java()
if (process.waitForStarted()) {
QVERIFY2(process.waitForFinished(), qPrintable(process.errorString()));
const QByteArray stdOut = process.readAllStandardOutput();
- QVERIFY2(stdOut.contains("Class-Path: car_jar.jar random_stuff.jar"), stdOut.constData());
+ QVERIFY2(stdOut.contains("Class-Path: random_stuff.jar car_jar.jar"), stdOut.constData());
QVERIFY2(stdOut.contains("Main-Class: Vehicles"), stdOut.constData());
QVERIFY2(stdOut.contains("Some-Property: Some-Value"), stdOut.constData());
QVERIFY2(stdOut.contains("Additional-Property: Additional-Value"), stdOut.constData());
@@ -184,6 +184,7 @@ void TestBlackboxJava::javaDependencyTracking_data()
"/usr/lib/jvm/java-" + minorVersion + "-openjdk" + dpkgArch("-"), // Debian
"/usr/lib/jvm/java-" + minorVersion + "-openjdk", // Arch
"/usr/lib/jvm/jre-1." + minorVersion + ".0-openjdk", // Fedora
+ "/usr/lib64/jvm/java-1." + minorVersion + ".0-openjdk", // OpenSuSE
};
for (const QString &searchPath : searchPaths) {
if (QFile::exists(searchPath + "/bin/javac"))
diff --git a/tests/auto/blackbox/tst_blackboxqt.cpp b/tests/auto/blackbox/tst_blackboxqt.cpp
index 035af959c..595a173a2 100644
--- a/tests/auto/blackbox/tst_blackboxqt.cpp
+++ b/tests/auto/blackbox/tst_blackboxqt.cpp
@@ -121,7 +121,7 @@ void TestBlackboxQt::combinedMoc()
void TestBlackboxQt::createProject()
{
QDir::setCurrent(testDataDir + "/create-project");
- QVERIFY(QFile::copy(SRCDIR "/../../../examples/helloworld-qt/main.cpp",
+ QVERIFY(QFile::copy(testSourceDir + "/../../../../examples/helloworld-qt/main.cpp",
QDir::currentPath() + "/main.cpp"));
QbsRunParameters createParams("create-project");
createParams.profile.clear();
@@ -210,12 +210,48 @@ void TestBlackboxQt::lrelease()
QVERIFY(!regularFileExists(relativeProductBuildDir("lrelease-test") + "/hu.qm"));
}
+void TestBlackboxQt::metaTypes_data()
+{
+ QTest::addColumn<bool>("generate");
+ QTest::addColumn<QString>("installDir");
+ QTest::newRow("don't generate") << false << QString();
+ QTest::newRow("don't generate with install info") << false << QString("blubb");
+ QTest::newRow("generate only") << true << QString();
+ QTest::newRow("generate and install") << true << QString("blubb");
+}
+
+void TestBlackboxQt::metaTypes()
+{
+ QDir::setCurrent(testDataDir + "/metatypes");
+ QFETCH(bool, generate);
+ QFETCH(QString, installDir);
+ const QStringList args{"modules.Qt.core.generateMetaTypesFile:"
+ + QString(generate ? "true" : "false"),
+ "modules.Qt.core.metaTypesInstallDir:" + installDir,
+ "-v", "--force-probe-execution"};
+ QCOMPARE(runQbs(QbsRunParameters("resolve", args)), 0);
+ const bool canGenerate = m_qbsStdout.contains("can generate");
+ const bool cannotGenerate = m_qbsStdout.contains("cannot generate");
+ QVERIFY(canGenerate != cannotGenerate);
+ const bool expectFiles = generate && canGenerate;
+ const bool expectInstalledFiles = expectFiles && !installDir.isEmpty();
+ QCOMPARE(runQbs(QStringList("--clean-install-root")), 0);
+ const QString productDir = relativeProductBuildDir("mylib");
+ const QString outputDir = productDir + "/qt.headers";
+ QVERIFY(!regularFileExists(outputDir + "/moc_unmocableclass.cpp.json"));
+ QCOMPARE(regularFileExists(outputDir + "/moc_mocableclass1.cpp.json"), expectFiles);
+ QCOMPARE(regularFileExists(outputDir + "/mocableclass2.moc.json"), expectFiles);
+ QCOMPARE(regularFileExists(productDir + "/mylib_metatypes.json"), expectFiles);
+ QCOMPARE(regularFileExists(relativeBuildDir() + "/install-root/some-prefix/" + installDir
+ + "/mylib_metatypes.json"), expectInstalledFiles);
+}
+
void TestBlackboxQt::mixedBuildVariants()
{
QDir::setCurrent(testDataDir + "/mixed-build-variants");
const SettingsPtr s = settings();
Profile profile(profileName(), s.get());
- if (profile.value("qbs.toolchain").toStringList().contains("msvc")) {
+ if (profileToolchain(profile).contains("msvc")) {
QbsRunParameters params;
params.arguments << "qbs.buildVariant:debug";
params.expectFailure = true;
@@ -339,7 +375,7 @@ void TestBlackboxQt::qmlDebugging()
QCOMPARE(runQbs(), 0);
const SettingsPtr s = settings();
Profile profile(profileName(), s.get());
- if (!profile.value("qbs.toolchain").toStringList().contains("gcc"))
+ if (!profileToolchain(profile).contains("gcc"))
return;
QProcess nm;
nm.start("nm", QStringList(relativeExecutableFilePath("debuggable-app")));
@@ -360,6 +396,40 @@ void TestBlackboxQt::qobjectInObjectiveCpp()
QCOMPARE(runQbs(), 0);
}
+void TestBlackboxQt::qmlTypeRegistrar_data()
+{
+ QTest::addColumn<QString>("importName");
+ QTest::addColumn<QString>("installDir");
+ QTest::newRow("don't generate") << QString() << QString();
+ QTest::newRow("don't generate with install info") << QString() << QString("blubb");
+ QTest::newRow("generate only") << QString("People") << QString();
+ QTest::newRow("generate and install") << QString("People") << QString("blubb");
+}
+
+void TestBlackboxQt::qmlTypeRegistrar()
+{
+ QDir::setCurrent(testDataDir + "/qmltyperegistrar");
+ QFETCH(QString, importName);
+ QFETCH(QString, installDir);
+ rmDirR(relativeBuildDir());
+ const QStringList args{"modules.Qt.qml.importName:" + importName,
+ "modules.Qt.qml.typesInstallDir:" + installDir};
+ QCOMPARE(runQbs(QbsRunParameters("resolve", args)), 0);
+ const bool hasRegistrar = m_qbsStdout.contains("has registrar");
+ const bool doesNotHaveRegistrar = m_qbsStdout.contains("does not have registrar");
+ QVERIFY(hasRegistrar != doesNotHaveRegistrar);
+ if (doesNotHaveRegistrar)
+ QSKIP("Qt version too old");
+ QCOMPARE(runQbs(), 0);
+ const bool enabled = !importName.isEmpty();
+ QCOMPARE(m_qbsStdout.contains("running qmltyperegistrar"), enabled);
+ QCOMPARE(m_qbsStdout.contains("compiling myapp_qmltyperegistrations.cpp"), enabled);
+ const QString buildDir = relativeProductBuildDir("myapp");
+ QCOMPARE(regularFileExists(buildDir + "/myapp.qmltypes"), enabled);
+ QCOMPARE(regularFileExists(relativeBuildDir() + "/install-root/" + installDir
+ + "/myapp.qmltypes"), enabled && !installDir.isEmpty());
+}
+
void TestBlackboxQt::qtKeywords()
{
QDir::setCurrent(testDataDir + "/qt-keywords");
diff --git a/tests/auto/blackbox/tst_blackboxqt.h b/tests/auto/blackbox/tst_blackboxqt.h
index 180f9e0c0..4008b14ca 100644
--- a/tests/auto/blackbox/tst_blackboxqt.h
+++ b/tests/auto/blackbox/tst_blackboxqt.h
@@ -53,6 +53,8 @@ private slots:
void includedMocCpp();
void linkerVariant();
void lrelease();
+ void metaTypes_data();
+ void metaTypes();
void mixedBuildVariants();
void mocAndCppCombining();
void mocFlags();
@@ -63,6 +65,8 @@ private slots:
void pluginSupport();
void qmlDebugging();
void qobjectInObjectiveCpp();
+ void qmlTypeRegistrar_data();
+ void qmlTypeRegistrar();
void qtKeywords();
void quickCompiler();
void qtScxml();
diff --git a/tests/auto/blackbox/tst_clangdb.cpp b/tests/auto/blackbox/tst_clangdb.cpp
index 3a6dd2d92..65e562484 100644
--- a/tests/auto/blackbox/tst_clangdb.cpp
+++ b/tests/auto/blackbox/tst_clangdb.cpp
@@ -202,9 +202,9 @@ void TestClangDb::checkClangDetectsSourceCodeProblems()
// clang-check.exe does not understand MSVC command-line syntax
const SettingsPtr s = settings();
qbs::Profile profile(profileName(), s.get());
- if (profile.value("qbs.toolchain").toStringList().contains("msvc")) {
+ if (profileToolchain(profile).contains("msvc")) {
arguments << "-extra-arg-before=--driver-mode=cl";
- } else if (profile.value("qbs.toolchain").toStringList().contains("mingw")) {
+ } else if (profileToolchain(profile).contains("mingw")) {
arguments << "-extra-arg-before=--driver-mode=g++";
}
diff --git a/tests/auto/buildgraph/tst_buildgraph.cpp b/tests/auto/buildgraph/tst_buildgraph.cpp
index 95314ad20..20f2cc6a5 100644
--- a/tests/auto/buildgraph/tst_buildgraph.cpp
+++ b/tests/auto/buildgraph/tst_buildgraph.cpp
@@ -51,6 +51,8 @@
#include <QtTest/qtest.h>
+#include <memory>
+
using namespace qbs;
using namespace qbs::Internal;
@@ -58,7 +60,7 @@ const TopLevelProjectPtr project = TopLevelProject::create();
TestBuildGraph::TestBuildGraph(ILogSink *logSink) : m_logSink(logSink)
{
- project->buildData.reset(new ProjectBuildData);
+ project->buildData = std::make_unique<ProjectBuildData>();
}
void TestBuildGraph::initTestCase()
@@ -84,7 +86,7 @@ ResolvedProductConstPtr TestBuildGraph::productWithDirectCycle()
{
const ResolvedProductPtr product = ResolvedProduct::create();
product->project = project;
- product->buildData.reset(new ProductBuildData);
+ product->buildData = std::make_unique<ProductBuildData>();
const auto root = new Artifact;
root->product = product;
const auto child = new Artifact;
@@ -101,7 +103,7 @@ ResolvedProductConstPtr TestBuildGraph::productWithLessDirectCycle()
{
const ResolvedProductPtr product = ResolvedProduct::create();
product->project = project;
- product->buildData.reset(new ProductBuildData);
+ product->buildData = std::make_unique<ProductBuildData>();
const auto root = new Artifact;
const auto child = new Artifact;
const auto grandchild = new Artifact;
@@ -123,7 +125,7 @@ ResolvedProductConstPtr TestBuildGraph::productWithNoCycle()
{
const ResolvedProductPtr product = ResolvedProduct::create();
product->project = project;
- product->buildData.reset(new ProductBuildData);
+ product->buildData = std::make_unique<ProductBuildData>();
const auto root = new Artifact;
const auto root2 = new Artifact;
root->product = product;
diff --git a/tests/auto/language/testdata/erroneous/ambiguous-multiplex-dependency.qbs b/tests/auto/language/testdata/erroneous/ambiguous-multiplex-dependency.qbs
new file mode 100644
index 000000000..6f60b1faf
--- /dev/null
+++ b/tests/auto/language/testdata/erroneous/ambiguous-multiplex-dependency.qbs
@@ -0,0 +1,14 @@
+Project {
+ Product {
+ name: "a"
+ multiplexByQbsProperties: ["architectures", "buildVariants"]
+ qbs.architectures: ["x86", "arm"]
+ qbs.buildVariants: ["debug", "release"]
+ }
+ Product {
+ name: "b"
+ Depends { name: "a" }
+ multiplexByQbsProperties: ["architectures"]
+ qbs.architectures: ["x86", "arm"]
+ }
+}
diff --git a/tests/auto/language/testdata/erroneous/dependency-profile-mismatch-2.qbs b/tests/auto/language/testdata/erroneous/dependency-profile-mismatch-2.qbs
new file mode 100644
index 000000000..d76907a35
--- /dev/null
+++ b/tests/auto/language/testdata/erroneous/dependency-profile-mismatch-2.qbs
@@ -0,0 +1,17 @@
+Project {
+ Profile {
+ name: "profile1"
+ }
+ Profile {
+ name: "profile2"
+ }
+
+ Product {
+ name: "dep"
+ qbs.profiles: ["profile1", "profile2"]
+ }
+ Product {
+ name: "main"
+ Depends { name: "dep"; profiles: ["profile47"]; }
+ }
+}
diff --git a/tests/auto/language/testdata/erroneous/dependency-profile-mismatch.qbs b/tests/auto/language/testdata/erroneous/dependency-profile-mismatch.qbs
new file mode 100644
index 000000000..e014fa9b1
--- /dev/null
+++ b/tests/auto/language/testdata/erroneous/dependency-profile-mismatch.qbs
@@ -0,0 +1,14 @@
+Project {
+ Profile {
+ name: "profile1"
+ }
+
+ Product {
+ name: "dep"
+ qbs.profiles: ["profile1"]
+ }
+ Product {
+ name: "main"
+ Depends { name: "dep"; profiles: ["profile47"]; }
+ }
+}
diff --git a/tests/auto/language/tst_language.cpp b/tests/auto/language/tst_language.cpp
index 31aebfa3a..25e549d18 100644
--- a/tests/auto/language/tst_language.cpp
+++ b/tests/auto/language/tst_language.cpp
@@ -79,8 +79,7 @@ using namespace qbs;
using namespace qbs::Internal;
static QString testDataDir() {
- return FileInfo::resolvePath(QStringLiteral(SRCDIR),
- QStringLiteral("../../../tests/auto/language/testdata"));
+ return testDataSourceDir(SRCDIR "/testdata");
}
static QString testProject(const char *fileName) {
return testDataDir() + QLatin1Char('/') + QLatin1String(fileName);
@@ -180,7 +179,7 @@ void TestLanguage::initTestCase()
m_engine = ScriptEngine::create(m_logger, EvalContext::PropertyEvaluation, this);
loader = new Loader(m_engine, m_logger);
loader->setSearchPaths(QStringList()
- << QStringLiteral(SRCDIR "/../../../share/qbs"));
+ << (testDataDir() + "/../../../../share/qbs"));
defaultParameters.setTopLevelProfile(profileName());
defaultParameters.setConfigurationName("default");
defaultParameters.expandBuildConfiguration();
@@ -925,9 +924,20 @@ void TestLanguage::erroneousFiles_data()
<< "original-in-export-item3.qbs:6:9.*Item 'x.y' is not declared. Did you forget "
"to add a Depends item";
QTest::newRow("mismatching-multiplex-dependency")
- << "mismatching-multiplex-dependency.qbs:7:5.*Dependency from product "
- "'b \\{\"architecture\":\"mips\"\\}' to product 'a \\{\"architecture\":\"mips\"\\}'"
- " not fulfilled.";
+ << "mismatching-multiplex-dependency.qbs:9:9.*Dependency from product "
+ "'b \\{\"architecture\":\"mips\"\\}' to product 'a'"
+ " not fulfilled. There are no eligible multiplex candidates.";
+ QTest::newRow("ambiguous-multiplex-dependency")
+ << "ambiguous-multiplex-dependency.qbs:10:9.*Dependency from product 'b "
+ "\\{\"architecture\":\"x86\"\\}' to product 'a' is ambiguous. Eligible multiplex "
+ "candidates: a \\{\"architecture\":\"x86\",\"buildVariant\":\"debug\"\\}, "
+ "a \\{\"architecture\":\"x86\",\"buildVariant\":\"release\"\\}.";
+ QTest::newRow("dependency-profile-mismatch")
+ << "dependency-profile-mismatch.qbs:10:5.*Product 'main' depends on 'dep', "
+ "which does not exist for the requested profile 'profile47'.";
+ QTest::newRow("dependency-profile-mismatch-2")
+ << "dependency-profile-mismatch-2.qbs:15:9 Dependency from product 'main' to "
+ "product 'dep' not fulfilled. There are no eligible multiplex candidates.";
QTest::newRow("duplicate-multiplex-value")
<< "duplicate-multiplex-value.qbs:3:1.*Duplicate entry 'x86' in qbs.architectures.";
QTest::newRow("duplicate-multiplex-value2")
@@ -1051,7 +1061,7 @@ void TestLanguage::exports()
propertyName = QStringList() << "dummy" << "defines";
propertyValue = product->moduleProperties->property(propertyName);
QCOMPARE(propertyValue.toStringList(),
- QStringList() << "LIBA" << "LIBB" << "LIBC" << "LIBD");
+ QStringList() << "LIBD" << "LIBC" << "LIBA" << "LIBB");
propertyName = QStringList() << "dummy" << "productName";
propertyValue = product->moduleProperties->property(propertyName);
QCOMPARE(propertyValue.toString(), QString("libE"));
@@ -1730,10 +1740,10 @@ void TestLanguage::moduleProperties_data()
QTest::newRow("init") << QString() << QVariant();
QTest::newRow("merge_lists")
<< "defines"
- << QVariant(QStringList() << "THE_PRODUCT" << "QT_CORE" << "QT_GUI" << "QT_NETWORK");
+ << QVariant(QStringList() << "THE_PRODUCT" << "QT_NETWORK" << "QT_GUI" << "QT_CORE");
QTest::newRow("merge_lists_and_values")
<< "defines"
- << QVariant(QStringList() << "THE_PRODUCT" << "QT_CORE" << "QT_GUI" << "QT_NETWORK");
+ << QVariant(QStringList() << "THE_PRODUCT" << "QT_NETWORK" << "QT_GUI" << "QT_CORE");
QTest::newRow("merge_lists_with_duplicates")
<< "cxxFlags"
<< QVariant(QStringList() << "-foo" << "BAR" << "-foo" << "BAZ");
@@ -2469,7 +2479,7 @@ void TestLanguage::projectFileLookup_data()
QTest::addColumn<QString>("projectFileOutput");
QTest::addColumn<bool>("failureExpected");
- const QString baseDir = QLatin1String(SRCDIR) + "/testdata";
+ const QString baseDir = testDataDir();
const QString multiProjectsDir = baseDir + "/dirwithmultipleprojects";
const QString noProjectsDir = baseDir + "/dirwithnoprojects";
const QString oneProjectDir = baseDir + "/dirwithoneproject";
@@ -3182,6 +3192,7 @@ void TestLanguage::wildcards()
QFile projectFile(projectFilePath);
QVERIFY(projectFile.open(QIODevice::WriteOnly));
QTextStream s(&projectFile);
+ using Qt::endl;
s << "import qbs.base 1.0" << endl << endl
<< "Application {" << endl
<< " name: \"MyProduct\"" << endl;
diff --git a/tests/auto/shared.h b/tests/auto/shared.h
index 8f85f5d6c..beda8fff3 100644
--- a/tests/auto/shared.h
+++ b/tests/auto/shared.h
@@ -31,6 +31,7 @@
#include <tools/hostosinfo.h>
#include <tools/profile.h>
#include <tools/settings.h>
+#include <tools/toolchains.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qcryptographichash.h>
@@ -46,6 +47,8 @@
#include <memory>
+
+
#define REPLACE_IN_FILE(filePath, oldContent, newContent) \
do { \
QFile f((filePath)); \
@@ -83,7 +86,7 @@ using SettingsPtr = std::unique_ptr<qbs::Settings>;
inline SettingsPtr settings()
{
const QString settingsDir = QLatin1String(qgetenv("QBS_AUTOTEST_SETTINGS_DIR"));
- return SettingsPtr(new qbs::Settings(settingsDir));
+ return std::make_unique<qbs::Settings>(settingsDir);
}
inline QString profileName()
@@ -268,14 +271,22 @@ inline void copyFileAndUpdateTimestamp(const QString &source, const QString &tar
touch(target);
}
+inline QStringList profileToolchain(const qbs::Profile &profile)
+{
+ const auto toolchainType = profile.value(QStringLiteral("qbs.toolchainType")).toString();
+ if (!toolchainType.isEmpty())
+ return qbs::canonicalToolchain(toolchainType);
+ return profile.value(QStringLiteral("qbs.toolchain")).toStringList();
+}
+
inline QString objectFileName(const QString &baseName, const QString &profileName)
{
const SettingsPtr s = settings();
qbs::Profile profile(profileName, s.get());
- const auto tc = profile.value("qbs.toolchainType").toString();
- const auto tcList = profile.value("qbs.toolchain").toStringList();
- const bool isMsvc = tc == "msvc" || tcList.contains("msvc")
- || (tc.isEmpty() && tcList.isEmpty() && qbs::Internal::HostOsInfo::isWindowsHost());
+
+ const auto tcList = profileToolchain(profile);
+ const bool isMsvc = tcList.contains("msvc")
+ || (tcList.isEmpty() && qbs::Internal::HostOsInfo::isWindowsHost());
const QString suffix = isMsvc ? "obj" : "o";
return baseName + '.' + suffix;
}
@@ -285,6 +296,30 @@ inline QString inputDirHash(const QString &dir)
return QCryptographicHash::hash(dir.toLatin1(), QCryptographicHash::Sha1).toHex().left(16);
}
+inline QString testDataSourceDir(const QString &dir)
+{
+ QDir result;
+ QString testSourceRootDirFromEnv = QDir::fromNativeSeparators(qEnvironmentVariable("QBS_TEST_SOURCE_ROOT"));
+ if (testSourceRootDirFromEnv.isEmpty()) {
+ result.setPath(dir);
+ } else {
+ QDir testSourceRootDir(dir);
+ while (testSourceRootDir.dirName() != "tests")
+ testSourceRootDir = QFileInfo(testSourceRootDir, "").dir();
+
+ QString relativeDataPath = testSourceRootDir.relativeFilePath(dir);
+ QString absoluteDataPath = QDir(testSourceRootDirFromEnv).absoluteFilePath(relativeDataPath);
+ result.setPath(absoluteDataPath);
+ }
+
+ if (!result.exists())
+ qFatal("Expected data folder '%s' to be present, but it does not exist. You may set "
+ "QBS_TEST_SOURCE_ROOT to the 'tests' folder in your qbs repository to configure "
+ "a custom location.", qPrintable(result.absolutePath()));
+
+ return result.absolutePath();
+}
+
inline QString testWorkDir(const QString &testName)
{
QString dir = QDir::fromNativeSeparators(QString::fromLocal8Bit(qgetenv("QBS_TEST_WORK_ROOT")));
diff --git a/tests/benchmarker/benchmarker.cpp b/tests/benchmarker/benchmarker.cpp
index 5ecdbf08b..2cc442a72 100644
--- a/tests/benchmarker/benchmarker.cpp
+++ b/tests/benchmarker/benchmarker.cpp
@@ -34,16 +34,17 @@
#include <QtConcurrent/qtconcurrentrun.h>
#include <iostream>
+#include <utility>
namespace qbsBenchmarker {
-Benchmarker::Benchmarker(Activities activities, const QString &oldCommit, const QString &newCommit,
- const QString &testProject, const QString &qbsRepo)
+Benchmarker::Benchmarker(Activities activities, QString oldCommit, QString newCommit,
+ QString testProject, QString qbsRepo)
: m_activities(activities)
- , m_oldCommit(oldCommit)
- , m_newCommit(newCommit)
- , m_testProject(testProject)
- , m_qbsRepo(qbsRepo)
+ , m_oldCommit(std::move(oldCommit))
+ , m_newCommit(std::move(newCommit))
+ , m_testProject(std::move(testProject))
+ , m_qbsRepo(std::move(qbsRepo))
{
}
diff --git a/tests/benchmarker/benchmarker.h b/tests/benchmarker/benchmarker.h
index 9b6d5a157..6313e8094 100644
--- a/tests/benchmarker/benchmarker.h
+++ b/tests/benchmarker/benchmarker.h
@@ -53,8 +53,8 @@ using BenchmarkResults = QHash<Activity, BenchmarkResult>;
class Benchmarker
{
public:
- Benchmarker(Activities activities, const QString &oldCommit, const QString &newCommit,
- const QString &testProject, const QString &qbsRepo);
+ Benchmarker(Activities activities, QString oldCommit, QString newCommit,
+ QString testProject, QString qbsRepo);
~Benchmarker();
void benchmark();
diff --git a/tests/benchmarker/commandlineparser.cpp b/tests/benchmarker/commandlineparser.cpp
index 4e5052453..9b08bd60d 100644
--- a/tests/benchmarker/commandlineparser.cpp
+++ b/tests/benchmarker/commandlineparser.cpp
@@ -41,9 +41,7 @@ static QString ruleExecutionActivity() { return "rule-execution"; }
static QString nullBuildActivity() { return "null-build"; }
static QString allActivities() { return "all"; }
-CommandLineParser::CommandLineParser()
-{
-}
+CommandLineParser::CommandLineParser() = default;
void CommandLineParser::parse()
{
@@ -84,6 +82,10 @@ void CommandLineParser::parse()
}
m_oldCommit = parser.value(oldCommitOption);
m_newCommit = parser.value(newCommitOption);
+ if (m_oldCommit == m_newCommit) {
+ throw Exception(QStringLiteral("Error parsing command line: "
+ "'new commit' and 'old commit' must be different commits.\n%1").arg(parser.helpText()));
+ }
m_testProjectFilePath = parser.value(testProjectOption);
m_qbsRepoDirPath = parser.value(qbsRepoOption);
const QStringList activitiesList = parser.value(activitiesOption).split(',');
diff --git a/tests/benchmarker/exception.h b/tests/benchmarker/exception.h
index b4df36974..9fab479ea 100644
--- a/tests/benchmarker/exception.h
+++ b/tests/benchmarker/exception.h
@@ -35,8 +35,8 @@ namespace qbsBenchmarker {
class Exception : public QException {
public:
- explicit Exception(const QString &description) : m_description(description) {}
- ~Exception() throw() override { }
+ explicit Exception(QString description) : m_description(std::move(description)) {}
+ ~Exception() throw() override = default;
QString description() const { return m_description; }
diff --git a/tests/benchmarker/valgrindrunner.cpp b/tests/benchmarker/valgrindrunner.cpp
index 344a23516..174781318 100644
--- a/tests/benchmarker/valgrindrunner.cpp
+++ b/tests/benchmarker/valgrindrunner.cpp
@@ -44,10 +44,10 @@
namespace qbsBenchmarker {
-ValgrindRunner::ValgrindRunner(Activities activities, const QString &testProject,
+ValgrindRunner::ValgrindRunner(Activities activities, QString testProject,
const QString &qbsBuildDir, const QString &baseOutputDir)
: m_activities(activities)
- , m_testProject(testProject)
+ , m_testProject(std::move(testProject))
, m_qbsBinary(qbsBuildDir + "/bin/qbs")
, m_baseOutputDir(baseOutputDir)
{
diff --git a/tests/benchmarker/valgrindrunner.h b/tests/benchmarker/valgrindrunner.h
index 3ec82a6a2..378723868 100644
--- a/tests/benchmarker/valgrindrunner.h
+++ b/tests/benchmarker/valgrindrunner.h
@@ -55,7 +55,7 @@ public:
class ValgrindRunner
{
public:
- ValgrindRunner(Activities activities, const QString &testProject, const QString &qbsBuildDir,
+ ValgrindRunner(Activities activities, QString testProject, const QString &qbsBuildDir,
const QString &baseOutputDir);
void run();
diff --git a/tests/fuzzy-test/commandlineparser.cpp b/tests/fuzzy-test/commandlineparser.cpp
index 18515604b..23be7b0ad 100644
--- a/tests/fuzzy-test/commandlineparser.cpp
+++ b/tests/fuzzy-test/commandlineparser.cpp
@@ -37,9 +37,7 @@ static QString maxDurationoption() { return "--max-duration"; }
static QString jobCountOption() { return "--jobs"; }
static QString logOption() { return "--log"; }
-CommandLineParser::CommandLineParser()
-{
-}
+CommandLineParser::CommandLineParser() = default;
void CommandLineParser::parse(const QStringList &commandLine)
{
diff --git a/tests/fuzzy-test/commandlineparser.h b/tests/fuzzy-test/commandlineparser.h
index a000a515d..76b49331b 100644
--- a/tests/fuzzy-test/commandlineparser.h
+++ b/tests/fuzzy-test/commandlineparser.h
@@ -35,8 +35,8 @@
class ParseException : public std::exception
{
public:
- ParseException(const QString &error) : errorMessage(error) { }
- ~ParseException() throw() override {}
+ ParseException(QString error) : errorMessage(std::move(error)) { }
+ ~ParseException() throw() override = default;
QString errorMessage;
diff --git a/tests/fuzzy-test/fuzzytester.cpp b/tests/fuzzy-test/fuzzytester.cpp
index b836ee623..045e46718 100644
--- a/tests/fuzzy-test/fuzzytester.cpp
+++ b/tests/fuzzy-test/fuzzytester.cpp
@@ -36,6 +36,7 @@
#include <algorithm>
#include <cstdlib>
#include <ctime>
+#include <random>
static QString resolveIncrementalActivity() { return "resolve-incremental"; }
static QString buildIncrementalActivity() { return "build-incremental"; }
@@ -71,7 +72,7 @@ void FuzzyTester::runTest(const QString &profile, const QString &startCommit,
// Shuffle the initial sequence. Otherwise all invocations of the tool with the same start
// commit would try the same sequence of commits.
std::srand(std::time(nullptr));
- std::random_shuffle(allCommits.begin(), allCommits.end());
+ std::shuffle(allCommits.begin(), allCommits.end(), std::mt19937(std::random_device()()));
quint64 run = 0;
QStringList buildSequence(workingStartCommit);
diff --git a/tests/fuzzy-test/fuzzytester.h b/tests/fuzzy-test/fuzzytester.h
index 2d75bb1af..2d0279e1a 100644
--- a/tests/fuzzy-test/fuzzytester.h
+++ b/tests/fuzzy-test/fuzzytester.h
@@ -35,8 +35,8 @@
class TestError {
public:
- TestError(const QString &errorMessage) : errorMessage(errorMessage) {}
- ~TestError() throw() {}
+ TestError(QString errorMessage) : errorMessage(std::move(errorMessage)) {}
+ ~TestError() throw() = default;
QString errorMessage;