aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2020-03-05 10:15:11 +0100
committerChristian Kandeler <christian.kandeler@qt.io>2020-03-05 11:04:24 +0000
commitee2509dcc7ed822e6b4a67016b83934e6375bbf3 (patch)
treedbe2dacecfd70e829687e62f82aa43b10dce1298 /tests
parent8eebdd24745c57be3baf0d56d3ac6780a38921f1 (diff)
Rule execution: Fix potential infinite loop
Dependency scanning can generate inverse dependencies. For instance, a Qt C++ file "myobject.cpp" containing the Q_OBJECT macro will typically include a file "myobject.moc", which is generated from the cpp file. When scanning the inputs of "myobject.moc", the artifact will encounter itself as a scan dependency. There is code that prevents a dependency cycle in this case. Let's now consider the case where such a rule has a second output artifact: When scanning the inputs of that artifact, we will encounter the first artifact as a scan dependency. This case was not handled, leading to an infinite loop in rule execution. We fix this by rejecting scan dependencies that have the same transformer as the artifact whose inputs are being scanned. Change-Id: I767ceaad387c2e315738070e01ef9322764afb65 Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'tests')
-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/tst_blackbox.cpp7
-rw-r--r--tests/auto/blackbox/tst_blackbox.h1
4 files changed, 43 insertions, 0 deletions
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/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index 324723ce3..1a3a1943c 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -942,6 +942,13 @@ void TestBlackbox::dependenciesProperty()
QCOMPARE(product2_cpp_defines.first().toString(), QLatin1String("DIGEDAG"));
}
+void TestBlackbox::dependencyScanningLoop()
+{
+ QDir::setCurrent(testDataDir + "/dependency-scanning-loop");
+ QCOMPARE(runQbs(), 0);
+ QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData());
+}
+
void TestBlackbox::deprecatedProperty()
{
QDir::setCurrent(testDataDir + "/deprecated-property");
diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h
index ec6b9f7e4..fb36d85e9 100644
--- a/tests/auto/blackbox/tst_blackbox.h
+++ b/tests/auto/blackbox/tst_blackbox.h
@@ -86,6 +86,7 @@ private slots:
void conanfileProbe();
void cpuFeatures();
void dependenciesProperty();
+ void dependencyScanningLoop();
void deprecatedProperty();
void disappearedProfile();
void discardUnusedData();