aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs5
-rw-r--r--tests/auto/api/testdata/is-runnable/project.qbs10
-rw-r--r--tests/auto/api/testdata/project-editing/project-with-no-files.qbs7
-rw-r--r--tests/auto/api/tst_api.cpp63
-rw-r--r--tests/auto/api/tst_api.h1
-rw-r--r--tests/auto/blackbox/testdata/appWithoutSources/a.c1
-rw-r--r--tests/auto/blackbox/testdata/appWithoutSources/b.c10
-rw-r--r--tests/auto/blackbox/testdata/appWithoutSources/project.qbs33
-rw-r--r--tests/auto/blackbox/testdata/build-directories/project.qbs44
-rw-r--r--tests/auto/blackbox/testdata/dynamicRuleOutputs/before/genlexer.qbs6
-rw-r--r--tests/auto/blackbox/testdata/empty-filetag-list/dontcompilethis.cpp1
-rw-r--r--tests/auto/blackbox/testdata/empty-filetag-list/project.qbs8
-rw-r--r--tests/auto/blackbox/testdata/nodejs/hello.js3
-rw-r--r--tests/auto/blackbox/testdata/nodejs/hello.qbs7
-rw-r--r--tests/auto/blackbox/testdata/non-broken-files-in-broken-product/broken.cpp1
-rw-r--r--tests/auto/blackbox/testdata/non-broken-files-in-broken-product/fine.cpp1
-rw-r--r--tests/auto/blackbox/testdata/non-broken-files-in-broken-product/project.qbs5
-rw-r--r--tests/auto/blackbox/testdata/rad-after-incomplete-build/dummy.txt (renamed from tests/auto/api/testdata/infinite-loop-process/dummy-input.txt)0
-rw-r--r--tests/auto/blackbox/testdata/rad-after-incomplete-build/project_with_rule.qbs26
-rw-r--r--tests/auto/blackbox/testdata/rad-after-incomplete-build/project_with_transformer.qbs21
-rw-r--r--tests/auto/blackbox/testdata/simpleProbe/main.cpp1
-rw-r--r--tests/auto/blackbox/testdata/simpleProbe/simpleProbe.qbs31
-rw-r--r--tests/auto/blackbox/testdata/typescript/animals.ts21
-rw-r--r--tests/auto/blackbox/testdata/typescript/extra.js3
-rw-r--r--tests/auto/blackbox/testdata/typescript/foo.ts5
-rw-r--r--tests/auto/blackbox/testdata/typescript/main.ts19
-rw-r--r--tests/auto/blackbox/testdata/typescript/typescript.qbs34
-rw-r--r--tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom1.in0
-rw-r--r--tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom2.in0
-rw-r--r--tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/project.qbs62
-rw-r--r--tests/auto/blackbox/testdata/wix/WiXInstallers.qbs4
-rw-r--r--tests/auto/blackbox/testdata/wix/de.wxl1
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp406
-rw-r--r--tests/auto/blackbox/tst_blackbox.h11
34 files changed, 721 insertions, 130 deletions
diff --git a/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs b/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs
index e2094576e..855528615 100644
--- a/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs
+++ b/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs
@@ -12,12 +12,7 @@ Project {
type: "mytype"
name: "caller"
Depends { name: "infinite-loop" }
- Group {
- files: "dummy-input.txt" // Needed because of QBS-277
- fileTags: "schnurz"
- }
Rule {
- inputs: "schnurz"
usings: "application"
Artifact {
fileName: "dummy"
diff --git a/tests/auto/api/testdata/is-runnable/project.qbs b/tests/auto/api/testdata/is-runnable/project.qbs
new file mode 100644
index 000000000..02200fff2
--- /dev/null
+++ b/tests/auto/api/testdata/is-runnable/project.qbs
@@ -0,0 +1,10 @@
+import qbs
+
+Project {
+ CppApplication {
+ name: "app"
+ }
+ DynamicLibrary {
+ name: "lib"
+ }
+}
diff --git a/tests/auto/api/testdata/project-editing/project-with-no-files.qbs b/tests/auto/api/testdata/project-editing/project-with-no-files.qbs
new file mode 100644
index 000000000..824ae6dcd
--- /dev/null
+++ b/tests/auto/api/testdata/project-editing/project-with-no-files.qbs
@@ -0,0 +1,7 @@
+import qbs
+
+CppApplication {
+ Group {
+ files: "file.cpp"
+ }
+}
diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp
index 3b0fb1828..124665b1e 100644
--- a/tests/auto/api/tst_api.cpp
+++ b/tests/auto/api/tst_api.cpp
@@ -368,6 +368,36 @@ void TestApi::changeContent()
waitForFinished(buildJob.data());
errorInfo = project.addGroup(newProjectData.products().first(), "blubb");
QVERIFY2(!errorInfo.hasError(), qPrintable(errorInfo.toString()));
+
+ // Add a file to the top level of a product that does not have a "files" binding yet.
+ setupParams.setProjectFilePath(QDir::cleanPath(m_workingDataDir +
+ "/project-editing/project-with-no-files.qbs"));
+ job.reset(qbs::Project::setupProject(setupParams, m_logSink, 0));
+ waitForFinished(job.data());
+ QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
+ project = job->project();
+ projectData = project.projectData();
+ QCOMPARE(projectData.allProducts().count(), 1);
+ product = projectData.allProducts().first();
+ errorInfo = project.addFiles(product, qbs::GroupData(), QStringList("main.cpp"));
+ QVERIFY2(!errorInfo.hasError(), qPrintable(errorInfo.toString()));
+ projectData = project.projectData();
+ rcvr.descriptions.clear();
+ buildJob.reset(project.buildAllProducts(buildOptions, this));
+ connect(buildJob.data(), SIGNAL(reportCommandDescription(QString,QString)), &rcvr,
+ SLOT(handleDescription(QString,QString)));
+ waitForFinished(buildJob.data());
+ QVERIFY2(!buildJob->error().hasError(), qPrintable(buildJob->error().toString()));
+ QVERIFY(rcvr.descriptions.contains("compiling main.cpp"));
+ job.reset(qbs::Project::setupProject(setupParams, m_logSink, 0));
+ waitForFinished(job.data());
+ QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
+ if (job->project().projectData() != projectData) {
+ printProjectData(projectData);
+ qDebug("\n====\n");
+ printProjectData(job->project().projectData());
+ }
+ QVERIFY(job->project().projectData() == projectData);
}
static qbs::ErrorInfo forceRuleEvaluation(const qbs::Project project)
@@ -425,7 +455,6 @@ void TestApi::fileTagsFilterOverride()
QList<qbs::InstallableFile> installableFiles
= project.installableFilesForProduct(product, qbs::InstallOptions());
QCOMPARE(installableFiles.count(), 1);
- QEXPECT_FAIL(0, "QBS-424", Continue);
QVERIFY(installableFiles.first().targetDirectory().contains("habicht"));
}
@@ -443,7 +472,7 @@ void TestApi::infiniteLoopBuilding()
qbs::Project project = setupJob->project();
const QScopedPointer<qbs::BuildJob> buildJob(project.buildAllProducts(qbs::BuildOptions()));
QTimer::singleShot(1000, buildJob.data(), SLOT(cancel()));
- QVERIFY(waitForFinished(buildJob.data(), 30000));
+ QVERIFY(waitForFinished(buildJob.data(), 300000));
}
void TestApi::infiniteLoopBuilding_data()
@@ -462,7 +491,7 @@ void TestApi::infiniteLoopResolving()
QScopedPointer<qbs::SetupProjectJob> setupJob(qbs::Project::setupProject(setupParams,
m_logSink, 0));
QTimer::singleShot(1000, setupJob.data(), SLOT(cancel()));
- QVERIFY(waitForFinished(setupJob.data(), 30000));
+ QVERIFY(waitForFinished(setupJob.data(), 300000));
QVERIFY2(setupJob->error().toString().toLower().contains("cancel"),
qPrintable(setupJob->error().toString()));
}
@@ -517,6 +546,27 @@ void TestApi::installableFiles()
QCOMPARE(installableFiles.last().targetFilePath(), QLatin1String("/tmp/dir/file2.txt"));
}
+void TestApi::isRunnable()
+{
+ qbs::SetupProjectParameters setupParams = defaultSetupParameters();
+ setupParams.setProjectFilePath(QDir::cleanPath(QLatin1String(SRCDIR "/testdata"
+ "/is-runnable/project.qbs")));
+ QScopedPointer<qbs::SetupProjectJob> job(qbs::Project::setupProject(setupParams,
+ m_logSink, 0));
+ waitForFinished(job.data());
+ QVERIFY2(!job->error().hasError(), qPrintable(job->error().toString()));
+ qbs::Project project = job->project();
+ const QList<qbs::ProductData> products = project.projectData().products();
+ QCOMPARE(products.count(), 2);
+ foreach (const qbs::ProductData &p, products) {
+ QVERIFY2(p.name() == "app" || p.name() == "lib", qPrintable(p.name()));
+ if (p.name() == "app")
+ QVERIFY(p.isRunnable());
+ else
+ QVERIFY(!p.isRunnable());
+ }
+}
+
void TestApi::listBuildSystemFiles()
{
qbs::SetupProjectParameters setupParams = defaultSetupParameters();
@@ -582,11 +632,8 @@ qbs::SetupProjectParameters TestApi::defaultSetupParameters() const
const qbs::Preferences prefs(settings.data(), profileName);
setupParams.setSearchPaths(prefs.searchPaths(qbsRootPath));
setupParams.setPluginPaths(prefs.pluginPaths(qbsRootPath + QLatin1String("/lib")));
- QVariantMap buildConfig;
- buildConfig.insert(QLatin1String("qbs.profile"), profileName);
- buildConfig.insert(QLatin1String("qbs.buildVariant"), QLatin1String("debug"));
- setupParams.setBuildConfiguration(buildConfig);
- setupParams.expandBuildConfiguration(settings.data());
+ setupParams.setTopLevelProfile(profileName);
+ setupParams.setBuildVariant(QLatin1String("debug"));
return setupParams;
}
diff --git a/tests/auto/api/tst_api.h b/tests/auto/api/tst_api.h
index 9aab60651..0ad65c5e5 100644
--- a/tests/auto/api/tst_api.h
+++ b/tests/auto/api/tst_api.h
@@ -55,6 +55,7 @@ private slots:
void infiniteLoopBuilding_data();
void infiniteLoopResolving();
void installableFiles();
+ void isRunnable();
void listBuildSystemFiles();
void nonexistingProjectPropertyFromProduct();
void nonexistingProjectPropertyFromCommandLine();
diff --git a/tests/auto/blackbox/testdata/appWithoutSources/a.c b/tests/auto/blackbox/testdata/appWithoutSources/a.c
new file mode 100644
index 000000000..bf7759e11
--- /dev/null
+++ b/tests/auto/blackbox/testdata/appWithoutSources/a.c
@@ -0,0 +1 @@
+int foo() { return 42; }
diff --git a/tests/auto/blackbox/testdata/appWithoutSources/b.c b/tests/auto/blackbox/testdata/appWithoutSources/b.c
new file mode 100644
index 000000000..e3841fa32
--- /dev/null
+++ b/tests/auto/blackbox/testdata/appWithoutSources/b.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+int foo(); // defined in a.cpp
+
+int main()
+{
+ printf("The answer is %d.\n", foo());
+ return 0;
+}
+
diff --git a/tests/auto/blackbox/testdata/appWithoutSources/project.qbs b/tests/auto/blackbox/testdata/appWithoutSources/project.qbs
new file mode 100644
index 000000000..dca195e29
--- /dev/null
+++ b/tests/auto/blackbox/testdata/appWithoutSources/project.qbs
@@ -0,0 +1,33 @@
+import qbs 1.0
+
+Project {
+ StaticLibrary {
+ name: "a"
+
+ Depends { name: "cpp" }
+
+ files: [
+ "a.c",
+ ]
+ }
+
+ StaticLibrary {
+ name: "b"
+
+ Depends { name: "a" }
+ Depends { name: "cpp" }
+
+ files: [
+ "b.c",
+ ]
+ }
+
+ CppApplication {
+ name: "appWithoutSources"
+ type: ["application"]
+ cpp.entryPoint: "main"
+
+ Depends { name: "a" }
+ Depends { name: "b" }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/build-directories/project.qbs b/tests/auto/blackbox/testdata/build-directories/project.qbs
new file mode 100644
index 000000000..cb83999e2
--- /dev/null
+++ b/tests/auto/blackbox/testdata/build-directories/project.qbs
@@ -0,0 +1,44 @@
+import qbs
+
+Project {
+ Product {
+ name: "p1"
+ type: "blubb1"
+ Transformer {
+ Artifact {
+ fileName: "dummy1.txt"
+ fileTags: product.type
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.silent = true;
+ cmd.sourceCode = function() {
+ print(product.buildDirectory);
+ }
+ return cmd;
+ }
+ }
+ }
+ Product {
+ name: "p2"
+ type: "blubb2"
+ Depends { name: "p1" }
+ Rule {
+ usings: "blubb1"
+ Artifact {
+ fileName: "dummy2.txt"
+ fileTags: product.type
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.silent = true;
+ cmd.sourceCode = function() {
+ print(product.buildDirectory);
+ print(project.buildDirectory);
+ print(project.sourceDirectory);
+ }
+ return cmd;
+ }
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/genlexer.qbs b/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/genlexer.qbs
index 61504573f..2c145682a 100644
--- a/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/genlexer.qbs
+++ b/tests/auto/blackbox/testdata/dynamicRuleOutputs/before/genlexer.qbs
@@ -64,12 +64,12 @@ Project {
var sourceFileName = options["outfile"] || "lex.yy.c";
var headerFileName = options["header-file"];
var result = [{
- filePath: "GeneratedFiles/" + product.name + "/" + sourceFileName,
+ filePath: "GeneratedFiles/" + sourceFileName,
fileTags: ["c"]
}];
if (headerFileName) {
result.push({
- filePath: "GeneratedFiles/" + product.name + "/" + headerFileName,
+ filePath: "GeneratedFiles/" + headerFileName,
fileTags: ["hpp"]
});
}
@@ -80,7 +80,7 @@ Project {
if (product.isFlexAvailable) {
// flex is available. Let's call it.
cmd = new Command("flex", [input.filePath]);
- cmd.workingDirectory = product.buildDirectory + "/GeneratedFiles/" + product.name;
+ cmd.workingDirectory = product.buildDirectory + "/GeneratedFiles";
} else {
// No flex available here, generate some C source and header.
cmd = new JavaScriptCommand();
diff --git a/tests/auto/blackbox/testdata/empty-filetag-list/dontcompilethis.cpp b/tests/auto/blackbox/testdata/empty-filetag-list/dontcompilethis.cpp
new file mode 100644
index 000000000..bac3b631d
--- /dev/null
+++ b/tests/auto/blackbox/testdata/empty-filetag-list/dontcompilethis.cpp
@@ -0,0 +1 @@
+This is not C++.
diff --git a/tests/auto/blackbox/testdata/empty-filetag-list/project.qbs b/tests/auto/blackbox/testdata/empty-filetag-list/project.qbs
new file mode 100644
index 000000000..294616124
--- /dev/null
+++ b/tests/auto/blackbox/testdata/empty-filetag-list/project.qbs
@@ -0,0 +1,8 @@
+import qbs
+
+CppApplication {
+ Group {
+ files: "dontcompilethis.cpp"
+ fileTags: []
+ }
+}
diff --git a/tests/auto/blackbox/testdata/nodejs/hello.js b/tests/auto/blackbox/testdata/nodejs/hello.js
new file mode 100644
index 000000000..43f1e2ffd
--- /dev/null
+++ b/tests/auto/blackbox/testdata/nodejs/hello.js
@@ -0,0 +1,3 @@
+if (console) {
+ console.log("hello world");
+}
diff --git a/tests/auto/blackbox/testdata/nodejs/hello.qbs b/tests/auto/blackbox/testdata/nodejs/hello.qbs
new file mode 100644
index 000000000..e11b1a599
--- /dev/null
+++ b/tests/auto/blackbox/testdata/nodejs/hello.qbs
@@ -0,0 +1,7 @@
+import qbs
+
+NodeJSApplication {
+ nodejs.applicationFile: "hello.js"
+ name: "hello"
+ files: "hello.js"
+}
diff --git a/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/broken.cpp b/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/broken.cpp
new file mode 100644
index 000000000..57f89ed17
--- /dev/null
+++ b/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/broken.cpp
@@ -0,0 +1 @@
+broken
diff --git a/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/fine.cpp b/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/fine.cpp
new file mode 100644
index 000000000..237c8ce18
--- /dev/null
+++ b/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/fine.cpp
@@ -0,0 +1 @@
+int main() {}
diff --git a/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/project.qbs b/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/project.qbs
new file mode 100644
index 000000000..97f1e9897
--- /dev/null
+++ b/tests/auto/blackbox/testdata/non-broken-files-in-broken-product/project.qbs
@@ -0,0 +1,5 @@
+import qbs
+
+CppApplication {
+ files: ["fine.cpp", "broken.cpp"]
+}
diff --git a/tests/auto/api/testdata/infinite-loop-process/dummy-input.txt b/tests/auto/blackbox/testdata/rad-after-incomplete-build/dummy.txt
index e69de29bb..e69de29bb 100644
--- a/tests/auto/api/testdata/infinite-loop-process/dummy-input.txt
+++ b/tests/auto/blackbox/testdata/rad-after-incomplete-build/dummy.txt
diff --git a/tests/auto/blackbox/testdata/rad-after-incomplete-build/project_with_rule.qbs b/tests/auto/blackbox/testdata/rad-after-incomplete-build/project_with_rule.qbs
new file mode 100644
index 000000000..8d36c6d11
--- /dev/null
+++ b/tests/auto/blackbox/testdata/rad-after-incomplete-build/project_with_rule.qbs
@@ -0,0 +1,26 @@
+import qbs
+import qbs.TextFile
+
+Product {
+ type: "custom"
+ Group {
+ files: "dummy.txt"
+ fileTags: "input"
+ }
+ Rule {
+ inputs: "input"
+ Artifact {
+ fileTags: "custom"
+ fileName: "oldfile"
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "creating file";
+ cmd.sourceCode = function() {
+ var f = new TextFile(output.filePath, TextFile.WriteOnly);
+ f.close();
+ }
+ return cmd;
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/rad-after-incomplete-build/project_with_transformer.qbs b/tests/auto/blackbox/testdata/rad-after-incomplete-build/project_with_transformer.qbs
new file mode 100644
index 000000000..a36bd108f
--- /dev/null
+++ b/tests/auto/blackbox/testdata/rad-after-incomplete-build/project_with_transformer.qbs
@@ -0,0 +1,21 @@
+import qbs
+import qbs.TextFile
+
+Product {
+ type: "custom"
+ Transformer {
+ Artifact {
+ fileTags: "custom"
+ fileName: "oldfile"
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "creating file";
+ cmd.sourceCode = function() {
+ var f = new TextFile(output.filePath, TextFile.WriteOnly);
+ f.close();
+ }
+ return cmd;
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/simpleProbe/main.cpp b/tests/auto/blackbox/testdata/simpleProbe/main.cpp
new file mode 100644
index 000000000..76e819701
--- /dev/null
+++ b/tests/auto/blackbox/testdata/simpleProbe/main.cpp
@@ -0,0 +1 @@
+int main() { return 0; }
diff --git a/tests/auto/blackbox/testdata/simpleProbe/simpleProbe.qbs b/tests/auto/blackbox/testdata/simpleProbe/simpleProbe.qbs
new file mode 100644
index 000000000..b409c7cc6
--- /dev/null
+++ b/tests/auto/blackbox/testdata/simpleProbe/simpleProbe.qbs
@@ -0,0 +1,31 @@
+import qbs 1.0
+import qbs.Probes
+
+CppApplication {
+ Probe {
+ id: probe1
+ property string someString
+ configure: {
+ someString = "one";
+ found = true;
+ }
+ }
+ Probe {
+ id: probe2
+ configure: {
+ found = false;
+ }
+ }
+ name: "MyApp"
+ type: {
+ if (!probe1.found)
+ throw "probe1 not found";
+ if (probe2.found)
+ throw "probe2 unexpectedly found";
+ if (probe1.someString !== "one")
+ throw "probe1.someString expected to be \"one\"."
+ return "application"
+ }
+ files: ["main.cpp"]
+}
+
diff --git a/tests/auto/blackbox/testdata/typescript/animals.ts b/tests/auto/blackbox/testdata/typescript/animals.ts
new file mode 100644
index 000000000..a33ae5c11
--- /dev/null
+++ b/tests/auto/blackbox/testdata/typescript/animals.ts
@@ -0,0 +1,21 @@
+export interface Mammal {
+ speak(): string;
+}
+
+export class Cat implements Mammal {
+ public speak() {
+ return "Meow"; // a cat says meow
+ }
+}
+
+export class Dog implements Mammal {
+ public speak() {
+ return "Woof"; // a dog says woof
+ }
+}
+
+export class Human implements Mammal {
+ public speak() {
+ return "Hello";
+ }
+}
diff --git a/tests/auto/blackbox/testdata/typescript/extra.js b/tests/auto/blackbox/testdata/typescript/extra.js
new file mode 100644
index 000000000..5500e4688
--- /dev/null
+++ b/tests/auto/blackbox/testdata/typescript/extra.js
@@ -0,0 +1,3 @@
+if (console) {
+ console.log("This doesn't do anything useful!");
+}
diff --git a/tests/auto/blackbox/testdata/typescript/foo.ts b/tests/auto/blackbox/testdata/typescript/foo.ts
new file mode 100644
index 000000000..3554d317a
--- /dev/null
+++ b/tests/auto/blackbox/testdata/typescript/foo.ts
@@ -0,0 +1,5 @@
+export class Greeter {
+ public getGreeting(): string {
+ return "guten Tag!";
+ }
+}
diff --git a/tests/auto/blackbox/testdata/typescript/main.ts b/tests/auto/blackbox/testdata/typescript/main.ts
new file mode 100644
index 000000000..c41eebea5
--- /dev/null
+++ b/tests/auto/blackbox/testdata/typescript/main.ts
@@ -0,0 +1,19 @@
+import Animals = require("animals");
+import Foo = require("foo");
+
+function main() {
+ var mammals: Animals.Mammal[] = [];
+ mammals.push(new Animals.Human());
+ mammals.push(new Animals.Dog());
+ mammals.push(new Animals.Cat());
+
+ // Make everyone speak
+ for (var i = 0; i < mammals.length; ++i) {
+ console.log(mammals[i].speak());
+ }
+
+ var greeting: string = (new Foo.Greeter()).getGreeting();
+ console.log(greeting);
+}
+
+main();
diff --git a/tests/auto/blackbox/testdata/typescript/typescript.qbs b/tests/auto/blackbox/testdata/typescript/typescript.qbs
new file mode 100644
index 000000000..8407d1203
--- /dev/null
+++ b/tests/auto/blackbox/testdata/typescript/typescript.qbs
@@ -0,0 +1,34 @@
+import qbs
+
+Project {
+ NodeJSApplication {
+ Depends { name: "typescript" }
+ Depends { name: "lib" }
+
+ typescript.warningLevel: ["pedantic"]
+ typescript.generateDeclarations: true
+ typescript.moduleLoader: "commonjs"
+ nodejs.applicationFile: "main.ts"
+
+ name: "animals"
+
+ files: [
+ "animals.ts",
+ "extra.js",
+ "main.ts"
+ ]
+ }
+
+ Product {
+ Depends { name: "typescript" }
+
+ typescript.generateDeclarations: true
+ typescript.moduleLoader: "commonjs"
+
+ name: "lib"
+
+ files: [
+ "foo.ts"
+ ]
+ }
+}
diff --git a/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom1.in b/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom1.in
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom1.in
diff --git a/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom2.in b/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom2.in
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/custom2.in
diff --git a/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/project.qbs b/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/project.qbs
new file mode 100644
index 000000000..80644232e
--- /dev/null
+++ b/tests/auto/blackbox/testdata/usings-as-sole-inputs-non-multiplexed/project.qbs
@@ -0,0 +1,62 @@
+import qbs
+import qbs.FileInfo
+import qbs.TextFile
+
+Project {
+ Product {
+ name: "p1"
+ type: "custom"
+ Group {
+ files: "custom1.in"
+ fileTags: "custom.in"
+ }
+ }
+ Product {
+ name: "p2"
+ type: "custom"
+ Group {
+ files: "custom2.in"
+ fileTags: "custom.in"
+ }
+ }
+
+ Rule {
+ inputs: "custom.in"
+ Artifact {
+ fileName: FileInfo.baseName(input.filePath) + ".out"
+ fileTags: "custom"
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "generating " + output.fileName;
+ cmd.sourceCode = function() {
+ var f = new TextFile(output.filePath, TextFile.WriteOnly);
+ f.close();
+ }
+ return cmd;
+ }
+ }
+
+ Product {
+ name: "p3"
+ type: "custom-plus"
+ Depends { name: "p1" }
+ Depends { name: "p2" }
+ Rule {
+ usings: "custom"
+ Artifact {
+ fileName: FileInfo.fileName(input.filePath) + ".plus"
+ fileTags: "custom-plus"
+ }
+ prepare: {
+ var cmd = new JavaScriptCommand();
+ cmd.description = "generating " + output.fileName;
+ cmd.sourceCode = function() {
+ var f = new TextFile(output.filePath, TextFile.WriteOnly);
+ f.close();
+ }
+ return cmd;
+ }
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/wix/WiXInstallers.qbs b/tests/auto/blackbox/testdata/wix/WiXInstallers.qbs
index 718901675..88f50733d 100644
--- a/tests/auto/blackbox/testdata/wix/WiXInstallers.qbs
+++ b/tests/auto/blackbox/testdata/wix/WiXInstallers.qbs
@@ -13,12 +13,12 @@ Project {
name: "QbsBootstrapper"
targetName: "qbs-setup-" + qbs.architecture
files: ["QbsBootstrapper.wxs"]
- wix.defines: ["msiName=qbs-" + qbs.architecture + ".msi"]
+ wix.defines: ["msiName=" + project.buildDirectory + "/QbsSetup/qbs-" + qbs.architecture + ".msi"]
}
WindowsInstallerPackage {
name: "RegressionBuster9000"
- files: ["QbsSetup.wxs", "Qt.wxs"]
+ files: ["QbsSetup.wxs", "Qt.wxs", "de.wxl"]
wix.defines: ["scriptName=ExampleScript.bat"]
wix.cultures: []
}
diff --git a/tests/auto/blackbox/testdata/wix/de.wxl b/tests/auto/blackbox/testdata/wix/de.wxl
new file mode 100644
index 000000000..75394cfdd
--- /dev/null
+++ b/tests/auto/blackbox/testdata/wix/de.wxl
@@ -0,0 +1 @@
+<WixLocalization xmlns="http://schemas.microsoft.com/wix/2006/localization"/>
diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index 5838be604..148066009 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -48,6 +48,12 @@ using qbs::Internal::HostOsInfo;
using qbs::Internal::removeDirectoryWithContents;
using qbs::Profile;
+static bool regularFileExists(const QString &filePath)
+{
+ const QFileInfo fi(filePath);
+ return fi.exists() && fi.isFile();
+}
+
static QString initQbsExecutableFilePath()
{
QString filePath = QCoreApplication::applicationDirPath() + QLatin1String("/qbs");
@@ -182,7 +188,7 @@ void TestBlackbox::sanitizeOutput(QByteArray *ba)
void TestBlackbox::initTestCase()
{
- QVERIFY(QFile::exists(qbsExecutableFilePath));
+ QVERIFY(regularFileExists(qbsExecutableFilePath));
SettingsPtr settings = qbsSettings(QString());
if (!settings->profiles().contains(buildProfileName))
@@ -268,49 +274,68 @@ void TestBlackbox::baseProperties()
QCOMPARE(runQbs(), 0);
}
+void TestBlackbox::buildDirectories()
+{
+ const QString projectDir
+ = QDir::cleanPath(testDataDir + QLatin1String("/build-directories"));
+ const QString projectBuildDir = projectDir + '/' + buildDir;
+ QDir::setCurrent(projectDir);
+ QCOMPARE(runQbs(QStringList("-qq")), 0);
+ const QStringList outputLines
+ = QString::fromLocal8Bit(m_qbsStderr.trimmed()).split('\n', QString::SkipEmptyParts);
+ QCOMPARE(outputLines.count(), 4);
+ QCOMPARE(outputLines.at(0).trimmed(), projectDir + '/' + productBuildDir("p1"));
+ QCOMPARE(outputLines.at(1).trimmed(), projectDir + '/' + productBuildDir("p2"));
+ QCOMPARE(outputLines.at(2).trimmed(), projectBuildDir);
+ QCOMPARE(outputLines.at(3).trimmed(), projectDir);
+}
+
void TestBlackbox::build_project_data()
{
QTest::addColumn<QString>("projectSubDir");
QTest::addColumn<QString>("productFileName");
QTest::newRow("BPs in Sources")
<< QString("buildproperties_source")
- << QString(HostOsInfo::appendExecutableSuffix(buildDir + "/HelloWorld"));
+ << executableFilePath("HelloWorld");
QTest::newRow("code generator")
<< QString("codegen")
- << QString(HostOsInfo::appendExecutableSuffix(buildDir + "/codegen"));
+ << executableFilePath("codegen");
QTest::newRow("link static libs")
<< QString("link_staticlib")
- << QString(buildDir + QLatin1String("/")
- + HostOsInfo::appendExecutableSuffix("HelloWorld"));
+ << executableFilePath("HelloWorld");
QTest::newRow("precompiled header")
<< QString("precompiledHeader")
- << QString(buildDir + QLatin1String("/")
- + HostOsInfo::appendExecutableSuffix("MyApp"));
+ << executableFilePath("MyApp");
QTest::newRow("lots of dots")
<< QString("lotsofdots")
- << QString(buildDir + QLatin1String("/")
- + HostOsInfo::appendExecutableSuffix("lots.of.dots"));
+ << executableFilePath("lots.of.dots");
QTest::newRow("Qt5 plugin")
<< QString("qt5plugin")
- << QString(buildDir + QLatin1String("/") + HostOsInfo::dynamicLibraryName("echoplugin"));
+ << productBuildDir("echoplugin") + '/' + HostOsInfo::dynamicLibraryName("echoplugin");
QTest::newRow("Q_OBJECT in source")
<< QString("moc_cpp")
- << QString(HostOsInfo::appendExecutableSuffix(buildDir + "/moc_cpp"));
+ << executableFilePath("moc_cpp");
QTest::newRow("Q_OBJECT in header")
<< QString("moc_hpp")
- << QString(HostOsInfo::appendExecutableSuffix(buildDir + "/moc_hpp"));
+ << executableFilePath("moc_hpp");
QTest::newRow("Q_OBJECT in header, moc_XXX.cpp included")
<< QString("moc_hpp_included")
- << QString(HostOsInfo::appendExecutableSuffix(buildDir + "/moc_hpp_included"));
+ << executableFilePath("moc_hpp_included");
QTest::newRow("app and lib with same source file")
<< QString("lib_samesource")
- << QString(HostOsInfo::appendExecutableSuffix(buildDir + "/HelloWorldApp"));
+ << executableFilePath("HelloWorldApp");
QTest::newRow("source files with the same base name but different extensions")
<< QString("sameBaseName")
- << QString(HostOsInfo::appendExecutableSuffix(buildDir + "/basename"));
+ << executableFilePath("basename");
QTest::newRow("static library dependencies")
<< QString("staticLibDeps")
- << QString(HostOsInfo::appendExecutableSuffix(buildDir + "/staticLibDeps"));
+ << executableFilePath("staticLibDeps");
+ QTest::newRow("simple probes")
+ << QString("simpleProbe")
+ << executableFilePath("MyApp");
+ QTest::newRow("application without sources")
+ << QString("appWithoutSources")
+ << executableFilePath("appWithoutSources");
}
void TestBlackbox::build_project()
@@ -324,13 +349,13 @@ void TestBlackbox::build_project()
rmDirR(buildDir);
QCOMPARE(runQbs(), 0);
- QVERIFY2(QFile::exists(productFileName), qPrintable(productFileName));
- QVERIFY(QFile::exists(buildGraphPath));
+ QVERIFY2(regularFileExists(productFileName), qPrintable(productFileName));
+ QVERIFY(regularFileExists(buildGraphPath));
QVERIFY2(QFile::remove(productFileName), qPrintable(productFileName));
waitForNewTimestamp();
QCOMPARE(runQbs(QbsRunParameters(QStringList("--check-timestamps"))), 0);
- QVERIFY2(QFile::exists(productFileName), qPrintable(productFileName));
- QVERIFY(QFile::exists(buildGraphPath));
+ QVERIFY2(regularFileExists(productFileName), qPrintable(productFileName));
+ QVERIFY(regularFileExists(buildGraphPath));
}
void TestBlackbox::build_project_dry_run_data()
@@ -396,7 +421,7 @@ void TestBlackbox::dependenciesProperty()
{
QDir::setCurrent(testDataDir + QLatin1String("/dependenciesProperty"));
QCOMPARE(runQbs(), 0);
- QFile depsFile(buildDir + QLatin1String("/product1.deps"));
+ QFile depsFile(productBuildDir("product1") + QLatin1String("/product1.deps"));
QVERIFY(depsFile.open(QFile::ReadOnly));
QString deps = QString::fromLatin1(depsFile.readAll());
QVERIFY(!deps.isEmpty());
@@ -454,7 +479,7 @@ void TestBlackbox::resolve_project()
QCOMPARE(runQbs(QbsRunParameters("resolve")), 0);
QVERIFY2(!QFile::exists(productFileName), qPrintable(productFileName));
- QVERIFY(QFile::exists(buildGraphPath));
+ QVERIFY(regularFileExists(buildGraphPath));
}
void TestBlackbox::resolve_project_dry_run_data()
@@ -477,6 +502,15 @@ void TestBlackbox::resolve_project_dry_run()
QVERIFY2(!QFile::exists(buildGraphPath), qPrintable(buildGraphPath));
}
+void TestBlackbox::usingsAsSoleInputsNonMultiplexed()
+{
+ QDir::setCurrent(testDataDir + QLatin1String("/usings-as-sole-inputs-non-multiplexed"));
+ QCOMPARE(runQbs(), 0);
+ const QString p3BuildDir = productBuildDir("p3");
+ QVERIFY(regularFileExists(p3BuildDir + "/custom1.out.plus"));
+ QVERIFY(regularFileExists(p3BuildDir + "/custom2.out.plus"));
+}
+
static bool symlinkExists(const QString &linkFilePath)
{
return QFileInfo(linkFilePath).isSymLink();
@@ -484,10 +518,10 @@ static bool symlinkExists(const QString &linkFilePath)
void TestBlackbox::clean()
{
- const QString appObjectFilePath = buildDir + "/.obj/app/main.cpp" + QTC_HOST_OBJECT_SUFFIX;
- const QString appExeFilePath = buildDir + "/app" + QTC_HOST_EXE_SUFFIX;
- const QString depObjectFilePath = buildDir + "/.obj/dep/dep.cpp" + QTC_HOST_OBJECT_SUFFIX;
- const QString depLibBase = buildDir + '/' + QTC_HOST_DYNAMICLIB_PREFIX + "dep";
+ const QString appObjectFilePath = productBuildDir("app") + "/.obj/main.cpp" + QTC_HOST_OBJECT_SUFFIX;
+ const QString appExeFilePath = executableFilePath("app");
+ const QString depObjectFilePath = productBuildDir("dep") + "/.obj/dep.cpp" + QTC_HOST_OBJECT_SUFFIX;
+ const QString depLibBase = productBuildDir("dep") + '/' + QTC_HOST_DYNAMICLIB_PREFIX + "dep";
QString depLibFilePath;
QStringList symlinks;
if (qbs::Internal::HostOsInfo::isOsxHost()) {
@@ -508,24 +542,24 @@ void TestBlackbox::clean()
// Default behavior: Remove only temporaries.
QCOMPARE(runQbs(), 0);
- QVERIFY(QFile(appObjectFilePath).exists());
- QVERIFY(QFile(appExeFilePath).exists());
- QVERIFY(QFile(depObjectFilePath).exists());
- QVERIFY(QFile(depLibFilePath).exists());
+ QVERIFY(regularFileExists(appObjectFilePath));
+ QVERIFY(regularFileExists(appExeFilePath));
+ QVERIFY(regularFileExists(depObjectFilePath));
+ QVERIFY(regularFileExists(depLibFilePath));
foreach (const QString &symLink, symlinks)
- QVERIFY2(QFile(symLink).exists(), qPrintable(symLink));
+ QVERIFY2(regularFileExists(symLink), qPrintable(symLink));
QCOMPARE(runQbs(QbsRunParameters("clean")), 0);
QVERIFY(!QFile(appObjectFilePath).exists());
- QVERIFY(QFile(appExeFilePath).exists());
+ QVERIFY(regularFileExists(appExeFilePath));
QVERIFY(!QFile(depObjectFilePath).exists());
- QVERIFY(QFile(depLibFilePath).exists());
+ QVERIFY(regularFileExists(depLibFilePath));
foreach (const QString &symLink, symlinks)
QVERIFY2(symlinkExists(symLink), qPrintable(symLink));
// Remove all.
QCOMPARE(runQbs(), 0);
- QVERIFY(QFile(appObjectFilePath).exists());
- QVERIFY(QFile(appExeFilePath).exists());
+ QVERIFY(regularFileExists(appObjectFilePath));
+ QVERIFY(regularFileExists(appExeFilePath));
QCOMPARE(runQbs(QbsRunParameters(QLatin1String("clean"), QStringList("--all-artifacts"))), 0);
QVERIFY(!QFile(appObjectFilePath).exists());
QVERIFY(!QFile(appExeFilePath).exists());
@@ -536,28 +570,28 @@ void TestBlackbox::clean()
// Dry run.
QCOMPARE(runQbs(), 0);
- QVERIFY(QFile(appObjectFilePath).exists());
- QVERIFY(QFile(appExeFilePath).exists());
+ QVERIFY(regularFileExists(appObjectFilePath));
+ QVERIFY(regularFileExists(appExeFilePath));
QCOMPARE(runQbs(QbsRunParameters(QLatin1String("clean"),
QStringList("--all-artifacts") << "-n")), 0);
- QVERIFY(QFile(appObjectFilePath).exists());
- QVERIFY(QFile(appExeFilePath).exists());
- QVERIFY(QFile(depObjectFilePath).exists());
- QVERIFY(QFile(depLibFilePath).exists());
+ QVERIFY(regularFileExists(appObjectFilePath));
+ QVERIFY(regularFileExists(appExeFilePath));
+ QVERIFY(regularFileExists(depObjectFilePath));
+ QVERIFY(regularFileExists(depLibFilePath));
foreach (const QString &symLink, symlinks)
QVERIFY2(symlinkExists(symLink), qPrintable(symLink));
// Product-wise, dependency only.
QCOMPARE(runQbs(), 0);
- QVERIFY(QFile(appObjectFilePath).exists());
- QVERIFY(QFile(appExeFilePath).exists());
- QVERIFY(QFile(depObjectFilePath).exists());
- QVERIFY(QFile(depLibFilePath).exists());
+ QVERIFY(regularFileExists(appObjectFilePath));
+ QVERIFY(regularFileExists(appExeFilePath));
+ QVERIFY(regularFileExists(depObjectFilePath));
+ QVERIFY(regularFileExists(depLibFilePath));
QCOMPARE(runQbs(QbsRunParameters(QLatin1String("clean"),
QStringList("--all-artifacts") << "-p" << "dep")),
0);
- QVERIFY(QFile(appObjectFilePath).exists());
- QVERIFY(QFile(appExeFilePath).exists());
+ QVERIFY(regularFileExists(appObjectFilePath));
+ QVERIFY(regularFileExists(appExeFilePath));
QVERIFY(!QFile(depObjectFilePath).exists());
QVERIFY(!QFile(depLibFilePath).exists());
foreach (const QString &symLink, symlinks)
@@ -565,17 +599,17 @@ void TestBlackbox::clean()
// Product-wise, dependent product only.
QCOMPARE(runQbs(), 0);
- QVERIFY(QFile(appObjectFilePath).exists());
- QVERIFY(QFile(appExeFilePath).exists());
- QVERIFY(QFile(depObjectFilePath).exists());
- QVERIFY(QFile(depLibFilePath).exists());
+ QVERIFY(regularFileExists(appObjectFilePath));
+ QVERIFY(regularFileExists(appExeFilePath));
+ QVERIFY(regularFileExists(depObjectFilePath));
+ QVERIFY(regularFileExists(depLibFilePath));
QCOMPARE(runQbs(QbsRunParameters(QLatin1String("clean"),
QStringList("--all-artifacts") << "-p" << "app")),
0);
QVERIFY(!QFile(appObjectFilePath).exists());
QVERIFY(!QFile(appExeFilePath).exists());
- QVERIFY(QFile(depObjectFilePath).exists());
- QVERIFY(QFile(depLibFilePath).exists());
+ QVERIFY(regularFileExists(depObjectFilePath));
+ QVERIFY(regularFileExists(depLibFilePath));
foreach (const QString &symLink, symlinks)
QVERIFY2(symlinkExists(symLink), qPrintable(symLink));
}
@@ -717,8 +751,8 @@ void TestBlackbox::track_qrc()
{
QDir::setCurrent(testDataDir + "/qrc");
QCOMPARE(runQbs(), 0);
- const QString fileName = HostOsInfo::appendExecutableSuffix(buildDir + "/i");
- QVERIFY2(QFile(fileName).exists(), qPrintable(fileName));
+ const QString fileName = executableFilePath("i");
+ QVERIFY2(regularFileExists(fileName), qPrintable(fileName));
QDateTime dt = QFileInfo(fileName).lastModified();
QTest::qSleep(2020);
{
@@ -729,7 +763,7 @@ void TestBlackbox::track_qrc()
f.close();
}
QCOMPARE(runQbs(), 0);
- QVERIFY(QFile(fileName).exists());
+ QVERIFY(regularFileExists(fileName));
QVERIFY(dt < QFileInfo(fileName).lastModified());
}
@@ -740,18 +774,18 @@ void TestBlackbox::track_qobject_change()
QVERIFY(QFile("bla_qobject.h").copy("bla.h"));
touch("bla.h");
QCOMPARE(runQbs(), 0);
- const QString productFilePath = HostOsInfo::appendExecutableSuffix(buildDir + "/i");
- QVERIFY2(QFile(productFilePath).exists(), qPrintable(productFilePath));
+ const QString productFilePath = executableFilePath("i");
+ QVERIFY2(regularFileExists(productFilePath), qPrintable(productFilePath));
QString moc_bla_objectFileName
- = buildDir + "/.obj/i/GeneratedFiles/i/moc_bla.cpp" QTC_HOST_OBJECT_SUFFIX;
- QVERIFY(QFile(moc_bla_objectFileName).exists());
+ = buildDir + "/i/.obj/GeneratedFiles/moc_bla.cpp" QTC_HOST_OBJECT_SUFFIX;
+ QVERIFY2(regularFileExists(moc_bla_objectFileName), qPrintable(moc_bla_objectFileName));
QTest::qSleep(1000);
QFile("bla.h").remove();
QVERIFY(QFile("bla_noqobject.h").copy("bla.h"));
touch("bla.h");
QCOMPARE(runQbs(), 0);
- QVERIFY(QFile(productFilePath).exists());
+ QVERIFY(regularFileExists(productFilePath));
QVERIFY(!QFile(moc_bla_objectFileName).exists());
}
@@ -767,7 +801,7 @@ void TestBlackbox::trackAddFile()
QDir::setCurrent(testDataDir + "/trackAddFile/work");
QCOMPARE(runQbs(), 0);
- process.start(buildDir + "/someapp");
+ process.start(executableFilePath("someapp"));
QVERIFY2(process.waitForStarted(), qPrintable(process.errorString()));
QVERIFY2(process.waitForFinished(), qPrintable(process.errorString()));
QCOMPARE(process.exitCode(), 0);
@@ -783,7 +817,7 @@ void TestBlackbox::trackAddFile()
touch("main.cpp");
QCOMPARE(runQbs(), 0);
- process.start(buildDir + "/someapp");
+ process.start(executableFilePath("someapp"));
QVERIFY(process.waitForStarted());
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitCode(), 0);
@@ -872,7 +906,7 @@ void TestBlackbox::trackRemoveFile()
QDir::setCurrent(testDataDir + "/trackAddFile/work");
QCOMPARE(runQbs(), 0);
- process.start(buildDir + "/someapp");
+ process.start(executableFilePath("someapp"));
QVERIFY2(process.waitForStarted(), qPrintable(process.errorString()));
QVERIFY2(process.waitForFinished(), qPrintable(process.errorString()));
QCOMPARE(process.exitCode(), 0);
@@ -896,7 +930,7 @@ void TestBlackbox::trackRemoveFile()
touch("project.qbs");
QCOMPARE(runQbs(), 0);
- process.start(buildDir + "/someapp");
+ process.start(executableFilePath("someapp"));
QVERIFY(process.waitForStarted());
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitCode(), 0);
@@ -909,7 +943,7 @@ void TestBlackbox::trackRemoveFile()
QCOMPARE(unchangedObjectFileTime1, unchangedObjectFileTime2);
// the object file for the removed cpp file should have vanished too
- QCOMPARE(QFile::exists(buildDir + "/someapp/zort.cpp" QTC_HOST_OBJECT_SUFFIX), false);
+ QCOMPARE(regularFileExists(buildDir + "/someapp/zort.cpp" QTC_HOST_OBJECT_SUFFIX), false);
}
void TestBlackbox::trackAddFileTag()
@@ -924,7 +958,7 @@ void TestBlackbox::trackAddFileTag()
QDir::setCurrent(testDataDir + "/trackFileTags/work");
QCOMPARE(runQbs(), 0);
- process.start(buildDir + "/someapp");
+ process.start(executableFilePath("someapp"));
QVERIFY2(process.waitForStarted(), qPrintable(process.errorString()));
QVERIFY2(process.waitForFinished(), qPrintable(process.errorString()));
QCOMPARE(process.exitCode(), 0);
@@ -937,7 +971,7 @@ void TestBlackbox::trackAddFileTag()
touch("project.qbs");
QCOMPARE(runQbs(), 0);
- process.start(buildDir + "/someapp");
+ process.start(executableFilePath("someapp"));
QVERIFY(process.waitForStarted());
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitCode(), 0);
@@ -958,12 +992,11 @@ void TestBlackbox::trackRemoveFileTag()
QCOMPARE(runQbs(), 0);
// check if the artifacts are here that will become stale in the 2nd step
- QVERIFY2(QFile::exists(buildDir + "/.obj/someapp/main_foo.cpp" QTC_HOST_OBJECT_SUFFIX),
- qPrintable(buildDir + "/.obj/someapp/main_foo.cpp" QTC_HOST_OBJECT_SUFFIX));
- QVERIFY2(QFile::exists(buildDir + "/main_foo.cpp"), qPrintable(buildDir + "/main_foo.cpp"));
- QVERIFY2(QFile::exists(buildDir + "/main.foo"), qPrintable(buildDir + "/main.foo"));
+ QVERIFY(regularFileExists(buildDir + "/someapp/.obj/main_foo.cpp" QTC_HOST_OBJECT_SUFFIX));
+ QVERIFY(regularFileExists(productBuildDir("someapp") + "/main_foo.cpp"));
+ QVERIFY(regularFileExists(productBuildDir("someapp") + "/main.foo"));
- process.start(buildDir + "/someapp");
+ process.start(executableFilePath("someapp"));
QVERIFY(process.waitForStarted());
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitCode(), 0);
@@ -976,7 +1009,7 @@ void TestBlackbox::trackRemoveFileTag()
touch("project.qbs");
QCOMPARE(runQbs(), 0);
- process.start(buildDir + "/someapp");
+ process.start(executableFilePath("someapp"));
QVERIFY(process.waitForStarted());
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitCode(), 0);
@@ -984,9 +1017,9 @@ void TestBlackbox::trackRemoveFileTag()
QCOMPARE(output.takeFirst().trimmed().constData(), "there's no foo here");
// check if stale artifacts have been removed
- QCOMPARE(QFile::exists(buildDir + "/someapp/main_foo.cpp" QTC_HOST_OBJECT_SUFFIX), false);
- QCOMPARE(QFile::exists(buildDir + "/someapp/main_foo.cpp"), false);
- QCOMPARE(QFile::exists(buildDir + "/someapp/main.foo"), false);
+ QCOMPARE(regularFileExists(productBuildDir("someapp") + "/.obj/main_foo.cpp" QTC_HOST_OBJECT_SUFFIX), false);
+ QCOMPARE(regularFileExists(productBuildDir("someapp") + "/main_foo.cpp"), false);
+ QCOMPARE(regularFileExists(productBuildDir("someapp") + "/main.foo"), false);
}
void TestBlackbox::trackAddMocInclude()
@@ -1117,10 +1150,10 @@ void TestBlackbox::ruleConditions()
{
QDir::setCurrent(testDataDir + "/ruleConditions");
QCOMPARE(runQbs(), 0);
- QVERIFY(QFileInfo(buildDir + HostOsInfo::appendExecutableSuffix("/zorted")).exists());
- QVERIFY(QFileInfo(buildDir + HostOsInfo::appendExecutableSuffix("/unzorted")).exists());
- QVERIFY(QFileInfo(buildDir + "/zorted.foo.narf.zort").exists());
- QVERIFY(!QFileInfo(buildDir + "/unzorted.foo.narf.zort").exists());
+ QVERIFY(QFileInfo(executableFilePath("zorted")).exists());
+ QVERIFY(QFileInfo(executableFilePath("unzorted")).exists());
+ QVERIFY(QFileInfo(productBuildDir("zorted") + "/zorted.foo.narf.zort").exists());
+ QVERIFY(!QFileInfo(productBuildDir("unzorted") + "/unzorted.foo.narf.zort").exists());
}
void TestBlackbox::ruleCycle()
@@ -1184,8 +1217,7 @@ void TestBlackbox::overrideProjectProperties()
<< QLatin1String("project.someInt:156")
<< QLatin1String("project.someStringList:one")
<< QLatin1String("MyAppForYou.mainFile:main.cpp"))), 0);
- QVERIFY(QFile::exists(buildDir + HostOsInfo::appendExecutableSuffix("/MyAppForYou")));
-
+ QVERIFY(regularFileExists(executableFilePath("MyAppForYou")));
QVERIFY(QFile::remove(buildGraphPath));
QbsRunParameters params;
params.arguments << QLatin1String("-f") << QLatin1String("project_using_helper_lib.qbs");
@@ -1205,7 +1237,7 @@ void TestBlackbox::productProperties()
QDir::setCurrent(testDataDir + "/productproperties");
QCOMPARE(runQbs(QbsRunParameters(QStringList() << QLatin1String("-f")
<< QLatin1String("project.qbs"))), 0);
- QVERIFY(QFile::exists(buildDir + HostOsInfo::appendExecutableSuffix("/blubb_user")));
+ QVERIFY(regularFileExists(executableFilePath("blubb_user")));
}
void TestBlackbox::propertyChanges()
@@ -1223,7 +1255,7 @@ void TestBlackbox::propertyChanges()
QVERIFY(m_qbsStdout.contains("linking product 1.debug"));
QVERIFY(m_qbsStdout.contains("generated.txt"));
QVERIFY(m_qbsStdout.contains("Making output from input"));
- QFile generatedFile(buildDir + QLatin1String("/generated.txt"));
+ QFile generatedFile(productBuildDir("generated text file") + "/generated.txt");
QVERIFY(generatedFile.open(QIODevice::ReadOnly));
QCOMPARE(generatedFile.readAll(), QByteArray("prefix 1contents 1suffix 1"));
generatedFile.close();
@@ -1489,15 +1521,15 @@ void TestBlackbox::dynamicRuleOutputs()
QDir::setCurrent(testDir + "/work");
QCOMPARE(runQbs(), 0);
- const QString appFile = buildDir + "/genlexer" + QTC_HOST_EXE_SUFFIX;
- const QString headerFile1 = buildDir + "/GeneratedFiles/genlexer/numberscanner.h";
- const QString sourceFile1 = buildDir + "/GeneratedFiles/genlexer/numberscanner.c";
- const QString sourceFile2 = buildDir + "/GeneratedFiles/genlexer/lex.yy.c";
+ const QString appFile = executableFilePath("genlexer");
+ const QString headerFile1 = productBuildDir("genlexer") + "/GeneratedFiles/numberscanner.h";
+ const QString sourceFile1 = productBuildDir("genlexer") + "/GeneratedFiles/numberscanner.c";
+ const QString sourceFile2 = productBuildDir("genlexer") + "/GeneratedFiles/lex.yy.c";
// Check build #1: source and header file name are specified in numbers.l
- QVERIFY(QFile::exists(appFile));
- QVERIFY(QFile::exists(headerFile1));
- QVERIFY(QFile::exists(sourceFile1));
+ QVERIFY(regularFileExists(appFile));
+ QVERIFY(regularFileExists(headerFile1));
+ QVERIFY(regularFileExists(sourceFile1));
QVERIFY(!QFile::exists(sourceFile2));
QDateTime appFileTimeStamp1 = QFileInfo(appFile).lastModified();
@@ -1513,7 +1545,7 @@ void TestBlackbox::dynamicRuleOutputs()
QVERIFY(appFileTimeStamp1 < appFileTimeStamp2);
QVERIFY(!QFile::exists(headerFile1));
QVERIFY(!QFile::exists(sourceFile1));
- QVERIFY(QFile::exists(sourceFile2));
+ QVERIFY(regularFileExists(sourceFile2));
waitForNewTimestamp();
QFile::remove("numbers.l");
@@ -1524,12 +1556,18 @@ void TestBlackbox::dynamicRuleOutputs()
// Check build #3: source and header file name are specified in numbers.l
QDateTime appFileTimeStamp3 = QFileInfo(appFile).lastModified();
QVERIFY(appFileTimeStamp2 < appFileTimeStamp3);
- QVERIFY(QFile::exists(appFile));
- QVERIFY(QFile::exists(headerFile1));
- QVERIFY(QFile::exists(sourceFile1));
+ QVERIFY(regularFileExists(appFile));
+ QVERIFY(regularFileExists(headerFile1));
+ QVERIFY(regularFileExists(sourceFile1));
QVERIFY(!QFile::exists(sourceFile2));
}
+void TestBlackbox::emptyFileTagList()
+{
+ QDir::setCurrent(testDataDir + "/empty-filetag-list");
+ QCOMPARE(runQbs(), 0);
+}
+
void TestBlackbox::erroneousFiles_data()
{
QTest::addColumn<QString>("errorMessage");
@@ -1572,8 +1610,8 @@ void TestBlackbox::fileDependencies()
QCOMPARE(runQbs(), 0);
QVERIFY(m_qbsStdout.contains("compiling narf.cpp"));
QVERIFY(m_qbsStdout.contains("compiling zort.cpp"));
- const QString productFileName = HostOsInfo::appendExecutableSuffix(buildDir + "/myapp");
- QVERIFY2(QFile::exists(productFileName), qPrintable(productFileName));
+ const QString productFileName = executableFilePath("myapp");
+ QVERIFY2(regularFileExists(productFileName), qPrintable(productFileName));
// Incremental build without changes.
QCOMPARE(runQbs(), 0);
@@ -1740,6 +1778,18 @@ void TestBlackbox::mocCppIncluded()
QCOMPARE(runQbs(), 0);
}
+void TestBlackbox::nonBrokenFilesInBrokenProduct()
+{
+ QDir::setCurrent(testDataDir + "/non-broken-files-in-broken-product");
+ QbsRunParameters params("-k");
+ params.expectFailure = true;
+ QVERIFY(runQbs(params) != 0);
+ QVERIFY(m_qbsStdout.contains("fine.cpp"));
+ QVERIFY(runQbs(params) != 0);
+ QEXPECT_FAIL("", "QBS-635", Continue);
+ QVERIFY(!m_qbsStdout.contains("fine.cpp")); // The non-broken file must not be recompiled.
+}
+
void TestBlackbox::objC()
{
QDir::setCurrent(testDataDir + "/objc");
@@ -1751,7 +1801,7 @@ void TestBlackbox::qmlDebugging()
QDir::setCurrent(testDataDir + "/qml-debugging");
QCOMPARE(runQbs(), 0);
QProcess nm;
- nm.start("nm", QStringList(HostOsInfo::appendExecutableSuffix(buildDir + "/debuggable-app")));
+ nm.start("nm", QStringList(executableFilePath("debuggable-app")));
if (nm.waitForStarted()) { // Let's ignore hosts without nm.
QVERIFY2(nm.waitForFinished(), qPrintable(nm.errorString()));
QVERIFY2(nm.exitCode() == 0, nm.readAllStandardError().constData());
@@ -1784,17 +1834,80 @@ void TestBlackbox::propertiesBlocks()
QCOMPARE(runQbs(), 0);
}
+void TestBlackbox::radAfterIncompleteBuild_data()
+{
+ QTest::addColumn<QString>("projectFileName");
+ QTest::newRow("Project with Rule") << "project_with_rule.qbs";
+ QTest::newRow("Project with Transformer") << "project_with_transformer.qbs";
+}
+
+void TestBlackbox::radAfterIncompleteBuild()
+{
+ QDir::setCurrent(testDataDir + "/rad-after-incomplete-build");
+ rmDirR(buildDir);
+ QFETCH(QString, projectFileName);
+
+ // Step 1: Have a directory where a file used to be.
+ QbsRunParameters params(QStringList() << "-f" << projectFileName);
+ QCOMPARE(runQbs(params), 0);
+ waitForNewTimestamp();
+ QFile projectFile(projectFileName);
+ QVERIFY(projectFile.open(QIODevice::ReadWrite));
+ QByteArray content = projectFile.readAll();
+ content.replace("oldfile", "oldfile/newfile");
+ projectFile.resize(0);
+ projectFile.write(content);
+ projectFile.flush();
+ params.expectFailure = true;
+ QVERIFY(runQbs(params) != 0);
+ waitForNewTimestamp();
+ content.replace("oldfile/newfile", "newfile");
+ projectFile.resize(0);
+ projectFile.write(content);
+ projectFile.flush();
+ params.expectFailure = false;
+ QCOMPARE(runQbs(params), 0);
+ waitForNewTimestamp();
+ content.replace("newfile", "oldfile/newfile");
+ projectFile.resize(0);
+ projectFile.write(content);
+ projectFile.flush();
+ QCOMPARE(runQbs(params), 0);
+
+ // Step 2: Have a file where a directory used to be.
+ waitForNewTimestamp();
+ content.replace("oldfile/newfile", "oldfile");
+ projectFile.resize(0);
+ projectFile.write(content);
+ projectFile.flush();
+ params.expectFailure = true;
+ QVERIFY(runQbs(params) != 0);
+ waitForNewTimestamp();
+ content.replace("oldfile", "newfile");
+ projectFile.resize(0);
+ projectFile.write(content);
+ projectFile.flush();
+ params.expectFailure = false;
+ QCOMPARE(runQbs(params), 0);
+ waitForNewTimestamp();
+ content.replace("newfile", "oldfile");
+ projectFile.resize(0);
+ projectFile.write(content);
+ projectFile.flush();
+ QCOMPARE(runQbs(params), 0);
+}
+
void TestBlackbox::installedApp()
{
QDir::setCurrent(testDataDir + "/installed_artifact");
QCOMPARE(runQbs(QbsRunParameters("install")), 0);
- QVERIFY(QFile::exists(defaultInstallRoot
+ QVERIFY(regularFileExists(defaultInstallRoot
+ HostOsInfo::appendExecutableSuffix(QLatin1String("/usr/bin/installedApp"))));
QCOMPARE(runQbs(QbsRunParameters(QLatin1String("install"), QStringList("--install-root")
<< (testDataDir + "/installed-app"))), 0);
- QVERIFY(QFile::exists(testDataDir
+ QVERIFY(regularFileExists(testDataDir
+ HostOsInfo::appendExecutableSuffix("/installed-app/usr/bin/installedApp")));
QFile addedFile(defaultInstallRoot + QLatin1String("/blubb.txt"));
@@ -1802,9 +1915,9 @@ void TestBlackbox::installedApp()
addedFile.close();
QVERIFY(addedFile.exists());
QCOMPARE(runQbs(QbsRunParameters(QLatin1String("install"), QStringList("--remove-first"))), 0);
- QVERIFY(QFile::exists(defaultInstallRoot
+ QVERIFY(regularFileExists(defaultInstallRoot
+ HostOsInfo::appendExecutableSuffix(QLatin1String("/usr/bin/installedApp"))));
- QVERIFY(QFile::exists(defaultInstallRoot + QLatin1String("/usr/src/main.cpp")));
+ QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/usr/src/main.cpp")));
QVERIFY(!addedFile.exists());
// Check whether changing install parameters on the product causes re-installation.
@@ -1817,9 +1930,9 @@ void TestBlackbox::installedApp()
projectFile.write(content);
QVERIFY(projectFile.flush());
QCOMPARE(runQbs(QbsRunParameters(QLatin1String("install"))), 0);
- QVERIFY(QFile::exists(defaultInstallRoot
+ QVERIFY(regularFileExists(defaultInstallRoot
+ HostOsInfo::appendExecutableSuffix(QLatin1String("/usr/local/bin/installedApp"))));
- QVERIFY(QFile::exists(defaultInstallRoot + QLatin1String("/usr/local/src/main.cpp")));
+ QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/usr/local/src/main.cpp")));
// Check whether changing install parameters on the artifact causes re-installation.
content.replace("qbs.installDir: \"bin\"", "qbs.installDir: 'custom'");
@@ -1828,7 +1941,7 @@ void TestBlackbox::installedApp()
projectFile.write(content);
QVERIFY(projectFile.flush());
QCOMPARE(runQbs(QbsRunParameters(QLatin1String("install"))), 0);
- QVERIFY(QFile::exists(defaultInstallRoot
+ QVERIFY(regularFileExists(defaultInstallRoot
+ HostOsInfo::appendExecutableSuffix(QLatin1String("/usr/local/custom/installedApp"))));
// Check whether changing install parameters on a source file causes re-installation.
@@ -1838,7 +1951,7 @@ void TestBlackbox::installedApp()
projectFile.write(content);
projectFile.close();
QCOMPARE(runQbs(QbsRunParameters(QLatin1String("install"))), 0);
- QVERIFY(QFile::exists(defaultInstallRoot + QLatin1String("/usr/local/source/main.cpp")));
+ QVERIFY(regularFileExists(defaultInstallRoot + QLatin1String("/usr/local/source/main.cpp")));
rmDirR(buildDir);
QbsRunParameters params;
@@ -1941,7 +2054,7 @@ void TestBlackbox::testNsis()
bool haveMakeNsis = false;
foreach (const QString &path, paths) {
- if (QFile::exists(QDir::fromNativeSeparators(path) +
+ if (regularFileExists(QDir::fromNativeSeparators(path) +
HostOsInfo::appendExecutableSuffix(QLatin1String("/makensis")))) {
haveMakeNsis = true;
break;
@@ -2001,9 +2114,9 @@ static bool haveWiX()
}
foreach (const QString &path, paths) {
- if (QFile::exists(QDir::fromNativeSeparators(path) +
+ if (regularFileExists(QDir::fromNativeSeparators(path) +
HostOsInfo::appendExecutableSuffix(QLatin1String("/candle"))) &&
- QFile::exists(QDir::fromNativeSeparators(path) +
+ regularFileExists(QDir::fromNativeSeparators(path) +
HostOsInfo::appendExecutableSuffix(QLatin1String("/light")))) {
return true;
}
@@ -2034,8 +2147,77 @@ void TestBlackbox::testWiX()
QVERIFY(m_qbsStdout.contains("compiling QbsBootstrapper.wxs"));
QVERIFY(m_qbsStdout.contains("linking qbs-" + arch + ".msi"));
QVERIFY(m_qbsStdout.contains("linking qbs-setup-" + arch + ".exe"));
- QVERIFY(QFile::exists(buildDir + "/qbs-" + arch + ".msi"));
- QVERIFY(QFile::exists(buildDir + "/qbs-setup-" + arch + ".exe"));
+ QVERIFY(regularFileExists(buildDir + "/QbsSetup/qbs-" + arch + ".msi"));
+ QVERIFY(regularFileExists(buildDir + "/QbsBootstrapper/qbs-setup-" + arch + ".exe"));
+}
+
+static QString findExecutable(const QStringList &fileNames)
+{
+ const QStringList path = QString::fromLocal8Bit(qgetenv("PATH"))
+ .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts);
+
+ foreach (const QString &fileName, fileNames) {
+ foreach (const QString &ppath, path) {
+ const QString fullPath = ppath + QLatin1Char('/') + fileName;
+ if (QFileInfo(fullPath).exists())
+ return QDir::cleanPath(fullPath);
+ }
+ }
+ return QString();
+}
+
+static bool haveNodeJs()
+{
+ // The Node.js binary is called nodejs on Debian/Ubuntu-family operating systems due to a
+ // conflict with another package containing a binary named node
+ return !findExecutable(QStringList()
+ << QLatin1String("nodejs")
+ << QLatin1String("node")).isEmpty();
+}
+
+void TestBlackbox::testNodeJs()
+{
+ if (!haveNodeJs()) {
+ SKIP_TEST("Node.js is not installed");
+ return;
+ }
+
+ QDir::setCurrent(testDataDir + QLatin1String("/nodejs"));
+
+ QbsRunParameters params;
+ params.command = QLatin1String("run");
+ QCOMPARE(runQbs(params), 0);
+ QVERIFY((bool)m_qbsStdout.contains("hello world"));
+ QVERIFY(regularFileExists(buildDir + "/hello/hello.js"));
+}
+
+void TestBlackbox::testTypeScript()
+{
+ if (!haveNodeJs()) {
+ SKIP_TEST("node.js is not installed");
+ return;
+ }
+
+ QDir::setCurrent(testDataDir + QLatin1String("/typescript"));
+
+ QbsRunParameters params;
+ params.command = QLatin1String("run");
+ params.arguments = QStringList() << "-p" << "animals";
+ QCOMPARE(runQbs(params), 0);
+
+ QVERIFY(regularFileExists(buildDir + "/animals/animals.js"));
+ QVERIFY(regularFileExists(buildDir + "/animals/extra.js"));
+ QVERIFY(regularFileExists(buildDir + "/animals/main.js"));
+}
+
+QString TestBlackbox::productBuildDir(const QString &productName) const
+{
+ return buildDir + '/' + productName;
+}
+
+QString TestBlackbox::executableFilePath(const QString &productName) const
+{
+ return productBuildDir(productName) + '/' + HostOsInfo::appendExecutableSuffix(productName);
}
QTEST_MAIN(TestBlackbox)
diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h
index c236d4273..568d1c08e 100644
--- a/tests/auto/blackbox/tst_blackbox.h
+++ b/tests/auto/blackbox/tst_blackbox.h
@@ -100,6 +100,7 @@ private slots:
void addedFilePersistent();
void addQObjectMacroToCppFile();
void baseProperties();
+ void buildDirectories();
void build_project_data();
void build_project();
void build_project_dry_run_data();
@@ -114,6 +115,7 @@ private slots:
void duplicateProductNames_data();
void dynamicLibs();
void dynamicRuleOutputs();
+ void emptyFileTagList();
void erroneousFiles_data();
void erroneousFiles();
void explicitlyDependsOn();
@@ -125,15 +127,19 @@ private slots:
void jsExtensionsTextFile();
void inheritQbsSearchPaths();
void mocCppIncluded();
+ void nonBrokenFilesInBrokenProduct();
void objC();
void qmlDebugging();
void projectWithPropertiesItem();
void properQuoting();
void propertiesBlocks();
+ void radAfterIncompleteBuild_data();
+ void radAfterIncompleteBuild();
void resolve_project_data();
void resolve_project();
void resolve_project_dry_run_data();
void resolve_project_dry_run();
+ void usingsAsSoleInputsNonMultiplexed();
void clean();
void exportSimple();
void exportWithRecursiveDepends();
@@ -173,8 +179,13 @@ private slots:
void testNsis();
void testEmbedInfoPlist();
void testWiX();
+ void testNodeJs();
+ void testTypeScript();
private:
+ QString productBuildDir(const QString &productName) const;
+ QString executableFilePath(const QString &productName) const;
+
QByteArray m_qbsStderr;
QByteArray m_qbsStdout;
};