aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/api/tst_api.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/api/tst_api.cpp')
-rw-r--r--tests/auto/api/tst_api.cpp159
1 files changed, 89 insertions, 70 deletions
diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp
index 200239081..3816eca2b 100644
--- a/tests/auto/api/tst_api.cpp
+++ b/tests/auto/api/tst_api.cpp
@@ -362,7 +362,10 @@ void TestApi::buildProject()
+ QLatin1String(".qbs");
qbs::SetupProjectParameters params = defaultSetupParameters(projectFilePath);
removeBuildDir(params);
- qbs::ErrorInfo errorInfo = doBuildProject(projectFilePath);
+ ProcessResultReceiver resultReceiver;
+ qbs::ErrorInfo errorInfo = doBuildProject(projectFilePath, nullptr, &resultReceiver);
+ if (resultReceiver.output.contains("mingw32_gt_pch_use_address"))
+ QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440");
VERIFY_NO_ERROR(errorInfo);
QVERIFY(regularFileExists(relativeBuildGraphFilePath()));
if (!productFileName.isEmpty()) {
@@ -483,9 +486,14 @@ void TestApi::buildSingleFile()
m_logSink->setLogLevel(qbs::LoggerMaxLevel);
std::unique_ptr<qbs::BuildJob> buildJob(project.buildAllProducts(options));
BuildDescriptionReceiver receiver;
+ ProcessResultReceiver resultReceiver;
+ connect(buildJob.get(), &qbs::BuildJob::reportProcessResult,
+ &resultReceiver, &ProcessResultReceiver::handleProcessResult);
connect(buildJob.get(), &qbs::BuildJob::reportCommandDescription, &receiver,
&BuildDescriptionReceiver::handleDescription);
waitForFinished(buildJob.get());
+ if (resultReceiver.output.contains("mingw32_gt_pch_use_address"))
+ QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440");
QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString()));
QCOMPARE(receiver.descriptions.count("compiling"), 2);
QCOMPARE(receiver.descriptions.count("precompiling"), 1);
@@ -920,16 +928,12 @@ void TestApi::dependencyOnMultiplexedType()
} else {
QVERIFY(p.name() == "p2");
++p2Count;
-
- // FIXME: This is an odd effect of our current algorithm: We collect the products
- // matching the requested type and add Depends items with their names ("p1" in
- // this case). Later, the algorithm checking for compatibility regarding the
- // multiplexing axes picks the aggregate. However, the aggregate does not have
- // a matching type... It's not entirely clear what the real expected
- // result should be here.
- QCOMPARE(p.dependencies().size(), 2);
+ QVERIFY(p.dependencies().contains("dep"));
}
}
+ QCOMPARE(depCount, 1);
+ QCOMPARE(p1Count, 3);
+ QCOMPARE(p2Count, 1);
std::unique_ptr<qbs::BuildJob> buildJob(project.buildAllProducts(qbs::BuildOptions()));
waitForFinished(buildJob.get());
QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString()));
@@ -1002,7 +1006,7 @@ void TestApi::errorInSetupRunEnvironment()
qbs::ErrorInfo error;
const QProcessEnvironment env = runEnv.runEnvironment(&error);
QVERIFY(error.hasError());
- QVERIFY(error.toString().contains("trallala"));
+ QVERIFY2(error.toString().contains("trallala"), qPrintable(error.toString()));
} catch (const qbs::ErrorInfo &) {
exceptionCaught = true;
}
@@ -1021,10 +1025,11 @@ void TestApi::excludedInputs()
waitForFinished(buildJob.get());
QVERIFY2(!buildJob->error().hasError(), qPrintable(job->error().toString()));
QVERIFY(project.isValid());
- QCOMPARE(project.projectData().products().size(), 2);
+ const qbs::ProjectData projectData = project.projectData();
+ QCOMPARE(projectData.products().size(), 2);
qbs::ProductData depProduct;
qbs::ProductData pProduct;
- for (const qbs::ProductData &p : project.projectData().products()) {
+ for (const qbs::ProductData &p : projectData.products()) {
if (p.name() == "dep")
depProduct = p;
else if (p.name() == "p")
@@ -1283,7 +1288,7 @@ void TestApi::fallbackGcc()
QVERIFY(project.isValid());
QList<qbs::ProductData> products = project.allProducts();
QCOMPARE(products.size(), 2);
- for (const qbs::ProductData &p : qAsConst(products)) {
+ for (const qbs::ProductData &p : std::as_const(products)) {
if (p.profile() == "unixProfile") {
qbs::PropertyMap moduleProps = p.moduleProperties();
QCOMPARE(moduleProps.getModuleProperty("qbs", "targetOS").toStringList(),
@@ -1417,6 +1422,9 @@ void TestApi::infiniteLoopBuilding_data()
QTest::addColumn<QString>("projectDirName");
QTest::newRow("JS Command") << QString("infinite-loop-js");
QTest::newRow("Process Command") << QString("infinite-loop-process");
+ QTest::newRow("Scanner (scan property)") << QString("infinite-loop-scanning-scan");
+ QTest::newRow("Scanner (searchPaths property)")
+ << QString("infinite-loop-scanning-searchpaths");
}
void TestApi::infiniteLoopResolving()
@@ -1545,27 +1553,30 @@ void TestApi::linkDynamicAndStaticLibs()
BuildDescriptionReceiver bdr;
qbs::BuildOptions options;
options.setEchoMode(qbs::CommandEchoModeCommandLine);
+ m_logSink->output.clear();
const qbs::ErrorInfo errorInfo = doBuildProject("link-dynamiclibs-staticlibs", &bdr, nullptr,
nullptr, options);
VERIFY_NO_ERROR(errorInfo);
+ const bool isGcc = m_logSink->output.contains("is gcc: true");
+ const bool isNotGcc = m_logSink->output.contains("is gcc: false");
+ if (isNotGcc)
+ QSKIP("The remainder of this test applies only to GCC");
+ QVERIFY(isGcc);
+
// 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 (profileToolchain(buildProfile).contains("gcc")) {
- static const std::regex appLinkCmdRex(" -o [^ ]*/HelloWorld" QBS_HOST_EXE_SUFFIX " ");
- QString appLinkCmd;
- for (const QString &line : qAsConst(bdr.descriptionLines)) {
- const auto ln = line.toStdString();
- if (std::regex_search(ln, appLinkCmdRex)) {
- appLinkCmd = line;
- break;
- }
+ static const std::regex appLinkCmdRex(" -o [^ ]*/HelloWorld" QBS_HOST_EXE_SUFFIX " ");
+ QString appLinkCmd;
+ for (const QString &line : std::as_const(bdr.descriptionLines)) {
+ const auto ln = line.toStdString();
+ if (std::regex_search(ln, appLinkCmdRex)) {
+ appLinkCmd = line;
+ break;
}
- QVERIFY(!appLinkCmd.isEmpty());
- QVERIFY(!appLinkCmd.contains("static1"));
- QVERIFY(!appLinkCmd.contains("static2"));
}
+ QVERIFY(!appLinkCmd.isEmpty());
+ QVERIFY(!appLinkCmd.contains("static1"));
+ QVERIFY(!appLinkCmd.contains("static2"));
}
void TestApi::linkStaticAndDynamicLibs()
@@ -1580,31 +1591,32 @@ void TestApi::linkStaticAndDynamicLibs()
const bool isNormalUnix = m_logSink->output.contains("is normal unix: yes");
const bool isNotNormalUnix = m_logSink->output.contains("is normal unix: no");
QVERIFY2(isNormalUnix != isNotNormalUnix, qPrintable(m_logSink->output));
+ const bool isGcc = m_logSink->output.contains("is gcc: true");
+ const bool isNotGcc = m_logSink->output.contains("is gcc: false");
+ if (isNotGcc)
+ QSKIP("The remainder of this test applies only to GCC");
+ QVERIFY(isGcc);
// The dependencies libdynamic1.so and libstatic2.a must not appear in the link command for the
// executable. The -rpath-link line for libdynamic1.so must be there.
- const SettingsPtr s = settings();
- const qbs::Profile buildProfile(profileName(), s.get());
- 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)) {
- const auto ln = line.toStdString();
- if (std::regex_search(ln, appLinkCmdRex)) {
- appLinkCmd = line;
- break;
- }
- }
- QVERIFY(!appLinkCmd.isEmpty());
- if (isNormalUnix) {
- const std::regex rpathLinkRex("-rpath-link=\\S*/"
- + relativeProductBuildDir("dynamic2").toStdString());
- const auto ln = appLinkCmd.toStdString();
- QVERIFY(std::regex_search(ln, rpathLinkRex));
+ static const std::regex appLinkCmdRex(" -o [^ ]*/HelloWorld" QBS_HOST_EXE_SUFFIX " ");
+ QString appLinkCmd;
+ for (const QString &line : std::as_const(bdr.descriptionLines)) {
+ const auto ln = line.toStdString();
+ if (std::regex_search(ln, appLinkCmdRex)) {
+ appLinkCmd = line;
+ break;
}
- QVERIFY(!appLinkCmd.contains("libstatic2.a"));
- QVERIFY(!appLinkCmd.contains("libdynamic2.so"));
}
+ QVERIFY(!appLinkCmd.isEmpty());
+ if (isNormalUnix) {
+ const std::regex rpathLinkRex("-rpath-link=\\S*/"
+ + relativeProductBuildDir("dynamic2").toStdString());
+ const auto ln = appLinkCmd.toStdString();
+ QVERIFY(std::regex_search(ln, rpathLinkRex));
+ }
+ QVERIFY(!appLinkCmd.contains("libstatic2.a"));
+ QVERIFY(!appLinkCmd.contains("libdynamic2.so"));
}
void TestApi::listBuildSystemFiles()
@@ -1652,7 +1664,7 @@ void TestApi::localProfiles()
qbs::ProductData libClang;
qbs::ProductData appDebug;
qbs::ProductData appRelease;
- for (const qbs::ProductData &p : qAsConst(products)) {
+ for (const qbs::ProductData &p : std::as_const(products)) {
if (p.name() == "lib") {
if (p.profile() == "mingwProfile")
libMingw = p;
@@ -1722,7 +1734,7 @@ void TestApi::localProfiles()
products = project.allProducts();
QCOMPARE(products.size(), 4);
int clangProfiles = 0;
- for (const qbs::ProductData &p : qAsConst(products)) {
+ for (const qbs::ProductData &p : std::as_const(products)) {
if (p.profile() == "clangProfile") {
++clangProfiles;
moduleProps = p.moduleProperties();
@@ -1818,7 +1830,8 @@ void TestApi::multiArch()
QVERIFY2(!setupJob->error().hasError(), qPrintable(setupJob->error().toString()));
qbs::Project project = setupJob->project();
QCOMPARE(project.profile(), profileName());
- const QList<qbs::ProductData> &products = project.projectData().products();
+ const qbs::ProjectData projectData = project.projectData();
+ const QList<qbs::ProductData> &products = projectData.products();
QCOMPARE(products.size(), 3);
QList<qbs::ProductData> hostProducts;
QList<qbs::ProductData> targetProducts;
@@ -1877,26 +1890,23 @@ void TestApi::multiArch()
QFile p2ArtifactInstalled(installRoot + "/host/host-tool.output");
QVERIFY2(p2ArtifactInstalled.exists(), qPrintable(p2ArtifactInstalled.fileName()));
- // Error check: Try to build for the same profile twice.
+ // Specifying the same profile twice should not result in an attempt to multiplex.
overriddenValues.insert("project.targetProfile", hostProfile.name());
setupParams.setOverriddenValues(overriddenValues);
setupJob.reset(project.setupProject(setupParams, m_logSink, nullptr));
waitForFinished(setupJob.get());
- QVERIFY(setupJob->error().hasError());
- QVERIFY2(setupJob->error().toString().contains("Duplicate entry 'host' in qbs.profiles."),
- qPrintable(setupJob->error().toString()));
+ QVERIFY(!setupJob->error().hasError());
+ QCOMPARE(int(setupJob->project().projectData().products().size()), 2);
- // Error check: Try to build for the same profile twice, this time attaching
- // the properties via the product name.
+ // The same, but this time attaching the properties via the product name.
overriddenValues.remove(QStringLiteral("project.targetProfile"));
overriddenValues.insert("products.p1.myProfiles",
targetProfile.name() + ',' + targetProfile.name());
setupParams.setOverriddenValues(overriddenValues);
setupJob.reset(project.setupProject(setupParams, m_logSink, nullptr));
waitForFinished(setupJob.get());
- QVERIFY(setupJob->error().hasError());
- QVERIFY2(setupJob->error().toString().contains("Duplicate entry 'target' in qbs.profiles."),
- qPrintable(setupJob->error().toString()));
+ QVERIFY(!setupJob->error().hasError());
+ QCOMPARE(int(setupJob->project().projectData().products().size()), 2);
}
struct ProductDataSelector
@@ -1915,7 +1925,8 @@ struct ProductDataSelector
bool qbsPropertiesMatch(const qbs::ProductData &p) const
{
for (auto it = qbsProperties.begin(); it != qbsProperties.end(); ++it) {
- if (it.value() != p.moduleProperties().getModuleProperty("qbs", it.key()))
+ if (!qbs::qVariantsEqual(
+ it.value(), p.moduleProperties().getModuleProperty("qbs", it.key())))
return false;
}
return true;
@@ -2210,7 +2221,7 @@ void TestApi::newPatternMatch()
void TestApi::nonexistingProjectPropertyFromProduct()
{
qbs::SetupProjectParameters setupParams
- = defaultSetupParameters("nonexistingprojectproperties");
+ = defaultSetupParameters("nonexistingprojectproperties/invalidaccessfromproduct.qbs");
std::unique_ptr<qbs::SetupProjectJob> job(qbs::Project().setupProject(setupParams,
m_logSink, nullptr));
waitForFinished(job.get());
@@ -2519,6 +2530,7 @@ qbs::SetupProjectParameters TestApi::defaultSetupParameters(const QString &proje
setupParams.setLibexecPath(QDir::cleanPath(QCoreApplication::applicationDirPath()
+ QLatin1String("/" QBS_RELATIVE_LIBEXEC_PATH)));
setupParams.setTopLevelProfile(profileName());
+ setupParams.setMaxJobCount(2);
setupParams.setConfigurationName(QStringLiteral("default"));
setupParams.setSettingsDirectory(settings()->baseDirectory());
return setupParams;
@@ -2703,12 +2715,15 @@ void TestApi::restoredWarnings()
waitForFinished(job.get());
QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
job.reset(nullptr);
- QCOMPARE(toSet(m_logSink->warnings).size(), 2);
+ QCOMPARE(toSet(m_logSink->warnings).size(), 5);
const auto beforeErrors = m_logSink->warnings;
for (const qbs::ErrorInfo &e : beforeErrors) {
const QString msg = e.toString();
QVERIFY2(msg.contains("Superfluous version")
- || msg.contains("Property 'blubb' is not declared"),
+ || msg.contains("Property 'blubb' is not declared")
+ || msg.contains("this one comes from a thread")
+ || msg.contains("Product 'theOtherProduct' had errors and was disabled")
+ || msg.contains("Product 'theProduct' had errors and was disabled"),
qPrintable(msg));
}
m_logSink->warnings.clear();
@@ -2718,25 +2733,29 @@ void TestApi::restoredWarnings()
waitForFinished(job.get());
QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
job.reset(nullptr);
- QCOMPARE(toSet(m_logSink->warnings).size(), 2);
+ QCOMPARE(toSet(m_logSink->warnings).size(), 5);
m_logSink->warnings.clear();
// Re-resolving with changes: Errors come from the re-resolving, stored ones must be suppressed.
QVariantMap overridenValues;
- overridenValues.insert("products.theProduct.moreFiles", true);
+ overridenValues.insert("products.aThirdProduct.moreFiles", true);
setupParams.setOverriddenValues(overridenValues);
job.reset(qbs::Project().setupProject(setupParams, m_logSink, nullptr));
waitForFinished(job.get());
QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
job.reset(nullptr);
- QCOMPARE(toSet(m_logSink->warnings).size(), 3); // One more for the additional group
+ QCOMPARE(toSet(m_logSink->warnings).size(), 6); // One more for the additional group
const auto afterErrors = m_logSink->warnings;
for (const qbs::ErrorInfo &e : afterErrors) {
const QString msg = e.toString();
- QVERIFY2(msg.contains("Superfluous version")
- || msg.contains("Property 'blubb' is not declared")
- || msg.contains("blubb.cpp' does not exist"),
- qPrintable(msg));
+ QVERIFY2(
+ msg.contains("Superfluous version") || msg.contains("Property 'blubb' is not declared")
+ || msg.contains("blubb.txt' does not exist")
+ || msg.contains("this one comes from a thread")
+ || msg.contains("Product 'theOtherProduct' had errors and was disabled")
+ || msg.contains("Product 'theThirdProduct' had errors and was disabled")
+ || msg.contains("Product 'theProduct' had errors and was disabled"),
+ qPrintable(msg));
}
m_logSink->warnings.clear();
}