aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2017-11-02 16:10:38 +0100
committerChristian Kandeler <christian.kandeler@qt.io>2017-11-10 10:01:20 +0000
commit4ede42b26d871b1571c0aba6c2b3cc54249356f5 (patch)
treec6c70038b945da681c8c533bb3c5943a0c3fd42e /tests
parent2530d46c5a8a9dfba6e02b48a376545cdaf7a361 (diff)
Better change tracking for imported JS files
We did both too much and too little: Firstly, we invalidated all rules that appeared in a file that imported a changed JS file, independent of whether that import was relevant to the rule. Secondly, we did not catch changes to recursively imported files at all. Now we track accesses to functions in imports and invalidate a rule or command only if a file to which such an access refers has been modified. More fine-grained checks (e.g. per function) would be possible, but incur more overhead, as we'd have to store the respective source code in the build graph. Change-Id: I95f62d233bf87d2c39abbe37056a8fe434f20b5a Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/blackbox/testdata/import-change-tracking/custom1command.js3
-rw-r--r--tests/auto/blackbox/testdata/import-change-tracking/custom1prepare1.js4
-rw-r--r--tests/auto/blackbox/testdata/import-change-tracking/custom1prepare2.js10
-rw-r--r--tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/custom2prepare1.js0
-rw-r--r--tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/custom2prepare2.js9
-rw-r--r--tests/auto/blackbox/testdata/import-change-tracking/import-change-tracking-product.qbs37
-rw-r--r--tests/auto/blackbox/testdata/import-change-tracking/import-change-tracking.qbs6
-rw-r--r--tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/custom2command1.js1
-rw-r--r--tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/custom2command2.js3
-rw-r--r--tests/auto/blackbox/testdata/import-change-tracking/input1.txt0
-rw-r--r--tests/auto/blackbox/testdata/import-change-tracking/input2.txt0
-rw-r--r--tests/auto/blackbox/testdata/import-change-tracking/irrelevant.js1
-rw-r--r--tests/auto/blackbox/tst_blackbox.cpp79
-rw-r--r--tests/auto/blackbox/tst_blackbox.h1
14 files changed, 154 insertions, 0 deletions
diff --git a/tests/auto/blackbox/testdata/import-change-tracking/custom1command.js b/tests/auto/blackbox/testdata/import-change-tracking/custom1command.js
new file mode 100644
index 000000000..1f21beb8d
--- /dev/null
+++ b/tests/auto/blackbox/testdata/import-change-tracking/custom1command.js
@@ -0,0 +1,3 @@
+var Irrelevant = require("./irrelevant.js");
+
+function sourceCode() { }
diff --git a/tests/auto/blackbox/testdata/import-change-tracking/custom1prepare1.js b/tests/auto/blackbox/testdata/import-change-tracking/custom1prepare1.js
new file mode 100644
index 000000000..5df9b3873
--- /dev/null
+++ b/tests/auto/blackbox/testdata/import-change-tracking/custom1prepare1.js
@@ -0,0 +1,4 @@
+var CustomPrepare = require("./custom1prepare2.js");
+var Irrelevant = require("./irrelevant.js");
+
+function prepare() { return CustomPrepare.prepare(); }
diff --git a/tests/auto/blackbox/testdata/import-change-tracking/custom1prepare2.js b/tests/auto/blackbox/testdata/import-change-tracking/custom1prepare2.js
new file mode 100644
index 000000000..79be59bf9
--- /dev/null
+++ b/tests/auto/blackbox/testdata/import-change-tracking/custom1prepare2.js
@@ -0,0 +1,10 @@
+var Custom1Command = require("./custom1command.js");
+var Irrelevant = require("./irrelevant.js");
+
+function prepare() {
+ console.info("running custom1 prepare script");
+ var cmd = new JavaScriptCommand();
+ cmd.description = "running custom1 command";
+ cmd.sourceCode = function() { return Custom1Command.sourceCode(); };
+ return cmd;
+}
diff --git a/tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/custom2prepare1.js b/tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/custom2prepare1.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/custom2prepare1.js
diff --git a/tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/custom2prepare2.js b/tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/custom2prepare2.js
new file mode 100644
index 000000000..5bd6852d8
--- /dev/null
+++ b/tests/auto/blackbox/testdata/import-change-tracking/custom2prepare/custom2prepare2.js
@@ -0,0 +1,9 @@
+var Custom2Command = require("custom2command");
+
+function prepare() {
+ console.info("running custom2 prepare script");
+ var cmd = new JavaScriptCommand();
+ cmd.description = "running custom2 command";
+ cmd.sourceCode = function() { return Custom2Command.sourceCode(); };
+ return cmd;
+}
diff --git a/tests/auto/blackbox/testdata/import-change-tracking/import-change-tracking-product.qbs b/tests/auto/blackbox/testdata/import-change-tracking/import-change-tracking-product.qbs
new file mode 100644
index 000000000..f7e9bc5de
--- /dev/null
+++ b/tests/auto/blackbox/testdata/import-change-tracking/import-change-tracking-product.qbs
@@ -0,0 +1,37 @@
+import qbs
+import "irrelevant.js" as Irrelevant
+import "custom1prepare1.js" as Custom1Prepare
+import "custom2prepare" as Custom2Prepare
+
+Product {
+ name: "customProduct"
+ type: ["custom1", "custom2"]
+
+ property string irrelevant: Irrelevant.irrelevant()
+
+ Group {
+ files: "input1.txt"
+ fileTags: "input.custom1"
+ }
+
+ Group {
+ files: "input2.txt"
+ fileTags: "input.custom2"
+ }
+
+ Rule {
+ inputs: "input.custom1"
+ Artifact { filePath: "dummy.custom1"; fileTags: "custom1" }
+ prepare: {
+ return Custom1Prepare.prepare();
+ }
+ }
+
+ Rule {
+ inputs: "input.custom2"
+ Artifact { filePath: "dummy.custom2"; fileTags: "custom2" }
+ prepare: {
+ return Custom2Prepare.prepare();
+ }
+ }
+}
diff --git a/tests/auto/blackbox/testdata/import-change-tracking/import-change-tracking.qbs b/tests/auto/blackbox/testdata/import-change-tracking/import-change-tracking.qbs
new file mode 100644
index 000000000..009c0897f
--- /dev/null
+++ b/tests/auto/blackbox/testdata/import-change-tracking/import-change-tracking.qbs
@@ -0,0 +1,6 @@
+import qbs
+
+Project {
+ qbsSearchPaths: ["."]
+ references: "import-change-tracking-product.qbs"
+}
diff --git a/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/custom2command1.js b/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/custom2command1.js
new file mode 100644
index 000000000..c008738be
--- /dev/null
+++ b/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/custom2command1.js
@@ -0,0 +1 @@
+var Irrelevant = require("../../irrelevant.js");
diff --git a/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/custom2command2.js b/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/custom2command2.js
new file mode 100644
index 000000000..98829a922
--- /dev/null
+++ b/tests/auto/blackbox/testdata/import-change-tracking/imports/custom2command/custom2command2.js
@@ -0,0 +1,3 @@
+var Irrelevant = require("../../irrelevant.js");
+
+function sourceCode() { }
diff --git a/tests/auto/blackbox/testdata/import-change-tracking/input1.txt b/tests/auto/blackbox/testdata/import-change-tracking/input1.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/import-change-tracking/input1.txt
diff --git a/tests/auto/blackbox/testdata/import-change-tracking/input2.txt b/tests/auto/blackbox/testdata/import-change-tracking/input2.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/auto/blackbox/testdata/import-change-tracking/input2.txt
diff --git a/tests/auto/blackbox/testdata/import-change-tracking/irrelevant.js b/tests/auto/blackbox/testdata/import-change-tracking/irrelevant.js
new file mode 100644
index 000000000..ebd6750a8
--- /dev/null
+++ b/tests/auto/blackbox/testdata/import-change-tracking/irrelevant.js
@@ -0,0 +1 @@
+function irrelevant() { return "irrelevant"; }
diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp
index d4e4c81ca..0567ed433 100644
--- a/tests/auto/blackbox/tst_blackbox.cpp
+++ b/tests/auto/blackbox/tst_blackbox.cpp
@@ -5277,6 +5277,85 @@ void TestBlackbox::groupsInModules()
QCOMPARE(output.readAll().trimmed(), QByteArray("diamond"));
}
+void TestBlackbox::importChangeTracking()
+{
+ QDir::setCurrent(testDataDir + "/import-change-tracking");
+ QCOMPARE(runQbs(QStringList({"-f", "import-change-tracking.qbs"})), 0);
+ QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData());
+
+ // Change in imported file that is not used in any rule or command.
+ WAIT_FOR_NEW_TIMESTAMP();
+ touch("irrelevant.js");
+ QCOMPARE(runQbs(), 0);
+ QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData());
+
+ // Change in directly imported file only used by one prepare script.
+ WAIT_FOR_NEW_TIMESTAMP();
+ touch("custom1prepare1.js");
+ QCOMPARE(runQbs(), 0);
+ QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData());
+
+ // Change in recursively imported file only used by one prepare script.
+ WAIT_FOR_NEW_TIMESTAMP();
+ touch("custom1prepare2.js");
+ QCOMPARE(runQbs(), 0);
+ QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData());
+
+ // Change in imported file used only by one command.
+ WAIT_FOR_NEW_TIMESTAMP();
+ touch("custom1command.js");
+ QCOMPARE(runQbs(), 0);
+ QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData());
+
+ // Change in file only used by one prepare script, using directory import.
+ WAIT_FOR_NEW_TIMESTAMP();
+ touch("custom2prepare/custom2prepare2.js");
+ QCOMPARE(runQbs(), 0);
+ QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData());
+
+ // Change in file used only by one command, imported via search path.
+ WAIT_FOR_NEW_TIMESTAMP();
+ touch("imports/custom2command/custom2command1.js");
+ QCOMPARE(runQbs(), 0);
+ QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData());
+ QVERIFY2(!m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData());
+
+ // Change everything at once.
+ WAIT_FOR_NEW_TIMESTAMP();
+ touch("irrelevant.js");
+ touch("custom1prepare1.js");
+ touch("custom1prepare2.js");
+ touch("custom1command.js");
+ touch("custom2prepare/custom2prepare1.js");
+ touch("imports/custom2command/custom2command2.js");
+ QCOMPARE(runQbs(), 0);
+ QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("running custom1 prepare script"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("running custom2 prepare script"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("running custom1 command"), m_qbsStdout.constData());
+ QVERIFY2(m_qbsStdout.contains("running custom2 command"), m_qbsStdout.constData());
+}
+
void TestBlackbox::probesInNestedModules()
{
QDir::setCurrent(testDataDir + "/probes-in-nested-modules");
diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h
index 05b8d4838..2fd561742 100644
--- a/tests/auto/blackbox/tst_blackbox.h
+++ b/tests/auto/blackbox/tst_blackbox.h
@@ -96,6 +96,7 @@ private slots:
void fileDependencies();
void generatedArtifactAsInputToDynamicRule();
void groupsInModules();
+ void importChangeTracking();
void importInPropertiesCondition();
void importingProduct();
void importsConflict();