diff options
Diffstat (limited to 'tests')
402 files changed, 5584 insertions, 1946 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3a868fbac..1ff088061 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,3 +1,5 @@ add_subdirectory(auto) add_subdirectory(benchmarker) +add_subdirectory(clang-format-test) add_subdirectory(fuzzy-test) +add_subdirectory(lspclient) diff --git a/tests/auto/api/api.pro b/tests/auto/api/api.pro deleted file mode 100644 index 36dcec237..000000000 --- a/tests/auto/api/api.pro +++ /dev/null @@ -1,27 +0,0 @@ -TARGET = tst_api - -HEADERS = tst_api.h -SOURCES = tst_api.cpp - -include(../../../src/library_dirname.pri) -isEmpty(QBS_RELATIVE_LIBEXEC_PATH) { - win32:QBS_RELATIVE_LIBEXEC_PATH=. - else:QBS_RELATIVE_LIBEXEC_PATH=../libexec/qbs -} -isEmpty(QBS_RELATIVE_PLUGINS_PATH):QBS_RELATIVE_PLUGINS_PATH=../$${QBS_LIBRARY_DIRNAME} -isEmpty(QBS_RELATIVE_SEARCH_PATH):QBS_RELATIVE_SEARCH_PATH=.. -DEFINES += QBS_RELATIVE_LIBEXEC_PATH=\\\"$${QBS_RELATIVE_LIBEXEC_PATH}\\\" -DEFINES += QBS_RELATIVE_PLUGINS_PATH=\\\"$${QBS_RELATIVE_PLUGINS_PATH}\\\" -DEFINES += QBS_RELATIVE_SEARCH_PATH=\\\"$${QBS_RELATIVE_SEARCH_PATH}\\\" - -include(../auto.pri) - -DATA_DIRS = testdata - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/api/testdata/QBS-728/QBS-728.qbs b/tests/auto/api/testdata/QBS-728/QBS-728.qbs index 5969e13cc..cdeb7c6db 100644 --- a/tests/auto/api/testdata/QBS-728/QBS-728.qbs +++ b/tests/auto/api/testdata/QBS-728/QBS-728.qbs @@ -1,5 +1,5 @@ Product { - property bool isBlubbOS: qbs.targetOS.contains("blubb-OS") + property bool isBlubbOS: qbs.targetOS.includes("blubb-OS") qbs.profiles: isBlubbOS ? ["blubb-profile"] : [project.profile] qbs.architecture: "blubb-arch" } diff --git a/tests/auto/api/testdata/app-without-sources/app-without-sources.qbs b/tests/auto/api/testdata/app-without-sources/app-without-sources.qbs index 4cc25ad66..db707f515 100644 --- a/tests/auto/api/testdata/app-without-sources/app-without-sources.qbs +++ b/tests/auto/api/testdata/app-without-sources/app-without-sources.qbs @@ -26,7 +26,7 @@ Project { // HACK: cpp.entryPoint currently not working 100% with gcc Properties { - condition: qbs.toolchain.contains("msvc") + condition: qbs.toolchain.includes("msvc") cpp.entryPoint: "main" cpp.dynamicLibraries: ["ucrt", "kernel32"] } diff --git a/tests/auto/api/testdata/change-dependent-lib/change-dependent-lib.qbs b/tests/auto/api/testdata/change-dependent-lib/change-dependent-lib.qbs index 222dc4476..cb925eeca 100644 --- a/tests/auto/api/testdata/change-dependent-lib/change-dependent-lib.qbs +++ b/tests/auto/api/testdata/change-dependent-lib/change-dependent-lib.qbs @@ -18,7 +18,7 @@ Project { cpp.defines: ["XXXX"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/api/testdata/codegen/codegen.qbs b/tests/auto/api/testdata/codegen/codegen.qbs index 29c7818c4..42e4c6b08 100644 --- a/tests/auto/api/testdata/codegen/codegen.qbs +++ b/tests/auto/api/testdata/codegen/codegen.qbs @@ -43,7 +43,7 @@ Project { // check whether multipart module name translation is working var actual = product.moduleProperty("Qt.core", "mocName"); - if (!actual || !actual.contains("moc")) + if (!actual || !actual.includes("moc")) throw "multipart module name translation is broken"; // check whether we can access project properties here @@ -57,7 +57,7 @@ Project { code = expandMacros(code, product.replacements); var args = ['echo ' + code + '>' + output.filePath] var cmd - if (product.moduleProperty("qbs", "hostOS").contains('windows')) { + if (product.moduleProperty("qbs", "hostOS").includes('windows')) { cmd = new Command(product.qbs.windowsShellPath, ['/C'].concat(args)); } else { args[0] = args[0].replace(/\(/g, '\\(') diff --git a/tests/auto/api/testdata/disabled-product/disabled-product.qbs b/tests/auto/api/testdata/disabled-product/disabled-product.qbs index dad8f5d4c..e7eea7380 100644 --- a/tests/auto/api/testdata/disabled-product/disabled-product.qbs +++ b/tests/auto/api/testdata/disabled-product/disabled-product.qbs @@ -2,7 +2,7 @@ CppApplication { condition: false files: "main.cpp" Group { - condition: qbs.targetOS.contains("stuff") + condition: qbs.targetOS.includes("stuff") qbs.install: false } } diff --git a/tests/auto/api/testdata/export-simple/export-simple.qbs b/tests/auto/api/testdata/export-simple/export-simple.qbs index 01177049d..84ce5541d 100644 --- a/tests/auto/api/testdata/export-simple/export-simple.qbs +++ b/tests/auto/api/testdata/export-simple/export-simple.qbs @@ -43,7 +43,7 @@ Project { } Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } 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 99aafea1c..687955f2f 100644 --- a/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs +++ b/tests/auto/api/testdata/infinite-loop-process/infinite-loop.qbs @@ -8,7 +8,7 @@ Project { name: "infinite-loop" cpp.cxxLanguageVersion: "c++11" Properties { - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") cpp.driverFlags: "-pthread" } } @@ -19,7 +19,7 @@ Project { Depends { name: "infinite-loop" } Depends { name: "cpp" // Make sure build environment is set up properly. - condition: Host.os().contains("windows") && qbs.toolchain.contains("gcc") + condition: Host.os().includes("windows") && qbs.toolchain.includes("gcc") } Rule { inputsFromDependencies: "application" diff --git a/tests/auto/blackbox/testdata/concurrent-executor/dummy1.input b/tests/auto/api/testdata/infinite-loop-scanning-scan/file.in index e69de29bb..e69de29bb 100644 --- a/tests/auto/blackbox/testdata/concurrent-executor/dummy1.input +++ b/tests/auto/api/testdata/infinite-loop-scanning-scan/file.in diff --git a/tests/auto/api/testdata/infinite-loop-scanning-scan/infinite-loop.qbs b/tests/auto/api/testdata/infinite-loop-scanning-scan/infinite-loop.qbs new file mode 100644 index 000000000..5e3e33b6e --- /dev/null +++ b/tests/auto/api/testdata/infinite-loop-scanning-scan/infinite-loop.qbs @@ -0,0 +1,21 @@ +Product { + type: "t" + Depends { name: "m" } + Group { + files: "file.in" + fileTags: "i" + } + Rule { + inputs: "i" + Artifact { + filePath: "dummy" + fileTags: "t" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.silent = true; + cmd.sourceCode = function() {}; + return cmd; + } + } +} diff --git a/tests/auto/api/testdata/infinite-loop-scanning-scan/modules/m/m.qbs b/tests/auto/api/testdata/infinite-loop-scanning-scan/modules/m/m.qbs new file mode 100644 index 000000000..9c8a18072 --- /dev/null +++ b/tests/auto/api/testdata/infinite-loop-scanning-scan/modules/m/m.qbs @@ -0,0 +1,6 @@ +Module { + Scanner { + inputs: "i" + scan: { while (true); } + } +}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/concurrent-executor/dummy2.input b/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/file.in index e69de29bb..e69de29bb 100644 --- a/tests/auto/blackbox/testdata/concurrent-executor/dummy2.input +++ b/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/file.in diff --git a/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/infinite-loop.qbs b/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/infinite-loop.qbs new file mode 100644 index 000000000..5e3e33b6e --- /dev/null +++ b/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/infinite-loop.qbs @@ -0,0 +1,21 @@ +Product { + type: "t" + Depends { name: "m" } + Group { + files: "file.in" + fileTags: "i" + } + Rule { + inputs: "i" + Artifact { + filePath: "dummy" + fileTags: "t" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.silent = true; + cmd.sourceCode = function() {}; + return cmd; + } + } +} diff --git a/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/modules/m/m.qbs b/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/modules/m/m.qbs new file mode 100644 index 000000000..0476478b9 --- /dev/null +++ b/tests/auto/api/testdata/infinite-loop-scanning-searchpaths/modules/m/m.qbs @@ -0,0 +1,7 @@ +Module { + Scanner { + inputs: "i" + searchPaths: { while (true); } + scan: [] + } +} diff --git a/tests/auto/api/testdata/is-runnable/is-runnable.qbs b/tests/auto/api/testdata/is-runnable/is-runnable.qbs index 870279294..e93cc38aa 100644 --- a/tests/auto/api/testdata/is-runnable/is-runnable.qbs +++ b/tests/auto/api/testdata/is-runnable/is-runnable.qbs @@ -5,7 +5,7 @@ Project { DynamicLibrary { name: "lib" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/api/testdata/link-dynamiclibs-staticlibs/link-dynamiclibs-staticlibs.qbs b/tests/auto/api/testdata/link-dynamiclibs-staticlibs/link-dynamiclibs-staticlibs.qbs index b2a54080c..0c86d05c6 100644 --- a/tests/auto/api/testdata/link-dynamiclibs-staticlibs/link-dynamiclibs-staticlibs.qbs +++ b/tests/auto/api/testdata/link-dynamiclibs-staticlibs/link-dynamiclibs-staticlibs.qbs @@ -12,7 +12,7 @@ Project { Depends { name: "cpp" } Depends { name: "static1" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -31,7 +31,7 @@ Project { Depends { name: "static2" } cpp.visibility: 'hidden' Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -40,6 +40,11 @@ Project { name: "static2" files: [ "static2.cpp", "static2.h" ] Depends { name: "cpp" } + Probe { + id: tcPrinter + property bool isGcc: qbs.toolchain.contains("gcc") + configure: { console.info("is gcc: " + isGcc); } + } } } diff --git a/tests/auto/api/testdata/link-dynamiclibs/link-dynamiclibs.qbs b/tests/auto/api/testdata/link-dynamiclibs/link-dynamiclibs.qbs index 2efe8d4e8..e0bce7264 100644 --- a/tests/auto/api/testdata/link-dynamiclibs/link-dynamiclibs.qbs +++ b/tests/auto/api/testdata/link-dynamiclibs/link-dynamiclibs.qbs @@ -17,7 +17,7 @@ Project { Depends { name: "cpp" } Depends { name: "lib2" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -31,7 +31,7 @@ Project { Depends { name: "cpp" } Depends { name: "lib3" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -44,7 +44,7 @@ Project { } Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -58,7 +58,7 @@ Project { } Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } diff --git a/tests/auto/api/testdata/link-staticlibs-dynamiclibs/link-staticlibs-dynamiclibs.qbs b/tests/auto/api/testdata/link-staticlibs-dynamiclibs/link-staticlibs-dynamiclibs.qbs index d7ed6c862..c30cf40f9 100644 --- a/tests/auto/api/testdata/link-staticlibs-dynamiclibs/link-staticlibs-dynamiclibs.qbs +++ b/tests/auto/api/testdata/link-staticlibs-dynamiclibs/link-staticlibs-dynamiclibs.qbs @@ -14,9 +14,13 @@ Project { Probe { id: osCheck - property bool isNormalUnix: qbs.targetOS.contains("unix") - && !qbs.targetOS.contains("darwin") - configure: { console.info("is normal unix: " + (isNormalUnix ? "yes" : "no")); } + property bool isNormalUnix: qbs.targetOS.includes("unix") + && !qbs.targetOS.includes("darwin") + property bool isGcc: qbs.toolchain.contains("gcc") + configure: { + console.info("is normal unix: " + (isNormalUnix ? "yes" : "no")); + console.info("is gcc: " + isGcc); + } } } @@ -26,7 +30,7 @@ Project { Depends { name: "cpp" } Depends { name: "static2" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -44,7 +48,7 @@ Project { Depends { name: "cpp" } cpp.visibility: 'hidden' Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/api/testdata/moc-hpp-included/moc-hpp-included.qbs b/tests/auto/api/testdata/moc-hpp-included/moc-hpp-included.qbs index a484b9c22..38d3d88ca 100644 --- a/tests/auto/api/testdata/moc-hpp-included/moc-hpp-included.qbs +++ b/tests/auto/api/testdata/moc-hpp-included/moc-hpp-included.qbs @@ -11,7 +11,7 @@ Project { files: ["object.cpp", "object.h"] Group { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") files: ["object2.mm", "object2.h"] } } diff --git a/tests/auto/api/testdata/new-output-artifact-in-dependency/new-output-artifact-in-dependency.qbs b/tests/auto/api/testdata/new-output-artifact-in-dependency/new-output-artifact-in-dependency.qbs index 5c3e475b0..e87af67c7 100644 --- a/tests/auto/api/testdata/new-output-artifact-in-dependency/new-output-artifact-in-dependency.qbs +++ b/tests/auto/api/testdata/new-output-artifact-in-dependency/new-output-artifact-in-dependency.qbs @@ -4,7 +4,7 @@ Project { name: "lib" files: "lib.cpp" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/api/testdata/objc/objc.qbs b/tests/auto/api/testdata/objc/objc.qbs index 845eb8d32..2fba48d9b 100644 --- a/tests/auto/api/testdata/objc/objc.qbs +++ b/tests/auto/api/testdata/objc/objc.qbs @@ -1,6 +1,6 @@ Project { CppApplication { - condition: qbs.targetOS.contains("macos") + condition: qbs.targetOS.includes("macos") files: "main.mm" cpp.frameworks: [ "Foundation" ] } diff --git a/tests/auto/api/testdata/project-with-properties-item/project-with-properties-item.qbs b/tests/auto/api/testdata/project-with-properties-item/project-with-properties-item.qbs index 866ec4ecb..812c6a65e 100644 --- a/tests/auto/api/testdata/project-with-properties-item/project-with-properties-item.qbs +++ b/tests/auto/api/testdata/project-with-properties-item/project-with-properties-item.qbs @@ -3,7 +3,7 @@ Project { property string libPath: "/usr/lib" Properties { - condition: qbs.targetOS.contains("macos") + condition: qbs.targetOS.includes("macos") binPath: "/Users/boo" libPath: "/Libraries/foo" } diff --git a/tests/auto/api/testdata/properties-blocks/properties-blocks.qbs b/tests/auto/api/testdata/properties-blocks/properties-blocks.qbs index dda4652d2..c234a6b41 100644 --- a/tests/auto/api/testdata/properties-blocks/properties-blocks.qbs +++ b/tests/auto/api/testdata/properties-blocks/properties-blocks.qbs @@ -14,7 +14,7 @@ Product { } Properties { - condition: qbs.targetOS.contains("weird") + condition: qbs.targetOS.includes("weird") cpp.staticLibraries: "abc" } diff --git a/tests/auto/api/testdata/qt5-plugin/qt5-plugin.qbs b/tests/auto/api/testdata/qt5-plugin/qt5-plugin.qbs index d50072ad8..1558e3bc9 100644 --- a/tests/auto/api/testdata/qt5-plugin/qt5-plugin.qbs +++ b/tests/auto/api/testdata/qt5-plugin/qt5-plugin.qbs @@ -7,7 +7,7 @@ DynamicLibrary { Depends { name: "Qt.core" } Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } diff --git a/tests/auto/api/testdata/rename-product/rename.qbs b/tests/auto/api/testdata/rename-product/rename.qbs index 9d23bf804..aa59d9650 100644 --- a/tests/auto/api/testdata/rename-product/rename.qbs +++ b/tests/auto/api/testdata/rename-product/rename.qbs @@ -11,7 +11,7 @@ Project { cpp.defines: "MY_EXPORT=DLL_EXPORT" files: "lib.cpp" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/api/testdata/rename-target-artifact/rename.qbs b/tests/auto/api/testdata/rename-target-artifact/rename.qbs index 810b0eb08..aea4b8d9e 100644 --- a/tests/auto/api/testdata/rename-target-artifact/rename.qbs +++ b/tests/auto/api/testdata/rename-target-artifact/rename.qbs @@ -14,7 +14,7 @@ Project { qbs.buildVariant: "release" files: "lib.cpp" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/api/testdata/restored-warnings/restored-warnings.qbs b/tests/auto/api/testdata/restored-warnings/restored-warnings.qbs index bbdfbeadb..9d4abb757 100644 --- a/tests/auto/api/testdata/restored-warnings/restored-warnings.qbs +++ b/tests/auto/api/testdata/restored-warnings/restored-warnings.qbs @@ -1,14 +1,25 @@ import qbs.Process 1.5 -CppApplication { - name: "theProduct" +Project { + CppApplication { + name: "theProduct" - property bool moreFiles: false - cpp.blubb: true + cpp.blubb: true - files: ["file.cpp", "main.cpp"] - Group { - condition: moreFiles - files: ["blubb.cpp"] + files: ["file.cpp", "main.cpp"] + } + + Product { + name: "theOtherProduct" + property bool dummy: { throw "this one comes from a thread"; } + } + + Product { + name: "aThirdProduct" + property bool moreFiles: false + Group { + condition: moreFiles + files: ["blubb.txt"] + } } } diff --git a/tests/auto/api/testdata/same-base-name/same-base-name.qbs b/tests/auto/api/testdata/same-base-name/same-base-name.qbs index 8448d04fd..ba0adfaac 100644 --- a/tests/auto/api/testdata/same-base-name/same-base-name.qbs +++ b/tests/auto/api/testdata/same-base-name/same-base-name.qbs @@ -16,7 +16,7 @@ Project { ] Group { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") files: [ "lib.m", "lib.mm" @@ -25,7 +25,7 @@ Project { Export { Depends { name: "cpp" } - cpp.frameworks: qbs.targetOS.contains("darwin") ? "Foundation" : undefined + cpp.frameworks: qbs.targetOS.includes("darwin") ? "Foundation" : undefined } } } diff --git a/tests/auto/api/testdata/static-lib-deps/static-lib-deps.qbs b/tests/auto/api/testdata/static-lib-deps/static-lib-deps.qbs index b584b4d41..67800b8eb 100644 --- a/tests/auto/api/testdata/static-lib-deps/static-lib-deps.qbs +++ b/tests/auto/api/testdata/static-lib-deps/static-lib-deps.qbs @@ -44,23 +44,23 @@ Project { ] Group { - condition: qbs.targetOS.contains("macos") + condition: qbs.targetOS.includes("macos") files: ["d.mm"] } Properties { - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") cpp.defines: ["WITH_SETUPAPI"] cpp.staticLibraries: ["setupapi"] } Properties { - condition: qbs.targetOS.contains("macos") + condition: qbs.targetOS.includes("macos") cpp.defines: ["WITH_LEX_YACC"] cpp.staticLibraries: ["l", "y"] cpp.frameworks: ["Foundation"] } Properties { - condition: qbs.targetOS.contains("linux") + condition: qbs.targetOS.includes("linux") cpp.defines: ["WITH_PTHREAD"] cpp.staticLibraries: ["pthread"] } @@ -84,7 +84,7 @@ Project { Depends { name: "e" } Properties { - condition: qbs.targetOS.contains("linux") + condition: qbs.targetOS.includes("linux") cpp.driverFlags: ["-static"] } diff --git a/tests/auto/api/testdata/timeout-process/timeout.qbs b/tests/auto/api/testdata/timeout-process/timeout.qbs index c95b5ae67..403506eed 100644 --- a/tests/auto/api/testdata/timeout-process/timeout.qbs +++ b/tests/auto/api/testdata/timeout-process/timeout.qbs @@ -9,7 +9,7 @@ Project { cpp.cxxLanguageVersion: "c++11" cpp.minimumOsxVersion: "10.8" // For <chrono> Properties { - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") cpp.driverFlags: "-pthread" } } @@ -26,7 +26,7 @@ Project { Depends { name: "infinite-loop" } Depends { name: "cpp" // Make sure build environment is set up properly. - condition: Host.os().contains("windows") && qbs.toolchain.contains("gcc") + condition: Host.os().includes("windows") && qbs.toolchain.includes("gcc") } Rule { inputsFromDependencies: "application" diff --git a/tests/auto/api/testdata/tool-in-module/use-outside-project/modules/thetool/thetool.qbs b/tests/auto/api/testdata/tool-in-module/use-outside-project/modules/thetool/thetool.qbs index de9c4e935..e2b1ec6df 100644 --- a/tests/auto/api/testdata/tool-in-module/use-outside-project/modules/thetool/thetool.qbs +++ b/tests/auto/api/testdata/tool-in-module/use-outside-project/modules/thetool/thetool.qbs @@ -6,7 +6,7 @@ Module { Group { name: "thetool binary" files: FileInfo.cleanPath(FileInfo.joinPaths(path, "..", "..", - "thetool" + (Host.os().contains("windows") ? ".exe" : ""))); + "thetool" + (Host.os().includes("windows") ? ".exe" : ""))); fileTags: ["thetool.thetool"] filesAreTargets: true } diff --git a/tests/auto/api/tst_api.cpp b/tests/auto/api/tst_api.cpp index 200239081..45463312b 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(); } @@ -2883,6 +2902,7 @@ void TestApi::targetArtifactStatus() void TestApi::timeout() { QFETCH(QString, projectDirName); + QFETCH(QString, cancelOutput); const auto setupParams = defaultSetupParameters(projectDirName + "/timeout.qbs"); std::unique_ptr<qbs::SetupProjectJob> setupJob{ qbs::Project().setupProject(setupParams, m_logSink, nullptr)}; @@ -2915,13 +2935,15 @@ void TestApi::timeout() const auto errorString = buildJob->error().toString(); QVERIFY2(errorString.contains("cancel"), qPrintable(errorString)); QVERIFY(errorString.contains("timeout")); + QVERIFY(errorString.contains(cancelOutput)); } void TestApi::timeout_data() { QTest::addColumn<QString>("projectDirName"); - QTest::newRow("JS Command") << QString("timeout-js"); - QTest::newRow("Process Command") << QString("timeout-process"); + QTest::addColumn<QString>("cancelOutput"); + QTest::newRow("JS Command") << QString("timeout-js") << QString("infinite loop"); + QTest::newRow("Process Command") << QString("timeout-process") << QString("infinite-loop"); } void TestApi::toolInModule() diff --git a/tests/auto/auto.pri b/tests/auto/auto.pri deleted file mode 100644 index e46f7640a..000000000 --- a/tests/auto/auto.pri +++ /dev/null @@ -1,18 +0,0 @@ -TEMPLATE = app -DESTDIR = ../../../bin -DEFINES += SRCDIR=\\\"$$_PRO_FILE_PWD_\\\" -qbs_test_suite_name = $$replace(_PRO_FILE_, ^.*/([^/.]+)\\.pro$, \\1) -qbs_test_suite_name = $$upper($$replace(qbs_test_suite_name, -, _)) -DEFINES += QBS_TEST_SUITE_NAME=\\\"$${qbs_test_suite_name}\\\" -INCLUDEPATH += $$PWD/../../src $$PWD/../../src/app/shared - -QT = core testlib -CONFIG += testcase console -CONFIG -= app_bundle -CONFIG += c++17 -target.CONFIG += no_default_install - -dev_lib_frameworks=$$QMAKE_XCODE_DEVELOPER_PATH/Library/Frameworks -exists($$dev_lib_frameworks): LIBS += -F$$dev_lib_frameworks - -include(../../src/lib/corelib/use_corelib.pri) diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro deleted file mode 100644 index af06ea131..000000000 --- a/tests/auto/auto.pro +++ /dev/null @@ -1,21 +0,0 @@ -TEMPLATE=subdirs - -qbs_enable_unit_tests { - SUBDIRS += \ - buildgraph \ - language \ - tools \ -} - -SUBDIRS += \ - cmdlineparser \ - blackbox/blackbox.pro \ - blackbox/blackbox-android.pro \ - blackbox/blackbox-apple.pro \ - blackbox/blackbox-baremetal.pro \ - blackbox/blackbox-clangdb.pro \ - blackbox/blackbox-examples.pro \ - blackbox/blackbox-java.pro \ - blackbox/blackbox-joblimits.pro \ - blackbox/blackbox-qt.pro \ - api diff --git a/tests/auto/auto.qbs b/tests/auto/auto.qbs index a4c4beedd..b042d180a 100644 --- a/tests/auto/auto.qbs +++ b/tests/auto/auto.qbs @@ -9,7 +9,9 @@ Project { "blackbox/blackbox-examples.qbs", "blackbox/blackbox-java.qbs", "blackbox/blackbox-joblimits.qbs", + "blackbox/blackbox-providers.qbs", "blackbox/blackbox-qt.qbs", + "blackbox/blackbox-tutorial.qbs", "blackbox/blackbox-windows.qbs", "blackbox/blackbox.qbs", "buildgraph/buildgraph.qbs", diff --git a/tests/auto/blackbox/CMakeLists.txt b/tests/auto/blackbox/CMakeLists.txt index 0bf79a433..88e19acdf 100644 --- a/tests/auto/blackbox/CMakeLists.txt +++ b/tests/auto/blackbox/CMakeLists.txt @@ -1,6 +1,7 @@ add_qbs_test(blackbox DEFINES ${QBS_UNIT_TESTS_DEFINES} + "QBS_VERSION=\"${QBS_VERSION}\"" SOURCES ../shared.h tst_blackboxbase.cpp @@ -62,6 +63,14 @@ add_qbs_test(blackbox-joblimits tst_blackboxjoblimits.cpp ) +add_qbs_test(blackbox-providers + SOURCES + ../shared.h + tst_blackboxbase.cpp + tst_blackboxbase.h + tst_blackboxproviders.cpp + ) + add_qbs_test(blackbox-qt SOURCES ../shared.h @@ -71,6 +80,15 @@ add_qbs_test(blackbox-qt tst_blackboxqt.h ) +add_qbs_test(blackbox-tutorial + SOURCES + ../shared.h + tst_blackboxbase.cpp + tst_blackboxbase.h + tst_blackboxtutorial.h + tst_blackboxtutorial.cpp + ) + add_qbs_test(blackbox-windows SOURCES ../shared.h diff --git a/tests/auto/blackbox/blackbox-android.pro b/tests/auto/blackbox/blackbox-android.pro deleted file mode 100644 index 7aca99e8d..000000000 --- a/tests/auto/blackbox/blackbox-android.pro +++ /dev/null @@ -1,21 +0,0 @@ -TARGET = tst_blackbox-android - -HEADERS = tst_blackboxandroid.h tst_blackboxbase.h -SOURCES = tst_blackboxandroid.cpp tst_blackboxbase.cpp -OBJECTS_DIR = android -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -DATA_DIRS = testdata-android ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES - -DISTFILES += \ - testdata/texttemplate/expected-output-one.txt diff --git a/tests/auto/blackbox/blackbox-apple.pro b/tests/auto/blackbox/blackbox-apple.pro deleted file mode 100644 index 1a009e222..000000000 --- a/tests/auto/blackbox/blackbox-apple.pro +++ /dev/null @@ -1,20 +0,0 @@ -TARGET = tst_blackbox-apple - -HEADERS = tst_blackboxapple.h tst_blackboxbase.h -SOURCES = tst_blackboxapple.cpp tst_blackboxbase.cpp -OBJECTS_DIR = apple -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -QT += xml - -DATA_DIRS = testdata-apple ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox-baremetal.pro b/tests/auto/blackbox/blackbox-baremetal.pro deleted file mode 100644 index 32789346c..000000000 --- a/tests/auto/blackbox/blackbox-baremetal.pro +++ /dev/null @@ -1,18 +0,0 @@ -TARGET = tst_blackbox-baremetal - -HEADERS = tst_blackboxbaremetal.h tst_blackboxbase.h -SOURCES = tst_blackboxbaremetal.cpp tst_blackboxbase.cpp -OBJECTS_DIR = baremetal -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -DATA_DIRS = testdata-baremetal ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox-clangdb.pro b/tests/auto/blackbox/blackbox-clangdb.pro deleted file mode 100644 index 6e4075175..000000000 --- a/tests/auto/blackbox/blackbox-clangdb.pro +++ /dev/null @@ -1,18 +0,0 @@ -TARGET = tst_blackbox-clangdb - -HEADERS = tst_blackboxbase.h tst_clangdb.h -SOURCES = tst_blackboxbase.cpp tst_clangdb.cpp -OBJECTS_DIR = clangdb -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -DATA_DIRS = testdata-clangdb - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox-examples.pro b/tests/auto/blackbox/blackbox-examples.pro deleted file mode 100644 index 70d5b6419..000000000 --- a/tests/auto/blackbox/blackbox-examples.pro +++ /dev/null @@ -1,18 +0,0 @@ -TARGET = tst_blackbox-examples - -HEADERS = tst_blackboxexamples.h tst_blackboxbase.h -SOURCES = tst_blackboxexamples.cpp tst_blackboxbase.cpp -OBJECTS_DIR = examples -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -DATA_DIRS = ../../../examples - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox-java.pro b/tests/auto/blackbox/blackbox-java.pro deleted file mode 100644 index d297d9e09..000000000 --- a/tests/auto/blackbox/blackbox-java.pro +++ /dev/null @@ -1,18 +0,0 @@ -TARGET = tst_blackbox-java - -HEADERS = tst_blackboxjava.h tst_blackboxbase.h -SOURCES = tst_blackboxjava.cpp tst_blackboxbase.cpp -OBJECTS_DIR = java -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -DATA_DIRS = testdata-java ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox-joblimits.pro b/tests/auto/blackbox/blackbox-joblimits.pro deleted file mode 100644 index 85413473e..000000000 --- a/tests/auto/blackbox/blackbox-joblimits.pro +++ /dev/null @@ -1,18 +0,0 @@ -TARGET = tst_blackbox-joblimits - -HEADERS = tst_blackboxbase.h -SOURCES = tst_blackboxjoblimits.cpp tst_blackboxbase.cpp -OBJECTS_DIR = joblimits -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -DATA_DIRS = testdata-joblimits ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox-providers.qbs b/tests/auto/blackbox/blackbox-providers.qbs new file mode 100644 index 000000000..95ebaa423 --- /dev/null +++ b/tests/auto/blackbox/blackbox-providers.qbs @@ -0,0 +1,21 @@ +import qbs.Utilities + +QbsAutotest { + testName: "blackbox-providers" + Depends { name: "qbs_app" } + Depends { name: "qbs-setup-toolchains" } + Group { + name: "testdata" + prefix: "testdata-providers/" + files: ["**/*"] + fileTags: [] + } + files: [ + "../shared.h", + "tst_blackboxbase.cpp", + "tst_blackboxbase.h", + "tst_blackboxproviders.cpp", + "tst_blackboxproviders.h", + ] + cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) +} diff --git a/tests/auto/blackbox/blackbox-qt.pro b/tests/auto/blackbox/blackbox-qt.pro deleted file mode 100644 index e17a04a7e..000000000 --- a/tests/auto/blackbox/blackbox-qt.pro +++ /dev/null @@ -1,18 +0,0 @@ -TARGET = tst_blackbox-qt - -HEADERS = tst_blackboxqt.h tst_blackboxbase.h -SOURCES = tst_blackboxqt.cpp tst_blackboxbase.cpp -OBJECTS_DIR = qt -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -DATA_DIRS = testdata-qt ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox-tutorial.qbs b/tests/auto/blackbox/blackbox-tutorial.qbs new file mode 100644 index 000000000..174821ffa --- /dev/null +++ b/tests/auto/blackbox/blackbox-tutorial.qbs @@ -0,0 +1,21 @@ +import qbs.Utilities + +QbsAutotest { + testName: "blackbox-tutorial" + Depends { name: "qbs_app" } + Depends { name: "qbs-setup-toolchains" } + Group { + name: "testdata" + prefix: "../../../tutorial/" + files: ["**/*"] + fileTags: [] + } + files: [ + "../shared.h", + "tst_blackboxtutorial.cpp", + "tst_blackboxtutorial.h", + "tst_blackboxbase.cpp", + "tst_blackboxbase.h", + ] + cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) +} diff --git a/tests/auto/blackbox/blackbox-windows.pro b/tests/auto/blackbox/blackbox-windows.pro deleted file mode 100644 index a9e8fdbd2..000000000 --- a/tests/auto/blackbox/blackbox-windows.pro +++ /dev/null @@ -1,18 +0,0 @@ -TARGET = tst_blackbox-windows - -HEADERS = tst_blackboxwindows.h tst_blackboxbase.h -SOURCES = tst_blackboxwindows.cpp tst_blackboxbase.cpp -OBJECTS_DIR = windows -MOC_DIR = $${OBJECTS_DIR}-moc - -include(../auto.pri) - -DATA_DIRS = testdata-windows ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox.pro b/tests/auto/blackbox/blackbox.pro deleted file mode 100644 index 42848d077..000000000 --- a/tests/auto/blackbox/blackbox.pro +++ /dev/null @@ -1,21 +0,0 @@ -TARGET = tst_blackbox - -HEADERS = tst_blackbox.h tst_blackboxbase.h -SOURCES = tst_blackbox.cpp tst_blackboxbase.cpp -OBJECTS_DIR = generic -MOC_DIR = $${OBJECTS_DIR}-moc -qbs_enable_unit_tests:DEFINES += QBS_ENABLE_UNIT_TESTS - -include(../auto.pri) - -QT += xml - -DATA_DIRS = testdata ../find - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES diff --git a/tests/auto/blackbox/blackbox.qbs b/tests/auto/blackbox/blackbox.qbs index 3f0ff959a..ac6bf750e 100644 --- a/tests/auto/blackbox/blackbox.qbs +++ b/tests/auto/blackbox/blackbox.qbs @@ -25,4 +25,5 @@ QbsAutotest { ] cpp.defines: base.concat(["SRCDIR=" + Utilities.cStringQuote(path)]) .concat(qbsbuildconfig.enableUnitTests ? ["QBS_ENABLE_UNIT_TESTS"] : []) + .concat("QBS_VERSION=" + Utilities.cStringQuote(qbsversion.version)) } diff --git a/tests/auto/blackbox/find/find-xcode.qbs b/tests/auto/blackbox/find/find-xcode.qbs index bb6ee9718..15c2aa17e 100644 --- a/tests/auto/blackbox/find/find-xcode.qbs +++ b/tests/auto/blackbox/find/find-xcode.qbs @@ -14,7 +14,9 @@ Product { cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; - if (product.moduleProperty("xcode", "present")) { + var present = product.moduleProperty("xcode", "present"); + tools["present"] = !!present; + if (present) { var keys = [ "developerPath", "version" diff --git a/tests/auto/blackbox/testdata-android/minimal-native/minimal-native.qbs b/tests/auto/blackbox/testdata-android/minimal-native/minimal-native.qbs index 570152707..7231f7e62 100644 --- a/tests/auto/blackbox/testdata-android/minimal-native/minimal-native.qbs +++ b/tests/auto/blackbox/testdata-android/minimal-native/minimal-native.qbs @@ -1,7 +1,7 @@ CppApplication { name: "minimalnative" qbs.buildVariant: "release" - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.sdk.packageName: "my.minimalnative" Android.sdk.apkBaseName: name Android.ndk.appStl: "stlport_shared" diff --git a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/product1.qbs b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/product1.qbs index c4a78a30b..c7b9b3de2 100644 --- a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/product1.qbs +++ b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/product1.qbs @@ -5,9 +5,12 @@ Project { name: "p1lib1" files: ["src/main/jni/lib1.cpp"] qbs.targetPlatform: "android" - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" - qbs.architectures: !qbs.architecture ? ["armv7a", "x86"] : undefined + Properties { + qbs.architectures: !qbs.architecture ? ["armv7a", "x86"] : undefined + overrideListProperties: true + } cpp.useRPaths: false } @@ -17,7 +20,7 @@ Project { name: "p1lib2" files: ["src/main/jni/lib2.cpp"] qbs.targetPlatform: "android" - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } diff --git a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/product2.qbs b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/product2.qbs index 9be70dcda..f880a576d 100644 --- a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/product2.qbs +++ b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/product2.qbs @@ -13,7 +13,7 @@ Project { name: "p2lib2" files: ["src/main/jni/lib2.cpp"] qbs.targetPlatform: "android" - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" } diff --git a/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/multiple-libs-per-apk.qbs b/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/multiple-libs-per-apk.qbs index 8b9ded211..a5e193905 100644 --- a/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/multiple-libs-per-apk.qbs +++ b/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/multiple-libs-per-apk.qbs @@ -5,7 +5,7 @@ Project { name: "lib1" files: ["src/main/jni/lib1.cpp"] qbs.targetPlatform: "android" - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } @@ -16,7 +16,7 @@ Project { name: "lib2" files: ["src/main/jni/lib2.cpp"] qbs.targetPlatform: "android" - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "stlport_shared" cpp.useRPaths: false } diff --git a/tests/auto/blackbox/testdata-android/qml-app/qml-app.qbs b/tests/auto/blackbox/testdata-android/qml-app/qml-app.qbs index 472f1b657..5760fa4f0 100644 --- a/tests/auto/blackbox/testdata-android/qml-app/qml-app.qbs +++ b/tests/auto/blackbox/testdata-android/qml-app/qml-app.qbs @@ -3,7 +3,7 @@ QtApplication { Depends { name: "Qt.quick" } Depends { name: "Qt.android_support" } Properties { - condition: qbs.targetOS.contains("android") + condition: qbs.targetOS.includes("android") Qt.android_support.extraPrefixDirs: path } Android.sdk.packageName: "my.qmlapp" diff --git a/tests/auto/blackbox/testdata-android/teapot/teapot.qbs b/tests/auto/blackbox/testdata-android/teapot/teapot.qbs index 30cfbb820..0b1dead6e 100644 --- a/tests/auto/blackbox/testdata-android/teapot/teapot.qbs +++ b/tests/auto/blackbox/testdata-android/teapot/teapot.qbs @@ -51,7 +51,7 @@ Project { files: ["*.cpp", "*.h"].concat( !File.exists(ndkHelperProbe.dir + "/gl3stub.cpp") ? ["gl3stub.c"] : []) } - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "gnustl_shared" cpp.cxxLanguageVersion: "c++11" @@ -137,7 +137,7 @@ Project { Android.sdk.apkBaseName: name Android.sdk.packageName: "com.sample.teapot" Android.sdk.sourceSetDir: teapotProbe.dir - Properties { condition: qbs.toolchain.contains("clang"); Android.ndk.appStl: "c++_shared" } + Properties { condition: qbs.toolchain.includes("clang"); Android.ndk.appStl: "c++_shared" } Android.ndk.appStl: "gnustl_shared" cpp.cxxLanguageVersion: "c++11" cpp.dynamicLibraries: ["log", "android", "EGL", "GLESv2"] diff --git a/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs b/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs index 0a06125eb..5615722d5 100644 --- a/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs +++ b/tests/auto/blackbox/testdata-apple/apple-multiconfig/apple-multiconfig.qbs @@ -56,7 +56,7 @@ Project { name: "singlelib" targetName: "singlelib" files: ["lib.c"] - cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined + cpp.sonamePrefix: qbs.targetOS.includes("darwin") ? "@rpath" : undefined cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] // Turn off multiplexing @@ -128,7 +128,7 @@ Project { targetName: "multilib" files: ["lib.c"] cpp.minimumIosVersion: "8.0" - cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined + cpp.sonamePrefix: qbs.targetOS.includes("darwin") ? "@rpath" : undefined cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) qbs.buildVariants: ["release", "debug", "profiling"] @@ -145,7 +145,7 @@ Project { targetName: "multilib-no-release" files: ["lib.c"] cpp.minimumIosVersion: "8.0" - cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined + cpp.sonamePrefix: qbs.targetOS.includes("darwin") ? "@rpath" : undefined cpp.defines: ["VARIANT=" + Utilities.cStringQuote(qbs.buildVariant)] qbs.architectures: Helpers.getArchitectures(qbs, project.xcodeVersion) qbs.buildVariants: ["debug", "profiling"] diff --git a/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs b/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs index 705f054a8..33ac58967 100644 --- a/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs +++ b/tests/auto/blackbox/testdata-apple/bundle-structure/bundle-structure.qbs @@ -17,7 +17,7 @@ Project { Depends { name: "B" } Depends { name: "C" } Depends { name: "D" } - condition: buildableProducts.contains("A") + condition: buildableProducts.includes("A") name: "A" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] @@ -33,7 +33,7 @@ Project { Depends { name: "B" } Depends { name: "C" } Depends { name: "D" } - condition: buildableProducts.contains("ABadApple") + condition: buildableProducts.includes("ABadApple") name: "ABadApple" bundle._productTypeIdentifier: "com.apple.product-type.will.never.exist.ever.guaranteed" bundle.isBundle: true @@ -50,7 +50,7 @@ Project { Depends { name: "B" } Depends { name: "C" } Depends { name: "D" } - condition: buildableProducts.contains("ABadThirdParty") + condition: buildableProducts.includes("ABadThirdParty") name: "ABadThirdParty" bundle._productTypeIdentifier: "org.special.third.party.non.existent.product.type" bundle.isBundle: true @@ -103,7 +103,7 @@ Project { ApplicationExtension { Depends { name: "cpp" } - condition: buildableProducts.contains("E") + condition: buildableProducts.includes("E") name: "E" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] @@ -116,7 +116,7 @@ Project { XPCService { Depends { name: "cpp" } - condition: buildableProducts.contains("F") + condition: buildableProducts.includes("F") name: "F" bundle.isBundle: true bundle.publicHeaders: ["dummy.h"] @@ -129,7 +129,7 @@ Project { Product { Depends { name: "bundle" } - condition: buildableProducts.contains("G") + condition: buildableProducts.includes("G") type: ["inapppurchase"] name: "G" bundle.isBundle: true diff --git a/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/ByteArray-Info.plist b/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/ByteArray-Info.plist new file mode 100644 index 000000000..df0429f25 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/ByteArray-Info.plist @@ -0,0 +1,11 @@ +<?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>DataKey</key> + <!--The data value--> + <data>VGhlIGRhdGEgdmFsdWU=</data> + <key>StringKey</key> + <string>The string value</string> +</dict> +</plist> diff --git a/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/byteArrayInfoPlist.qbs b/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/byteArrayInfoPlist.qbs new file mode 100644 index 000000000..4df0886ff --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/byteArrayInfoPlist.qbs @@ -0,0 +1,37 @@ +import qbs.BundleTools +import qbs.TextFile + +CppApplication { + Depends { name: "bundle" } + cpp.minimumMacosVersion: "10.7" + files: ["main.c", "ByteArray-Info.plist"] + type: base.concat(["txt_output"]) + + Properties { + condition: qbs.targetOS.includes("darwin") + bundle.isBundle: true + bundle.identifierPrefix: "com.test" + } + + Rule { + inputs: ["aggregate_infoplist"] + Artifact { + filePath: input.fileName + ".out" + fileTags: ["txt_output"] + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "generating" + output.fileName + " from " + input.fileName; + cmd.highlight = "codegen"; + cmd.sourceCode = function() { + var plist = new BundleTools.infoPlistContents(input.filePath); + var content = plist["DataKey"]; + var int8view = new Uint8Array(content); + file = new TextFile(output.filePath, TextFile.WriteOnly); + file.write(String.fromCharCode.apply(null, int8view)); + file.close(); + } + return [cmd]; + } + } +} diff --git a/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/main.c b/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/main.c new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/byteArrayInfoPlist/main.c @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata-apple/codesign/codesign.qbs b/tests/auto/blackbox/testdata-apple/codesign/codesign.qbs index 08c8f730b..c1fc0502a 100644 --- a/tests/auto/blackbox/testdata-apple/codesign/codesign.qbs +++ b/tests/auto/blackbox/testdata-apple/codesign/codesign.qbs @@ -2,10 +2,13 @@ import "../multiarch-helpers.js" as Helpers Project { name: "p" + // we do not have the access to xcode version in qbs.architectures so we need to pass it here property string xcodeVersion property bool isBundle: true property bool enableSigning: true + property bool multiArch: false + property bool multiVariant: false CppApplication { name: "A" @@ -18,7 +21,8 @@ Project { installDir: "" qbs.architectures: - project.xcodeVersion ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] + multiArch ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] + qbs.buildVariants: project.multiVariant ? ["debug", "release"] : [] } DynamicLibrary { @@ -32,7 +36,8 @@ Project { install: true installDir: "" qbs.architectures: - project.xcodeVersion ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] + multiArch ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] + qbs.buildVariants: project.multiVariant ? ["debug", "release"] : [] } LoadableModule { @@ -46,6 +51,7 @@ Project { install: true installDir: "" qbs.architectures: - project.xcodeVersion ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] + multiArch ? Helpers.getArchitectures(qbs, project.xcodeVersion) : [] + qbs.buildVariants: project.multiVariant ? ["debug", "release"] : [] } } diff --git a/tests/auto/blackbox/testdata-apple/deploymentTarget/deployment.qbs b/tests/auto/blackbox/testdata-apple/deploymentTarget/deployment.qbs index 9eff57b60..2179e9c84 100644 --- a/tests/auto/blackbox/testdata-apple/deploymentTarget/deployment.qbs +++ b/tests/auto/blackbox/testdata-apple/deploymentTarget/deployment.qbs @@ -5,7 +5,7 @@ CppApplication { // - will actually link (as of Xcode 8.1) // - exist for the given architecture(s) cpp.minimumMacosVersion: qbs.architecture === "x86_64h" ? "10.12" : "10.6" - cpp.minimumIosVersion: ["armv7s", "arm64", "x86_64"].contains(qbs.architecture) ? "7.0" : "6.0" + cpp.minimumIosVersion: ["armv7s", "arm64", "x86_64"].includes(qbs.architecture) ? "7.0" : "6.0" cpp.minimumTvosVersion: "9.0" cpp.minimumWatchosVersion: "2.0" diff --git a/tests/auto/blackbox/testdata-apple/ib/assetcatalog/assetcatalogempty.qbs b/tests/auto/blackbox/testdata-apple/ib/assetcatalog/assetcatalogempty.qbs index 7cbb58051..d06e24eb3 100644 --- a/tests/auto/blackbox/testdata-apple/ib/assetcatalog/assetcatalogempty.qbs +++ b/tests/auto/blackbox/testdata-apple/ib/assetcatalog/assetcatalogempty.qbs @@ -3,7 +3,7 @@ import qbs.Utilities Project { condition: { - var result = qbs.targetOS.contains("macos"); + var result = qbs.targetOS.includes("macos"); if (!result) console.info("Skip this test"); return result; diff --git a/tests/auto/blackbox/testdata-apple/infoPlistVariables/infoPlistVariables.qbs b/tests/auto/blackbox/testdata-apple/infoPlistVariables/infoPlistVariables.qbs index 3f083278f..47ca80f07 100644 --- a/tests/auto/blackbox/testdata-apple/infoPlistVariables/infoPlistVariables.qbs +++ b/tests/auto/blackbox/testdata-apple/infoPlistVariables/infoPlistVariables.qbs @@ -4,7 +4,7 @@ CppApplication { files: ["main.c", "Info.plist"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: true bundle.identifierPrefix: "com.test" bundle.extraEnv: { diff --git a/tests/auto/blackbox/testdata-apple/multiarch-helpers.js b/tests/auto/blackbox/testdata-apple/multiarch-helpers.js index 5d1c0f273..a8054b63c 100644 --- a/tests/auto/blackbox/testdata-apple/multiarch-helpers.js +++ b/tests/auto/blackbox/testdata-apple/multiarch-helpers.js @@ -34,35 +34,35 @@ var Utilities = require("qbs.Utilities"); // For example: x86 -> x86_64 on macOS, armv7 -> arm64 on iOS function enableOldArch(qbs, xcodeVersion) { - return qbs.targetOS.contains("macos") + return qbs.targetOS.includes("macos") && xcodeVersion && (Utilities.versionCompare(xcodeVersion, "10") < 0 || Utilities.versionCompare(xcodeVersion, "12.2") >= 0) - || qbs.targetOS.contains("ios") + || qbs.targetOS.includes("ios") } function getNewArch(qbs, xcodeVersion) { - if (qbs.targetOS.contains("macos")) + if (qbs.targetOS.includes("macos")) return xcodeVersion && Utilities.versionCompare(xcodeVersion, "12.2") >= 0 ? "arm64" : "x86_64"; - else if (qbs.targetOS.contains("ios-simulator")) + else if (qbs.targetOS.includes("ios-simulator")) return "x86_64" - else if (qbs.targetOS.contains("ios")) + else if (qbs.targetOS.includes("ios")) return "arm64" - else if (qbs.targetOS.contains("tvos")) + else if (qbs.targetOS.includes("tvos")) return "arm64" - else if (qbs.targetOS.contains("watchos")) + else if (qbs.targetOS.includes("watchos")) return "armv7k" throw "unsupported targetOS: " + qbs.targetOS; } function getOldArch(qbs, xcodeVersion) { - if (qbs.targetOS.contains("macos")) + if (qbs.targetOS.includes("macos")) return xcodeVersion && Utilities.versionCompare(xcodeVersion, "12.2") >= 0 ? "x86_64" : "x86"; - else if (qbs.targetOS.contains("ios-simulator")) + else if (qbs.targetOS.includes("ios-simulator")) return "x86" - else if (qbs.targetOS.contains("ios")) + else if (qbs.targetOS.includes("ios")) return "armv7a" throw "unsupported targetOS: " + qbs.targetOS; } diff --git a/tests/auto/blackbox/testdata-apple/objc-arc/objc-arc.qbs b/tests/auto/blackbox/testdata-apple/objc-arc/objc-arc.qbs index 545d5701c..ce128059f 100644 --- a/tests/auto/blackbox/testdata-apple/objc-arc/objc-arc.qbs +++ b/tests/auto/blackbox/testdata-apple/objc-arc/objc-arc.qbs @@ -2,7 +2,7 @@ Product { Depends { name: "cpp" } consoleApplication: true type: ["application"] - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") Group { cpp.automaticReferenceCounting: true diff --git a/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs index e70584ed8..270a0792c 100644 --- a/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs +++ b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs @@ -4,7 +4,7 @@ CppApplication { files: ["main.c", "Override-Info.plist"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: true bundle.identifierPrefix: "com.test" diff --git a/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs b/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs index fa4c67b96..e7bf4739a 100644 --- a/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs +++ b/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs @@ -16,19 +16,19 @@ Project { console.info("Available SDK versions: " + xcode.availableSdkVersions.join(", ")); var targetOsToKey = function(targetOS) { - if (targetOS.contains("ios")) + if (targetOS.includes("ios")) return "iphoneos"; - if (targetOS.contains("ios-simulator")) + if (targetOS.includes("ios-simulator")) return "iphonesimulator"; - if (targetOS.contains("macos")) + if (targetOS.includes("macos")) return "macosx"; - if (targetOS.contains("tvos")) + if (targetOS.includes("tvos")) return "appletvos"; - if (targetOS.contains("tvos-simulator")) + if (targetOS.includes("tvos-simulator")) return "appletvsimulator"; - if (targetOS.contains("watchos")) + if (targetOS.includes("watchos")) return "watchos"; - if (targetOS.contains("watchos-simulator")) + if (targetOS.includes("watchos-simulator")) return "watchossimulator"; throw "Unsupported OS" + targetOS; } diff --git a/tests/auto/blackbox/testdata-baremetal/BareMetalApplication.qbs b/tests/auto/blackbox/testdata-baremetal/BareMetalApplication.qbs index a11855727..7a35e4e13 100644 --- a/tests/auto/blackbox/testdata-baremetal/BareMetalApplication.qbs +++ b/tests/auto/blackbox/testdata-baremetal/BareMetalApplication.qbs @@ -22,7 +22,7 @@ BareMetalProduct { } Group { - condition: qbs.toolchain.contains("cosmic") + condition: qbs.toolchain.includes("cosmic") files: "cosmic.lkf" fileTags: "linkerscript" } diff --git a/tests/auto/blackbox/testdata-baremetal/BareMetalProduct.qbs b/tests/auto/blackbox/testdata-baremetal/BareMetalProduct.qbs index eaddef340..446cfe086 100644 --- a/tests/auto/blackbox/testdata-baremetal/BareMetalProduct.qbs +++ b/tests/auto/blackbox/testdata-baremetal/BareMetalProduct.qbs @@ -2,7 +2,7 @@ Product { Depends { name: "cpp" } cpp.positionIndependentCode: false Properties { - condition: qbs.toolchain.contains("iar") + condition: qbs.toolchain.includes("iar") && qbs.architecture === "stm8" cpp.driverLinkerFlags: [ "--config_def", "_CSTACK_SIZE=0x100", @@ -10,7 +10,7 @@ Product { ] } Properties { - condition: qbs.toolchain.contains("iar") + condition: qbs.toolchain.includes("iar") && qbs.architecture === "rl78" cpp.driverLinkerFlags: [ "--config_def", "_NEAR_HEAP_SIZE=256", @@ -24,7 +24,7 @@ Product { ] } Properties { - condition: qbs.toolchain.contains("iar") + condition: qbs.toolchain.includes("iar") && qbs.architecture === "rh850" cpp.driverLinkerFlags: [ "--config_def", "CSTACK_SIZE=0x1000", @@ -33,7 +33,7 @@ Product { ] } Properties { - condition: qbs.toolchain.contains("iar") + condition: qbs.toolchain.includes("iar") && qbs.architecture === "v850" cpp.driverLinkerFlags: [ "-D_CSTACK_SIZE=1000", @@ -42,7 +42,7 @@ Product { ] } Properties { - condition: qbs.toolchain.contains("iar") + condition: qbs.toolchain.includes("iar") && qbs.architecture === "78k" cpp.commonCompilerFlags: [ "--core", "78k0", @@ -59,7 +59,7 @@ Product { ] } Properties { - condition: qbs.toolchain.contains("iar") + condition: qbs.toolchain.includes("iar") && qbs.architecture === "sh" cpp.driverLinkerFlags: [ "--config_def", "_CSTACK_SIZE=0x800", @@ -69,7 +69,7 @@ Product { ] } Properties { - condition: qbs.toolchain.contains("iar") + condition: qbs.toolchain.includes("iar") && qbs.architecture === "hcs8" cpp.driverLinkerFlags: [ "-D_CSTACK_SIZE=200", @@ -78,7 +78,7 @@ Product { ] } Properties { - condition: qbs.toolchain.contains("iar") + condition: qbs.toolchain.includes("iar") && qbs.architecture === "m32c" cpp.driverLinkerFlags: [ "-D_CSTACK_SIZE=100", @@ -91,7 +91,7 @@ Product { ] } Properties { - condition: qbs.toolchain.contains("iar") + condition: qbs.toolchain.includes("iar") && qbs.architecture === "riscv" cpp.driverLinkerFlags: [ "--config_def", "CSTACK_SIZE=0x1000", @@ -99,7 +99,7 @@ Product { ] } Properties { - condition: qbs.toolchain.contains("iar") + condition: qbs.toolchain.includes("iar") && qbs.architecture === "m68k" cpp.cFlags: [ "--no_div" @@ -117,41 +117,41 @@ Product { ] } Properties { - condition: qbs.toolchain.contains("keil") + condition: qbs.toolchain.includes("keil") && qbs.architecture.startsWith("arm") && cpp.compilerName.startsWith("armcc") cpp.assemblerFlags: ["--cpu", "cortex-m0"] cpp.commonCompilerFlags: ["--cpu", "cortex-m0"] } Properties { - condition: qbs.toolchain.contains("keil") + condition: qbs.toolchain.includes("keil") && qbs.architecture.startsWith("arm") && cpp.compilerName.startsWith("armclang") cpp.assemblerFlags: ["--cpu", "cortex-m0"] cpp.commonCompilerFlags: ["-mcpu=cortex-m0", "--target=arm-arm-none-eabi"] } Properties { - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") && qbs.architecture.startsWith("arm") cpp.driverFlags: ["-specs=nosys.specs"] } Properties { - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") && qbs.architecture === "xtensa" cpp.driverFlags: ["-nostdlib"] } Properties { - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") && qbs.architecture === "msp430" cpp.driverFlags: ["-mmcu=msp430f5529", "-nostdlib"] } Properties { - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") && qbs.architecture === "m32r" cpp.driverFlags: ["-nostdlib"] } Properties { - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") && qbs.architecture === "riscv" cpp.driverFlags: ["-nostdlib"] } diff --git a/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/compiler-defines-by-language.qbs b/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/compiler-defines-by-language.qbs index 7eb2af6db..73365ada4 100644 --- a/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/compiler-defines-by-language.qbs +++ b/tests/auto/blackbox/testdata-baremetal/compiler-defines-by-language/compiler-defines-by-language.qbs @@ -2,11 +2,11 @@ import "../BareMetalApplication.qbs" as BareMetalApplication Project { property bool supportsCpp: { - if (qbs.toolchain.contains("cosmic")) + if (qbs.toolchain.includes("cosmic")) return false; - if (qbs.toolchain.contains("sdcc")) + if (qbs.toolchain.includes("sdcc")) return false; - if (qbs.toolchain.contains("keil")) { + if (qbs.toolchain.includes("keil")) { if (qbs.architecture === "mcs51" || qbs.architecture === "mcs251" || qbs.architecture === "c166") { diff --git a/tests/auto/blackbox/testdata-baremetal/compiler-listing/compiler-listing.qbs b/tests/auto/blackbox/testdata-baremetal/compiler-listing/compiler-listing.qbs index bcf983c88..6bd51e3bd 100644 --- a/tests/auto/blackbox/testdata-baremetal/compiler-listing/compiler-listing.qbs +++ b/tests/auto/blackbox/testdata-baremetal/compiler-listing/compiler-listing.qbs @@ -2,7 +2,7 @@ import "../BareMetalApplication.qbs" as BareMetalApplication BareMetalApplication { condition: { - if (!qbs.toolchain.contains("gcc")) { + if (!qbs.toolchain.includes("gcc")) { console.info("compiler listing suffix: %%" + cpp.compilerListingSuffix + "%%"); return true; } diff --git a/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbs b/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbs index fffb6a03d..7336e3970 100644 --- a/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbs +++ b/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbs @@ -2,13 +2,13 @@ import "../BareMetalApplication.qbs" as BareMetalApplication import "../BareMetalStaticLibrary.qbs" as BareMetalStaticLibrary Project { - property string outputLibrariesDirectory: sourceDirectory + "/libs" + property string outputLibrariesDirectory: buildDirectory + "/libs" BareMetalStaticLibrary { name: "lib-a" destinationDirectory: project.outputLibrariesDirectory Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib-a.c"] @@ -19,7 +19,7 @@ Project { Depends { name: "cpp" } Depends { name: "lib-a" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib-b.c"] diff --git a/tests/auto/blackbox/testdata-clangdb/project1/project.qbs b/tests/auto/blackbox/testdata-clangdb/project1/project.qbs index ecfc562b0..313f33ead 100644 --- a/tests/auto/blackbox/testdata-clangdb/project1/project.qbs +++ b/tests/auto/blackbox/testdata-clangdb/project1/project.qbs @@ -7,8 +7,8 @@ Project { Application { Probe { id: dummy - property bool isMingw: qbs.toolchain.contains("mingw") - property bool isMsvc: qbs.toolchain.contains("msvc") + property bool isMingw: qbs.toolchain.includes("mingw") + property bool isMsvc: qbs.toolchain.includes("msvc") property var buildEnv: cpp.buildEnv configure: { if (!buildEnv) diff --git a/tests/auto/blackbox/testdata-java/java/vehicles.qbs b/tests/auto/blackbox/testdata-java/java/vehicles.qbs index 2fc01e102..8a4bb732f 100644 --- a/tests/auto/blackbox/testdata-java/java/vehicles.qbs +++ b/tests/auto/blackbox/testdata-java/java/vehicles.qbs @@ -7,7 +7,7 @@ Project { Depends { name: "cpp" } Depends { name: "car_jar" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } diff --git a/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs b/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs index c9f712a85..76f54807a 100644 --- a/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs +++ b/tests/auto/blackbox/testdata-joblimits/job-limits/job-limits.qbs @@ -19,7 +19,7 @@ Project { consoleApplication: true cpp.cxxLanguageVersion: "c++14" Properties { - condition: qbs.targetOS.contains("macos") + condition: qbs.targetOS.includes("macos") cpp.minimumMacosVersion: "10.9" } files: "main.cpp" diff --git a/tests/auto/blackbox/testdata-providers/allowed-values/allowed-values.qbs b/tests/auto/blackbox/testdata-providers/allowed-values/allowed-values.qbs new file mode 100644 index 000000000..e6dbaddde --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/allowed-values/allowed-values.qbs @@ -0,0 +1,4 @@ +Product { + Depends { name: "qbsmetatestmodule" } + qbsModuleProviders: "provider" +} diff --git a/tests/auto/blackbox/testdata-providers/allowed-values/module-providers/provider.qbs b/tests/auto/blackbox/testdata-providers/allowed-values/module-providers/provider.qbs new file mode 100644 index 000000000..c0e426c96 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/allowed-values/module-providers/provider.qbs @@ -0,0 +1,14 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + isEager: false + property stringList aProperty: "zero" + PropertyOptions { + name: "aProperty" + allowedValues: ["one", "two"] + } + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, moduleName, "from_provider"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/broken-provider/broken-provider.qbs b/tests/auto/blackbox/testdata-providers/broken-provider/broken-provider.qbs new file mode 100644 index 000000000..461c7e30e --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/broken-provider/broken-provider.qbs @@ -0,0 +1,13 @@ +Project { + qbsModuleProviders: "provider_a" + name: "project" + Project { + name: "innerProject" + Product { + name: "p1" + Depends { name: "qbsothermodule"; required: false } + Depends { name: "qbsmetatestmodule" } + } + } + +} diff --git a/tests/auto/blackbox/testdata-providers/broken-provider/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/broken-provider/module-providers/provider_a.qbs new file mode 100644 index 000000000..f446d2d13 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/broken-provider/module-providers/provider_a.qbs @@ -0,0 +1,5 @@ +ModuleProvider { + relativeSearchPaths: { + throw "This provider is broken"; + } +} diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/conan-module-provider.qbs b/tests/auto/blackbox/testdata-providers/conan-provider/conan-module-provider.qbs new file mode 100644 index 000000000..e8880fc96 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/conan-module-provider.qbs @@ -0,0 +1,11 @@ +CppApplication { + consoleApplication: true + name: "p" + files: "main.cpp" + qbsModuleProviders: "conan" + qbs.buildVariant: "release" + qbs.installPrefix: "" + install: true + Depends { name: "conanmoduleprovider.testlib" } + Depends { name: "conanmoduleprovider.testlibheader" } +} diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/conanfile.txt b/tests/auto/blackbox/testdata-providers/conan-provider/conanfile.txt new file mode 100644 index 000000000..7c40ff7d6 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/conanfile.txt @@ -0,0 +1,3 @@ +[requires] +conanmoduleprovider.testlib/1.2.3 +conanmoduleprovider.testlibheader/0.1.0 diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/main.cpp b/tests/auto/blackbox/testdata-providers/conan-provider/main.cpp new file mode 100644 index 000000000..6250927b3 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/main.cpp @@ -0,0 +1,8 @@ +#include <testlib.h> + +#include <header.h> + +int main() +{ + HelloWorld h(42 + hello()); +} diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlib/CMakeLists.txt b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/CMakeLists.txt new file mode 100644 index 000000000..d186d1906 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.15) +project(conanmoduleprovider.testlib) + +find_package(conanmoduleprovider.testlibdep REQUIRED) + +add_library(${PROJECT_NAME} STATIC testlib.cpp) +set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "testlib.h") +target_link_libraries(${PROJECT_NAME} conanmoduleprovider.testlibdep::conanmoduleprovider.testlibdep) +install(TARGETS ${PROJECT_NAME}) diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlib/conanfile.py b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/conanfile.py new file mode 100644 index 000000000..7cb91f9ef --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/conanfile.py @@ -0,0 +1,36 @@ +from conan import ConanFile +from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps +from conan.tools.files import collect_libs +import os + +class ConanModuleProviderTestlib(ConanFile): + name = "conanmoduleprovider.testlib" + license = "none" + version = "1.2.3" + + exports_sources = "*.cpp", "*.h", "CMakeLists.txt" + settings = "os", "compiler", "build_type", "arch" + + def requirements(self): + self.requires("conanmoduleprovider.testlibdep/1.2.3") + + def layout(self): + cmake_layout(self) + + def generate(self): + deps = CMakeDeps(self) + deps.generate() + tc = CMakeToolchain(self, generator="Ninja") + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + cmake = CMake(self) + cmake.install() + + def package_info(self): + self.cpp_info.libs = collect_libs(self) diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.cpp b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.cpp new file mode 100644 index 000000000..7118dfda9 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.cpp @@ -0,0 +1,7 @@ +#include "testlib.h" + +#include <testlibdep.h> + +HelloWorld::HelloWorld(int x) + : m_x(foo(x)) +{} diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.h b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.h new file mode 100644 index 000000000..11a354b70 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlib/testlib.h @@ -0,0 +1,10 @@ +#pragma once + +class HelloWorld +{ +public: + explicit HelloWorld(int x); + +private: + int m_x; +}; diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/CMakeLists.txt b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/CMakeLists.txt new file mode 100644 index 000000000..5510a9250 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.15) +project(conanmoduleprovider.testlibdep) + +add_library(${PROJECT_NAME} STATIC testlibdep.cpp) +set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER "testlibdep.h") +install(TARGETS ${PROJECT_NAME}) +install(FILES lorem_ipsum.txt DESTINATION share)
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/conanfile.py b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/conanfile.py new file mode 100644 index 000000000..f2c577c5e --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/conanfile.py @@ -0,0 +1,35 @@ +from conan import ConanFile +from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps +from conan.tools.files import collect_libs, copy +import os + +class ConanModuleProviderTestlib(ConanFile): + name = "conanmoduleprovider.testlibdep" + license = "none" + version = "1.2.3" + + exports_sources = "*.cpp", "*.h", "*.txt" + settings = "os", "compiler", "build_type", "arch" + + def layout(self): + cmake_layout(self) + + def generate(self): + deps = CMakeDeps(self) + deps.generate() + tc = CMakeToolchain(self, generator="Ninja") + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + cmake = CMake(self) + cmake.install() + + def package_info(self): + self.cpp_info.libs = collect_libs(self) + self.cpp_info.resdirs = ['share'] + diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/lorem_ipsum.txt b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/lorem_ipsum.txt new file mode 100644 index 000000000..d8634396c --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/lorem_ipsum.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit.
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.cpp b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.cpp new file mode 100644 index 000000000..893478c82 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.cpp @@ -0,0 +1,6 @@ +#include "testlibdep.h" + +int foo(int i) +{ + return i * i; +}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.h b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.h new file mode 100644 index 000000000..ca7bd3cbc --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibdep/testlibdep.h @@ -0,0 +1,3 @@ +#pragma once + +int foo(int i);
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/conanfile.py b/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/conanfile.py new file mode 100644 index 000000000..6078b9750 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/conanfile.py @@ -0,0 +1,15 @@ +from conan import ConanFile +from conan.tools.files import copy + +import os + +class Recipe(ConanFile): + exports_sources = ("header.h") + version = '0.1.0' + name = 'conanmoduleprovider.testlibheader' + + def package(self): + copy(self, + "header.h", + src=self.source_folder, + dst=os.path.join(self.package_folder, "include"))
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/header.h b/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/header.h new file mode 100644 index 000000000..66bd50d57 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/conan-provider/testlibheader/header.h @@ -0,0 +1,6 @@ +#pragma once + +inline int hello() +{ + return 0; +}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/fallback-module-provider/fallback-module-provider.qbs b/tests/auto/blackbox/testdata-providers/fallback-module-provider/fallback-module-provider.qbs index a798e15b3..a798e15b3 100644 --- a/tests/auto/blackbox/testdata/fallback-module-provider/fallback-module-provider.qbs +++ b/tests/auto/blackbox/testdata-providers/fallback-module-provider/fallback-module-provider.qbs diff --git a/tests/auto/blackbox/testdata/fallback-module-provider/libdir/qbsmetatestmodule.pc b/tests/auto/blackbox/testdata-providers/fallback-module-provider/libdir/qbsmetatestmodule.pc index ae4daba89..ae4daba89 100644 --- a/tests/auto/blackbox/testdata/fallback-module-provider/libdir/qbsmetatestmodule.pc +++ b/tests/auto/blackbox/testdata-providers/fallback-module-provider/libdir/qbsmetatestmodule.pc diff --git a/tests/auto/blackbox/testdata/fallback-module-provider/main.cpp b/tests/auto/blackbox/testdata-providers/fallback-module-provider/main.cpp index 442b755bf..442b755bf 100644 --- a/tests/auto/blackbox/testdata/fallback-module-provider/main.cpp +++ b/tests/auto/blackbox/testdata-providers/fallback-module-provider/main.cpp diff --git a/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers-cache.qbs b/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers-cache.qbs new file mode 100644 index 000000000..508ed84d2 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers-cache.qbs @@ -0,0 +1,11 @@ +Project { + qbsModuleProviders: ["provider_a"] + name: "project" + property string dummyProp + + Product { + name: "p1" + Depends { name: "qbsothermodule" } + Depends { name: "qbsmetatestmodule" } + } +} diff --git a/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers/provider_a.qbs new file mode 100644 index 000000000..782cf7d25 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/module-providers-cache/module-providers/provider_a.qbs @@ -0,0 +1,9 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", "from_provider_a"); + Helpers.writeModule(outputBaseDir, "qbsothermodule", "from_provider_a"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata/module-providers/main.cpp b/tests/auto/blackbox/testdata-providers/module-providers/main.cpp index 85a4f551c..85a4f551c 100644 --- a/tests/auto/blackbox/testdata/module-providers/main.cpp +++ b/tests/auto/blackbox/testdata-providers/module-providers/main.cpp diff --git a/tests/auto/blackbox/testdata/module-providers/module-providers.qbs b/tests/auto/blackbox/testdata-providers/module-providers/module-providers.qbs index e83c80bb1..89bd1a11d 100644 --- a/tests/auto/blackbox/testdata/module-providers/module-providers.qbs +++ b/tests/auto/blackbox/testdata-providers/module-providers/module-providers.qbs @@ -10,10 +10,11 @@ Project { readonly property string beginning: "beginning" CppApplication { name: "app1" + property string chooseLettersFrom: project.beginning // This indirection tests QBS-1747. Depends { name: "mygenerator.module1" } Depends { name: "mygenerator.module2" } Depends { name: "othergenerator" } - moduleProviders.mygenerator.chooseLettersFrom: project.beginning + moduleProviders.mygenerator.chooseLettersFrom: chooseLettersFrom moduleProviders.othergenerator.someDefines: name files: "main.cpp" } diff --git a/tests/auto/blackbox/testdata/module-providers/module-providers/mygenerator/provider.qbs b/tests/auto/blackbox/testdata-providers/module-providers/module-providers/mygenerator/provider.qbs index dae02c03a..dae02c03a 100644 --- a/tests/auto/blackbox/testdata/module-providers/module-providers/mygenerator/provider.qbs +++ b/tests/auto/blackbox/testdata-providers/module-providers/module-providers/mygenerator/provider.qbs diff --git a/tests/auto/blackbox/testdata/module-providers/module-providers/othergenerator/provider.qbs b/tests/auto/blackbox/testdata-providers/module-providers/module-providers/othergenerator/provider.qbs index 66557037c..66557037c 100644 --- a/tests/auto/blackbox/testdata/module-providers/module-providers/othergenerator/provider.qbs +++ b/tests/auto/blackbox/testdata-providers/module-providers/module-providers/othergenerator/provider.qbs diff --git a/tests/auto/blackbox/testdata-providers/non-eager-provider/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/non-eager-provider/module-providers/provider_a.qbs new file mode 100644 index 000000000..6cd9177db --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/non-eager-provider/module-providers/provider_a.qbs @@ -0,0 +1,11 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + isEager: false + relativeSearchPaths: { + if (moduleName === "nonexistentmodule") + return undefined; + Helpers.writeModule(outputBaseDir, moduleName, "from_provider_a"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/non-eager-provider/non-eager-provider.qbs b/tests/auto/blackbox/testdata-providers/non-eager-provider/non-eager-provider.qbs new file mode 100644 index 000000000..bd3662de3 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/non-eager-provider/non-eager-provider.qbs @@ -0,0 +1,13 @@ +Project { + Product { + name: "p1" + Depends { name: "qbsmetatestmodule" } + Depends { name: "qbsothermodule" } + Depends { name: "nonexistentmodule"; required: false } + property bool dummy: { + console.info("p1.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); + console.info("p1.qbsothermodule.prop: " + qbsothermodule.prop); + } + qbsModuleProviders: "provider_a" + } +} diff --git a/tests/auto/blackbox/testdata-providers/probe-in-module-provider/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/probe-in-module-provider/module-providers/provider_a.qbs new file mode 100644 index 000000000..476a83143 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/probe-in-module-provider/module-providers/provider_a.qbs @@ -0,0 +1,23 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + property string sysroot: qbs.sysroot + Probe { + id: theProbe + property string theValue: "value" + property string dummy: sysroot + configure: { + console.info("Running probe with irrelevant value '" + dummy + "'"); + found = true; + } + } + isEager: false + property bool found: theProbe.found + property string theValue: theProbe.theValue + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", theValue, undefined, found); + if (sysroot !== qbs.sysroot) + throw "this is unexpected"; + return ""; + } +} diff --git a/tests/auto/blackbox/testdata/probe-in-module-provider/probe-in-module-provider.qbs b/tests/auto/blackbox/testdata-providers/probe-in-module-provider/probe-in-module-provider.qbs index cb346beeb..1f2b3d387 100644 --- a/tests/auto/blackbox/testdata/probe-in-module-provider/probe-in-module-provider.qbs +++ b/tests/auto/blackbox/testdata-providers/probe-in-module-provider/probe-in-module-provider.qbs @@ -4,5 +4,6 @@ Product { Depends { name: "qbsmetatestmodule" } property bool dummy: { console.info("p.qbsmetatestmodule.boolProp: " + JSON.stringify(qbsmetatestmodule.boolProp)); + console.info("p.qbsmetatestmodule.prop: " + JSON.stringify(qbsmetatestmodule.prop)); } } diff --git a/tests/auto/blackbox/testdata/providers-properties/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_a.qbs index ab9d475d8..ab9d475d8 100644 --- a/tests/auto/blackbox/testdata/providers-properties/module-providers/provider_a.qbs +++ b/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_a.qbs diff --git a/tests/auto/blackbox/testdata/providers-properties/module-providers/provider_b.qbs b/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_b.qbs index 1b2a79979..1b2a79979 100644 --- a/tests/auto/blackbox/testdata/providers-properties/module-providers/provider_b.qbs +++ b/tests/auto/blackbox/testdata-providers/providers-properties/module-providers/provider_b.qbs diff --git a/tests/auto/blackbox/testdata/providers-properties/providers-properties.qbs b/tests/auto/blackbox/testdata-providers/providers-properties/providers-properties.qbs index 258a973fa..258a973fa 100644 --- a/tests/auto/blackbox/testdata/providers-properties/providers-properties.qbs +++ b/tests/auto/blackbox/testdata-providers/providers-properties/providers-properties.qbs diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/module-providers/provider_a.qbs new file mode 100644 index 000000000..95c89cd1c --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/module-providers/provider_a.qbs @@ -0,0 +1,9 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + property string sysroot: qbs.sysroot + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", sysroot); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/qbs-module-properties-in-providers.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/qbs-module-properties-in-providers.qbs new file mode 100644 index 000000000..c2fc58299 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/qbs-module-properties-in-providers/qbs-module-properties-in-providers.qbs @@ -0,0 +1,34 @@ +Project { + qbsModuleProviders: "provider_a" + name: "project" + + Profile { + name: "profile1" + qbs.sysroot: "/sysroot1" + } + + Profile { + name: "profile2" + qbs.sysroot: "/sysroot2" + } + + Product { + name: "product1" + Depends { name: "qbsmetatestmodule" } + property bool dummy: { + console.info("product1.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); + } + // multiplex over profiles, sysroot should not be cached + qbs.profiles: ["profile1", "profile2"] + } + + Product { + name: "product2" + Depends { name: "qbsmetatestmodule" } + property bool dummy: { + console.info("product2.qbsmetatestmodule.prop: " + qbsmetatestmodule.prop); + } + // multiplex over profiles, sysroot should not be cached + qbs.profiles: ["profile1", "profile2"] + } +} diff --git a/tests/auto/blackbox/testdata/qbs-module-providers-cli-override/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-providers/provider_a.qbs index d34d1cac5..d34d1cac5 100644 --- a/tests/auto/blackbox/testdata/qbs-module-providers-cli-override/module-providers/provider_a.qbs +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-providers/provider_a.qbs diff --git a/tests/auto/blackbox/testdata/qbs-module-providers-cli-override/module-providers/provider_b.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-providers/provider_b.qbs index 767e30923..767e30923 100644 --- a/tests/auto/blackbox/testdata/qbs-module-providers-cli-override/module-providers/provider_b.qbs +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/module-providers/provider_b.qbs diff --git a/tests/auto/blackbox/testdata/qbs-module-providers-cli-override/qbs-module-providers-cli-override.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/qbs-module-providers-cli-override.qbs index 6f94ab207..6f94ab207 100644 --- a/tests/auto/blackbox/testdata/qbs-module-providers-cli-override/qbs-module-providers-cli-override.qbs +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-cli-override/qbs-module-providers-cli-override.qbs diff --git a/tests/auto/blackbox/testdata/qbs-module-providers-compatibility/module-providers/named_provider.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/named_provider.qbs index 07114b5ef..07114b5ef 100644 --- a/tests/auto/blackbox/testdata/qbs-module-providers-compatibility/module-providers/named_provider.qbs +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/named_provider.qbs diff --git a/tests/auto/blackbox/testdata/qbs-module-providers-compatibility/module-providers/qbsmetatestmodule/provider.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/qbsmetatestmodule/provider.qbs index b04a52261..b04a52261 100644 --- a/tests/auto/blackbox/testdata/qbs-module-providers-compatibility/module-providers/qbsmetatestmodule/provider.qbs +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/module-providers/qbsmetatestmodule/provider.qbs diff --git a/tests/auto/blackbox/testdata/qbs-module-providers-compatibility/qbs-module-providers-compatibility.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/qbs-module-providers-compatibility.qbs index 7885b540a..7885b540a 100644 --- a/tests/auto/blackbox/testdata/qbs-module-providers-compatibility/qbs-module-providers-compatibility.qbs +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-compatibility/qbs-module-providers-compatibility.qbs diff --git a/tests/auto/blackbox/testdata/qbs-module-providers-helpers.js b/tests/auto/blackbox/testdata-providers/qbs-module-providers-helpers.js index 8b6d9e275..8b6d9e275 100644 --- a/tests/auto/blackbox/testdata/qbs-module-providers-helpers.js +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers-helpers.js diff --git a/tests/auto/blackbox/testdata/qbs-module-providers/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_a.qbs index d34d1cac5..d34d1cac5 100644 --- a/tests/auto/blackbox/testdata/qbs-module-providers/module-providers/provider_a.qbs +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_a.qbs diff --git a/tests/auto/blackbox/testdata/qbs-module-providers/module-providers/provider_b.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_b.qbs index 767e30923..767e30923 100644 --- a/tests/auto/blackbox/testdata/qbs-module-providers/module-providers/provider_b.qbs +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers/module-providers/provider_b.qbs diff --git a/tests/auto/blackbox/testdata/qbs-module-providers/qbs-module-providers.qbs b/tests/auto/blackbox/testdata-providers/qbs-module-providers/qbs-module-providers.qbs index 00776a62e..00776a62e 100644 --- a/tests/auto/blackbox/testdata/qbs-module-providers/qbs-module-providers.qbs +++ b/tests/auto/blackbox/testdata-providers/qbs-module-providers/qbs-module-providers.qbs diff --git a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libA.cpp b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libA.cpp index 0c5274415..0c5274415 100644 --- a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libA.cpp +++ b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libA.cpp diff --git a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libA.h b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libA.h index ddaaf1609..ddaaf1609 100644 --- a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libA.h +++ b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libA.h diff --git a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libs.qbs b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libs.qbs index 9d482415b..b473083c6 100644 --- a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libs/libs.qbs +++ b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/libs/libs.qbs @@ -6,6 +6,8 @@ Project { DynamicLibrary { Depends { name: "cpp" } Depends { name: "bundle" } + Depends { name: "Exporter.pkgconfig" } + Exporter.pkgconfig.versionEntry: "1.0" name: "libA" bundle.isBundle: project.isBundle bundle.publicHeaders: ["libA.h"] @@ -16,7 +18,7 @@ Project { result.push("MYLIB_FRAMEWORK"); return result; } - qbs.installPrefix: "" + qbs.installPrefix: "/usr" install: true installImportLib: true installDir: "lib" @@ -25,5 +27,16 @@ Project { qbs.install: !project.isBundle qbs.installDir: FileInfo.joinPaths("include", product.name) } + Group { + fileTagsFilter: ["Exporter.pkgconfig.pc"] + qbs.install: !project.isBundle + qbs.installDir: FileInfo.joinPaths("share", "pkgconfig") + } + Export { + Depends { name: "cpp" } + cpp.defines: ["THE_MAGIC_DEFINE"] + cpp.includePaths: [FileInfo.joinPaths(exportingProduct.qbs.installPrefix, "include")] + cpp.libraryPaths: [FileInfo.joinPaths(exportingProduct.qbs.installPrefix, "lib")] + } } } diff --git a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/main.cpp b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/main.cpp index 5fa0f7eed..5fa0f7eed 100644 --- a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/main.cpp +++ b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/main.cpp diff --git a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/qbspkgconfig-module-provider.qbs b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/qbspkgconfig-module-provider.qbs index d2b3654ae..d2b3654ae 100644 --- a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/qbspkgconfig-module-provider.qbs +++ b/tests/auto/blackbox/testdata-providers/qbspkgconfig-module-provider/qbspkgconfig-module-provider.qbs diff --git a/tests/auto/blackbox/testdata-providers/removal-version/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata-providers/removal-version/module-providers/provider_a.qbs new file mode 100644 index 000000000..7f358acbc --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/removal-version/module-providers/provider_a.qbs @@ -0,0 +1,14 @@ +import "../../qbs-module-providers-helpers.js" as Helpers + +ModuleProvider { + isEager: false + property bool deprecated: false + PropertyOptions { + name: "deprecated" + removalVersion: "2.2.0" + } + relativeSearchPaths: { + Helpers.writeModule(outputBaseDir, moduleName, "from_provider_a"); + return ""; + } +} diff --git a/tests/auto/blackbox/testdata-providers/removal-version/removal-version.qbs b/tests/auto/blackbox/testdata-providers/removal-version/removal-version.qbs new file mode 100644 index 000000000..1aa5e2ce9 --- /dev/null +++ b/tests/auto/blackbox/testdata-providers/removal-version/removal-version.qbs @@ -0,0 +1,12 @@ +Project { + qbsModuleProviders: "provider_a" + name: "project" + Project { + name: "innerProject" + Product { + name: "p1" + Depends { name: "qbsmetatestmodule" } + } + } + +} diff --git a/tests/auto/blackbox/testdata-qt/linker-variant/qt-linker-variant.qbs b/tests/auto/blackbox/testdata-qt/linker-variant/qt-linker-variant.qbs index ab5889007..c1a77d696 100644 --- a/tests/auto/blackbox/testdata-qt/linker-variant/qt-linker-variant.qbs +++ b/tests/auto/blackbox/testdata-qt/linker-variant/qt-linker-variant.qbs @@ -3,7 +3,7 @@ QtApplication { id: qtConfigProbe property stringList moduleConfig: Qt.core.moduleConfig configure: { - console.info("Qt requires gold: " + moduleConfig.contains("use_gold_linker")); + console.info("Qt requires gold: " + moduleConfig.includes("use_gold_linker")); } } files: "main.cpp" diff --git a/tests/auto/blackbox/testdata-qt/mixed-build-variants/mixed-build-variants.qbs b/tests/auto/blackbox/testdata-qt/mixed-build-variants/mixed-build-variants.qbs index 7d8ab1b90..dea30eef4 100644 --- a/tests/auto/blackbox/testdata-qt/mixed-build-variants/mixed-build-variants.qbs +++ b/tests/auto/blackbox/testdata-qt/mixed-build-variants/mixed-build-variants.qbs @@ -1,6 +1,6 @@ QtApplication { Properties { - condition: qbs.toolchain.contains("msvc") + condition: qbs.toolchain.includes("msvc") Qt.core.qtBuildVariant: "release" } Qt.core.qtBuildVariant: "dummy" diff --git a/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/symbols-test.qbs b/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/symbols-test.qbs index 94a29d2b2..a614d96c4 100644 --- a/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/symbols-test.qbs +++ b/tests/auto/blackbox/testdata-qt/no-relink-on-qdebug/symbols-test.qbs @@ -3,9 +3,9 @@ Project { name: "app" Depends { name: "lib" } property bool dummy: { - console.info("is GCC: " + qbs.toolchain.contains("gcc")); - console.info("is MinGW: " + qbs.toolchain.contains("mingw")); - console.info("is Darwin: " + qbs.targetOS.contains("darwin")); + console.info("is GCC: " + qbs.toolchain.includes("gcc")); + console.info("is MinGW: " + qbs.toolchain.includes("mingw")); + console.info("is Darwin: " + qbs.targetOS.includes("darwin")); } files: "main.cpp" } diff --git a/tests/auto/blackbox/testdata-qt/plugin-meta-data/plugin-meta-data.qbs b/tests/auto/blackbox/testdata-qt/plugin-meta-data/plugin-meta-data.qbs index a3067f0b0..dbe64d5ea 100644 --- a/tests/auto/blackbox/testdata-qt/plugin-meta-data/plugin-meta-data.qbs +++ b/tests/auto/blackbox/testdata-qt/plugin-meta-data/plugin-meta-data.qbs @@ -23,7 +23,7 @@ Project { cpp.cxxLanguageVersion: "c++11" Properties { - condition: qbs.targetOS.contains("unix") + condition: qbs.targetOS.includes("unix") cpp.rpaths: [cpp.rpathOrigin] } @@ -43,12 +43,12 @@ Project { Depends { name: "Qt.core" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.defines: [Qt.core.staticBuild ? "QT_STATICPLUGIN" : "QT_PLUGIN"] cpp.cxxLanguageVersion: "c++11" - cpp.sonamePrefix: qbs.targetOS.contains("darwin") ? "@rpath" : undefined + cpp.sonamePrefix: qbs.targetOS.includes("darwin") ? "@rpath" : undefined cpp.includePaths: ["."] Qt.core.pluginMetaData: ["theKey=theValue"] diff --git a/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qbs b/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qbs new file mode 100644 index 000000000..4b82bc405 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qbs @@ -0,0 +1,22 @@ +import qbs.Utilities + +Product { + condition: { + var ok = Utilities.versionCompare(Qt.core.version, "5.0.0") >= 0; + if (!ok) + console.info("Qt is too old"); + return ok; + } + name: "QDoc Test" + type: ["qdoc-html", "qch"] + + Depends { name: "Qt.core" } + + files: ["qdoc.qdoc"] + + Group { + name: "main qdocconf file" + files: "qdoc.qdocconf" + fileTags: "qdocconf-main" + } +} diff --git a/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdoc b/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdoc new file mode 100644 index 000000000..9e44e0948 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdoc @@ -0,0 +1,7 @@ +/*! + \page index.html + + \title QDoc Test + + QDoc Test is a test for QDoc. +*/
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdocconf b/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdocconf new file mode 100644 index 000000000..8c82bb575 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qdoc/qdoc.qdocconf @@ -0,0 +1,13 @@ +project = QDoc Test +description = QDoc Test + +headerdirs = . +sourcedirs = . +exampledirs = . + +outputdir = doc/html + +qhp.projects = QDocTest +qhp.QDocTest.file = qdoctest.qhp +qhp.QDocTest.namespace = org.qt-project.QDocTest +qhp.QDocTest.virtualFolder = doc diff --git a/tests/auto/blackbox/testdata-qt/qml-debugging/qml-debugging.qbs b/tests/auto/blackbox/testdata-qt/qml-debugging/qml-debugging.qbs index 8176a7c3e..0885e6b0b 100644 --- a/tests/auto/blackbox/testdata-qt/qml-debugging/qml-debugging.qbs +++ b/tests/auto/blackbox/testdata-qt/qml-debugging/qml-debugging.qbs @@ -4,4 +4,9 @@ QtApplication { Depends { name: "Qt.quick" } Qt.quick.qmlDebugging: true files: "main.cpp" + Probe { + id: checker + property bool isGcc: qbs.toolchain.contains("gcc") + configure: { console.info("is gcc: " + isGcc); } + } } diff --git a/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs b/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs index 90f7e5b96..6fee91479 100644 --- a/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs +++ b/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs @@ -42,9 +42,9 @@ Project { cmd.description = "running " + input.filePath; var envVars = {}; - if (Host.os().contains("windows")) { + if (Host.os().includes("windows")) { envVars["PATH"] = FileInfo.toWindowsSeparators(input["Qt.core"].binPath); - } else if (Host.os().contains("macos")) { + } else if (Host.os().includes("macos")) { envVars["DYLD_LIBRARY_PATH"] = input["Qt.core"].libPath; envVars["DYLD_FRAMEWORK_PATH"] = input["Qt.core"].libPath; } else { diff --git a/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/static-qt-plugin-linking.qbs b/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/static-qt-plugin-linking.qbs index a9608c001..e4e56bb4b 100644 --- a/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/static-qt-plugin-linking.qbs +++ b/tests/auto/blackbox/testdata-qt/static-qt-plugin-linking/static-qt-plugin-linking.qbs @@ -11,12 +11,12 @@ Product { } Group { - condition: type.contains("application") + condition: type.includes("application") files: "main.cpp" } Group { - condition: type.contains("staticlibrary") + condition: type.includes("staticlibrary") files: "lib.cpp" } diff --git a/tests/auto/blackbox/testdata-windows/codesign/codesign.qbs b/tests/auto/blackbox/testdata-windows/codesign/codesign.qbs index f9f49e636..1963f6926 100644 --- a/tests/auto/blackbox/testdata-windows/codesign/codesign.qbs +++ b/tests/auto/blackbox/testdata-windows/codesign/codesign.qbs @@ -9,7 +9,7 @@ Project { CppApplication { name: "A" files: "app.cpp" - condition: qbs.toolchain.contains("msvc") + condition: qbs.toolchain.includes("msvc") codesign.enableCodeSigning: project.enableSigning codesign.hashAlgorithm: project.hashAlgorithm codesign.subjectName: project.subjectName @@ -27,7 +27,7 @@ Project { Depends { name: "cpp" } name: "B" files: "app.cpp" - condition: qbs.toolchain.contains("msvc") + condition: qbs.toolchain.includes("msvc") codesign.enableCodeSigning: project.enableSigning codesign.hashAlgorithm: project.hashAlgorithm codesign.subjectName: project.subjectName diff --git a/tests/auto/blackbox/testdata-windows/innosetup/innosetup.qbs b/tests/auto/blackbox/testdata-windows/innosetup/innosetup.qbs index 718dec6f5..fd8868900 100644 --- a/tests/auto/blackbox/testdata-windows/innosetup/innosetup.qbs +++ b/tests/auto/blackbox/testdata-windows/innosetup/innosetup.qbs @@ -3,7 +3,7 @@ import qbs.FileInfo Project { InnoSetup { property bool _test: { - var present = qbs.targetOS.contains("windows") && innosetup.present; + var present = qbs.targetOS.includes("windows") && innosetup.present; console.info("has innosetup: " + present); } diff --git a/tests/auto/blackbox/testdata-windows/innosetupDependencies/innosetupDependencies.qbs b/tests/auto/blackbox/testdata-windows/innosetupDependencies/innosetupDependencies.qbs index ab68d3011..3ef8c30e7 100644 --- a/tests/auto/blackbox/testdata-windows/innosetupDependencies/innosetupDependencies.qbs +++ b/tests/auto/blackbox/testdata-windows/innosetupDependencies/innosetupDependencies.qbs @@ -3,7 +3,7 @@ import qbs.TextFile Project { InnoSetup { property bool _test: { - var present = qbs.targetOS.contains("windows") && innosetup.present; + var present = qbs.targetOS.includes("windows") && innosetup.present; console.info("has innosetup: " + present); } Depends { name: "app" } diff --git a/tests/auto/blackbox/testdata-windows/wix/WiXInstallers.qbs b/tests/auto/blackbox/testdata-windows/wix/WiXInstallers.qbs index 1316d07d7..acc7cf7b3 100644 --- a/tests/auto/blackbox/testdata-windows/wix/WiXInstallers.qbs +++ b/tests/auto/blackbox/testdata-windows/wix/WiXInstallers.qbs @@ -20,7 +20,7 @@ Project { WindowsSetupPackage { Depends { name: "QbsSetup" } - condition: Host.os().contains("windows") // currently does not work in Wine with WiX 3.9 + condition: Host.os().includes("windows") // currently does not work in Wine with WiX 3.9 name: "QbsBootstrapper" targetName: "qbs-setup-" + qbs.architecture files: ["QbsBootstrapper.wxs"] diff --git a/tests/auto/blackbox/testdata/assembly/assembly.qbs b/tests/auto/blackbox/testdata/assembly/assembly.qbs index f7bd4ecad..9d5584af5 100644 --- a/tests/auto/blackbox/testdata/assembly/assembly.qbs +++ b/tests/auto/blackbox/testdata/assembly/assembly.qbs @@ -30,9 +30,9 @@ Project { name : "testa" files : [ "testa.s" ] Depends { name: "cpp" } - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -40,9 +40,9 @@ Project { name : "testb" files : [ "testb.S" ] Depends { name: "cpp" } - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -50,9 +50,9 @@ Project { name : "testc" files : [ "testc.sx" ] Depends { name: "cpp" } - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } @@ -63,10 +63,10 @@ Project { files: ["testd_" + qbs.architecture + ".asm"] } Depends { name: "cpp" } - condition: qbs.toolchain.contains("msvc") + condition: qbs.toolchain.includes("msvc") && (qbs.architecture === "x86" || qbs.architecture === "x86_64") Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs b/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs index 08de04fc7..b6094ed22 100644 --- a/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs +++ b/tests/auto/blackbox/testdata/autotest-timeout/autotests-timeout.qbs @@ -14,7 +14,7 @@ Project { cpp.cxxLanguageVersion: "c++11" cpp.minimumOsxVersion: "10.8" // For <chrono> Properties { - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") cpp.driverFlags: "-pthread" } files: "test-main.cpp" @@ -22,7 +22,7 @@ Project { AutotestRunner { Depends { name: "cpp" // Make sure build environment is set up properly. - condition: Host.os().contains("windows") && qbs.toolchain.contains("gcc") + condition: Host.os().includes("windows") && qbs.toolchain.includes("gcc") } } } diff --git a/tests/auto/blackbox/testdata/autotest-with-dependencies/autotest-with-dependencies.qbs b/tests/auto/blackbox/testdata/autotest-with-dependencies/autotest-with-dependencies.qbs index 8f4634368..bea74796a 100644 --- a/tests/auto/blackbox/testdata/autotest-with-dependencies/autotest-with-dependencies.qbs +++ b/tests/auto/blackbox/testdata/autotest-with-dependencies/autotest-with-dependencies.qbs @@ -30,7 +30,7 @@ Project { AutotestRunner { Depends { name: "cpp" // Make sure build environment is set up properly. - condition: Host.os().contains("windows") && qbs.toolchain.contains("gcc") + condition: Host.os().includes("windows") && qbs.toolchain.includes("gcc") } arguments: FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix, "bin") auxiliaryInputs: "test-helper" diff --git a/tests/auto/blackbox/testdata/autotests/autotests.qbs b/tests/auto/blackbox/testdata/autotests/autotests.qbs index dc27d8288..cfb7fc560 100644 --- a/tests/auto/blackbox/testdata/autotests/autotests.qbs +++ b/tests/auto/blackbox/testdata/autotests/autotests.qbs @@ -11,7 +11,7 @@ Project { } Depends { name: "cpp" // Make sure build environment is set up properly. - condition: Host.os().contains("windows") && qbs.toolchain.contains("gcc") + condition: Host.os().includes("windows") && qbs.toolchain.includes("gcc") } } } diff --git a/tests/auto/blackbox/testdata/buildenv-change/buildenv-change.qbs b/tests/auto/blackbox/testdata/buildenv-change/buildenv-change.qbs index 6c0bcc73e..54005e76a 100644 --- a/tests/auto/blackbox/testdata/buildenv-change/buildenv-change.qbs +++ b/tests/auto/blackbox/testdata/buildenv-change/buildenv-change.qbs @@ -3,7 +3,7 @@ CppApplication { id: dummy property stringList toolchain: qbs.toolchain configure: { - if (toolchain.contains("msvc")) + if (toolchain.includes("msvc")) console.info("msvc"); } } diff --git a/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.qbs b/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.qbs index 0d7c8a1bb..4674d6a6a 100644 --- a/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.qbs +++ b/tests/auto/blackbox/testdata/capnproto/capnproto_absolute_import.qbs @@ -17,4 +17,5 @@ CppApplication { "capnproto_absolute_import.cpp", "imports/foo.capnp", ] + qbs.buildVariant: "release" } diff --git a/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.qbs b/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.qbs index c31824bb0..9f287e906 100644 --- a/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.qbs +++ b/tests/auto/blackbox/testdata/capnproto/capnproto_cpp.qbs @@ -15,4 +15,5 @@ CppApplication { "capnproto_cpp.cpp", "foo.capnp" ] + qbs.buildVariant: "release" } diff --git a/tests/auto/blackbox/testdata/capnproto/capnproto_cpp_pkgconfig.qbs b/tests/auto/blackbox/testdata/capnproto/capnproto_cpp_pkgconfig.qbs deleted file mode 100644 index 90201e440..000000000 --- a/tests/auto/blackbox/testdata/capnproto/capnproto_cpp_pkgconfig.qbs +++ /dev/null @@ -1,19 +0,0 @@ -import qbs.Host - -CppApplication { - Depends { name: "capnproto.cpp"; required: false } - condition: { - var result = qbs.targetPlatform === Host.platform(); - if (!result) - console.info("targetPlatform differs from hostPlatform"); - if (!capnproto.cpp.present) - console.info("capnproto is not present"); - return result && capnproto.cpp.present; - } - cpp.minimumMacosVersion: "10.8" - files: [ - "capnproto_cpp.cpp", - "foo.capnp" - ] - qbsModuleProviders: "qbspkgconfig" -} diff --git a/tests/auto/blackbox/testdata/capnproto/conanfile.txt b/tests/auto/blackbox/testdata/capnproto/conanfile.txt new file mode 100644 index 000000000..7313bb82e --- /dev/null +++ b/tests/auto/blackbox/testdata/capnproto/conanfile.txt @@ -0,0 +1,6 @@ +[requires] +capnproto/1.0.2 +[tool_requires] +capnproto/1.0.2 +[generators] +QbsDeps diff --git a/tests/auto/blackbox/testdata/capnproto/greeter_cpp.qbs b/tests/auto/blackbox/testdata/capnproto/greeter_cpp.qbs index 7266e9e15..5fc5464b1 100644 --- a/tests/auto/blackbox/testdata/capnproto/greeter_cpp.qbs +++ b/tests/auto/blackbox/testdata/capnproto/greeter_cpp.qbs @@ -14,11 +14,14 @@ Project { name: "server" consoleApplication: true cpp.minimumMacosVersion: "10.8" + // workaround for broken capnproto + cpp.staticLibraries: qbs.targetOS.contains("windows") ? "Advapi32" : [] capnproto.cpp.useRpc: true files: [ "greeter.capnp", "greeter-server.cpp" ] + qbs.buildVariant: "release" } CppApplication { Depends { name: "capnproto.cpp"; required: false } @@ -26,9 +29,11 @@ Project { consoleApplication: true capnproto.cpp.useRpc: true cpp.minimumMacosVersion: "10.8" + cpp.staticLibraries: qbs.targetOS.contains("windows") ? "Advapi32" : [] files: [ "greeter.capnp", "greeter-client.cpp" ] + qbs.buildVariant: "release" } } diff --git a/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/change-tracking-and-multiplexing.qbs b/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/change-tracking-and-multiplexing.qbs index d1215355c..096778cd3 100644 --- a/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/change-tracking-and-multiplexing.qbs +++ b/tests/auto/blackbox/testdata/change-tracking-and-multiplexing/change-tracking-and-multiplexing.qbs @@ -1,8 +1,8 @@ StaticLibrary { name: "l" - Depends { condition: qbs.targetOS.contains("darwin"); name: "bundle" } - Properties { condition: qbs.targetOS.contains("darwin"); bundle.isBundle: false } + Depends { condition: qbs.targetOS.includes("darwin"); name: "bundle" } + Properties { condition: qbs.targetOS.includes("darwin"); bundle.isBundle: false } multiplexByQbsProperties: ["buildVariants"] qbs.buildVariants: ["debug", "release"] diff --git a/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/limerick/generic.qbs b/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/limerick/generic.qbs index 2ebaaac11..bd8e901c7 100644 --- a/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/limerick/generic.qbs +++ b/tests/auto/blackbox/testdata/choose-module-instance/other-searchpath/modules/limerick/generic.qbs @@ -1,3 +1,3 @@ Module { - condition: !qbs.targetOS.contains("Beatles") + condition: !qbs.targetOS.includes("Beatles") } diff --git a/tests/auto/blackbox/testdata/clean/clean.qbs b/tests/auto/blackbox/testdata/clean/clean.qbs index ce3a8eb12..10eca2d41 100644 --- a/tests/auto/blackbox/testdata/clean/clean.qbs +++ b/tests/auto/blackbox/testdata/clean/clean.qbs @@ -5,7 +5,7 @@ Project { name: "dep" files: "dep.cpp" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/blackbox/testdata/cli/dotnettest.qbs b/tests/auto/blackbox/testdata/cli/dotnettest.qbs index 9a10b8068..5685be8c4 100644 --- a/tests/auto/blackbox/testdata/cli/dotnettest.qbs +++ b/tests/auto/blackbox/testdata/cli/dotnettest.qbs @@ -1,7 +1,7 @@ Project { Application { Depends { name: "cli" } - Depends { name: "HelloWorldModule"; condition: !qbs.toolchain.contains("mono") } + Depends { name: "HelloWorldModule"; condition: !qbs.toolchain.includes("mono") } Depends { name: "NetLib" } type: "application" @@ -16,7 +16,7 @@ Project { // Mono's VB compiler doesn't support modules yet, and if we try with C#, it crashes anyways NetModule { - condition: !qbs.toolchain.contains("mono") + condition: !qbs.toolchain.includes("mono") Depends { name: "cli" } name: "HelloWorldModule" @@ -37,7 +37,7 @@ Project { // fill-in for missing NetModule Group { - condition: qbs.toolchain.contains("mono") + condition: qbs.toolchain.includes("mono") files: ["Module.cs"] } diff --git a/tests/auto/blackbox/testdata/command-file/command-file.qbs b/tests/auto/blackbox/testdata/command-file/command-file.qbs index 8e25221c5..87dd0e054 100644 --- a/tests/auto/blackbox/testdata/command-file/command-file.qbs +++ b/tests/auto/blackbox/testdata/command-file/command-file.qbs @@ -4,7 +4,7 @@ Project { destinationDirectory: project.buildDirectory Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib.cpp"] @@ -14,6 +14,6 @@ Project { cpp.libraryPaths: project.buildDirectory files: ["main.cpp"] cpp.staticLibraries: ['@' + sourceDirectory + '/' - + (qbs.toolchain.contains("msvc") ? "list.msvc" : "list.gcc")] + + (qbs.toolchain.includes("msvc") ? "list.msvc" : "list.gcc")] } } diff --git a/tests/auto/blackbox/testdata/compilerDefinesByLanguage/CppDefinesApp.qbs b/tests/auto/blackbox/testdata/compilerDefinesByLanguage/CppDefinesApp.qbs index b205ef2a7..f2da212f6 100644 --- a/tests/auto/blackbox/testdata/compilerDefinesByLanguage/CppDefinesApp.qbs +++ b/tests/auto/blackbox/testdata/compilerDefinesByLanguage/CppDefinesApp.qbs @@ -1,7 +1,7 @@ CppApplication { files: ["app.c"] - property bool enableObjectiveC: qbs.targetOS.contains("darwin") + property bool enableObjectiveC: qbs.targetOS.includes("darwin") Group { name: "C/C++" diff --git a/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs b/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs deleted file mode 100644 index 802aa1450..000000000 --- a/tests/auto/blackbox/testdata/concurrent-executor/concurrent-executor.qbs +++ /dev/null @@ -1,67 +0,0 @@ -import qbs.File -import qbs.TextFile -import "util.js" as Utils - -Product { - type: ["final1", "final2"] - Group { - files: ["dummy1.input"] - fileTags: ["input1"] - } - Group { - files: ["dummy2.input"] - fileTags: ["input2"] - } - Rule { - inputs: ["input1"] - Artifact { - filePath: project.buildDirectory + "/dummy1.final" - fileTags: ["final1"] - } - prepare: { - var cmds = []; - for (var i = 0; i < 10; ++i) { - var cmd = new JavaScriptCommand(); - cmd.silent = true; - cmd.createFile = i == 9; - cmd.sourceCode = function() { - if (createFile) { - console.info("Creating file"); - var file = new TextFile(output.filePath, TextFile.WriteOnly); - file.close(); - } - }; - cmds.push(cmd); - } - return cmds; - } - } - Rule { - inputs: ["input2"] - Artifact { - filePath: "dummy.intermediate" - fileTags: ["intermediate"] - } - prepare: { - var cmd = new JavaScriptCommand(); - cmd.silent = true; - cmd.sourceCode = function() { }; - return [cmd]; - } - } - Rule { - inputs: ["intermediate"] - outputFileTags: "final2" - prepare: { - do - Utils.sleep(6000); - while (!File.exists(project.buildDirectory + "/dummy1.final")); - var cmd = new JavaScriptCommand(); - cmd.silent = true; - cmd.sourceCode = function() { }; - return [cmd]; - } - } -} - - diff --git a/tests/auto/blackbox/testdata/concurrent-executor/util.js b/tests/auto/blackbox/testdata/concurrent-executor/util.js deleted file mode 100644 index a37a8cbb1..000000000 --- a/tests/auto/blackbox/testdata/concurrent-executor/util.js +++ /dev/null @@ -1,8 +0,0 @@ -function sleep(timeInMs) -{ - var referenceTime = new Date(); - var time = null; - do { - time = new Date(); - } while (time - referenceTime < timeInMs); -} diff --git a/tests/auto/blackbox/testdata/configure/modules/definition/module.qbs b/tests/auto/blackbox/testdata/configure/modules/definition/module.qbs index 1d647faa2..6a1dbe67d 100644 --- a/tests/auto/blackbox/testdata/configure/modules/definition/module.qbs +++ b/tests/auto/blackbox/testdata/configure/modules/definition/module.qbs @@ -12,7 +12,7 @@ Module { var cmd; var args; var p = path; - if (targetOS.contains("windows")) { + if (targetOS.includes("windows")) { cmd = windowsShellPath; args = ["/c", "date", "/t"]; } else { diff --git a/tests/auto/blackbox/testdata/conflicting-property-values/conflicting-property-values.qbs b/tests/auto/blackbox/testdata/conflicting-property-values/conflicting-property-values.qbs new file mode 100644 index 000000000..23b6ee5a3 --- /dev/null +++ b/tests/auto/blackbox/testdata/conflicting-property-values/conflicting-property-values.qbs @@ -0,0 +1,41 @@ +Project { + Product { + name: "low" + Export { property string prop: "low"; property string prop2: "low" } + } + Product { + name: "higher1" + Export { Depends { name: "low" } low.prop: "higher1" } + } + Product { + name: "higher2" + Export { Depends { name: "low" } low.prop: "higher2" } + } + Product { + name: "highest1" + Export { + Depends { name: "low" } + Depends { name: "higher1" } + Depends { name: "higher2" } + low.prop: "highest1" + low.prop2: "highest" + } + } + Product { + name: "highest2" + Export { + Depends { name: "low" } + Depends { name: "higher1" } + Depends { name: "higher2" } + low.prop: "highest2" + low.prop2: "highest" + } + } + Product { + name: "toplevel" + Depends { name: "highest1" } + Depends { name: "highest2" } + low.prop: name + property bool dummy: { console.info("final prop value: " + low.prop); } + } +} diff --git a/tests/auto/blackbox/testdata/cpu-features/cpu-features.qbs b/tests/auto/blackbox/testdata/cpu-features/cpu-features.qbs index 0bfdaceba..36e805516 100644 --- a/tests/auto/blackbox/testdata/cpu-features/cpu-features.qbs +++ b/tests/auto/blackbox/testdata/cpu-features/cpu-features.qbs @@ -8,7 +8,7 @@ CppApplication { property bool dummy: { console.info("is x86: " + (qbs.architecture === "x86")); console.info("is x64: " + (qbs.architecture === "x86_64")); - console.info("is gcc: " + qbs.toolchain.contains("gcc")); - console.info("is msvc: " + qbs.toolchain.contains("msvc")); + console.info("is gcc: " + qbs.toolchain.includes("gcc")); + console.info("is msvc: " + qbs.toolchain.includes("msvc")); } } diff --git a/tests/auto/blackbox/testdata/cxx-language-version/cxx-language-version.qbs b/tests/auto/blackbox/testdata/cxx-language-version/cxx-language-version.qbs index 322ded85c..24c37951c 100644 --- a/tests/auto/blackbox/testdata/cxx-language-version/cxx-language-version.qbs +++ b/tests/auto/blackbox/testdata/cxx-language-version/cxx-language-version.qbs @@ -13,10 +13,10 @@ CppApplication { var isEvenNewerMsvc; var isOlderMsvc; var isGcc; - if (toolchain.contains("clang-cl")) { + if (toolchain.includes("clang-cl")) { isEvenNewerMsvc = true; isNewerMsvc = true; - } else if (toolchain.contains("msvc")) { + } else if (toolchain.includes("msvc")) { if (compilerVersion >= "19.12.25831") isEvenNewerMsvc = true; if (compilerVersion >= "18.00.30723") diff --git a/tests/auto/blackbox/testdata/date-property/date-property.qbs b/tests/auto/blackbox/testdata/date-property/date-property.qbs new file mode 100644 index 000000000..ffd584802 --- /dev/null +++ b/tests/auto/blackbox/testdata/date-property/date-property.qbs @@ -0,0 +1,18 @@ +Product { + type: "date" + property var theDate: new Date(1999, 11, 31); + Rule { + multiplex: true + Artifact { filePath: "dummy"; fileTags: "date" } + prepare: { + var cmd = new JavaScriptCommand; + cmd.silent = true; + cmd.sourceCode = function() { + var d = product.theDate; + console.info("The stored date was " + d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + + d.getDate()); + }; + return cmd; + } + } +} diff --git a/tests/auto/blackbox/testdata/deprecated-property/deprecated-property.qbs b/tests/auto/blackbox/testdata/deprecated-property/deprecated-property.qbs index e3dacffea..7d1550312 100644 --- a/tests/auto/blackbox/testdata/deprecated-property/deprecated-property.qbs +++ b/tests/auto/blackbox/testdata/deprecated-property/deprecated-property.qbs @@ -1,8 +1,6 @@ -import qbs // FIXME: Don't remove this import because then the test fails! - Product { Depends { name: "themodule" } themodule.newProp: true - themodule.oldProp: false + themodule.expiringProp: false themodule.veryOldProp: false } diff --git a/tests/auto/blackbox/testdata/deprecated-property/modules/themodule/m.qbs b/tests/auto/blackbox/testdata/deprecated-property/modules/themodule/m.qbs index cd6b0b70c..58164e918 100644 --- a/tests/auto/blackbox/testdata/deprecated-property/modules/themodule/m.qbs +++ b/tests/auto/blackbox/testdata/deprecated-property/modules/themodule/m.qbs @@ -1,8 +1,8 @@ -import qbs // FIXME: Don't remove this import because then the test fails! +import qbs.Environment Module { property bool newProp - property bool oldProp + property bool expiringProp property bool forgottenProp PropertyOptions { @@ -10,9 +10,9 @@ Module { description: "Use this, it's good!" } PropertyOptions { - name: "oldProp" + name: "expiringProp" description: "Use newProp instead." - removalVersion: "99.9" + removalVersion: Environment.getEnv("REMOVAL_VERSION") } PropertyOptions { name: "veryOldProp" diff --git a/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs b/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs index fdd3aa1f7..367bb665c 100644 --- a/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs +++ b/tests/auto/blackbox/testdata/discard-unused-data/discard-unused-data.qbs @@ -4,9 +4,9 @@ CppApplication { files: "main.cpp" - Depends { name: "bundle"; condition: qbs.targetOS.contains("darwin") } + Depends { name: "bundle"; condition: qbs.targetOS.includes("darwin") } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } @@ -17,7 +17,7 @@ CppApplication { var cmd = new JavaScriptCommand(); cmd.silent = true; cmd.sourceCode = function() { - console.info("is Darwin: " + product.qbs.targetOS.contains("darwin")); + console.info("is Darwin: " + product.qbs.targetOS.includes("darwin")); console.info("---" + product.cpp.nmPath + "---"); } return [cmd]; diff --git a/tests/auto/blackbox/testdata/dot-dot-pc-file/dot-dot-pc-file.qbs b/tests/auto/blackbox/testdata/dot-dot-pc-file/dot-dot-pc-file.qbs new file mode 100644 index 000000000..60c4ea2bc --- /dev/null +++ b/tests/auto/blackbox/testdata/dot-dot-pc-file/dot-dot-pc-file.qbs @@ -0,0 +1,7 @@ +CppApplication { + name: "p" + Depends { name: "qbs-metatest-module"; } + files: "main.cpp" + moduleProviders.qbspkgconfig.libDirs: "libdir" + qbsModuleProviders: "qbspkgconfig" +} diff --git a/tests/auto/blackbox/testdata/dot-dot-pc-file/libdir/qbs.metatest.module.pc b/tests/auto/blackbox/testdata/dot-dot-pc-file/libdir/qbs.metatest.module.pc new file mode 100644 index 000000000..c00fd26d6 --- /dev/null +++ b/tests/auto/blackbox/testdata/dot-dot-pc-file/libdir/qbs.metatest.module.pc @@ -0,0 +1,5 @@ +Name: qbs.metatest.module +Description: just a test +Version: 0.0.1 + +Cflags: -DTHE_MAGIC_DEFINE diff --git a/tests/auto/blackbox/testdata/dot-dot-pc-file/main.cpp b/tests/auto/blackbox/testdata/dot-dot-pc-file/main.cpp new file mode 100644 index 000000000..442b755bf --- /dev/null +++ b/tests/auto/blackbox/testdata/dot-dot-pc-file/main.cpp @@ -0,0 +1,5 @@ +#ifndef THE_MAGIC_DEFINE +#error "missing the magic define" +#endif + +int main() {} diff --git a/tests/auto/blackbox/testdata/driver-linker-flags/driver-linker-flags.qbs b/tests/auto/blackbox/testdata/driver-linker-flags/driver-linker-flags.qbs index 5de0fe053..57f096494 100644 --- a/tests/auto/blackbox/testdata/driver-linker-flags/driver-linker-flags.qbs +++ b/tests/auto/blackbox/testdata/driver-linker-flags/driver-linker-flags.qbs @@ -8,7 +8,7 @@ CppApplication { Probe { id: toolchainProbe - condition: qbs.toolchain.contains("gcc") + condition: qbs.toolchain.includes("gcc") configure: { console.info("toolchain is GCC-like"); found = true; diff --git a/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs b/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs index 1acf606dc..c95d88052 100644 --- a/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs +++ b/tests/auto/blackbox/testdata/dynamic-library-in-module/Dll.qbs @@ -1,8 +1,8 @@ DynamicLibrary { Depends { name: "cpp" } - Depends { name: "bundle"; condition: qbs.targetOS.contains("darwin") } + Depends { name: "bundle"; condition: qbs.targetOS.includes("darwin") } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false cpp.minimumMacosVersion: "10.7" // For -rpath } diff --git a/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/thelib.qbs b/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/thelib.qbs index 30f87337d..3059fa5e9 100644 --- a/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/thelib.qbs +++ b/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/thelib/thelib.qbs @@ -13,7 +13,7 @@ Module { } Group { name: "thelib dll import" - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") files: FileInfo.joinPaths(product.thelib.baseDir, "thelib.lib") fileTags: ["dynamiclibrary_import"] filesAreTargets: true diff --git a/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/theotherlib/theotherlib.qbs b/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/theotherlib/theotherlib.qbs index 1eb1e01a5..f387feb80 100644 --- a/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/theotherlib/theotherlib.qbs +++ b/tests/auto/blackbox/testdata/dynamic-library-in-module/modules/theotherlib/theotherlib.qbs @@ -13,7 +13,7 @@ Module { } Group { name: "theotherlib dll import" - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") files: FileInfo.joinPaths(product.theotherlib.baseDir, "theotherlib.lib") fileTags: ["dynamiclibrary_import"] filesAreTargets: true diff --git a/tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs b/tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs index 9a75043a8..e1d09f7e0 100644 --- a/tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs +++ b/tests/auto/blackbox/testdata/enableExceptions/exceptions.qbs @@ -1,5 +1,5 @@ CppApplication { files: ["main.cpp"] cpp.treatWarningsAsErrors: true - cpp.defines: qbs.toolchain.contains("msvc") && !cpp.enableExceptions ? ["FORCE_FAIL_VS"] : [] + cpp.defines: qbs.toolchain.includes("msvc") && !cpp.enableExceptions ? ["FORCE_FAIL_VS"] : [] } diff --git a/tests/auto/blackbox/testdata/enableExceptions/none.qbs b/tests/auto/blackbox/testdata/enableExceptions/none.qbs index 8fb052476..439ea3037 100644 --- a/tests/auto/blackbox/testdata/enableExceptions/none.qbs +++ b/tests/auto/blackbox/testdata/enableExceptions/none.qbs @@ -2,7 +2,7 @@ CppApplication { files: ["emptymain.cpp"] Group { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") files: ["empty.m", "empty.mm"] } } diff --git a/tests/auto/blackbox/testdata/escaped-linker-flags/escaped-linker-flags.qbs b/tests/auto/blackbox/testdata/escaped-linker-flags/escaped-linker-flags.qbs index f48bf8d1f..b4fb0df4d 100644 --- a/tests/auto/blackbox/testdata/escaped-linker-flags/escaped-linker-flags.qbs +++ b/tests/auto/blackbox/testdata/escaped-linker-flags/escaped-linker-flags.qbs @@ -10,4 +10,9 @@ CppApplication { cpp.linkerFlags: ["-s"] } files: ["main.cpp"] + Probe { + id: checker + property bool isUnixGcc: qbs.toolchain.contains("gcc") && !qbs.targetOS.contains("macos") + configure: { console.info("is gcc: " + isUnixGcc); } + } } diff --git a/tests/auto/blackbox/testdata/exports-cmake/Foo.cpp b/tests/auto/blackbox/testdata/exports-cmake/Foo.cpp new file mode 100644 index 000000000..ea334f9af --- /dev/null +++ b/tests/auto/blackbox/testdata/exports-cmake/Foo.cpp @@ -0,0 +1,5 @@ +#include "Foo.h" +int someFooWork() +{ + return 42; +} diff --git a/tests/auto/blackbox/testdata/exports-cmake/Foo.h b/tests/auto/blackbox/testdata/exports-cmake/Foo.h new file mode 100644 index 000000000..2f279f577 --- /dev/null +++ b/tests/auto/blackbox/testdata/exports-cmake/Foo.h @@ -0,0 +1,16 @@ +#ifndef FOO_H +#define FOO_H +#include <dllexport.h> + +#ifdef FOO_LIB_STATIC +#define FOO_LIB_EXPORT +#else +#ifdef FOO_LIB +#define FOO_LIB_EXPORT DLL_EXPORT +#else +#define FOO_LIB_EXPORT DLL_IMPORT +#endif +#endif + +FOO_LIB_EXPORT int someFooWork(); +#endif // FOO_H diff --git a/tests/auto/blackbox/testdata/exports-cmake/cmake/CMakeLists.txt b/tests/auto/blackbox/testdata/exports-cmake/cmake/CMakeLists.txt new file mode 100644 index 000000000..d874e0e92 --- /dev/null +++ b/tests/auto/blackbox/testdata/exports-cmake/cmake/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.10) + +project(qbs_import) + +find_package(Bar PATHS REQUIRED) +add_executable(Consumer main.cpp) +target_link_libraries(Consumer Bar) diff --git a/tests/auto/blackbox/testdata/exports-cmake/cmake/main.cpp b/tests/auto/blackbox/testdata/exports-cmake/cmake/main.cpp new file mode 100644 index 000000000..1a1fa90ec --- /dev/null +++ b/tests/auto/blackbox/testdata/exports-cmake/cmake/main.cpp @@ -0,0 +1,6 @@ +#include <Foo.h> + +int main() +{ + return someFooWork(); +} diff --git a/tests/auto/blackbox/testdata/exports-cmake/exports-cmake.qbs b/tests/auto/blackbox/testdata/exports-cmake/exports-cmake.qbs new file mode 100644 index 000000000..6464af705 --- /dev/null +++ b/tests/auto/blackbox/testdata/exports-cmake/exports-cmake.qbs @@ -0,0 +1,70 @@ +import qbs.FileInfo + +Project { + property bool isStatic: false + property bool isBundle: false + + property string headersInstallDir: "include" + + Product { + name: "DllExport" + Depends { name: "Exporter.cmake" } + Group { + name: "API headers" + files: ["../dllexport.h"] + qbs.install: true + qbs.installDir: project.headersInstallDir + } + Group { + fileTagsFilter: ["Exporter.cmake.package"] + qbs.install: true + qbs.installDir: "/lib/cmake/DllExport" + } + Export { + Depends { name: "cpp" } + cpp.includePaths: FileInfo.joinPaths( + exportingProduct.qbs.installRoot, + exportingProduct.qbs.installPrefix, + project.headersInstallDir) + } + } + + Library { + type: project.isStatic ? "staticlibrary" : "dynamiclibrary" + Depends { name: "cpp" } + Depends { name: "DllExport" } + Depends { name: "Exporter.cmake" } + Exporter.cmake.packageName: "Bar" + name: "Foo" + files: ["Foo.cpp"] + version: "1.2.3" + cpp.includePaths: "." + cpp.defines: "FOO_LIB" + Group { + name: "API headers" + files: ["Foo.h"] + qbs.install: true + qbs.installDir: project.headersInstallDir + } + install: true + installImportLib: true + Group { + fileTagsFilter: ["Exporter.cmake.package"] + qbs.install: true + qbs.installDir: "/lib/cmake/Bar" + } + Export { + Depends { name: "cpp" } + cpp.includePaths: FileInfo.joinPaths( + exportingProduct.qbs.installRoot, + exportingProduct.qbs.installPrefix, + project.headersInstallDir) + cpp.defines: ["FOO=1"].concat(project.isStatic ? ["FOO_LIB_STATIC"] : []) + cpp.commonCompilerFlags: "-DOTHER_DEF=1" + cpp.linkerFlags: exportingProduct.qbs.toolchain.contains("gcc") ? ["-s"] : [] + } + + Depends { name: 'bundle' } + bundle.isBundle: qbs.targetOS.includes("darwin") && project.isBundle + } +} diff --git a/tests/auto/blackbox/testdata/exports-cmake/find-cmake.qbs b/tests/auto/blackbox/testdata/exports-cmake/find-cmake.qbs new file mode 100644 index 000000000..52f388966 --- /dev/null +++ b/tests/auto/blackbox/testdata/exports-cmake/find-cmake.qbs @@ -0,0 +1,46 @@ +import qbs.Probes + +Product { + Depends { name: "cpp" } + + Probes.BinaryProbe { + id: cmakeProbe + names: "cmake" + } + + Probes.BinaryProbe { + id: ninjaProbe + names: ["ninja"] + } + + property bool test: { + var data = { + cmakeFound: cmakeProbe.found, + cmakeFilePath: cmakeProbe.filePath, + crossCompiling: qbs.targetPlatform !== qbs.hostPlatform, + installPrefix: qbs.installPrefix + }; + data.buildEnv = {} + Object.assign(data.buildEnv, cpp.buildEnv); // deep copy buildEnv from a probe + if (qbs.toolchain.includes("gcc")) { + data.buildEnv["CC"] = cpp.cCompilerName; + data.buildEnv["CXX"] = cpp.cxxCompilerName; + } else { + data.buildEnv["CC"] = cpp.compilerName; + data.buildEnv["CXX"] = cpp.compilerName; + } + + if (ninjaProbe.found) { + data.generator = "Ninja"; + } else { + if (qbs.toolchain.includes("msvc")) { + data.generator = "NMake Makefiles" + } else if (qbs.toolchain.includes("mingw")) { + data.generator = "MinGW Makefiles"; + } else if (qbs.toolchain.includes("gcc")) { + data.generator = "Unix Makefiles"; + } + } + console.info("---" + JSON.stringify(data) + "---"); + } +} diff --git a/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs b/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs index 94632053a..23331f93f 100644 --- a/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs +++ b/tests/auto/blackbox/testdata/exports-pkgconfig/exports-pkgconfig.qbs @@ -43,7 +43,7 @@ Project { Depends { name: "Qt.core"; required: false } Depends { name: "helper1" } Depends { name: "helper3" } - property bool someCondition: Host.os().contains("windows") // hostOS for easier testing + property bool someCondition: Host.os().includes("windows") // hostOS for easier testing property bool someOtherCondition: someCondition Properties { condition: !someOtherCondition diff --git a/tests/auto/blackbox/testdata/exports-qbs/lib.qbs b/tests/auto/blackbox/testdata/exports-qbs/lib.qbs index 453dac562..01f89a221 100644 --- a/tests/auto/blackbox/testdata/exports-qbs/lib.qbs +++ b/tests/auto/blackbox/testdata/exports-qbs/lib.qbs @@ -16,7 +16,7 @@ DynamicLibrary { cpp.defines: ["MYLIB_BUILD"] cpp.variantSuffix: qbs.buildVariant === "debug" ? "d" : "" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["mylib.cpp"] @@ -52,7 +52,7 @@ DynamicLibrary { condition: true prefixMapping: [{ prefix: includeDir, - replacement: FileInfo.joinPaths(qbs.installPrefix, exportingProduct.headersInstallDir) + replacement: FileInfo.joinPaths(exportingProduct.qbs.installPrefix, exportingProduct.headersInstallDir) }] } } diff --git a/tests/auto/blackbox/testdata/external-libs/external-libs.qbs b/tests/auto/blackbox/testdata/external-libs/external-libs.qbs index 619f40867..326bf5dae 100644 --- a/tests/auto/blackbox/testdata/external-libs/external-libs.qbs +++ b/tests/auto/blackbox/testdata/external-libs/external-libs.qbs @@ -1,13 +1,13 @@ import qbs.TextFile Project { - property string libDir: sourceDirectory + "/libs" + property string libDir: buildDirectory + "/libs" StaticLibrary { name: "lib1" destinationDirectory: project.libDir Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib1.cpp"] @@ -18,7 +18,7 @@ Project { Depends { name: "cpp" } Depends { name: "lib1" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } files: ["lib2.cpp"] diff --git a/tests/auto/blackbox/testdata/flatbuf/bar.fbs b/tests/auto/blackbox/testdata/flatbuf/bar.fbs new file mode 100644 index 000000000..47148f800 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/bar.fbs @@ -0,0 +1,9 @@ +include "foo.fbs"; + +namespace QbsTest; + +table Bar { + foo:Foo; +} + +root_type Bar; diff --git a/tests/auto/blackbox/testdata/flatbuf/baz.fbs b/tests/auto/blackbox/testdata/flatbuf/baz.fbs new file mode 100644 index 000000000..312183710 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/baz.fbs @@ -0,0 +1,9 @@ +include "imported_foo/imported_foo.fbs"; + +namespace QbsTest; + +table Baz { + foo:Foo; +} + +root_type Baz; diff --git a/tests/auto/blackbox/testdata/flatbuf/conanfile.txt b/tests/auto/blackbox/testdata/flatbuf/conanfile.txt new file mode 100644 index 000000000..188da5897 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/conanfile.txt @@ -0,0 +1,6 @@ +[requires] +flatbuffers/24.3.25 +[tool_requires] +flatbuffers/24.3.25 +[generators] +QbsDeps diff --git a/tests/auto/blackbox/testdata/flatbuf/flat.c b/tests/auto/blackbox/testdata/flatbuf/flat.c new file mode 100644 index 000000000..55e25e556 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat.c @@ -0,0 +1,36 @@ +#include "foo_builder.h" + +#include <stdio.h> + +#undef ns +#define ns(x) FLATBUFFERS_WRAP_NAMESPACE(QbsTest, x) // Specified in the schema. + +#define test_assert(x) do { if (!(x)) { assert(0); return -1; }} while (0) + +int main() +{ + void *buffer = NULL; + size_t size = 0; + + flatcc_builder_t builder; + flatcc_builder_init(&builder); + + flatbuffers_string_ref_t name = flatbuffers_string_create_str(&builder, "John Doe"); + + ns(Foo_create_as_root(&builder, name, 42)); + + buffer = flatcc_builder_finalize_aligned_buffer(&builder, &size); + + ns(Foo_table_t) foo = ns(Foo_as_root(buffer)); + + test_assert(strcmp(ns(Foo_name(foo)), "John Doe") == 0); + test_assert(ns(Foo_count(foo)) == 42); + + free(buffer); + + flatcc_builder_clear(&builder); + + printf("The FlatBuffer was successfully created and accessed!\n"); + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat.cpp b/tests/auto/blackbox/testdata/flatbuf/flat.cpp new file mode 100644 index 000000000..56332bacd --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat.cpp @@ -0,0 +1,22 @@ +#include "foo_generated.h" + +#include <iostream> + +using namespace QbsTest; + +int main() +{ + flatbuffers::FlatBufferBuilder builder; + auto name = builder.CreateString("John Doe"); + auto newFoo = QbsTest::CreateFoo(builder, name, 42); + builder.Finish(newFoo); + + auto foo = GetFoo(builder.GetBufferPointer()); + + assert(foo->name()->str() == "John Doe"); + assert(foo->count() == 42); + + std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.cpp new file mode 100644 index 000000000..b7c43d8a5 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.cpp @@ -0,0 +1,25 @@ +#include "baz_generated.h" + +#include <iostream> + +using namespace QbsTest; + +int main() +{ + flatbuffers::FlatBufferBuilder builder; + + auto name = builder.CreateString("John Doe"); + auto newFoo = QbsTest::CreateFoo(builder, name, 42); + + auto newBaz = QbsTest::CreateBaz(builder, newFoo); + builder.Finish(newBaz); + + auto baz = GetBaz(builder.GetBufferPointer()); + + assert(baz->foo()->name()->str() == "John Doe"); + assert(baz->foo()->count() == 42); + + std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.qbs new file mode 100644 index 000000000..888bfd4e3 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_absolute_import.qbs @@ -0,0 +1,24 @@ +CppApplication { + Depends { name: "flatbuf.cpp"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuf.cpp.present); + return flatbuf.cpp.present; + } + + flatbuf.cpp.importPaths: "imports/" + + files: [ + "flat_absolute_import.cpp", + "baz.fbs", + "imports/imported_foo/imported_foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_c.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_c.qbs new file mode 100644 index 000000000..6d365252e --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_c.qbs @@ -0,0 +1,21 @@ +CppApplication { + Depends { name: "flatbuffers.c"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuffers.c.present); + return flatbuffers.c.present; + } + + files: [ + "flat.c", + "foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_cpp.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_cpp.qbs new file mode 100644 index 000000000..99e89a5fa --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_cpp.qbs @@ -0,0 +1,21 @@ +CppApplication { + Depends { name: "flatbuf.cpp"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuf.cpp.present); + return flatbuf.cpp.present; + } + + files: [ + "flat.cpp", + "foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.cpp new file mode 100644 index 000000000..77ed64acd --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.cpp @@ -0,0 +1,22 @@ +#include "foo_generated.hpp" + +#include <iostream> + +using namespace QbsTest; + +int main() +{ + flatbuffers::FlatBufferBuilder builder; + auto name = builder.CreateString("John Doe"); + auto newFoo = QbsTest::CreateFoo(builder, name, 42); + builder.Finish(newFoo); + + auto foo = GetFoo(builder.GetBufferPointer()); + + assert(foo->name()->str() == "John Doe"); + assert(foo->count() == 42); + + std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.qbs new file mode 100644 index 000000000..31eec7629 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_filename_extension.qbs @@ -0,0 +1,23 @@ +CppApplication { + Depends { name: "flatbuf.cpp"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuf.cpp.present); + return flatbuf.cpp.present; + } + + flatbuf.cpp.filenameExtension: "hpp" + + files: [ + "flat_filename_extension.cpp", + "foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.cpp new file mode 100644 index 000000000..630e4aaef --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.cpp @@ -0,0 +1,22 @@ +#include "foo.fbs.h" + +#include <iostream> + +using namespace QbsTest; + +int main() +{ + flatbuffers::FlatBufferBuilder builder; + auto name = builder.CreateString("John Doe"); + auto newFoo = QbsTest::CreateFoo(builder, name, 42); + builder.Finish(newFoo); + + auto foo = GetFoo(builder.GetBufferPointer()); + + assert(foo->name()->str() == "John Doe"); + assert(foo->count() == 42); + + std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.qbs new file mode 100644 index 000000000..5103b041f --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_filename_suffix.qbs @@ -0,0 +1,23 @@ +CppApplication { + Depends { name: "flatbuf.cpp"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuf.cpp.present); + return flatbuf.cpp.present; + } + + flatbuf.cpp.filenameSuffix: ".fbs" + + files: [ + "flat_filename_suffix.cpp", + "foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.cpp new file mode 100644 index 000000000..5f4b55e96 --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.cpp @@ -0,0 +1,26 @@ +#include "baz_generated.h" +#include "imported_foo/imported_foo_generated.h" + +#include <iostream> + +using namespace QbsTest; + +int main() +{ + flatbuffers::FlatBufferBuilder builder; + + auto name = builder.CreateString("John Doe"); + auto newFoo = QbsTest::CreateFoo(builder, name, 42); + + auto newBaz = QbsTest::CreateBaz(builder, newFoo); + builder.Finish(newBaz); + + auto baz = GetBaz(builder.GetBufferPointer()); + + assert(baz->foo()->name()->str() == "John Doe"); + assert(baz->foo()->count() == 42); + + std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.qbs new file mode 100644 index 000000000..0ea0d1dac --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_keep_prefix.qbs @@ -0,0 +1,25 @@ +CppApplication { + Depends { name: "flatbuf.cpp"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuf.cpp.present); + return flatbuf.cpp.present; + } + + flatbuf.cpp.importPaths: "imports/" + flatbuf.cpp.keepPrefix: true + + files: [ + "flat_keep_prefix.cpp", + "baz.fbs", + "imports/imported_foo/imported_foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.cpp b/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.cpp new file mode 100644 index 000000000..bec6dadfd --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.cpp @@ -0,0 +1,25 @@ +#include "bar_generated.h" + +#include <iostream> + +using namespace QbsTest; + +int main() +{ + flatbuffers::FlatBufferBuilder builder; + + auto name = builder.CreateString("John Doe"); + auto newFoo = QbsTest::CreateFoo(builder, name, 42); + + auto newBar = QbsTest::CreateBar(builder, newFoo); + builder.Finish(newBar); + + auto bar = GetBar(builder.GetBufferPointer()); + + assert(bar->foo()->name()->str() == "John Doe"); + assert(bar->foo()->count() == 42); + + std::cout << "The FlatBuffer was successfully created and accessed!" << std::endl; + + return 0; +} diff --git a/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.qbs b/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.qbs new file mode 100644 index 000000000..f5a2c5d0b --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/flat_relative_import.qbs @@ -0,0 +1,22 @@ +CppApplication { + Depends { name: "flatbuf.cpp"; required: false } + + consoleApplication: true + condition: { + var result = qbs.targetPlatform === qbs.hostPlatform; + if (!result) + console.info("targetPlatform differs from hostPlatform"); + return result && hasFlatbuffers; + } + property bool hasFlatbuffers: { + console.info("has flatbuffers: " + flatbuf.cpp.present); + return flatbuf.cpp.present; + } + + files: [ + "flat_relative_import.cpp", + "bar.fbs", + "foo.fbs", + ] + qbsModuleProviders: "conan" +} diff --git a/tests/auto/blackbox/testdata/flatbuf/foo.fbs b/tests/auto/blackbox/testdata/flatbuf/foo.fbs new file mode 100644 index 000000000..dff3b488f --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/foo.fbs @@ -0,0 +1,8 @@ +namespace QbsTest; + +table Foo { + name:string; + count:int; +} + +root_type Foo; diff --git a/tests/auto/blackbox/testdata/flatbuf/imports/imported_foo/imported_foo.fbs b/tests/auto/blackbox/testdata/flatbuf/imports/imported_foo/imported_foo.fbs new file mode 100644 index 000000000..dff3b488f --- /dev/null +++ b/tests/auto/blackbox/testdata/flatbuf/imports/imported_foo/imported_foo.fbs @@ -0,0 +1,8 @@ +namespace QbsTest; + +table Foo { + name:string; + count:int; +} + +root_type Foo; diff --git a/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs b/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs index b3519ba4c..1efe5c91c 100644 --- a/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs +++ b/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs @@ -10,7 +10,7 @@ Project { Depends { name: "freedesktop" } - freedesktop.name: "My App" + freedesktop.appName: "My App" freedesktop.desktopKeys: ({ 'Icon': "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 8c971a747..0d67fa54c 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 @@ -3,13 +3,13 @@ Project { 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" } + Properties { condition: qbs.toolchain.includes("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" } + Properties { condition: qbs.toolchain.includes("clang-cl"); cpp.linkerVariant: "lld" } cpp.generateLinkerMapFile: false } CppApplication { @@ -19,8 +19,8 @@ Project { Probe { id: toolchainProbe - property bool isUsed: qbs.toolchain.contains("msvc") - || qbs.toolchain.contains("gcc") + property bool isUsed: qbs.toolchain.includes("msvc") + || qbs.toolchain.includes("gcc") configure: { console.info("use test: " + isUsed); } diff --git a/tests/auto/blackbox/testdata/generator/generator.qbs b/tests/auto/blackbox/testdata/generator/generator.qbs index d0857beb5..9f6d452e7 100644 --- a/tests/auto/blackbox/testdata/generator/generator.qbs +++ b/tests/auto/blackbox/testdata/generator/generator.qbs @@ -18,12 +18,12 @@ CppApplication { var f = new TextFile(input.filePath, TextFile.ReadOnly); var content = f.readAll(); f.close(); - if (content.contains("file1")) { + if (content.includes("file1")) { f = new TextFile(outputs.file1[0].filePath, TextFile.WriteOnly); f.writeLine("void f1() {}"); f.close(); } - if (content.contains("file2")) { + if (content.includes("file2")) { f = new TextFile(outputs.file2[0].filePath, TextFile.WriteOnly); f.writeLine("void f2() {}"); f.close(); diff --git a/tests/auto/blackbox/testdata/groups-in-modules/groups-in-modules.qbs b/tests/auto/blackbox/testdata/groups-in-modules/groups-in-modules.qbs index 1d1d2d54e..47275821f 100644 --- a/tests/auto/blackbox/testdata/groups-in-modules/groups-in-modules.qbs +++ b/tests/auto/blackbox/testdata/groups-in-modules/groups-in-modules.qbs @@ -14,6 +14,9 @@ Project { name: "helper3" required: false } + Depends { name: "helper7" } + helper7.fileName: "helper7.c" + type: ["diamond"] files: [ diff --git a/tests/auto/blackbox/testdata/groups-in-modules/imports/Helper7Base.qbs b/tests/auto/blackbox/testdata/groups-in-modules/imports/Helper7Base.qbs new file mode 100644 index 000000000..cc55e6351 --- /dev/null +++ b/tests/auto/blackbox/testdata/groups-in-modules/imports/Helper7Base.qbs @@ -0,0 +1,8 @@ +Module { + property string directory + property string fileName + Group { + prefix: directory + "/" + files: fileName + } +} diff --git a/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.c b/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.c new file mode 100644 index 000000000..a83f5476e --- /dev/null +++ b/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.c @@ -0,0 +1 @@ +void helper7(void) {} diff --git a/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.qbs b/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.qbs new file mode 100644 index 000000000..90e1f11e2 --- /dev/null +++ b/tests/auto/blackbox/testdata/groups-in-modules/modules/helper7/helper7.qbs @@ -0,0 +1,3 @@ +Helper7Base { + directory: path +} diff --git a/tests/auto/blackbox/testdata/grpc/conanfile.txt b/tests/auto/blackbox/testdata/grpc/conanfile.txt new file mode 100644 index 000000000..f88e6e8d6 --- /dev/null +++ b/tests/auto/blackbox/testdata/grpc/conanfile.txt @@ -0,0 +1,7 @@ +[requires] +grpc/1.54.3 +[tool_requires] +protobuf/3.21.12 +grpc/1.54.3 +[generators] +QbsDeps diff --git a/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs b/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs index 6f5360ccb..d1bdd5d60 100644 --- a/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs +++ b/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs @@ -11,17 +11,19 @@ CppApplication { } Depends { name: "cpp" } - cpp.cxxLanguageVersion: "c++11" - cpp.minimumMacosVersion: "10.8" + cpp.cxxLanguageVersion: "c++17" + cpp.minimumMacosVersion: "10.15" cpp.warningLevel: "none" + qbs.buildVariant: "release" Depends { name: "protobuf.cpp"; required: false } + Depends { name: "grpc++"; id: grpcpp; required: false } protobuf.cpp.useGrpc: true property bool hasDependencies: { console.info("has grpc: " + protobuf.cpp.present); console.info("has modules: " + grpcpp.present); - return protobuf.cpp.present; + return protobuf.cpp.present && grpcpp.present; } files: "grpc.cpp" diff --git a/tests/auto/blackbox/testdata/input-tags-change-tracking/input-tags-change-tracking.qbs b/tests/auto/blackbox/testdata/input-tags-change-tracking/input-tags-change-tracking.qbs index ef2c5c55b..1e4248009 100644 --- a/tests/auto/blackbox/testdata/input-tags-change-tracking/input-tags-change-tracking.qbs +++ b/tests/auto/blackbox/testdata/input-tags-change-tracking/input-tags-change-tracking.qbs @@ -43,10 +43,10 @@ Product { inputs: "txt" outputFileTags: "p_tag" outputArtifacts: { - if (input.fileTags.contains("empty")) + if (input.fileTags.includes("empty")) return []; return [{ - filePath: input.fileTags.contains("y") ? "y.out" : "x.out", + filePath: input.fileTags.includes("y") ? "y.out" : "x.out", fileTags: "p_tag" }] } diff --git a/tests/auto/blackbox/testdata/install-locations/install-locations.qbs b/tests/auto/blackbox/testdata/install-locations/install-locations.qbs index 994b4b146..ba51c0dc1 100644 --- a/tests/auto/blackbox/testdata/install-locations/install-locations.qbs +++ b/tests/auto/blackbox/testdata/install-locations/install-locations.qbs @@ -1,16 +1,16 @@ Project { property bool dummy: { - if (qbs.targetOS.contains("windows")) { + if (qbs.targetOS.includes("windows")) { console.info("is windows"); - } else if (qbs.targetOS.contains("darwin")) { + } else if (qbs.targetOS.includes("darwin")) { console.info("is darwin"); - if (qbs.targetOS.contains("macos")) + if (qbs.targetOS.includes("macos")) console.info("is mac"); } else { console.info("is unix"); } - if (qbs.toolchain.contains("mingw")) + if (qbs.toolchain.includes("mingw")) console.info("is mingw"); } CppApplication { diff --git a/tests/auto/blackbox/testdata/installpackage/installpackage.qbs b/tests/auto/blackbox/testdata/installpackage/installpackage.qbs index a0649a578..3396b79a4 100644 --- a/tests/auto/blackbox/testdata/installpackage/installpackage.qbs +++ b/tests/auto/blackbox/testdata/installpackage/installpackage.qbs @@ -2,7 +2,7 @@ Project { CppApplication { name: "public_tool" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } Depends { name: "mylib" } @@ -20,7 +20,7 @@ Project { } DynamicLibrary { Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } Depends { name: "cpp" } diff --git a/tests/auto/blackbox/testdata/invalid-artifact-path/invalid-artifact-path.qbs b/tests/auto/blackbox/testdata/invalid-artifact-path/invalid-artifact-path.qbs new file mode 100644 index 000000000..650233d86 --- /dev/null +++ b/tests/auto/blackbox/testdata/invalid-artifact-path/invalid-artifact-path.qbs @@ -0,0 +1,18 @@ +Project { + property string artifactDir + Product { + type: "t" + Rule { + multiplex: true + Artifact { + filePath: project.artifactDir + "/file.out" + fileTags: "t" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.sourceCode = function() {}; + return cmd; + } + } + } +} diff --git a/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs b/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs index 1e7426744..5824fe518 100644 --- a/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs +++ b/tests/auto/blackbox/testdata/jsextensions-binaryfile/binaryfile.qbs @@ -36,6 +36,9 @@ Product { destination.write(source.atEof() ? [ 0xFF ] : [ 0x00 ]); source.close(); destination.close(); + source = new BinaryFile("destination.dat", BinaryFile.ReadOnly); + destination = new BinaryFile("destination2.dat", BinaryFile.WriteOnly); + destination.write(source.read(8)); }; commands.push(cmd); return commands; diff --git a/tests/auto/blackbox/testdata/jsextensions-file/file.qbs b/tests/auto/blackbox/testdata/jsextensions-file/file.qbs index 6adf714e2..7a47cf3cd 100644 --- a/tests/auto/blackbox/testdata/jsextensions-file/file.qbs +++ b/tests/auto/blackbox/testdata/jsextensions-file/file.qbs @@ -33,10 +33,10 @@ Product { if (!created || !File.exists(zePath)) throw new Error("zePath was not created."); var entries = File.directoryEntries(product.sourceDirectory, File.AllEntries | File.NoDotAndDotDot); - if (entries.length < 3 || !entries.contains("file.qbs")) + if (entries.length < 3 || !entries.includes("file.qbs")) throw new Error("Directory did not contain file.qbs"); entries = File.directoryEntries(product.sourceDirectory, File.Dirs | File.NoDotAndDotDot); - if (entries.length < 1 || !entries.contains("zePath")) + if (entries.length < 1 || !entries.includes("zePath")) throw new Error("Directory did not contain only zePath"); var moveSource = FileInfo.joinPaths(product.sourceDirectory, "tomove.txt"); var moveTarget = FileInfo.joinPaths(product.sourceDirectory, "moved.txt"); diff --git a/tests/auto/blackbox/testdata/jsextensions-process/process.qbs b/tests/auto/blackbox/testdata/jsextensions-process/process.qbs index fa184fa91..50f22cdfc 100644 --- a/tests/auto/blackbox/testdata/jsextensions-process/process.qbs +++ b/tests/auto/blackbox/testdata/jsextensions-process/process.qbs @@ -55,7 +55,7 @@ Project { // closeWriteChannel test process = new Process(); - if (Host.os().contains("windows")) + if (Host.os().includes("windows")) process.start(product.qbs.windowsShellPath, ["/C", product.qbs.windowsSystemRoot + "\\system32\\sort.exe"]); else @@ -76,7 +76,7 @@ Project { testReadlineFile.close(); process = new Process(); - if (Host.os().contains("windows")) + if (Host.os().includes("windows")) process.exec(product.qbs.windowsShellPath, ["/C", "type", "123.txt"], true); diff --git a/tests/auto/blackbox/testdata/ld/ld.qbs b/tests/auto/blackbox/testdata/ld/ld.qbs index 25fede1b0..cb04d3d9a 100644 --- a/tests/auto/blackbox/testdata/ld/ld.qbs +++ b/tests/auto/blackbox/testdata/ld/ld.qbs @@ -5,7 +5,7 @@ Project { targetName: "qbs can handle any file paths, even the crazy ones! ;)" files: ["coreutils.cpp", "coreutils.h"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false cpp.sonamePrefix: "@rpath" } diff --git a/tests/auto/blackbox/testdata/lexyacc/modules/bisonhelper/bisonhelper.qbs b/tests/auto/blackbox/testdata/lexyacc/modules/bisonhelper/bisonhelper.qbs index cb93547d4..4cce9a1e3 100644 --- a/tests/auto/blackbox/testdata/lexyacc/modules/bisonhelper/bisonhelper.qbs +++ b/tests/auto/blackbox/testdata/lexyacc/modules/bisonhelper/bisonhelper.qbs @@ -7,7 +7,7 @@ Module { property string yaccBinary: lex_yacc.yaccBinary configure: { var p = Process(); - found = p.exec(yaccBinary, ["-V"]) == 0 && p.readStdOut().contains("bison"); + found = p.exec(yaccBinary, ["-V"]) == 0 && p.readStdOut().includes("bison"); p.close(); } } diff --git a/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs b/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs index 243ab09b5..faa5d1fac 100644 --- a/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs +++ b/tests/auto/blackbox/testdata/lexyacc/one-grammar/one-grammar.qbs @@ -19,10 +19,10 @@ CppApplication { Probe { id: pathCheck property string theDir: { - if (qbs.targetOS.contains("windows")) { - if (qbs.toolchain.contains("mingw")) + if (qbs.targetOS.includes("windows")) { + if (qbs.toolchain.includes("mingw")) return cpp.toolchainInstallPath; - if (qbs.toolchain.contains("clang") && qbs.sysroot) + if (qbs.toolchain.includes("clang") && qbs.sysroot) return qbs.sysroot + "/bin"; } } diff --git a/tests/auto/blackbox/testdata/lexyacc/two-grammars/two-grammars.qbs b/tests/auto/blackbox/testdata/lexyacc/two-grammars/two-grammars.qbs index a126d725d..648860d9c 100644 --- a/tests/auto/blackbox/testdata/lexyacc/two-grammars/two-grammars.qbs +++ b/tests/auto/blackbox/testdata/lexyacc/two-grammars/two-grammars.qbs @@ -5,7 +5,7 @@ CppApplication { consoleApplication: true cpp.includePaths: ".." Properties { - condition: Host.os().contains("darwin") && qbs.toolchain.contains("clang") + condition: Host.os().includes("darwin") && qbs.toolchain.includes("clang") cpp.cFlags: "-Wno-implicit-function-declaration" } files: [ diff --git a/tests/auto/blackbox/testdata/linker-library-duplicates/setup-run-environment.qbs b/tests/auto/blackbox/testdata/linker-library-duplicates/setup-run-environment.qbs index e69cde064..c41e8f1d7 100644 --- a/tests/auto/blackbox/testdata/linker-library-duplicates/setup-run-environment.qbs +++ b/tests/auto/blackbox/testdata/linker-library-duplicates/setup-run-environment.qbs @@ -6,6 +6,11 @@ Project { files: ["lib1.cpp"] Depends { name: "bundle" } bundle.isBundle: false + Probe { + id: checker + property bool isGcc: qbs.toolchain.contains("gcc") + configure: { console.info("is gcc: " + isGcc); } + } } DynamicLibrary { diff --git a/tests/auto/blackbox/testdata/linker-variant/linker-variant.qbs b/tests/auto/blackbox/testdata/linker-variant/linker-variant.qbs index 57bd4ccba..9256bf767 100644 --- a/tests/auto/blackbox/testdata/linker-variant/linker-variant.qbs +++ b/tests/auto/blackbox/testdata/linker-variant/linker-variant.qbs @@ -3,7 +3,7 @@ CppApplication { property string linkerVariant Probe { id: gccProbe - property bool isGcc: qbs.toolchain.contains("gcc") + property bool isGcc: qbs.toolchain.includes("gcc") configure: { console.info("is GCC: " + isGcc); if (isGcc) diff --git a/tests/auto/blackbox/testdata/linkerMode/darwin.s b/tests/auto/blackbox/testdata/linkerMode/darwin.s new file mode 100644 index 000000000..fb165114b --- /dev/null +++ b/tests/auto/blackbox/testdata/linkerMode/darwin.s @@ -0,0 +1,6 @@ +.globl _main +.globl main + +_main: +main: + ret diff --git a/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs b/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs index 1be50c0aa..176730ce0 100644 --- a/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs +++ b/tests/auto/blackbox/testdata/linkerMode/linkerMode.qbs @@ -2,7 +2,7 @@ Project { CppApplication { consoleApplication: true name: "LinkedProduct-Assembly" - files: ["main.s"] + files: qbs.targetOS.includes("darwin") ? "darwin.s" : "main.s" cpp.linkerPath: cpp.compilerPathByLanguage["c"] @@ -24,7 +24,7 @@ Project { } CppApplication { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") consoleApplication: true name: "LinkedProduct-Objective-C" @@ -50,7 +50,7 @@ Project { } CppApplication { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") consoleApplication: true name: "LinkedProduct-Objective-C++" diff --git a/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs b/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs index 0b4de0ab9..6d068b6a2 100644 --- a/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs +++ b/tests/auto/blackbox/testdata/linkerscripts/linkerscripts.qbs @@ -55,6 +55,13 @@ DynamicLibrary { } } + Probe { + id: checker + property bool isGcc: qbs.toolchain.contains("gcc") + property bool isLinux: qbs.targetOS.contains("linux") + configure: { console.info("is Linux gcc: " + (isGcc && isLinux)) } + } + qbs.installPrefix: "" install: true installDir: "" diff --git a/tests/auto/blackbox/testdata/loadablemodule/loadablemodule.qbs b/tests/auto/blackbox/testdata/loadablemodule/loadablemodule.qbs index a5705a865..8023eed36 100644 --- a/tests/auto/blackbox/testdata/loadablemodule/loadablemodule.qbs +++ b/tests/auto/blackbox/testdata/loadablemodule/loadablemodule.qbs @@ -4,7 +4,7 @@ Project { LoadableModule { Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } name: "CoolPlugIn" @@ -30,10 +30,10 @@ Project { files: ["main.cpp"] cpp.cxxLanguageVersion: "c++11" - cpp.dynamicLibraries: [qbs.targetOS.contains("windows") ? "kernel32" : "dl"] + cpp.dynamicLibraries: [qbs.targetOS.includes("windows") ? "kernel32" : "dl"] Properties { - condition: qbs.targetOS.contains("unix") && !qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("unix") && !qbs.targetOS.includes("darwin") cpp.rpaths: [cpp.rpathOrigin] } diff --git a/tests/auto/blackbox/testdata/lsp/lsp.qbs b/tests/auto/blackbox/testdata/lsp/lsp.qbs new file mode 100644 index 000000000..24479e0ec --- /dev/null +++ b/tests/auto/blackbox/testdata/lsp/lsp.qbs @@ -0,0 +1,11 @@ +Project { + Product { + name: "dep" + Depends { name: "m" } + Depends { name: "Prefix"; submodules: ["m1", "m2", "m3"] } + + } + Product { + Depends { name: "dep" } + } +} diff --git a/tests/auto/blackbox/testdata/lsp/modules/Prefix/m1/m1.qbs b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m1/m1.qbs new file mode 100644 index 000000000..09bac2dc2 --- /dev/null +++ b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m1/m1.qbs @@ -0,0 +1,5 @@ +Module { + property bool p1 + property string p2 + property bool x +} diff --git a/tests/auto/language/testdata/erroneous/modules/prefix1/prefix1.qbs b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m2/m2.qbs index 84957060c..84957060c 100644 --- a/tests/auto/language/testdata/erroneous/modules/prefix1/prefix1.qbs +++ b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m2/m2.qbs diff --git a/tests/auto/blackbox/testdata/lsp/modules/Prefix/m3/m3.qbs b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m3/m3.qbs new file mode 100644 index 000000000..84957060c --- /dev/null +++ b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m3/m3.qbs @@ -0,0 +1,2 @@ +Module { +} diff --git a/tests/auto/blackbox/testdata/lsp/modules/m/m.qbs b/tests/auto/blackbox/testdata/lsp/modules/m/m.qbs new file mode 100644 index 000000000..84957060c --- /dev/null +++ b/tests/auto/blackbox/testdata/lsp/modules/m/m.qbs @@ -0,0 +1,2 @@ +Module { +} diff --git a/tests/auto/blackbox/testdata/makefile-generator/app.qbs b/tests/auto/blackbox/testdata/makefile-generator/app.qbs index 367f484cf..fd3fbb91b 100644 --- a/tests/auto/blackbox/testdata/makefile-generator/app.qbs +++ b/tests/auto/blackbox/testdata/makefile-generator/app.qbs @@ -13,7 +13,7 @@ CppApplication { cpp.cxxLanguageVersion: "c++11" cpp.separateDebugInformation: false Properties { - condition: qbs.targetOS.contains("macos") + condition: qbs.targetOS.includes("macos") bundle.embedInfoPlist: false cpp.minimumMacosVersion: "10.7" } diff --git a/tests/auto/blackbox/testdata/minimumSystemVersion/fakewindows.qbs b/tests/auto/blackbox/testdata/minimumSystemVersion/fakewindows.qbs index 1a56e0b7e..da836e609 100644 --- a/tests/auto/blackbox/testdata/minimumSystemVersion/fakewindows.qbs +++ b/tests/auto/blackbox/testdata/minimumSystemVersion/fakewindows.qbs @@ -4,7 +4,7 @@ import qbs.Utilities // (but will still compile and link since we avoid passing a // bad value to the linker) CppApplication { - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") files: ["main.cpp"] consoleApplication: true cpp.minimumWindowsVersion: "5.3" diff --git a/tests/auto/blackbox/testdata/minimumSystemVersion/macappstore.qbs b/tests/auto/blackbox/testdata/minimumSystemVersion/macappstore.qbs index a94b7a80e..26a94e132 100644 --- a/tests/auto/blackbox/testdata/minimumSystemVersion/macappstore.qbs +++ b/tests/auto/blackbox/testdata/minimumSystemVersion/macappstore.qbs @@ -8,7 +8,7 @@ CppApplication { var result = qbs.targetPlatform === Host.platform(); if (!result) console.info("targetPlatform differs from hostPlatform"); - return result && qbs.targetOS.contains("macos"); + return result && qbs.targetOS.includes("macos"); } files: ["main.mm"] consoleApplication: true diff --git a/tests/auto/blackbox/testdata/minimumSystemVersion/specific.qbs b/tests/auto/blackbox/testdata/minimumSystemVersion/specific.qbs index 4dca16df0..b2b67642a 100644 --- a/tests/auto/blackbox/testdata/minimumSystemVersion/specific.qbs +++ b/tests/auto/blackbox/testdata/minimumSystemVersion/specific.qbs @@ -10,22 +10,22 @@ CppApplication { var result = qbs.targetPlatform === Host.platform(); if (!result) console.info("targetPlatform differs from hostPlatform"); - return result && qbs.targetOS.contains("windows") || qbs.targetOS.contains("macos"); + return result && qbs.targetOS.includes("windows") || qbs.targetOS.includes("macos"); } - files: [qbs.targetOS.contains("darwin") ? "main.mm" : "main.cpp"] + files: [qbs.targetOS.includes("darwin") ? "main.mm" : "main.cpp"] consoleApplication: true Properties { - condition: qbs.targetOS.contains("windows") - cpp.minimumWindowsVersion: "6.0" + condition: qbs.targetOS.includes("windows") + cpp.minimumWindowsVersion: "6.2" cpp.defines: [ - "QBS_WINVER=0x600", + "QBS_WINVER=0x602", "TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath) ] } Properties { - condition: qbs.targetOS.contains("macos") + condition: qbs.targetOS.includes("macos") cpp.frameworks: "Foundation" cpp.minimumMacosVersion: "10.7" } diff --git a/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified-forced.qbs b/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified-forced.qbs index 36756137e..adb61a6d8 100644 --- a/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified-forced.qbs +++ b/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified-forced.qbs @@ -11,7 +11,7 @@ CppApplication { console.info("targetPlatform differs from hostPlatform"); return result; } - files: [qbs.targetOS.contains("darwin") ? "main.mm" : "main.cpp"] + files: [qbs.targetOS.includes("darwin") ? "main.mm" : "main.cpp"] consoleApplication: true cpp.minimumWindowsVersion: undefined cpp.minimumMacosVersion: undefined @@ -19,12 +19,12 @@ CppApplication { cpp.minimumAndroidVersion: undefined Properties { - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") cpp.defines: ["TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath)] } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.frameworks: "Foundation" } } diff --git a/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified.qbs b/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified.qbs index 1440925f3..3c6559c39 100644 --- a/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified.qbs +++ b/tests/auto/blackbox/testdata/minimumSystemVersion/unspecified.qbs @@ -10,16 +10,16 @@ CppApplication { console.info("targetPlatform differs from hostPlatform"); return result; } - files: [qbs.targetOS.contains("darwin") ? "main.mm" : "main.cpp"] + files: [qbs.targetOS.includes("darwin") ? "main.mm" : "main.cpp"] consoleApplication: true Properties { - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") cpp.defines: ["TOOLCHAIN_INSTALL_PATH=" + Utilities.cStringQuote(cpp.toolchainInstallPath)] } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.frameworks: "Foundation" } } diff --git a/tests/auto/blackbox/testdata/msvc-asm-flags/include/header.inc b/tests/auto/blackbox/testdata/msvc-asm-flags/include/header.inc new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/msvc-asm-flags/include/header.inc diff --git a/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.asm b/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.asm new file mode 100644 index 000000000..eddc49131 --- /dev/null +++ b/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.asm @@ -0,0 +1,8 @@ +include header.inc + +.code +main proc + mov ecx, 16 +main endp + +end
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.qbs b/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.qbs new file mode 100644 index 000000000..d632098c9 --- /dev/null +++ b/tests/auto/blackbox/testdata/msvc-asm-flags/msvc-asm-flags.qbs @@ -0,0 +1,6 @@ +StaticLibrary { + condition: qbs.toolchain.includes("msvc") + Depends { name: "cpp" } + files: "msvc-asm-flags.asm" + cpp.assemblerFlags: ["/I", "include"] +} diff --git a/tests/auto/blackbox/testdata/no-exported-symbols/no-exported-symbols.qbs b/tests/auto/blackbox/testdata/no-exported-symbols/no-exported-symbols.qbs index 346a94e21..9aad3d032 100644 --- a/tests/auto/blackbox/testdata/no-exported-symbols/no-exported-symbols.qbs +++ b/tests/auto/blackbox/testdata/no-exported-symbols/no-exported-symbols.qbs @@ -12,7 +12,7 @@ Project { id: toolchainProbe property stringList toolchain: qbs.toolchain configure: { - if (toolchain.contains("msvc") && !toolchain.contains("clang-cl")) + if (toolchain.includes("msvc") && !toolchain.includes("clang-cl")) console.info("compiler is MSVC") else console.info("compiler is not MSVC") diff --git a/tests/auto/blackbox/testdata/nsis/hello.qbs b/tests/auto/blackbox/testdata/nsis/hello.qbs index a161a6998..f70f27e2b 100644 --- a/tests/auto/blackbox/testdata/nsis/hello.qbs +++ b/tests/auto/blackbox/testdata/nsis/hello.qbs @@ -1,5 +1,5 @@ NSISSetup { - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") name: "Qbs Hello" targetName: "qbs-hello-" + qbs.architecture files: ["hello.nsi", "hello.bat"] diff --git a/tests/auto/blackbox/testdata/nsisDependencies/nsisDependencies.qbs b/tests/auto/blackbox/testdata/nsisDependencies/nsisDependencies.qbs index d8185aabf..a4ce92067 100644 --- a/tests/auto/blackbox/testdata/nsisDependencies/nsisDependencies.qbs +++ b/tests/auto/blackbox/testdata/nsisDependencies/nsisDependencies.qbs @@ -2,7 +2,7 @@ import qbs.FileInfo import qbs.TextFile Project { - condition: qbs.targetOS.contains("windows") + condition: qbs.targetOS.includes("windows") NSISSetup { Depends { name: "app" } diff --git a/tests/auto/blackbox/testdata/output-redirection/output-redirection.qbs b/tests/auto/blackbox/testdata/output-redirection/output-redirection.qbs index 37b5b3778..d2474cecf 100644 --- a/tests/auto/blackbox/testdata/output-redirection/output-redirection.qbs +++ b/tests/auto/blackbox/testdata/output-redirection/output-redirection.qbs @@ -22,7 +22,7 @@ Product { prepare: { var binary; var prefixArgs; - if (Host.os().contains("windows")) { + if (Host.os().includes("windows")) { binary = product.qbs.windowsShellPath; prefixArgs = ["/c", "type"]; } else { diff --git a/tests/auto/blackbox/testdata/overrideProjectProperties/helper_lib.qbs b/tests/auto/blackbox/testdata/overrideProjectProperties/helper_lib.qbs index b69dd0da8..c7eab99e2 100644 --- a/tests/auto/blackbox/testdata/overrideProjectProperties/helper_lib.qbs +++ b/tests/auto/blackbox/testdata/overrideProjectProperties/helper_lib.qbs @@ -3,7 +3,7 @@ DynamicLibrary { files: "helperlib.cpp" Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/blackbox/testdata/path-list-in-probe/main.cpp b/tests/auto/blackbox/testdata/path-list-in-probe/main.cpp new file mode 100644 index 000000000..5bc549337 --- /dev/null +++ b/tests/auto/blackbox/testdata/path-list-in-probe/main.cpp @@ -0,0 +1,4 @@ +int main() +{ + return 0; +}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/path-list-in-probe/path-list-in-probe.qbs b/tests/auto/blackbox/testdata/path-list-in-probe/path-list-in-probe.qbs new file mode 100644 index 000000000..3bf36367a --- /dev/null +++ b/tests/auto/blackbox/testdata/path-list-in-probe/path-list-in-probe.qbs @@ -0,0 +1,18 @@ +Project { + CppApplication { + Probe { + id: theProbe + property pathList result + configure: { + result = ["main.cpp"] + found = true + } + } + property pathList res: theProbe.found ? theProbe.result : [] + + Group { + name: "files" + files: res + } + } +} diff --git a/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs b/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs index c40f22736..5c259ae9b 100644 --- a/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs +++ b/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs @@ -4,8 +4,9 @@ BaseApp { inputNames: ["tool.1", "tool.2"] inputSearchPaths: "bin" inputCandidateFilter: { + var fi = FileInfo; return function(f) { - return FileInfo.fileName(f) == "tool.2"; + return fi.fileName(f) == "tool.2"; } } outputFilePaths: ["bin/tool.2"] diff --git a/tests/auto/blackbox/testdata/plugin-dependency/plugin-dependency.qbs b/tests/auto/blackbox/testdata/plugin-dependency/plugin-dependency.qbs index 30b7f4ace..752673b78 100644 --- a/tests/auto/blackbox/testdata/plugin-dependency/plugin-dependency.qbs +++ b/tests/auto/blackbox/testdata/plugin-dependency/plugin-dependency.qbs @@ -11,8 +11,8 @@ Project { Depends { name: "plugin2" } // not to be linked Depends { name: "plugin3" // supposed to be linked - //property bool theCondition: true - cpp.link: /*theCondition && */product.name === "myapp" // TODO: Make this work + property bool theCondition: true + cpp.link: theCondition && product.name === "myapp" } Depends { name: "plugin4" } // supposed to be linked Depends { name: "helper1" } // supposed to be linked diff --git a/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/precompiled-headers-and-redefine.qbs b/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/precompiled-headers-and-redefine.qbs index 55b53a7af..3974b514e 100644 --- a/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/precompiled-headers-and-redefine.qbs +++ b/tests/auto/blackbox/testdata/precompiled-headers-and-redefine/precompiled-headers-and-redefine.qbs @@ -8,7 +8,7 @@ CppApplication { Group { files: ["file.cpp"] cpp.defines: ["MYDEF=1"] - cpp.cxxFlags: base.concat(qbs.toolchain.contains("clang-cl") ? ["-Wno-clang-cl-pch"] : []) + cpp.cxxFlags: base.concat(qbs.toolchain.includes("clang-cl") ? ["-Wno-clang-cl-pch"] : []) } cpp.treatWarningsAsErrors: true diff --git a/tests/auto/blackbox/testdata/probe-in-module-provider/module-providers/provider_a.qbs b/tests/auto/blackbox/testdata/probe-in-module-provider/module-providers/provider_a.qbs deleted file mode 100644 index 8a7c7d6ed..000000000 --- a/tests/auto/blackbox/testdata/probe-in-module-provider/module-providers/provider_a.qbs +++ /dev/null @@ -1,16 +0,0 @@ -import "../../qbs-module-providers-helpers.js" as Helpers - -ModuleProvider { - Probe { - id: theProbe - configure: { - console.info("Running probe"); - found = true; - } - } - property bool found: theProbe.found - relativeSearchPaths: { - Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", undefined, undefined, found); - return ""; - } -} diff --git a/tests/auto/blackbox/testdata/product-dependencies-by-type/product-dependencies-by-type.qbs b/tests/auto/blackbox/testdata/product-dependencies-by-type/product-dependencies-by-type.qbs index 6772acf27..8e1f291f3 100644 --- a/tests/auto/blackbox/testdata/product-dependencies-by-type/product-dependencies-by-type.qbs +++ b/tests/auto/blackbox/testdata/product-dependencies-by-type/product-dependencies-by-type.qbs @@ -91,7 +91,7 @@ Project { name: "lib-product" files: "main.cpp" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/blackbox/testdata/property-assignment-on-non-present-module/property-assignment-on-non-present-module.qbs b/tests/auto/blackbox/testdata/property-assignment-on-non-present-module/property-assignment-on-non-present-module.qbs deleted file mode 100644 index a01d6c561..000000000 --- a/tests/auto/blackbox/testdata/property-assignment-on-non-present-module/property-assignment-on-non-present-module.qbs +++ /dev/null @@ -1,4 +0,0 @@ -Product { - Depends { name: "nein"; required: false } - nein.doch: "ohhh!" -} diff --git a/tests/auto/blackbox/testdata/propertyChanges/propertyChanges.qbs b/tests/auto/blackbox/testdata/propertyChanges/propertyChanges.qbs index 0ae8c1550..29365a887 100644 --- a/tests/auto/blackbox/testdata/propertyChanges/propertyChanges.qbs +++ b/tests/auto/blackbox/testdata/propertyChanges/propertyChanges.qbs @@ -27,7 +27,7 @@ Project { name: "library" files: "lib.cpp" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } } diff --git a/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs b/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs index cf63eb17f..959552ea5 100644 --- a/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs +++ b/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs @@ -11,8 +11,7 @@ CppApplication { consoleApplication: true Depends { name: "cpp" } - cpp.cxxLanguageVersion: "c++11" - cpp.minimumMacosVersion: "10.8" + cpp.minimumMacosVersion: "10.15" Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { diff --git a/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.qbs b/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.qbs index ccb724ef5..3dfc911e1 100644 --- a/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.qbs +++ b/tests/auto/blackbox/testdata/protobuf/addressbook_nanopb.qbs @@ -11,7 +11,6 @@ CppApplication { consoleApplication: true Depends { name: "cpp" } - cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.8" Depends { name: "protobuf.nanopb"; required: false } diff --git a/tests/auto/blackbox/testdata/protobuf/conanfile.txt b/tests/auto/blackbox/testdata/protobuf/conanfile.txt new file mode 100644 index 000000000..e7d849b1a --- /dev/null +++ b/tests/auto/blackbox/testdata/protobuf/conanfile.txt @@ -0,0 +1,6 @@ +[requires] +protobuf/3.21.12 +[tool_requires] +protobuf/3.21.12 +[generators] +QbsDeps diff --git a/tests/auto/blackbox/testdata/protobuf/create-proto-library.qbs b/tests/auto/blackbox/testdata/protobuf/create-proto-library.qbs index 967bf2bb8..005752fd8 100644 --- a/tests/auto/blackbox/testdata/protobuf/create-proto-library.qbs +++ b/tests/auto/blackbox/testdata/protobuf/create-proto-library.qbs @@ -11,7 +11,6 @@ Project { name: "proto_lib" Depends { name: "cpp" } - cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.8" protobuf.cpp.importPaths: product.sourceDirectory diff --git a/tests/auto/blackbox/testdata/protobuf/import.qbs b/tests/auto/blackbox/testdata/protobuf/import.qbs index 41669020d..56d489de8 100644 --- a/tests/auto/blackbox/testdata/protobuf/import.qbs +++ b/tests/auto/blackbox/testdata/protobuf/import.qbs @@ -12,7 +12,6 @@ CppApplication { protobuf.cpp.importPaths: [sourceDirectory] - cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.8" Depends { name: "protobuf.cpp"; required: false } diff --git a/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs b/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs index 143e9c20f..07be566cb 100644 --- a/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs +++ b/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs @@ -13,7 +13,6 @@ CppApplication { property path theImportDir protobuf.cpp.importPaths: (theImportDir ? [theImportDir] : []).concat([sourceDirectory]) - cpp.cxxLanguageVersion: "c++11" cpp.minimumMacosVersion: "10.8" Depends { name: "protobuf.cpp"; required: false } diff --git a/tests/auto/blackbox/testdata/qbs-config-import-export/config.json b/tests/auto/blackbox/testdata/qbs-config-import-export/config.json new file mode 100644 index 000000000..edcaf238a --- /dev/null +++ b/tests/auto/blackbox/testdata/qbs-config-import-export/config.json @@ -0,0 +1,11 @@ +{ + "group": { + "key1": "value1", + "key2": "value2" + }, + "key": "value", + "listKey": [ + "valueOne", + "valueTwo" + ] +} diff --git a/tests/auto/blackbox/testdata/qbs-config-import-export/config.txt b/tests/auto/blackbox/testdata/qbs-config-import-export/config.txt new file mode 100644 index 000000000..2bd19c422 --- /dev/null +++ b/tests/auto/blackbox/testdata/qbs-config-import-export/config.txt @@ -0,0 +1,4 @@ +group.key1: "value1" +group.key2: "value2" +key: "value" +listKey: ["valueOne", "valueTwo"] diff --git a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libdir/libA.pc b/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libdir/libA.pc deleted file mode 100644 index 077a05893..000000000 --- a/tests/auto/blackbox/testdata/qbspkgconfig-module-provider/libdir/libA.pc +++ /dev/null @@ -1,6 +0,0 @@ -Name: libA -Description: just a test -Version: 0.0.1 - -Cflags: -DTHE_MAGIC_DEFINE -I/usr/local/include -Libs: -L/usr/local/lib -llibA diff --git a/tests/auto/blackbox/testdata/remove-duplicate-libs/remove-duplicate-libs.qbs b/tests/auto/blackbox/testdata/remove-duplicate-libs/remove-duplicate-libs.qbs index 040e12b3a..d89e47414 100644 --- a/tests/auto/blackbox/testdata/remove-duplicate-libs/remove-duplicate-libs.qbs +++ b/tests/auto/blackbox/testdata/remove-duplicate-libs/remove-duplicate-libs.qbs @@ -7,7 +7,7 @@ Project { property bool dummy: { // most BSD systems (including macOS) use LLVM linker now console.info("is bfd linker: " - + (qbs.toolchain.contains("gcc") && !Host.os().contains("bsd"))) + + (qbs.toolchain.includes("gcc") && !Host.os().includes("bsd"))) } qbsSearchPaths: "." diff --git a/tests/auto/blackbox/testdata/reproducible-build/reproducible-build.qbs b/tests/auto/blackbox/testdata/reproducible-build/reproducible-build.qbs index f7ed8e61a..fabdf48db 100644 --- a/tests/auto/blackbox/testdata/reproducible-build/reproducible-build.qbs +++ b/tests/auto/blackbox/testdata/reproducible-build/reproducible-build.qbs @@ -2,4 +2,9 @@ CppApplication { name: "the product" files: ["file1.cpp", "file2.cpp", "main.cpp"] cpp.cxxFlags: ["-flto"] + Probe { + id: checker + property bool isGcc: qbs.toolchain.contains("gcc") && !qbs.toolchain.contains("clang") + configure: { console.info("is gcc: " + isGcc); } + } } diff --git a/tests/auto/blackbox/testdata/require-deprecated/blubb.js b/tests/auto/blackbox/testdata/require-deprecated/blubb.js deleted file mode 100644 index 9acc13968..000000000 --- a/tests/auto/blackbox/testdata/require-deprecated/blubb.js +++ /dev/null @@ -1,13 +0,0 @@ -var TextFile = loadExtension("qbs.TextFile") -var zort = loadFile("zort.js") - -function createCommands(filePaths) { - var cmd = new JavaScriptCommand(); - cmd.description = "Write an empty file"; - cmd.filePath = filePaths[0]; - cmd.sourceCode = function() { - var f = new TextFile(filePath, TextFile.WriteOnly); - f.close(); - } - return [cmd, zort.createCommand(filePaths)]; -} diff --git a/tests/auto/blackbox/testdata/require-deprecated/require.qbs b/tests/auto/blackbox/testdata/require-deprecated/require.qbs deleted file mode 100644 index 87d8b054b..000000000 --- a/tests/auto/blackbox/testdata/require-deprecated/require.qbs +++ /dev/null @@ -1,21 +0,0 @@ -import 'blubb.js' as blubb - -Product { - type: ["text"] - Rule { - multiplex: true - Artifact { - fileTags: ["text"] - filePath: "one.txt" - } - Artifact { - fileTags: ["text"] - filePath: "two.txt" - } - prepare: { - var filePaths = outputs.text.map(function (artifact) {return artifact.filePath; }); - return blubb.createCommands(filePaths); - } - } -} - diff --git a/tests/auto/blackbox/testdata/require-deprecated/zort.js b/tests/auto/blackbox/testdata/require-deprecated/zort.js deleted file mode 100644 index 0dcffb767..000000000 --- a/tests/auto/blackbox/testdata/require-deprecated/zort.js +++ /dev/null @@ -1,11 +0,0 @@ -var File = loadExtension("qbs.File") - -function createCommand(filePaths) { - var cmd = new JavaScriptCommand(); - cmd.description = "Create another empty file"; - cmd.filePaths = filePaths; - cmd.sourceCode = function() { - File.copy(filePaths[0], filePaths[1]); - }; - return cmd; -} diff --git a/tests/auto/blackbox/testdata/response-files/response-files.qbs b/tests/auto/blackbox/testdata/response-files/response-files.qbs index 9158a85fa..c18fcac43 100644 --- a/tests/auto/blackbox/testdata/response-files/response-files.qbs +++ b/tests/auto/blackbox/testdata/response-files/response-files.qbs @@ -47,7 +47,7 @@ Project { 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 + cpp.linkerMode: qbs.toolchain.includes("clang-cl") ? "manual" : original Depends { name: "cpp" } Rule { multiplex: true diff --git a/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-lib.cpp b/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-lib.cpp new file mode 100644 index 000000000..6418df94d --- /dev/null +++ b/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-lib.cpp @@ -0,0 +1,3 @@ +int dynamicFunc() { + return 1; +}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-main.cpp b/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-main.cpp new file mode 100644 index 000000000..60f8494f6 --- /dev/null +++ b/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication-main.cpp @@ -0,0 +1,5 @@ +extern int dynamicFunc(); + +int main() { + return dynamicFunc(); +}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication.qbs b/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication.qbs new file mode 100644 index 000000000..adb63872a --- /dev/null +++ b/tests/auto/blackbox/testdata/rpathlink-deduplication/rpathlink-deduplication.qbs @@ -0,0 +1,47 @@ +Project { + DynamicLibrary { + Depends { name: "bundle" } + Depends { name: "cpp" } + + bundle.isBundle: false + name: "DynamicLibraryA" + files: ["rpathlink-deduplication-lib.cpp"] + } + + DynamicLibrary { + Depends { name: "bundle" } + Depends { name: "cpp" } + Depends { name: "DynamicLibraryA" } + + bundle.isBundle: false + name: "DynamicLibraryB" + files: ["rpathlink-deduplication-lib.cpp"] + } + + DynamicLibrary { + Depends { name: "bundle" } + Depends { name: "cpp" } + Depends { name: "DynamicLibraryA" } + + bundle.isBundle: false + name: "DynamicLibraryC" + files: ["rpathlink-deduplication-lib.cpp"] + } + + CppApplication { + Depends { name: "bundle" } + Depends { name: "DynamicLibraryB" } + Depends { name: "DynamicLibraryC" } + consoleApplication: true + bundle.isBundle: false + cpp.removeDuplicateLibraries: false + files: "rpathlink-deduplication-main.cpp" + property bool test: { + if (cpp.useRPathLink) + console.info("useRPathLink: true"); + else + console.info("useRPathLink: false"); + console.info("===" + cpp.rpathLinkFlag + "==="); + } + } +}
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/run-multiplexed/main.cpp b/tests/auto/blackbox/testdata/run-multiplexed/main.cpp new file mode 100644 index 000000000..237c8ce18 --- /dev/null +++ b/tests/auto/blackbox/testdata/run-multiplexed/main.cpp @@ -0,0 +1 @@ +int main() {} diff --git a/tests/auto/blackbox/testdata/run-multiplexed/run-multiplexed.qbs b/tests/auto/blackbox/testdata/run-multiplexed/run-multiplexed.qbs new file mode 100644 index 000000000..11577b54a --- /dev/null +++ b/tests/auto/blackbox/testdata/run-multiplexed/run-multiplexed.qbs @@ -0,0 +1,21 @@ +import qbs.Host + +CppApplication { + aggregate: false + consoleApplication: true + name: "app" + multiplexByQbsProperties: "buildVariants" + + qbs.buildVariants: ["debug", "release"] + + files: "main.cpp" + + Probe { + id: checker + property string targetPlatform: qbs.targetPlatform + configure: { + if (targetPlatform !== Host.platform()) + console.info("targetPlatform differs from hostPlatform"); + } + } +} diff --git a/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs b/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs index 9126a7913..438f3cc39 100644 --- a/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs +++ b/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs @@ -4,12 +4,12 @@ CppApplication { property string sanitizer property bool supportsSanitizer: { - if (qbs.toolchain.contains("mingw")) + if (qbs.toolchain.includes("mingw")) return false; if (sanitizer === "address") return Sanitizers.address._supported; - if (qbs.toolchain.contains("clang-cl")) { - if (cpp.toolchainInstallPath.contains("Microsoft Visual Studio") + if (qbs.toolchain.includes("clang-cl")) { + if (cpp.toolchainInstallPath.includes("Microsoft Visual Studio") && qbs.architecture === "x86_64") { // 32 bit sanitizer shipped with VS misses the x86_64 libraries return false; @@ -17,9 +17,9 @@ CppApplication { // only these are supported return sanitizer === "address" || sanitizer === "undefined"; } - if (!qbs.toolchain.contains("gcc")) + if (!qbs.toolchain.includes("gcc")) return false; - if (qbs.targetOS.contains("ios")) { + if (qbs.targetOS.includes("ios")) { // thread sanitizer is not supported return sanitizer !== "thread"; } diff --git a/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs b/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs index 48e70f260..4198b863f 100644 --- a/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs +++ b/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs @@ -8,10 +8,13 @@ Project { Probe { id: osProbe property stringList targetOS: qbs.targetOS + property stringList toolchain: qbs.toolchain configure: { - console.info("is windows: " + (targetOS.contains("windows") ? "yes" : "no")); - console.info("is macos: " + (targetOS.contains("macos") ? "yes" : "no")); - console.info("is darwin: " + (targetOS.contains("darwin") ? "yes" : "no")); + console.info("is windows: " + (targetOS.includes("windows") ? "yes" : "no")); + console.info("is macos: " + (targetOS.includes("macos") ? "yes" : "no")); + console.info("is darwin: " + (targetOS.includes("darwin") ? "yes" : "no")); + console.info("is gcc: " + (toolchain.includes("gcc") ? "yes" : "no")); + console.info("is msvc: " + (toolchain.includes("msvc") ? "yes" : "no")); } } } @@ -55,7 +58,7 @@ Project { files: ["main.cpp"] cpp.separateDebugInformation: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } @@ -66,7 +69,7 @@ Project { files: ["foo.cpp"] cpp.separateDebugInformation: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } @@ -76,7 +79,7 @@ Project { files: ["foo.cpp"] cpp.separateDebugInformation: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } @@ -94,7 +97,7 @@ Project { type: ["dynamiclibrary"] files: ["foo.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true @@ -104,7 +107,7 @@ Project { name: "bar4" files: ["foo.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true @@ -115,12 +118,12 @@ Project { type: ["application"] files: ["main.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } @@ -130,12 +133,12 @@ Project { type: ["dynamiclibrary"] files: ["foo.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } @@ -144,12 +147,12 @@ Project { name: "bar5" files: ["foo.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } cpp.separateDebugInformation: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.dsymutilFlags: ["--flat"] } } diff --git a/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs b/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs index 02f5ec7b1..b1310c005 100644 --- a/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs +++ b/tests/auto/blackbox/testdata/setup-run-environment/setup-run-environment.qbs @@ -8,13 +8,13 @@ Project { files: ["lib1.cpp"] - install: !qbs.targetOS.contains("darwin") + install: !qbs.targetOS.includes("darwin") installImportLib: true installDir: "lib1" importLibInstallDir: installDir Group { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") fileTagsFilter: ["bundle.content"] qbs.install: true qbs.installSourceBase: destinationDirectory @@ -27,7 +27,7 @@ Project { Depends { name: "lib5" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } @@ -41,7 +41,7 @@ Project { files: ["lib3.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } @@ -58,14 +58,14 @@ Project { files: ["lib4.cpp"] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } // Testing shows that clang (8.0) does not find dynamic libraries via // the -L<dir> and -l<libname> mechanism unless the name is "lib<libname>.a". Properties { - condition: Host.os().contains("windows") && qbs.toolchain.contains("clang") + condition: Host.os().includes("windows") && qbs.toolchain.includes("clang") cpp.dynamicLibraryPrefix: "lib" cpp.dynamicLibraryImportSuffix: ".a" } @@ -83,7 +83,7 @@ Project { Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } @@ -108,7 +108,7 @@ Project { property string fullInstallPrefix: FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix) property string lib3FilePath: FileInfo.joinPaths(fullInstallPrefix, "lib3", - cpp.dynamicLibraryPrefix + "lib3" + (qbs.targetOS.contains("windows") + cpp.dynamicLibraryPrefix + "lib3" + (qbs.targetOS.includes("windows") ? cpp.dynamicLibraryImportSuffix : cpp.dynamicLibrarySuffix)) cpp.dynamicLibraries: [lib3FilePath, "lib4"] @@ -117,7 +117,7 @@ Project { Probe { id: osPrinter - property bool isWindows: qbs.targetOS.contains("windows") + property bool isWindows: qbs.targetOS.includes("windows") configure: { console.info("is windows"); found = true; diff --git a/tests/auto/blackbox/testdata/smart-relinking/smart-relinking.qbs b/tests/auto/blackbox/testdata/smart-relinking/smart-relinking.qbs index aac0692a8..29e6c2e17 100644 --- a/tests/auto/blackbox/testdata/smart-relinking/smart-relinking.qbs +++ b/tests/auto/blackbox/testdata/smart-relinking/smart-relinking.qbs @@ -5,7 +5,7 @@ Project { property stringList toolchain: qbs.toolchain property stringList targetOS: qbs.targetOS configure: { - found = toolchain.contains("gcc") && targetOS.contains("unix"); + found = toolchain.includes("gcc") && targetOS.includes("unix"); if (!found) console.info("project disabled"); } diff --git a/tests/auto/blackbox/testdata/source-artifact-changes/source-artifact-changes.qbs b/tests/auto/blackbox/testdata/source-artifact-changes/source-artifact-changes.qbs index de56376df..a53819753 100644 --- a/tests/auto/blackbox/testdata/source-artifact-changes/source-artifact-changes.qbs +++ b/tests/auto/blackbox/testdata/source-artifact-changes/source-artifact-changes.qbs @@ -4,7 +4,7 @@ CppApplication { consoleApplication: true Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.embedInfoPlist: false } @@ -12,7 +12,7 @@ CppApplication { id: toolchainProbe property stringList toolchain: qbs.toolchain configure: { - console.info("is gcc: " + toolchain.contains("gcc")); + console.info("is gcc: " + toolchain.includes("gcc")); found = true; } } diff --git a/tests/auto/blackbox/testdata/static-lib-without-sources/static-lib-without-sources.qbs b/tests/auto/blackbox/testdata/static-lib-without-sources/static-lib-without-sources.qbs index 32a58c94b..54ec5e230 100644 --- a/tests/auto/blackbox/testdata/static-lib-without-sources/static-lib-without-sources.qbs +++ b/tests/auto/blackbox/testdata/static-lib-without-sources/static-lib-without-sources.qbs @@ -6,7 +6,7 @@ StaticLibrary { } Product { - type: qbs.targetOS.contains("darwin") ? undefined : ["staticlibrary"] + type: qbs.targetOS.includes("darwin") ? undefined : ["staticlibrary"] name: "b" Depends { name: "cpp" } Depends { name: "a" } diff --git a/tests/auto/blackbox/testdata/symbolLinkMode/symbolLinkMode.qbs b/tests/auto/blackbox/testdata/symbolLinkMode/symbolLinkMode.qbs index 086a9455b..49bcd9951 100644 --- a/tests/auto/blackbox/testdata/symbolLinkMode/symbolLinkMode.qbs +++ b/tests/auto/blackbox/testdata/symbolLinkMode/symbolLinkMode.qbs @@ -16,7 +16,7 @@ Project { Depends { name: "functions"; cpp.symbolLinkMode: product.symbolLinkMode - cpp.link: !(product.qbs.targetOS.contains("linux") && product.symbolLinkMode === "weak") + cpp.link: !(product.qbs.targetOS.includes("linux") && product.symbolLinkMode === "weak") } property string symbolLinkMode: project.lazy ? "lazy" : "weak" @@ -27,7 +27,7 @@ Project { property string installLib: "SHOULD_INSTALL_LIB=" + project.shouldInstallLibrary cpp.defines: { if (symbolLinkMode === "weak") { - return qbs.targetOS.contains("darwin") + return qbs.targetOS.includes("darwin") ? ["WEAK_IMPORT=__attribute__((weak_import))", installLib] : ["WEAK_IMPORT=__attribute__((weak))", installLib]; } @@ -49,7 +49,7 @@ Project { Depends { name: "indirect"; cpp.symbolLinkMode: "reexport" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } name: "functions" @@ -59,7 +59,7 @@ Project { cpp.rpaths: [cpp.rpathOrigin] Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") cpp.sonamePrefix: "@rpath" } @@ -72,7 +72,7 @@ Project { Export { // let the autotest pass on Linux where reexport is not supported - Depends { name: "indirect"; condition: !qbs.targetOS.contains("darwin") } + Depends { name: "indirect"; condition: !qbs.targetOS.includes("darwin") } // on Linux, there is no LC_WEAK_LOAD_DYLIB equivalent (the library is simply omitted // from the list of load commands entirely), so use LD_PRELOAD to emulate @@ -91,7 +91,7 @@ Project { Depends { name: "cpp" } Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.isBundle: false } name: "indirect" @@ -100,7 +100,7 @@ Project { cpp.minimumMacosVersion: "10.7" Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") // reexport is incompatible with rpath, // "ERROR: ld: file not found: @rpath/libindirect.dylib for architecture x86_64" cpp.sonamePrefix: qbs.installRoot + "/lib" diff --git a/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs b/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs index 6e2137173..35dd7a00f 100644 --- a/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs +++ b/tests/auto/blackbox/testdata/system-run-paths/system-run-paths.qbs @@ -20,4 +20,9 @@ Project { cpp.rpaths: qbs.installRoot + "/lib" cpp.systemRunPaths: project.setRunPaths ? [qbs.installRoot + "/lib"] : [] } + Probe { + id: checker + property bool isUnix: qbs.targetOS.contains("unix") + configure: { console.info("is unix: " + isUnix); } + } } diff --git a/tests/auto/blackbox/testdata/trackExternalProductChanges/trackExternalProductChanges.qbs b/tests/auto/blackbox/testdata/trackExternalProductChanges/trackExternalProductChanges.qbs index 534f49ff2..0e28e5687 100644 --- a/tests/auto/blackbox/testdata/trackExternalProductChanges/trackExternalProductChanges.qbs +++ b/tests/auto/blackbox/testdata/trackExternalProductChanges/trackExternalProductChanges.qbs @@ -11,4 +11,9 @@ CppApplication { name: "file that needs help from the environment to find a header" files: "including.cpp" } + Probe { + id: checker + property bool isGcc: qbs.toolchain.contains("gcc") + configure: { console.info("is gcc: " + isGcc); } + } } diff --git a/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs b/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs index b6e025e4c..1131e6a2f 100644 --- a/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs +++ b/tests/auto/blackbox/testdata/variant-suffix/variant-suffix.qbs @@ -1,8 +1,8 @@ StaticLibrary { name: "l" - Depends { condition: qbs.targetOS.contains("darwin"); name: "bundle" } - Properties { condition: qbs.targetOS.contains("darwin"); bundle.isBundle: false } + Depends { condition: qbs.targetOS.includes("darwin"); name: "bundle" } + Properties { condition: qbs.targetOS.includes("darwin"); bundle.isBundle: false } aggregate: false property string variantSuffix @@ -31,8 +31,8 @@ StaticLibrary { id: targetOSProbe property stringList targetOS: qbs.targetOS configure: { - console.info("is Windows: " + targetOS.contains("windows")); - console.info("is Apple: " + targetOS.contains("darwin")); + console.info("is Windows: " + targetOS.includes("windows")); + console.info("is Apple: " + targetOS.includes("darwin")); } } } diff --git a/tests/auto/blackbox/testdata/versionscript/versionscript.qbs b/tests/auto/blackbox/testdata/versionscript/versionscript.qbs index cc5c7b1cc..fcb4314a2 100644 --- a/tests/auto/blackbox/testdata/versionscript/versionscript.qbs +++ b/tests/auto/blackbox/testdata/versionscript/versionscript.qbs @@ -20,6 +20,12 @@ DynamicLibrary { return [cmd]; } } + Probe { + id: checker + property bool isLinux: qbs.targetOS.includes("linux") + property bool isGcc: qbs.toolchain.contains("gcc") + configure: { console.info("is gcc for Linux: " + (isLinux && isGcc)); } + } qbs.installPrefix: "" install: true diff --git a/tests/auto/blackbox/testdata/whole-archive/whole-archive.qbs b/tests/auto/blackbox/testdata/whole-archive/whole-archive.qbs index f3bcff2cd..c138e46c0 100644 --- a/tests/auto/blackbox/testdata/whole-archive/whole-archive.qbs +++ b/tests/auto/blackbox/testdata/whole-archive/whole-archive.qbs @@ -32,7 +32,8 @@ Project { property string compilerVersion: cpp.compilerVersion property string dummy: product.linkWholeArchive // To force probe re-execution configure: { - if (!toolchain.contains("msvc") + if (!toolchain.includes("msvc") + || toolchain.includes("clang-cl") || Utilities.versionCompare(compilerVersion, "19.0.24215.1") >= 0) { console.info("can link whole archives"); } else { diff --git a/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir1/file.txt b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir1/file.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir1/file.txt diff --git a/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir2/file.txt b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir2/file.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/nonrecursive/subdir2/file.txt diff --git a/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive1/recursive.txt b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive1/recursive.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive1/recursive.txt diff --git a/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive2/recursive.txt b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive2/recursive.txt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/recursive2/recursive.txt diff --git a/tests/auto/blackbox/testdata/wildcards-and-change-tracking/wildcards-and-change-tracking.qbs b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/wildcards-and-change-tracking.qbs new file mode 100644 index 000000000..0a889bab3 --- /dev/null +++ b/tests/auto/blackbox/testdata/wildcards-and-change-tracking/wildcards-and-change-tracking.qbs @@ -0,0 +1,16 @@ +Product { + Group { + name: "recursive" + files: "**/file.txt" + } + Group { + name: "directories" + prefix: "nonrecursive/" + files: "subdi?/file.txt" + } + Group { + prefix: "nonrecursive/empty/" + name: "no files" + files: "*.txt" + } +} diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp index 20d85d543..dbabfb311 100644 --- a/tests/auto/blackbox/tst_blackbox.cpp +++ b/tests/auto/blackbox/tst_blackbox.cpp @@ -53,6 +53,7 @@ #include <QtCore/qsettings.h> #include <QtCore/qtemporarydir.h> #include <QtCore/qtemporaryfile.h> +#include <QtCore/qversionnumber.h> #include <algorithm> #include <functional> @@ -62,7 +63,6 @@ #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) using qbs::Internal::HostOsInfo; -using qbs::Profile; class MacosTarHealer { public: @@ -138,12 +138,32 @@ QString TestBlackbox::findArchiver(const QString &fileName, int *status) QString binary = findExecutable(QStringList(fileName)); if (binary.isEmpty()) { const SettingsPtr s = settings(); - Profile p(profileName(), s.get()); + qbs::Profile p(profileName(), s.get()); binary = findExecutable(p.value("archiver.command").toStringList()); } return binary; } +bool TestBlackbox::prepareAndRunConan() +{ + QString executable = findExecutable({"conan"}); + if (executable.isEmpty()) { + qInfo() << "conan is not installed or not available in PATH."; + return false; + } + const auto profilePath = QDir::homePath() + "/.conan2/profiles/qbs-test"; + if (!QFileInfo(profilePath).exists()) { + qInfo() << "conan profile is not installed, run './scripts/setup-conan-profiles.sh'"; + return false; + } + QProcess conan; + QDir::setCurrent(testDataDir + "/conan-provider/testlibdep"); + rmDirR("build"); + QStringList arguments{"install", ".", "--profile:all=qbs-test", "--output-folder=build"}; + conan.start(executable, arguments); + return waitForProcessSuccess(conan, 60000); +} + bool TestBlackbox::lexYaccExist() { return !findExecutable(QStringList("lex")).isEmpty() @@ -298,7 +318,7 @@ void TestBlackbox::textTemplate() static QStringList sortedFileList(const QByteArray &ba) { - auto list = QString::fromUtf8(ba).split(QRegularExpression("[\r\n]"), QBS_SKIP_EMPTY_PARTS); + auto list = QString::fromUtf8(ba).split(QRegularExpression("[\r\n]"), Qt::SkipEmptyParts); std::sort(list.begin(), list.end()); return list; } @@ -698,7 +718,7 @@ void TestBlackbox::buildDirectories() QDir::setCurrent(projectDir); QCOMPARE(runQbs(), 0); const QStringList outputLines - = QString::fromLocal8Bit(m_qbsStdout.trimmed()).split('\n', QBS_SKIP_EMPTY_PARTS); + = QString::fromLocal8Bit(m_qbsStdout.trimmed()).split('\n', Qt::SkipEmptyParts); QVERIFY2(outputLines.contains(projectDir + '/' + relativeProductBuildDir("p1")), m_qbsStdout.constData()); QVERIFY2(outputLines.contains(projectDir + '/' + relativeProductBuildDir("p2")), @@ -707,6 +727,45 @@ void TestBlackbox::buildDirectories() QVERIFY2(outputLines.contains(projectDir), m_qbsStdout.constData()); } +void TestBlackbox::buildDirPlaceholders_data() +{ + QTest::addColumn<QString>("buildDir"); + QTest::addColumn<bool>("setProjectFile"); + QTest::addColumn<bool>("successExpected"); + + QTest::newRow("normal dir, with project file") << "somedir" << true << true; + QTest::newRow("normal dir, without project file") << "somedir" << false << true; + QTest::newRow("@project, with project file") << "somedir/@project" << true << true; + QTest::newRow("@project, without project file") << "somedir/@project" << false << false; + QTest::newRow("@path, with project file") << "somedir/@path" << true << true; + QTest::newRow("@path, without project file") << "somedir/@path" << false << false; +} + +void TestBlackbox::buildDirPlaceholders() +{ + QFETCH(QString, buildDir); + QFETCH(bool, setProjectFile); + QFETCH(bool, successExpected); + + const QString projectDir = testDataDir + "/build-dir-placeholders"; + rmDirR(projectDir); + QVERIFY(QDir().mkpath(projectDir)); + QDir::setCurrent(projectDir); + QFile projectFile("build-dir-placeholders.qbs"); + QVERIFY(projectFile.open(QIODevice::WriteOnly)); + projectFile.write("Product {\n}\n"); + projectFile.flush(); + rmDirR(relativeBuildDir()); + QbsRunParameters params; + params.buildDirectory = buildDir; + if (setProjectFile) { + params.arguments << "-f" + << "build-dir-placeholders.qbs"; + } + params.expectFailure = !successExpected; + QCOMPARE(runQbs(params) == 0, successExpected); +} + void TestBlackbox::buildEnvChange() { QDir::setCurrent(testDataDir + "/buildenv-change"); @@ -793,28 +852,45 @@ void TestBlackbox::buildVariantDefaults() void TestBlackbox::capnproto() { QFETCH(QString, projectFile); + QFETCH(QStringList, arguments); QDir::setCurrent(testDataDir + "/capnproto"); rmDirR(relativeBuildDir()); + if (QTest::currentDataTag() == QLatin1String("cpp-conan") + || QTest::currentDataTag() == QLatin1String("rpc-conan")) { + if (!prepareAndRunConan()) + QSKIP("conan is not prepared, check messages above"); + } + QbsRunParameters params{QStringLiteral("resolve"), {QStringLiteral("-f"), projectFile}}; + params.arguments << arguments; + QCOMPARE(runQbs(params), 0); if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) QSKIP("Cannot run binaries in cross-compiled build"); if (m_qbsStdout.contains("capnproto is not present")) QSKIP("capnproto is not present"); - params.command.clear(); + params.command = QStringLiteral("build"); QCOMPARE(runQbs(params), 0); } void TestBlackbox::capnproto_data() { QTest::addColumn<QString>("projectFile"); + QTest::addColumn<QStringList>("arguments"); - QTest::newRow("cpp") << QStringLiteral("capnproto_cpp.qbs"); - QTest::newRow("cpp-pkgconfig") << QStringLiteral("capnproto_cpp_pkgconfig.qbs"); - QTest::newRow("greeter cpp (grpc)") << QStringLiteral("greeter_cpp.qbs"); - QTest::newRow("relative import") << QStringLiteral("capnproto_relative_import.qbs"); - QTest::newRow("absolute import") << QStringLiteral("capnproto_absolute_import.qbs"); + QStringList pkgConfigArgs({"project.qbsModuleProviders:qbspkgconfig"}); + QTest::newRow("cpp-pkgconfig") << QStringLiteral("capnproto_cpp.qbs") << pkgConfigArgs; + QTest::newRow("rpc-pkgconfig") << QStringLiteral("greeter_cpp.qbs") << pkgConfigArgs; + QTest::newRow("relative import") + << QStringLiteral("capnproto_relative_import.qbs") << pkgConfigArgs; + QTest::newRow("absolute import") + << QStringLiteral("capnproto_absolute_import.qbs") << pkgConfigArgs; + + QStringList conanArgs( + {"project.qbsModuleProviders:conan", "moduleProviders.conan.installDirectory:build"}); + QTest::newRow("cpp-conan") << QStringLiteral("capnproto_cpp.qbs") << conanArgs; + QTest::newRow("rpc-conan") << QStringLiteral("greeter_cpp.qbs") << conanArgs; } void TestBlackbox::changedFiles_data() @@ -1055,22 +1131,68 @@ void TestBlackbox::dependencyScanningLoop() void TestBlackbox::deprecatedProperty() { + QFETCH(QString, version); + QFETCH(QString, mode); + QFETCH(bool, expiringWarning); + QFETCH(bool, expiringError); + QDir::setCurrent(testDataDir + "/deprecated-property"); QbsRunParameters params(QStringList("-q")); params.expectFailure = true; + params.environment.insert("REMOVAL_VERSION", version); + if (!mode.isEmpty()) + params.arguments << "--deprecation-warnings" << mode; QVERIFY(runQbs(params) != 0); m_qbsStderr = QDir::fromNativeSeparators(QString::fromLocal8Bit(m_qbsStderr)).toLocal8Bit(); - QVERIFY2(m_qbsStderr.contains("deprecated-property.qbs:6:24 The property 'oldProp' is " - "deprecated and will be removed in Qbs 99.9.0."), m_qbsStderr.constData()); - QVERIFY2(m_qbsStderr.contains("deprecated-property.qbs:7:28 The property 'veryOldProp' can no " - "longer be used. It was removed in Qbs 1.3.0."), m_qbsStderr.constData()); + const bool hasExpiringWarning = m_qbsStderr.contains(QByteArray( + "deprecated-property.qbs:4:29 The property 'expiringProp' is " + "deprecated and will be removed in Qbs ") + version.toLocal8Bit()); + QVERIFY2(expiringWarning == hasExpiringWarning, m_qbsStderr.constData()); + const bool hasRemovedOutput = m_qbsStderr.contains( + "deprecated-property.qbs:5:28 The property 'veryOldProp' can no " + "longer be used. It was removed in Qbs 1.3.0."); + QVERIFY2(hasRemovedOutput == !expiringError, m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("Property 'forgottenProp' was scheduled for removal in version " "1.8.0, but is still present."), m_qbsStderr.constData()); QVERIFY2(m_qbsStderr.contains("themodule/m.qbs:22:5 Removal version for 'forgottenProp' " "specified here."), m_qbsStderr.constData()); - QVERIFY2(m_qbsStderr.count("Use newProp instead.") == 2, m_qbsStderr.constData()); - QVERIFY2(m_qbsStderr.count("is deprecated") == 1, m_qbsStderr.constData()); - QVERIFY2(m_qbsStderr.count("was removed") == 1, m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.count("Use newProp instead.") == 1 + + int(expiringWarning && !expiringError), m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.count("is deprecated") == int(expiringWarning), m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.count("was removed") == int(!expiringError), m_qbsStderr.constData()); +} + +void TestBlackbox::deprecatedProperty_data() +{ + QTest::addColumn<QString>("version"); + QTest::addColumn<QString>("mode"); + QTest::addColumn<bool>("expiringWarning"); + QTest::addColumn<bool>("expiringError"); + + const auto current = QVersionNumber::fromString(QBS_VERSION); + const QString next = QVersionNumber(current.majorVersion(), current.minorVersion() + 1) + .toString(); + const QString nextNext = QVersionNumber(current.majorVersion(), current.minorVersion() + 2) + .toString(); + const QString nextMajor = QVersionNumber(current.majorVersion() + 1).toString(); + + QTest::newRow("default/next") << next << QString() << true << false; + QTest::newRow("default/nextnext") << nextNext << QString() << false << false; + QTest::newRow("default/nextmajor") << nextMajor << QString() << true << false; + QTest::newRow("error/next") << next << QString("error") << true << true; + QTest::newRow("error/nextnext") << nextNext << QString("error") << true << true; + QTest::newRow("error/nextmajor") << nextMajor << QString("error") << true << true; + QTest::newRow("on/next") << next << QString("on") << true << false; + QTest::newRow("on/nextnext") << nextNext << QString("on") << true << false; + QTest::newRow("on/nextmajor") << nextMajor << QString("on") << true << false; + QTest::newRow("before-removal/next") << next << QString("before-removal") << true << false; + QTest::newRow("before-removal/nextnext") << nextNext << QString("before-removal") + << false << false; + QTest::newRow("before-removal/nextmajor") << nextMajor << QString("before-removal") + << true << false; + QTest::newRow("off/next") << next << QString("off") << false << false; + QTest::newRow("off/nextnext") << nextNext << QString("off") << false << false; + QTest::newRow("off/nextmajor") << nextMajor << QString("off") << false << false; } void TestBlackbox::disappearedProfile() @@ -1179,6 +1301,13 @@ void TestBlackbox::discardUnusedData_data() QTest::newRow("default") << QString() << true; } +void TestBlackbox::dotDotPcFile() +{ + QDir::setCurrent(testDataDir + "/dot-dot-pc-file"); + + QCOMPARE(runQbs(), 0); +} + void TestBlackbox::driverLinkerFlags() { QDir::setCurrent(testDataDir + QLatin1String("/driver-linker-flags")); @@ -1333,19 +1462,6 @@ void TestBlackbox::variantSuffix_data() std::make_pair(QString("unix"), QStringList())}); } -static bool waitForProcessSuccess(QProcess &p) -{ - if (!p.waitForStarted() || !p.waitForFinished()) { - qDebug() << p.errorString(); - return false; - } - if (p.exitCode() != 0) { - qDebug() << p.readAllStandardError(); - return false; - } - return true; -} - void TestBlackbox::vcsGit() { const QString gitFilePath = findExecutable(QStringList("git")); @@ -1540,14 +1656,14 @@ void TestBlackbox::versionCheck_data() void TestBlackbox::versionScript() { - const SettingsPtr s = settings(); - Profile buildProfile(profileName(), s.get()); - QStringList toolchain = profileToolchain(buildProfile); - if (!toolchain.contains("gcc") || targetOs() != HostOsInfo::HostOsLinux) - QSKIP("version script test only applies to Linux"); QDir::setCurrent(testDataDir + "/versionscript"); - QCOMPARE(runQbs(QbsRunParameters(QStringList("-q") - << ("qbs.installRoot:" + QDir::currentPath()))), 0); + QCOMPARE(runQbs(QbsRunParameters("resolve", {"qbs.installRoot:" + QDir::currentPath()})), 0); + const bool isLinuxGcc = m_qbsStdout.contains("is gcc for Linux: true"); + const bool isNotLinuxGcc = m_qbsStdout.contains("is gcc for Linux: false"); + if (isNotLinuxGcc) + QSKIP("version script test only applies to Linux"); + QVERIFY(isLinuxGcc); + QCOMPARE(runQbs(QbsRunParameters(QStringList("-q"))), 0); const QString output = QString::fromLocal8Bit(m_qbsStderr); const QRegularExpression pattern(QRegularExpression::anchoredPattern(".*---(.*)---.*"), QRegularExpression::DotMatchesEverythingOption); @@ -1665,7 +1781,7 @@ void TestBlackbox::clean() QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); - for (const QString &symLink : qAsConst(symlinks)) + for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Remove all, with a forced re-resolve in between. @@ -1684,7 +1800,7 @@ void TestBlackbox::clean() QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); - for (const QString &symLink : qAsConst(symlinks)) + for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Dry run. @@ -1696,7 +1812,7 @@ void TestBlackbox::clean() QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); - for (const QString &symLink : qAsConst(symlinks)) + for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(symlinkExists(symLink), qPrintable(symLink)); // Product-wise, dependency only. @@ -1710,7 +1826,7 @@ void TestBlackbox::clean() QVERIFY(regularFileExists(appExeFilePath)); QVERIFY(!QFile(depObjectFilePath).exists()); QVERIFY(!QFile(depLibFilePath).exists()); - for (const QString &symLink : qAsConst(symlinks)) + for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(!symlinkExists(symLink), qPrintable(symLink)); // Product-wise, dependent product only. @@ -1724,17 +1840,10 @@ void TestBlackbox::clean() QVERIFY(!QFile(appExeFilePath).exists()); QVERIFY(regularFileExists(depObjectFilePath)); QVERIFY(regularFileExists(depLibFilePath)); - for (const QString &symLink : qAsConst(symlinks)) + for (const QString &symLink : std::as_const(symlinks)) QVERIFY2(symlinkExists(symLink), qPrintable(symLink)); } -void TestBlackbox::concurrentExecutor() -{ - QDir::setCurrent(testDataDir + "/concurrent-executor"); - QCOMPARE(runQbs(QStringList() << "-j" << "2"), 0); - QVERIFY2(!m_qbsStderr.contains("ASSERT"), m_qbsStderr.constData()); -} - void TestBlackbox::conditionalExport() { QDir::setCurrent(testDataDir + "/conditional-export"); @@ -1879,6 +1988,9 @@ void TestBlackbox::conanfileProbe() { QFETCH(bool, forceFailure); + if (qEnvironmentVariableIsSet("GITHUB_ACTIONS")) + QSKIP("Skip this test when running on GitHub"); + QString executable = findExecutable({"conan"}); if (executable.isEmpty()) QSKIP("conan is not installed or not available in PATH."); @@ -1914,6 +2026,42 @@ void TestBlackbox::conanfileProbe() QCOMPARE(actualResults, expectedResults); } +void TestBlackbox::conflictingPropertyValues_data() +{ + QTest::addColumn<bool>("overrideInProduct"); + QTest::newRow("don't override in product") << false; + QTest::newRow("override in product") << true; +} + +void TestBlackbox::conflictingPropertyValues() +{ + QFETCH(bool, overrideInProduct); + + QDir::setCurrent(testDataDir + "/conflicting-property-values"); + if (overrideInProduct) + REPLACE_IN_FILE("conflicting-property-values.qbs", "// low.prop: name", "low.prop: name"); + else + REPLACE_IN_FILE("conflicting-property-values.qbs", "low.prop: name", "// low.prop: name"); + WAIT_FOR_NEW_TIMESTAMP(); + QCOMPARE(runQbs(QString("resolve")), 0); + if (overrideInProduct) { + // Binding in product itself overrides everything else, module-level conflicts + // are irrelevant. + QVERIFY2(m_qbsStdout.contains("final prop value: toplevel"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); + } else { + // Only the conflicts in the highest-level modules are reported, lower-level conflicts + // are irrelevant. + // prop2 does not cause a conflict, because the values are the same. + QVERIFY2(m_qbsStdout.contains("final prop value: highest"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStderr.contains("Conflicting scalar values for property 'prop'"), + m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.count("values.qbs") == 2, m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.contains("values.qbs:20:23"), m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.contains("values.qbs:30:23"), m_qbsStderr.constData()); + } +} + void TestBlackbox::cpuFeatures() { QDir::setCurrent(testDataDir + "/cpu-features"); @@ -1945,6 +2093,13 @@ void TestBlackbox::cpuFeatures() } } +void TestBlackbox::dateProperty() +{ + QDir::setCurrent(testDataDir + "/date-property"); + QCOMPARE(runQbs(), 0); + QVERIFY2(m_qbsStdout.contains("The stored date was 1999-12-31"), m_qbsStdout.constData()); +} + void TestBlackbox::renameDependency() { QDir::setCurrent(testDataDir + "/renameDependency"); @@ -1978,10 +2133,13 @@ void TestBlackbox::separateDebugInfo() const bool isDarwin = m_qbsStdout.contains("is darwin: yes"); const bool isNotDarwin = m_qbsStdout.contains("is darwin: no"); QVERIFY(isDarwin != isNotDarwin); + const bool isGcc = m_qbsStdout.contains("is gcc: yes"); + const bool isNotGcc = m_qbsStdout.contains("is gcc: no"); + QVERIFY(isGcc != isNotGcc); + const bool isMsvc = m_qbsStdout.contains("is msvc: yes"); + const bool isNotMsvc = m_qbsStdout.contains("is msvc: no"); + QVERIFY(isMsvc != isNotMsvc); - const SettingsPtr s = settings(); - Profile buildProfile(profileName(), s.get()); - QStringList toolchain = profileToolchain(buildProfile); if (isDarwin) { QVERIFY(directoryExists(relativeProductBuildDir("app1") + "/app1.app.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("app1") @@ -2061,7 +2219,7 @@ void TestBlackbox::separateDebugInfo() + "/bar4.bundle.dSYM/Contents/Resources/DWARF") .entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries).size(), 1); QVERIFY(regularFileExists(relativeProductBuildDir("bar5") + "/bar5.bundle.dwarf")); - } else if (toolchain.contains("gcc")) { + } else if (isGcc) { const QString exeSuffix = isWindows ? ".exe" : ""; const QString dllPrefix = isWindows ? "" : "lib"; const QString dllSuffix = isWindows ? ".dll" : ".so"; @@ -2075,7 +2233,7 @@ void TestBlackbox::separateDebugInfo() + '/' + dllPrefix + "bar1" + dllSuffix + ".debug")); QVERIFY(!QFile::exists(relativeProductBuildDir("bar2") + '/' + dllPrefix + "bar2" + dllSuffix + ".debug")); - } else if (toolchain.contains("msvc")) { + } else if (isMsvc) { QVERIFY(QFile::exists(relativeProductBuildDir("app1") + "/app1.pdb")); QVERIFY(QFile::exists(relativeProductBuildDir("foo1") + "/foo1.pdb")); QVERIFY(QFile::exists(relativeProductBuildDir("bar1") + "/bar1.pdb")); @@ -2132,6 +2290,9 @@ void TestBlackbox::trackExternalProductChanges() QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(!m_qbsStdout.contains("compiling fileExists.cpp")); + const bool isGcc = m_qbsStdout.contains("is gcc: true"); + const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); + QbsRunParameters params; params.environment.insert("QBS_TEST_PULL_IN_FILE_VIA_ENV", "1"); QCOMPARE(runQbs(params), 0); @@ -2181,12 +2342,11 @@ void TestBlackbox::trackExternalProductChanges() QVERIFY(!m_qbsStdout.contains("compiling jsFileChange.cpp")); QVERIFY(m_qbsStdout.contains("compiling fileExists.cpp")); + if (isNotGcc) + QSKIP("The remainder of this test requires a GCC-like toolchain"); + QVERIFY(isGcc); + rmDirR(relativeBuildDir()); - const SettingsPtr s = settings(); - const Profile profile(profileName(), s.get()); - const QStringList toolchainTypes = profileToolchain(profile); - if (!toolchainTypes.contains("gcc")) - QSKIP("Need GCC-like compiler to run this test"); params.environment = QbsRunParameters::defaultEnvironment(); params.environment.insert("INCLUDE_PATH_TEST", "1"); params.expectFailure = true; @@ -2451,8 +2611,8 @@ void TestBlackbox::referenceErrorInExport() QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); - QVERIFY(m_qbsStderr.contains( - "referenceErrorInExport.qbs:15:12 ReferenceError: Can't find variable: includePaths")); + QVERIFY2(m_qbsStderr.contains("referenceErrorInExport.qbs:5:27 'includePaths' is not defined"), + m_qbsStderr.constData()); } void TestBlackbox::removeDuplicateLibraries_data() @@ -2479,22 +2639,21 @@ void TestBlackbox::removeDuplicateLibraries() void TestBlackbox::reproducibleBuild() { - const SettingsPtr s = settings(); - const Profile profile(profileName(), s.get()); - 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); QDir::setCurrent(testDataDir + "/reproducible-build"); - QbsRunParameters params; + QbsRunParameters params("resolve"); params.arguments << QString("modules.cpp.enableReproducibleBuilds:") + (reproducible ? "true" : "false"); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); + const bool isGcc = m_qbsStdout.contains("is gcc: true"); + const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); + if (isNotGcc) + QSKIP("reproducible builds only supported for gcc"); + QVERIFY(isGcc); + + QCOMPARE(runQbs(), 0); QFile object(relativeProductBuildDir("the product") + '/' + inputDirHash(".") + '/' + objectFileName("file1.cpp", profileName())); QVERIFY2(object.open(QIODevice::ReadOnly), qPrintable(object.fileName())); @@ -2502,6 +2661,7 @@ void TestBlackbox::reproducibleBuild() object.close(); QCOMPARE(runQbs(QbsRunParameters("clean")), 0); QVERIFY(!object.exists()); + params.command = "build"; QCOMPARE(runQbs(params), 0); if (reproducible) { QVERIFY(object.open(QIODevice::ReadOnly)); @@ -2563,6 +2723,32 @@ void TestBlackbox::retaggedOutputArtifact() QVERIFY2(!QFile::exists(a3), qPrintable(a3)); } +void TestBlackbox::rpathlinkDeduplication() +{ + QDir::setCurrent(testDataDir + "/rpathlink-deduplication"); + QbsRunParameters resolveParams{"resolve"}; + QCOMPARE(runQbs(resolveParams), 0); + const bool useRPathLink = m_qbsStdout.contains("useRPathLink: true"); + const bool dontUseRPathLink = m_qbsStdout.contains("useRPathLink: false"); + QVERIFY2(useRPathLink || dontUseRPathLink, m_qbsStdout); + if (dontUseRPathLink) + QSKIP("Only applies to toolchains that support rPathLink"); + const QString output = QString::fromLocal8Bit(m_qbsStdout); + const QRegularExpression pattern(QRegularExpression::anchoredPattern(".*===(.*)===.*"), + QRegularExpression::DotMatchesEverythingOption); + const QRegularExpressionMatch match = pattern.match(output); + QVERIFY2(match.hasMatch(), qPrintable(output)); + QCOMPARE(pattern.captureCount(), 1); + const QString linkFlag = match.captured(1); + + QbsRunParameters buildParams; + buildParams.arguments = QStringList({"--command-echo-mode", "command-line"}); + QCOMPARE(runQbs(buildParams), 0); + // private DynamicLibraryA is a dependency for 2 other libs but should only appear once + const auto libDir = QFileInfo(relativeProductBuildDir("DynamicLibraryA")).absoluteFilePath(); + QCOMPARE(m_qbsStdout.count((linkFlag + libDir).toUtf8()), 1); +} + void TestBlackbox::ruleConditions() { QDir::setCurrent(testDataDir + "/ruleConditions"); @@ -2647,6 +2833,25 @@ void TestBlackbox::ruleWithNonRequiredInputs() QVERIFY2(m_qbsStdout.contains("generating"), m_qbsStdout.constData()); } +void TestBlackbox::runMultiplexed() +{ + QDir::setCurrent(testDataDir + "/run-multiplexed"); + QCOMPARE(runQbs({"resolve"}), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + + QbsRunParameters params("run"); + params.expectFailure = true; + QVERIFY(runQbs(params) != 0); + params.arguments = QStringList{"-p", "app"}; + QVERIFY(runQbs(params) != 0); + params.expectFailure = false; + params.arguments.last() = "app {\"buildVariant\":\"debug\"}"; + QCOMPARE(runQbs(params), 0); + params.arguments.last() = "app {\"buildVariant\":\"release\"}"; + QCOMPARE(runQbs(params), 0); +} + void TestBlackbox::sanitizer_data() { QTest::addColumn<QString>("sanitizer"); @@ -3051,20 +3256,35 @@ void TestBlackbox::pathProbe() QVERIFY2(m_qbsStderr.contains("Probe failed to find files"), m_qbsStderr); } +void TestBlackbox::pathListInProbe() +{ + QDir::setCurrent(testDataDir + "/path-list-in-probe"); + QCOMPARE(runQbs(), 0); +} + void TestBlackbox::pchChangeTracking() { QDir::setCurrent(testDataDir + "/pch-change-tracking"); - QCOMPARE(runQbs(), 0); + bool success = runQbs() == 0; + if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) + QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); + QVERIFY(success); QVERIFY(m_qbsStdout.contains("precompiling pch.h (cpp)")); WAIT_FOR_NEW_TIMESTAMP(); touch("header1.h"); - QCOMPARE(runQbs(), 0); + success = runQbs() == 0; + if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) + QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); + QVERIFY(success); QVERIFY(m_qbsStdout.contains("precompiling pch.h (cpp)")); QVERIFY(m_qbsStdout.contains("compiling header2.cpp")); QVERIFY(m_qbsStdout.contains("compiling main.cpp")); WAIT_FOR_NEW_TIMESTAMP(); touch("header2.h"); - QCOMPARE(runQbs(), 0); + success = runQbs() == 0; + if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) + QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); + QVERIFY(success); QVERIFY2(!m_qbsStdout.contains("precompiling pch.h (cpp)"), m_qbsStdout.constData()); } @@ -3194,13 +3414,19 @@ void TestBlackbox::pluginDependency() void TestBlackbox::precompiledAndPrefixHeaders() { QDir::setCurrent(testDataDir + "/precompiled-and-prefix-headers"); - QCOMPARE(runQbs(), 0); + const bool success = runQbs() == 0; + if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) + QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); + QVERIFY(success); } void TestBlackbox::precompiledHeaderAndRedefine() { QDir::setCurrent(testDataDir + "/precompiled-headers-and-redefine"); - QCOMPARE(runQbs(), 0); + const bool success = runQbs() == 0; + if (!success && m_qbsStderr.contains("mingw32_gt_pch_use_address")) + QSKIP("https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91440"); + QVERIFY(success); } void TestBlackbox::preventFloatingPointValues() @@ -3333,23 +3559,6 @@ void TestBlackbox::probeInExportedModule() QVERIFY2(m_qbsStdout.contains("listProp: myother,my"), m_qbsStdout.constData()); } -void TestBlackbox::probeInModuleProvider() -{ - QDir::setCurrent(testDataDir + "/probe-in-module-provider"); - - QbsRunParameters params; - params.command = "build"; - params.arguments << "--force-probe-execution"; - QCOMPARE(runQbs(params), 0); - QVERIFY2(m_qbsStdout.contains("Running probe"), m_qbsStdout); - QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.boolProp: true"), m_qbsStdout); - WAIT_FOR_NEW_TIMESTAMP(); - touch("probe-in-module-provider.qbs"); - QCOMPARE(runQbs(), 0); - QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.boolProp: true"), m_qbsStdout); - QVERIFY2(!m_qbsStdout.contains("Running probe"), m_qbsStdout); -} - void TestBlackbox::probesAndArrayProperties() { QDir::setCurrent(testDataDir + "/probes-and-array-properties"); @@ -3369,13 +3578,6 @@ void TestBlackbox::productProperties() QVERIFY(regularFileExists(relativeExecutableFilePath("blubb_user"))); } -void TestBlackbox::propertyAssignmentOnNonPresentModule() -{ - QDir::setCurrent(testDataDir + "/property-assignment-on-non-present-module"); - QCOMPARE(runQbs(), 0); - QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); -} - void TestBlackbox::propertyAssignmentInFailedModule() { QDir::setCurrent(testDataDir + "/property-assignment-in-failed-module"); @@ -3385,7 +3587,7 @@ void TestBlackbox::propertyAssignmentInFailedModule() QVERIFY(runQbs(failParams) != 0); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("modules.m.doFail:true"))), 0); QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); - QEXPECT_FAIL(nullptr, "circular dependency between module merging and validation", Continue); + failParams.expectFailure = false; QCOMPARE(runQbs(failParams), 0); } @@ -3714,7 +3916,7 @@ void TestBlackbox::emptyProfile() QDir::setCurrent(testDataDir + "/empty-profile"); const SettingsPtr s = settings(); - const Profile buildProfile(profileName(), s.get()); + const qbs::Profile buildProfile(profileName(), s.get()); bool isMsvc = false; auto toolchainType = buildProfile.value(QStringLiteral("qbs.toolchainType")).toString(); QbsRunParameters params; @@ -3735,7 +3937,7 @@ void TestBlackbox::emptyProfile() QDir::toNativeSeparators( buildProfile.value(QStringLiteral("cpp.toolchainInstallPath")).toString()); auto paths = params.environment.value(QStringLiteral("PATH")) - .split(HostOsInfo::pathListSeparator(), QBS_SKIP_EMPTY_PARTS); + .split(HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts); if (!tcPath.isEmpty() && !paths.contains(tcPath)) { paths.prepend(tcPath); params.environment.insert( @@ -3835,15 +4037,16 @@ void TestBlackbox::errorInfo() void TestBlackbox::escapedLinkerFlags() { - const SettingsPtr s = settings(); - const Profile buildProfile(profileName(), s.get()); - 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")); + QbsRunParameters params("resolve", QStringList("products.app.escapeLinkerFlags:false")); + QCOMPARE(runQbs(params), 0); + const bool isGcc = m_qbsStdout.contains("is gcc: true"); + const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); + if (isNotGcc) + QSKIP("escaped linker flags test only applies on plain unix with gcc and GNU ld"); + QVERIFY(isGcc); + + params.command = "build"; QCOMPARE(runQbs(params), 0); params.command = "resolve"; params.arguments = QStringList() << "products.app.escapeLinkerFlags:true"; @@ -3900,26 +4103,24 @@ void TestBlackbox::exportedPropertyInDisabledProduct_data() void TestBlackbox::systemRunPaths() { - const SettingsPtr s = settings(); - const Profile buildProfile(profileName(), s.get()); - switch (targetOs()) { - case HostOsInfo::HostOsLinux: - case HostOsInfo::HostOsMacos: - case HostOsInfo::HostOsOtherUnix: - break; - default: - QSKIP("only applies on Unix"); - } - const QString lddFilePath = findExecutable(QStringList() << "ldd"); if (lddFilePath.isEmpty()) QSKIP("ldd not found"); + QDir::setCurrent(testDataDir + "/system-run-paths"); QFETCH(bool, setRunPaths); rmDirR(relativeBuildDir()); - QbsRunParameters params; + QbsRunParameters params("resolve"); params.arguments << QString("project.setRunPaths:") + (setRunPaths ? "true" : "false"); QCOMPARE(runQbs(params), 0); + const bool isUnix = m_qbsStdout.contains("is unix: true"); + const bool isNotUnix = m_qbsStdout.contains("is unix: false"); + if (isNotUnix) + QSKIP("only applies on Unix"); + QVERIFY(isUnix); + + params.command = "build"; + QCOMPARE(runQbs(params), 0); QProcess ldd; ldd.start(lddFilePath, QStringList() << relativeExecutableFilePath("app")); QVERIFY2(ldd.waitForStarted(), qPrintable(ldd.errorString())); @@ -3970,6 +4171,82 @@ void TestBlackbox::exportToOutsideSearchPath() m_qbsStderr.constData()); } +void TestBlackbox::exportsCMake() +{ + QFETCH(QStringList, arguments); + + QDir::setCurrent(testDataDir + "/exports-cmake"); + rmDirR(relativeBuildDir()); + QbsRunParameters findCMakeParams("resolve", {"-f", "find-cmake.qbs"}); + QCOMPARE(runQbs(findCMakeParams), 0); + const QString output = QString::fromLocal8Bit(m_qbsStdout); + const QRegularExpression pattern( + QRegularExpression::anchoredPattern(".*---(.*)---.*"), + QRegularExpression::DotMatchesEverythingOption); + const QRegularExpressionMatch match = pattern.match(output); + QVERIFY2(match.hasMatch(), qPrintable(output)); + QCOMPARE(pattern.captureCount(), 1); + const QString jsonString = match.captured(1); + const QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8()); + const QJsonObject jsonData = jsonDoc.object(); + + rmDirR(relativeBuildDir()); + const QStringList exporterArgs{"-f", "exports-cmake.qbs"}; + QbsRunParameters exporterRunParams("build", exporterArgs); + exporterRunParams.arguments << arguments; + QCOMPARE(runQbs(exporterRunParams), 0); + + if (!jsonData.value(u"cmakeFound").toBool()) { + QSKIP("cmake is not installed"); + return; + } + + if (jsonData.value(u"crossCompiling").toBool()) { + QSKIP("test is not applicable with cross-compile toolchains"); + return; + } + + const auto cmakeFilePath = jsonData.value(u"cmakeFilePath").toString(); + QVERIFY(!cmakeFilePath.isEmpty()); + + const auto generator = jsonData.value(u"generator").toString(); + if (generator.isEmpty()) { + QSKIP("cannot detect cmake generator"); + return; + } + + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + const auto buildEnv = jsonData.value(u"buildEnv").toObject(); + for (auto it = buildEnv.begin(), end = buildEnv.end(); it != end; ++it) { + env.insert(it.key(), it.value().toString()); + } + + const auto installPrefix = jsonData.value(u"installPrefix").toString(); + const auto cmakePrefixPath = QFileInfo(relativeBuildDir()).absoluteFilePath() + "/install-root/" + + installPrefix + "/lib/cmake"; + const auto sourceDirectory = testDataDir + "/exports-cmake/cmake"; + QProcess configure; + configure.setProcessEnvironment(env); + configure.setWorkingDirectory(sourceDirectory); + configure.start( + cmakeFilePath, {".", "-DCMAKE_PREFIX_PATH=" + cmakePrefixPath, "-G" + generator}); + QVERIFY(waitForProcessSuccess(configure, 120000)); + + QProcess build; + build.setProcessEnvironment(env); + build.setWorkingDirectory(sourceDirectory); + build.start(cmakeFilePath, QStringList{"--build", "."}); + QVERIFY(waitForProcessSuccess(build)); +} + +void TestBlackbox::exportsCMake_data() +{ + QTest::addColumn<QStringList>("arguments"); + QTest::newRow("dynamic lib") << QStringList("project.isStatic: false"); + QTest::newRow("static lib") << QStringList("project.isStatic: true"); + QTest::newRow("framework") << QStringList("project.isBundle: true"); +} + void TestBlackbox::exportsPkgconfig() { QDir::setCurrent(testDataDir + "/exports-pkgconfig"); @@ -4027,7 +4304,8 @@ void TestBlackbox::exportsQbs() paramsExternalBuild.buildDirectory = QDir::currentPath() + "/external-consumer-profile"; paramsExternalBuild.expectFailure = true; QVERIFY(runQbs(paramsExternalBuild) != 0); - QVERIFY2(m_qbsStderr.contains("MyLib could not be loaded"), m_qbsStderr.constData()); + QVERIFY2(m_qbsStderr.contains("Dependency 'MyLib' not found for product 'consumer'"), + m_qbsStderr.constData()); // Removing the condition from the generated module leaves us with two conflicting // candidates. @@ -4131,6 +4409,43 @@ void TestBlackbox::fileTagsFilterMerging() QVERIFY2(QFile::exists(otherOutput), qPrintable(otherOutput)); } +void TestBlackbox::flatbuf() +{ + QFETCH(QString, projectFile); + + QDir::setCurrent(testDataDir + "/flatbuf"); + + rmDirR(relativeBuildDir()); + if (!prepareAndRunConan()) + QSKIP("conan is not prepared, check messages above"); + + QbsRunParameters resolveParams( + "resolve", QStringList{"-f", projectFile, "moduleProviders.conan.installDirectory:build"}); + QCOMPARE(runQbs(resolveParams), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + const bool withFlatbuffers = m_qbsStdout.contains("has flatbuffers: true"); + const bool withoutFlatbuffers = m_qbsStdout.contains("has flatbuffers: false"); + QVERIFY2(withFlatbuffers || withoutFlatbuffers, m_qbsStdout.constData()); + if (withoutFlatbuffers) + QSKIP("flatbuf module not present"); + QbsRunParameters runParams("run"); + QCOMPARE(runQbs(runParams), 0); +} + +void TestBlackbox::flatbuf_data() +{ + QTest::addColumn<QString>("projectFile"); + + // QTest::newRow("c") << QString("flat_c.qbs"); + QTest::newRow("cpp") << QString("flat_cpp.qbs"); + QTest::newRow("relative import") << QString("flat_relative_import.qbs"); + QTest::newRow("absolute import") << QString("flat_absolute_import.qbs"); + QTest::newRow("filename suffix") << QString("flat_filename_suffix.qbs"); + QTest::newRow("filename extension") << QString("flat_filename_extension.qbs"); + QTest::newRow("keep prefix") << QString("flat_keep_prefix.qbs"); +} + void TestBlackbox::freedesktop() { if (!HostOsInfo::isAnyUnixHost()) @@ -4338,7 +4653,7 @@ void TestBlackbox::installPackage() cleanOutputLines.push_back(trimmedLine); } QCOMPARE(cleanOutputLines.size(), 3); - for (const QByteArray &line : qAsConst(cleanOutputLines)) { + for (const QByteArray &line : std::as_const(cleanOutputLines)) { QVERIFY2(line.contains("public_tool") || line.contains("mylib") || line.contains("lib.h"), line.constData()); } @@ -4385,6 +4700,33 @@ void TestBlackbox::installTree() QVERIFY(QFile::exists(installRoot + "content/subdir2/baz.txt")); } +void TestBlackbox::invalidArtifactPath_data() +{ + QTest::addColumn<QString>("baseDir"); + QTest::addColumn<bool>("isValid"); + + QTest::newRow("inside, normal case") << "subdir" << true; + QTest::newRow("inside, build dir 1") << "project.buildDirectory" << true; + QTest::newRow("inside, build dir 2") << "subdir/.." << true; + QTest::newRow("outside, absolute") << "/tmp" << false; + QTest::newRow("outside, relative 1") << "../../" << false; + QTest::newRow("outside, relative 2") << "subdir/../../.." << false; +} + +void TestBlackbox::invalidArtifactPath() +{ + QFETCH(QString, baseDir); + QFETCH(bool, isValid); + + rmDirR(relativeBuildDir()); + QDir::setCurrent(testDataDir + "/invalid-artifact-path"); + QbsRunParameters params(QStringList("project.artifactDir:" + baseDir)); + params.expectFailure = !isValid; + QCOMPARE(runQbs(params) == 0, isValid); + if (!isValid) + QVERIFY2(m_qbsStderr.contains("outside of build directory"), m_qbsStderr.constData()); +} + void TestBlackbox::invalidCommandProperty_data() { QTest::addColumn<QString>("errorType"); @@ -4415,7 +4757,7 @@ void TestBlackbox::invalidLibraryNames() QbsRunParameters params(QStringList("project.valueIndex:" + index)); params.expectFailure = !success; QCOMPARE(runQbs(params) == 0, success); - for (const QString &diag : qAsConst(diagnostics)) + for (const QString &diag : std::as_const(diagnostics)) QVERIFY2(m_qbsStderr.contains(diag.toLocal8Bit()), m_qbsStderr.constData()); } @@ -4476,7 +4818,7 @@ void TestBlackbox::cli() QCOMPARE(status, 0); const SettingsPtr s = settings(); - Profile p("qbs_autotests-cli", s.get()); + qbs::Profile p("qbs_autotests-cli", s.get()); const QStringList toolchain = profileToolchain(p); if (!p.exists() || !(toolchain.contains("dotnet") || toolchain.contains("mono"))) QSKIP("No suitable Common Language Infrastructure test profile"); @@ -4744,6 +5086,10 @@ void TestBlackbox::jsExtensionsBinaryFile() QCOMPARE(data.at(5), char(0x05)); QCOMPARE(data.at(6), char(0x06)); QCOMPARE(data.at(7), char(0xFF)); + QFile destination2("destination2.dat"); + QVERIFY(destination2.exists()); + QVERIFY(destination2.open(QIODevice::ReadOnly)); + QCOMPARE(destination2.readAll(), data); } void TestBlackbox::lastModuleCandidateBroken() @@ -4752,7 +5098,8 @@ void TestBlackbox::lastModuleCandidateBroken() QbsRunParameters params; params.expectFailure = true; QVERIFY(runQbs(params) != 0); - QVERIFY2(m_qbsStderr.contains("Module Foo could not be loaded"), m_qbsStderr); + QVERIFY2(m_qbsStderr.contains("Dependency 'Foo' not found for product " + "'last-module-candidate-broken'"), m_qbsStderr); } void TestBlackbox::ld() @@ -4858,6 +5205,7 @@ void TestBlackbox::linkerVariant_data() QTest::newRow("default") << QString(); QTest::newRow("bfd") << QString("bfd"); QTest::newRow("gold") << QString("gold"); + QTest::newRow("mold") << QString("mold"); } void TestBlackbox::linkerVariant() @@ -4991,22 +5339,20 @@ void TestBlackbox::lexyaccOutputs_data() void TestBlackbox::linkerLibraryDuplicates() { - const SettingsPtr s = settings(); - Profile buildProfile(profileName(), s.get()); - QStringList toolchain = profileToolchain(buildProfile); - if (!toolchain.contains("gcc")) - QSKIP("linkerLibraryDuplicates test only applies to GCC toolchain"); - QDir::setCurrent(testDataDir + "/linker-library-duplicates"); rmDirR(relativeBuildDir()); - QFETCH(QString, removeDuplicateLibraries); QStringList runParams; - if (!removeDuplicateLibraries.isEmpty()) { + if (!removeDuplicateLibraries.isEmpty()) runParams.append(removeDuplicateLibraries); - } QCOMPARE(runQbs(QbsRunParameters("resolve", runParams)), 0); + const bool isGcc = m_qbsStdout.contains("is gcc: true"); + const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); + if (isNotGcc) + QSKIP("linkerLibraryDuplicates test only applies to GCC toolchain"); + QVERIFY(isGcc); + QCOMPARE(runQbs(QStringList { "--command-echo-mode", "command-line" }), 0); const QByteArrayList output = m_qbsStdout.split('\n'); QByteArray linkLine; @@ -5071,20 +5417,20 @@ void TestBlackbox::linkerLibraryDuplicates_data() void TestBlackbox::linkerScripts() { - const SettingsPtr s = settings(); - Profile buildProfile(profileName(), s.get()); - QStringList toolchain = profileToolchain(buildProfile); - if (!toolchain.contains("gcc") || targetOs() != HostOsInfo::HostOsLinux) - QSKIP("linker script test only applies to Linux "); - - QbsRunParameters runParams(QStringList() -// << "--log-level" << "debug" - << ("qbs.installRoot:" + QDir::currentPath())); const QString sourceDir = QDir::cleanPath(testDataDir + "/linkerscripts"); + QbsRunParameters runParams("resolve", {"qbs.installRoot:" + QDir::currentPath()}); runParams.buildDirectory = sourceDir + "/build"; runParams.workingDir = sourceDir; QCOMPARE(runQbs(runParams), 0); + const bool isGcc = m_qbsStdout.contains("is Linux gcc: true"); + const bool isNotGcc = m_qbsStdout.contains("is Linux gcc: false"); + if (isNotGcc) + QSKIP("linker script test only applies to Linux"); + QVERIFY(isGcc); + + runParams.command = "build"; + QCOMPARE(runQbs(runParams), 0); const QString output = QString::fromLocal8Bit(m_qbsStderr); const QRegularExpression pattern(QRegularExpression::anchoredPattern(".*---(.*)---.*"), QRegularExpression::DotMatchesEverythingOption); @@ -5228,16 +5574,6 @@ void TestBlackbox::require() QCOMPARE(runQbs(), 0); } -void TestBlackbox::requireDeprecated() -{ - QDir::setCurrent(testDataDir + "/require-deprecated"); - QCOMPARE(runQbs(), 0); - QVERIFY2(m_qbsStderr.contains("loadExtension() function is deprecated"), - m_qbsStderr.constData()); - QVERIFY2(m_qbsStderr.contains("loadFile() function is deprecated"), - m_qbsStderr.constData()); -} - void TestBlackbox::rescueTransformerData() { QDir::setCurrent(testDataDir + "/rescue-transformer-data"); @@ -5522,11 +5858,7 @@ void TestBlackbox::propertyPrecedence() 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_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"nonleaf\",\"leaf\"]\n"), m_qbsStdout.constData()); @@ -5534,10 +5866,7 @@ 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()); + 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\",\"nonleaf\",\"profile\"]\n"), @@ -5859,22 +6188,25 @@ void TestBlackbox::protobuf_data() QTest::addColumn<QStringList>("properties"); QTest::addColumn<bool>("hasModules"); QTest::addColumn<bool>("successExpected"); - QTest::newRow("cpp") << QString("addressbook_cpp.qbs") << QStringList() << false << true; QTest::newRow("cpp-pkgconfig") << QString("addressbook_cpp.qbs") - << QStringList("project.qbsModuleProviders:qbspkgconfig") - << true - << true; + << QStringList({"project.qbsModuleProviders:qbspkgconfig"}) << true << true; + QTest::newRow("cpp-conan") << QString("addressbook_cpp.qbs") + << QStringList( + {"project.qbsModuleProviders:conan", + "qbs.buildVariant:release", + "moduleProviders.conan.installDirectory:build"}) + << true << true; QTest::newRow("objc") << QString("addressbook_objc.qbs") << QStringList() << false << true; QTest::newRow("nanopb") << QString("addressbook_nanopb.qbs") << QStringList() << false << true; - QTest::newRow("import") << QString("import.qbs") << QStringList() << false << true; + QTest::newRow("import") << QString("import.qbs") << QStringList() << true << true; QTest::newRow("missing import dir") << QString("needs-import-dir.qbs") - << QStringList() << false << false; + << QStringList() << true << false; QTest::newRow("provided import dir") << QString("needs-import-dir.qbs") - << QStringList("products.app.theImportDir:subdir") << false << true; + << QStringList("products.app.theImportDir:subdir") << true << true; QTest::newRow("create proto library") - << QString("create-proto-library.qbs") << QStringList() << false << true; + << QString("create-proto-library.qbs") << QStringList() << true << true; } void TestBlackbox::protobuf() @@ -5885,6 +6217,12 @@ void TestBlackbox::protobuf() QFETCH(bool, hasModules); QFETCH(bool, successExpected); rmDirR(relativeBuildDir()); + + if (QTest::currentDataTag() == QLatin1String("cpp-conan")) { + if (!prepareAndRunConan()) + QSKIP("conan is not prepared, check messages above"); + } + QbsRunParameters resolveParams("resolve", QStringList{"-f", projectFile} << properties); QCOMPARE(runQbs(resolveParams), 0); if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) @@ -5925,19 +6263,6 @@ void TestBlackbox::protobufLibraryInstall() QFileInfo::exists(installRootInclude + "/hello/world.pb.h")); } -// Tests whether it is possible to set providers properties in a Product or from command-line -void TestBlackbox::providersProperties() -{ - QDir::setCurrent(testDataDir + "/providers-properties"); - - QbsRunParameters params("build"); - params.arguments = QStringList("moduleProviders.provider_b.someProp: \"first,second\""); - QCOMPARE(runQbs(params), 0); - QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.listProp: [\"someValue\"]"), m_qbsStdout); - QVERIFY2(m_qbsStdout.contains( - "p.qbsothermodule.listProp: [\"first\",\"second\"]"), m_qbsStdout); -} - void TestBlackbox::pseudoMultiplexing() { // This is "pseudo-multiplexing" on all platforms that initialize qbs.architectures @@ -6047,6 +6372,10 @@ void TestBlackbox::qbsConfig() if (!canWriteToSystemSettings) { QVERIFY2(m_qbsStderr.contains("You do not have permission to write to that location."), m_qbsStderr.constData()); + } else { + // cleanup system settings + params.arguments = QStringList{"--system", "--unset", "key.subkey.scalar"}; + QCOMPARE(runQbs(params) == 0, canWriteToSystemSettings); } } @@ -6111,138 +6440,90 @@ void TestBlackbox::qbsConfigAddProfile_data() << QString("Profile properties must be key/value pairs"); } -// Tests whether it is possible to set qbsModuleProviders in Product and Project items -// and that the order of providers results in correct priority -void TestBlackbox::qbsModuleProviders() +void TestBlackbox::qbsConfigImport() { - QFETCH(QStringList, arguments); - QFETCH(QString, firstProp); - QFETCH(QString, secondProp); + QFETCH(QString, format); - QDir::setCurrent(testDataDir + "/qbs-module-providers"); + QDir::setCurrent(testDataDir + "/qbs-config-import-export"); - QbsRunParameters params("resolve"); - params.arguments = arguments; + QbsRunParameters params("config"); + QTemporaryDir settingsDir; + QVERIFY(settingsDir.isValid()); + const QStringList settingsDirArgs = QStringList{"--settings-dir", settingsDir.path()}; + params.arguments = settingsDirArgs; + params.arguments << "--import" << "config." + format; + + QCOMPARE(runQbs(params), 0); + + params.arguments = settingsDirArgs; + params.arguments << "--list"; QCOMPARE(runQbs(params), 0); - QVERIFY2(m_qbsStdout.contains(("p1.qbsmetatestmodule.prop: " + firstProp).toUtf8()), - m_qbsStdout); - QVERIFY2(m_qbsStdout.contains(("p1.qbsothermodule.prop: " + secondProp).toUtf8()), - m_qbsStdout); - QVERIFY2(m_qbsStdout.contains(("p2.qbsmetatestmodule.prop: " + firstProp).toUtf8()), - m_qbsStdout); - QVERIFY2(m_qbsStdout.contains(("p2.qbsothermodule.prop: " + secondProp).toUtf8()), - m_qbsStdout); + const QByteArray output = m_qbsStdout; + const auto lines = output.split('\n'); + QCOMPARE(lines.count(), 5); + QCOMPARE(lines[0], "group.key1: \"value1\""); + QCOMPARE(lines[1], "group.key2: \"value2\""); + QCOMPARE(lines[2], "key: \"value\""); + QCOMPARE(lines[3], "listKey: [\"valueOne\", \"valueTwo\"]"); + QCOMPARE(lines[4], ""); } -void TestBlackbox::qbsModuleProviders_data() +void TestBlackbox::qbsConfigImport_data() { - QTest::addColumn<QStringList>("arguments"); - QTest::addColumn<QString>("firstProp"); - QTest::addColumn<QString>("secondProp"); - - QTest::newRow("default") << QStringList() << "from_provider_a" << "undefined"; - QTest::newRow("override") - << QStringList("projects.project.qbsModuleProviders:provider_b") - << "from_provider_b" - << "from_provider_b"; - QTest::newRow("override list a") - << QStringList("projects.project.qbsModuleProviders:provider_a,provider_b") - << "from_provider_a" - << "from_provider_b"; - QTest::newRow("override list b") - << QStringList("projects.project.qbsModuleProviders:provider_b,provider_a") - << "from_provider_b" - << "from_provider_b"; -} - -// Tests possible use-cases how to override providers from command-line -void TestBlackbox::qbsModuleProvidersCliOverride() -{ - QFETCH(QStringList, arguments); - QFETCH(QString, propertyValue); - - QDir::setCurrent(testDataDir + "/qbs-module-providers-cli-override"); + QTest::addColumn<QString>("format"); - QbsRunParameters params("resolve"); - params.arguments = arguments; - QCOMPARE(runQbs(params), 0); - QVERIFY2(m_qbsStdout.contains(("qbsmetatestmodule.prop: " + propertyValue).toUtf8()), - m_qbsStdout); + QTest::newRow("text") << QStringLiteral("txt"); + QTest::newRow("json") << QStringLiteral("json"); } -void TestBlackbox::qbsModuleProvidersCliOverride_data() +void TestBlackbox::qbsConfigExport() { - QTest::addColumn<QStringList>("arguments"); - QTest::addColumn<QString>("propertyValue"); - - QTest::newRow("default") << QStringList() << "undefined"; - QTest::newRow("project-wide") - << QStringList("project.qbsModuleProviders:provider_a") - << "from_provider_a"; - QTest::newRow("concrete project") - << QStringList("projects.innerProject.qbsModuleProviders:provider_a") - << "from_provider_a"; - QTest::newRow("concrete product") - << QStringList("products.product.qbsModuleProviders:provider_a") - << "from_provider_a"; - QTest::newRow("concrete project override project-wide") - << QStringList({ - "project.qbsModuleProviders:provider_a", - "projects.innerProject.qbsModuleProviders:provider_b"}) - << "from_provider_b"; - QTest::newRow("concrete product override project-wide") - << QStringList({ - "project.qbsModuleProviders:provider_a", - "products.product.qbsModuleProviders:provider_b"}) - << "from_provider_b"; -} - -// Tests whether scoped providers can be used as named, i.e. new provider machinery -// is compatible with the old one -void TestBlackbox::qbsModuleProvidersCompatibility() -{ - QFETCH(QStringList, arguments); - QFETCH(QString, propertyValue); + QFETCH(QString, format); - QDir::setCurrent(testDataDir + "/qbs-module-providers-compatibility"); + QDir::setCurrent(testDataDir + "/qbs-config-import-export"); + + QbsRunParameters params("config"); + QTemporaryDir settingsDir; + const QString fileName = "config." + format; + const QString filePath = settingsDir.path() + "/" + fileName; + QVERIFY(settingsDir.isValid()); + const QStringList commonArgs = QStringList{"--settings-dir", settingsDir.path(), "--user"}; + + std::pair<QString, QString> values[] = { + {"key", "value"}, + {"listKey", "[\"valueOne\",\"valueTwo\"]"}, + {"group.key1", "value1"}, + {"group.key2", "value2"} + }; + + for (const auto &value: values) { + params.arguments = commonArgs; + params.arguments << value.first << value.second; + QCOMPARE(runQbs(params), 0); + } + + params.arguments = commonArgs; + params.arguments << "--export" << filePath; - QbsRunParameters params("resolve"); - params.arguments = arguments; QCOMPARE(runQbs(params), 0); - QVERIFY2(m_qbsStdout.contains(("qbsmetatestmodule.prop: " + propertyValue).toUtf8()), - m_qbsStdout); -} -void TestBlackbox::qbsModuleProvidersCompatibility_data() -{ - QTest::addColumn<QStringList>("arguments"); - QTest::addColumn<QString>("propertyValue"); + QVERIFY(QFileInfo(filePath).canonicalPath() != QFileInfo(fileName).canonicalPath()); - QTest::newRow("default") << QStringList() << "from_scoped_provider"; - QTest::newRow("scoped by name") << QStringList("project.qbsModuleProviders:qbsmetatestmodule") << "from_scoped_provider"; - QTest::newRow("named") << QStringList("project.qbsModuleProviders:named_provider") << "from_named_provider"; -} + QFile exported(filePath); + QFile expected(fileName); -void TestBlackbox::qbspkgconfigModuleProvider() -{ - QDir::setCurrent(testDataDir + "/qbspkgconfig-module-provider/libs"); + QVERIFY(exported.open(QIODevice::ReadOnly | QIODevice::Text)); + QVERIFY(expected.open(QIODevice::ReadOnly | QIODevice::Text)); - const auto commonParams = QbsRunParameters(QStringLiteral("install"), { - QStringLiteral("qbs.installPrefix:/usr/local"), - QStringLiteral("--install-root"), - QStringLiteral("install-root") - }); - auto dynamicParams = commonParams; - dynamicParams.arguments << "config:library" << "projects.libs.isBundle:false"; - QCOMPARE(runQbs(dynamicParams), 0); + QCOMPARE(exported.readAll(), expected.readAll()); +} - QDir::setCurrent(testDataDir + "/qbspkgconfig-module-provider"); +void TestBlackbox::qbsConfigExport_data() +{ + QTest::addColumn<QString>("format"); - QbsRunParameters params; - params.arguments - << "moduleProviders.qbspkgconfig.libDirs:libdir" - << "moduleProviders.qbspkgconfig.sysroot:" + QDir::currentPath() + "/libs/install-root"; - QCOMPARE(runQbs(params), 0); + QTest::newRow("text") << QStringLiteral("txt"); + QTest::newRow("json") << QStringLiteral("json"); } static QJsonObject getNextSessionPacket(QProcess &session, QByteArray &data) @@ -6281,6 +6562,137 @@ static QJsonObject getNextSessionPacket(QProcess &session, QByteArray &data) return QJsonDocument::fromJson(QByteArray::fromBase64(msg)).object(); } +static void sendSessionPacket(QProcess &sessionProc, const QJsonObject &message) +{ + const QByteArray data = QJsonDocument(message).toJson().toBase64(); + sessionProc.write("qbsmsg:"); + sessionProc.write(QByteArray::number(data.length())); + sessionProc.write("\n"); + sessionProc.write(data); +} + +void TestBlackbox::qbsLanguageServer_data() +{ + QTest::addColumn<QString>("request"); + QTest::addColumn<QString>("location"); + QTest::addColumn<QString>("insertLocation"); + QTest::addColumn<QString>("insertString"); + QTest::addColumn<QString>("expectedReply"); + + QTest::addRow("follow to module") << "--goto-def" + << (testDataDir + "/lsp/lsp.qbs:4:9") + << QString() << QString() + << (testDataDir + "/lsp/modules/m/m.qbs:1:1"); + QTest::addRow("follow to submodules") + << "--goto-def" + << (testDataDir + "/lsp/lsp.qbs:5:35") + << QString() << QString() + << ((testDataDir + "/lsp/modules/Prefix/m1/m1.qbs:1:1\n") + + (testDataDir + "/lsp/modules/Prefix/m2/m2.qbs:1:1\n") + + (testDataDir + "/lsp/modules/Prefix/m3/m3.qbs:1:1")); + QTest::addRow("follow to product") + << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:9:19") << QString() << QString() + << (testDataDir + "/lsp/lsp.qbs:2:5"); + QTest::addRow("follow to module, non-invalidating insert") + << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:4:9") << "5:9" + << QString("property bool dummy\n") << (testDataDir + "/lsp/modules/m/m.qbs:1:1"); + QTest::addRow("follow to module, invalidating insert") + << "--goto-def" << (testDataDir + "/lsp/lsp.qbs:4:9") << QString() + << QString("property bool dummy\n") << QString(); + QTest::addRow("completion: LHS, module prefix") + << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() << QString("P") + << QString("Prefix.m1\nPrefix.m2\nPrefix.m3"); + QTest::addRow("completion: LHS, module name") + << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() << QString("Prefix.m") + << QString("m1\nm2\nm3"); + QTest::addRow("completion: LHS, module property right after dot") + << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() + << QString("Prefix.m1.") << QString("p1 bool\np2 string\nx bool"); + QTest::addRow("completion: LHS, module property with identifier prefix") + << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() + << QString("Prefix.m1.p") << QString("p1 bool\np2 string"); + QTest::addRow("completion: simple RHS, module property") + << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() + << QString("property bool dummy: Prefix.m1.p") << QString("p1 bool\np2 string"); + QTest::addRow("completion: complex RHS, module property") + << "--completion" << (testDataDir + "/lsp/lsp.qbs:7:1") << QString() + << QString("property bool dummy: { return Prefix.m1.p") << QString("p1 bool\np2 string"); +} + +void TestBlackbox::qbsLanguageServer() +{ + QFETCH(QString, request); + QFETCH(QString, location); + QFETCH(QString, insertLocation); + QFETCH(QString, insertString); + QFETCH(QString, expectedReply); + + QDir::setCurrent(testDataDir + "/lsp"); + QProcess sessionProc; + sessionProc.start(qbsExecutableFilePath, QStringList("session")); + + QVERIFY(sessionProc.waitForStarted()); + + QByteArray incomingData; + + // Wait for and verify hello packet. + QJsonObject receivedMessage = getNextSessionPacket(sessionProc, incomingData); + const QString socketPath = receivedMessage.value("lsp-socket").toString(); + QVERIFY(!socketPath.isEmpty()); + + // Resolve project. + QJsonObject resolveMessage; + resolveMessage.insert("type", "resolve-project"); + resolveMessage.insert("top-level-profile", profileName()); + resolveMessage.insert("project-file-path", QDir::currentPath() + "/lsp.qbs"); + resolveMessage.insert("build-root", QDir::currentPath()); + resolveMessage.insert("settings-directory", settings()->baseDirectory()); + sendSessionPacket(sessionProc, resolveMessage); + bool receivedReply = false; + 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()); + } + } + QVERIFY(receivedReply); + + // Employ client app to send request. + QProcess lspClient; + const QFileInfo qbsFileInfo(qbsExecutableFilePath); + const QString clientFilePath = HostOsInfo::appendExecutableSuffix( + qbsFileInfo.absolutePath() + "/qbs_lspclient"); + QStringList args{"--socket", socketPath, request, location}; + if (!insertString.isEmpty()) + args << "--insert-code" << insertString; + if (!insertLocation.isEmpty()) + args << "--insert-location" << insertLocation; + lspClient.start(clientFilePath, args); + QVERIFY2(lspClient.waitForStarted(), qPrintable(lspClient.errorString())); + QVERIFY2(lspClient.waitForFinished(), qPrintable(lspClient.errorString())); + QString errMsg; + if (lspClient.exitStatus() != QProcess::NormalExit) + errMsg = lspClient.errorString(); + if (errMsg.isEmpty()) + errMsg = QString::fromLocal8Bit(lspClient.readAllStandardError()); + QVERIFY2(lspClient.exitCode() == 0, qPrintable(errMsg)); + QVERIFY2(errMsg.isEmpty(), qPrintable(errMsg)); + QString output = QString::fromUtf8(lspClient.readAllStandardOutput().trimmed()); + output.replace("\r\n", "\n"); + QCOMPARE(output, expectedReply); + + QJsonObject quitRequest; + quitRequest.insert("type", "quit"); + sendSessionPacket(sessionProc, quitRequest); + QVERIFY(sessionProc.waitForFinished(3000)); +} + void TestBlackbox::qbsSession() { QDir::setCurrent(testDataDir + "/qbs-session"); @@ -6297,11 +6709,7 @@ void TestBlackbox::qbsSession() QVERIFY(sessionProc.waitForStarted()); const auto sendPacket = [&sessionProc](const QJsonObject &message) { - const QByteArray data = QJsonDocument(message).toJson().toBase64(); - sessionProc.write("qbsmsg:"); - sessionProc.write(QByteArray::number(data.length())); - sessionProc.write("\n"); - sessionProc.write(data); + sendSessionPacket(sessionProc, message); }; static const auto envToJson = [](const QProcessEnvironment &env) { @@ -6325,7 +6733,7 @@ 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(), 2); + QCOMPARE(receivedMessage.value("api-level").toInt(), 5); QCOMPARE(receivedMessage.value("api-compat-level").toInt(), 2); // Resolve & verify structure @@ -6341,6 +6749,7 @@ void TestBlackbox::qbsSession() resolveMessage.insert("overridden-properties", overriddenValues); resolveMessage.insert("environment", envToJson(QbsRunParameters::defaultEnvironment())); resolveMessage.insert("data-mode", "only-if-changed"); + resolveMessage.insert("max-job-count", 2); resolveMessage.insert("log-time", true); resolveMessage.insert("module-properties", QJsonArray::fromStringList({"cpp.cxxLanguageVersion"})); @@ -7264,6 +7673,7 @@ void TestBlackbox::autotestTimeout() { QFETCH(QStringList, resolveParams); QFETCH(bool, expectFailure); + QFETCH(QString, errorDetails); QDir::setCurrent(testDataDir + "/autotest-timeout"); QbsRunParameters resolveParameters("resolve", resolveParams); QCOMPARE(runQbs(resolveParameters), 0); @@ -7273,7 +7683,9 @@ void TestBlackbox::autotestTimeout() buildParameters.expectFailure = expectFailure; if (expectFailure) { QVERIFY(runQbs(buildParameters) != 0); - QVERIFY(m_qbsStderr.contains("cancelled") && m_qbsStderr.contains("timeout")); + QVERIFY( + m_qbsStderr.contains("cancelled") && m_qbsStderr.contains("timeout") + && m_qbsStderr.contains(errorDetails.toLocal8Bit())); } else QVERIFY(runQbs(buildParameters) == 0); @@ -7283,11 +7695,12 @@ void TestBlackbox::autotestTimeout_data() { QTest::addColumn<QStringList>("resolveParams"); QTest::addColumn<bool>("expectFailure"); - QTest::newRow("no timeout") << QStringList() << false; - QTest::newRow("timeout on test") << QStringList({"products.testApp.autotest.timeout:2"}) - << true; - QTest::newRow("timeout on runner") << QStringList({"products.autotest-runner.timeout:2"}) - << true; + QTest::addColumn<QString>("errorDetails"); + QTest::newRow("no timeout") << QStringList() << false << QString(); + QTest::newRow("timeout on test") + << QStringList({"products.testApp.autotest.timeout:2"}) << true << QString("testApp"); + QTest::newRow("timeout on runner") + << QStringList({"products.autotest-runner.timeout:2"}) << true << QString("testApp"); } void TestBlackbox::autotests_data() @@ -7414,9 +7827,9 @@ static bool haveMakeNsis() << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS"); QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH") - .split(HostOsInfo::pathListSeparator(), QBS_SKIP_EMPTY_PARTS); + .split(HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts); - for (const QString &key : qAsConst(regKeys)) { + for (const QString &key : std::as_const(regKeys)) { QSettings settings(key, QSettings::NativeFormat); QString str = settings.value(QStringLiteral(".")).toString(); if (!str.isEmpty()) @@ -7424,7 +7837,7 @@ static bool haveMakeNsis() } bool haveMakeNsis = false; - for (const QString &path : qAsConst(paths)) { + for (const QString &path : std::as_const(paths)) { if (regularFileExists(QDir::fromNativeSeparators(path) + HostOsInfo::appendExecutableSuffix(QStringLiteral("/makensis")))) { haveMakeNsis = true; @@ -7652,7 +8065,7 @@ void TestBlackbox::generator_data() void TestBlackbox::nodejs() { const SettingsPtr s = settings(); - Profile p(profileName(), s.get()); + qbs::Profile p(profileName(), s.get()); int status; findNodejs(&status); @@ -7671,6 +8084,11 @@ void TestBlackbox::nodejs() QSKIP("nodejs.packageManagerFilePath not set and automatic detection failed"); } + if (p.value("nodejs.interpreterFilePath").toString().isEmpty() + && status != 0 && m_qbsStderr.contains("interpreterPath")) { + QSKIP("nodejs.interpreterFilePath not set and automatic detection failed"); + } + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) QSKIP("Cannot run binaries in cross-compiled build"); QCOMPARE(status, 0); @@ -7688,7 +8106,7 @@ void TestBlackbox::typescript() QSKIP("Skip this test when running on GitHub"); const SettingsPtr s = settings(); - Profile p(profileName(), s.get()); + qbs::Profile p(profileName(), s.get()); int status; findTypeScript(&status); @@ -7855,6 +8273,35 @@ void TestBlackbox::wildCardsAndRules() QVERIFY(!m_qbsStdout.contains("creating output artifact")); } +void TestBlackbox::wildCardsAndChangeTracking_data() +{ + QTest::addColumn<QString>("dirToModify"); + QTest::addColumn<bool>("expectReResolve"); + + QTest::newRow("root path") << QString(".") << false; + QTest::newRow("dir with recursive match") << QString("recursive1") << false; + QTest::newRow("non-recursive base dir") << QString("nonrecursive") << true; + QTest::newRow("empty base dir with file patterns") << QString("nonrecursive/empty") << true; +} + +void TestBlackbox::wildCardsAndChangeTracking() +{ + QFETCH(QString, dirToModify); + QFETCH(bool, expectReResolve); + + const QString srcDir = testDataDir + "/wildcards-and-change-tracking"; + QDir::setCurrent(srcDir); + rmDirR("default"); + QDir::current().mkdir("nonrecursive/empty"); + + QCOMPARE(runQbs({"resolve"}), 0); + QVERIFY2(m_qbsStdout.contains("Resolving"), m_qbsStdout.constData()); + WAIT_FOR_NEW_TIMESTAMP(); + touch(dirToModify + "/blubb.txt"); + QCOMPARE(runQbs({"resolve"}), 0); + QCOMPARE(m_qbsStdout.contains("Resolving"), expectReResolve); +} + void TestBlackbox::loadableModule() { QDir::setCurrent(testDataDir + QLatin1String("/loadablemodule")); @@ -7945,112 +8392,6 @@ void TestBlackbox::maximumCxxLanguageVersion() m_qbsStdout.constData()); } -void TestBlackbox::moduleProviders() -{ - QDir::setCurrent(testDataDir + "/module-providers"); - - // Resolving in dry-run mode must not leave any data behind. - QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); - if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) - QSKIP("Cannot run binaries in cross-compiled build"); - QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 2); - QVERIFY(!QFile::exists(relativeBuildDir())); - - // Initial build. - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); - QVERIFY(QFile::exists(relativeBuildDir())); - QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 2); - QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); - QVERIFY2(m_qbsStdout.contains("The MY_DEFINE is app1"), m_qbsStdout.constData()); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are Z and Y"), m_qbsStdout.constData()); - QVERIFY2(m_qbsStdout.contains("The MY_DEFINE is app2"), m_qbsStdout.constData()); - - // Rebuild with overridden module provider config. The output for product 2 must change, - // but no setup script must be re-run, because both config values have already been - // handled in the first run. - const QStringList resolveArgs("moduleProviders.mygenerator.chooseLettersFrom:beginning"); - QCOMPARE(runQbs(QbsRunParameters("resolve", resolveArgs)), 0); - QVERIFY2(!m_qbsStdout.contains("Running setup script"), m_qbsStdout.constData()); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); - - // Forcing Probe execution triggers a re-run of the setup script. But only once, - // because the module provider config is the same now. - QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList(resolveArgs) - << "--force-probe-execution")), 0); - QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 1); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); - - // Now re-run without the module provider config override. Again, the setup script must - // run once, for the config value that was not present in the last run. - QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); - QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 1); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); - QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); - QVERIFY2(m_qbsStdout.contains("The letters are Z and Y"), m_qbsStdout.constData()); -} - -void TestBlackbox::fallbackModuleProvider_data() -{ - QTest::addColumn<bool>("fallbacksEnabledGlobally"); - QTest::addColumn<bool>("fallbacksEnabledInProduct"); - QTest::addColumn<QStringList>("pkgConfigLibDirs"); - QTest::addColumn<bool>("successExpected"); - QTest::newRow("without custom lib dir, fallbacks disabled globally and in product") - << false << false << QStringList() << false; - QTest::newRow("without custom lib dir, fallbacks disabled globally, enabled in product") - << false << true << QStringList() << false; - QTest::newRow("without custom lib dir, fallbacks enabled globally, disabled in product") - << true << false << QStringList() << false; - QTest::newRow("without custom lib dir, fallbacks enabled globally and in product") - << true << true << QStringList() << false; - QTest::newRow("with custom lib dir, fallbacks disabled globally and in product") - << false << false << QStringList(testDataDir + "/fallback-module-provider/libdir") - << false; - QTest::newRow("with custom lib dir, fallbacks disabled globally, enabled in product") - << false << true << QStringList(testDataDir + "/fallback-module-provider/libdir") - << false; - QTest::newRow("with custom lib dir, fallbacks enabled globally, disabled in product") - << true << false << QStringList(testDataDir + "/fallback-module-provider/libdir") - << false; - QTest::newRow("with custom lib dir, fallbacks enabled globally and in product") - << true << true << QStringList(testDataDir + "/fallback-module-provider/libdir") - << true; -} - -void TestBlackbox::fallbackModuleProvider() -{ - QFETCH(bool, fallbacksEnabledInProduct); - QFETCH(bool, fallbacksEnabledGlobally); - QFETCH(QStringList, pkgConfigLibDirs); - QFETCH(bool, successExpected); - - QDir::setCurrent(testDataDir + "/fallback-module-provider"); - static const auto b2s = [](bool b) { return QString(b ? "true" : "false"); }; - QbsRunParameters resolveParams("resolve", - QStringList{"modules.pkgconfig.libDirs:" + pkgConfigLibDirs.join(','), - "products.p.fallbacksEnabled:" + b2s(fallbacksEnabledInProduct), - "--force-probe-execution"}); - if (!fallbacksEnabledGlobally) - resolveParams.arguments << "--no-fallback-module-provider"; - QCOMPARE(runQbs(resolveParams), 0); - const bool pkgConfigPresent = m_qbsStdout.contains("pkg-config present: true"); - const bool pkgConfigNotPresent = m_qbsStdout.contains("pkg-config present: false"); - QVERIFY(pkgConfigPresent != pkgConfigNotPresent); - if (pkgConfigNotPresent) - successExpected = false; - QbsRunParameters buildParams; - buildParams.expectFailure = !successExpected; - QCOMPARE(runQbs(buildParams) == 0, successExpected); -} - void TestBlackbox::minimumSystemVersion() { rmDirR(relativeBuildDir()); @@ -8143,7 +8484,7 @@ void TestBlackbox::minimumSystemVersion_data() return "__MAC_OS_X_VERSION_MIN_REQUIRED=1070\nversion 10.7\n"; if (HostOsInfo::isWindowsHost()) - return "WINVER=1536\n6.00 operating system version\n6.00 subsystem version\n"; + return "WINVER=1538\n6.02 operating system version\n6.02 subsystem version\n"; return ""; }(); @@ -8171,7 +8512,7 @@ void TestBlackbox::missingBuildGraph() QbsRunParameters params; params.expectFailure = true; params.arguments << QLatin1String("config:") + actualConfigName; - for (const QString &command : qAsConst(commands)) { + for (const QString &command : std::as_const(commands)) { params.command = command; QVERIFY2(runQbs(params) != 0, qPrintable(command)); const QString expectedErrorMessage = QString("Build graph not found for " @@ -8281,6 +8622,12 @@ void TestBlackbox::movedFileDependency() QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } +void TestBlackbox::msvcAsmLinkerFlags() +{ + QDir::setCurrent(testDataDir + "/msvc-asm-flags"); + QCOMPARE(runQbs(), 0); +} + void TestBlackbox::badInterpreter() { if (!HostOsInfo::isAnyUnixHost()) @@ -8402,6 +8749,7 @@ void TestBlackbox::groupsInModules() QVERIFY(m_qbsStdout.contains("compiling helper4.c")); QVERIFY(m_qbsStdout.contains("compiling helper5.c")); QVERIFY(!m_qbsStdout.contains("compiling helper6.c")); + QVERIFY(m_qbsStdout.contains("compiling helper7.c")); QCOMPARE(runQbs(params), 0); QVERIFY(!m_qbsStdout.contains("compiling rock.coal to rock.diamond")); @@ -8427,15 +8775,16 @@ void TestBlackbox::grpc_data() QTest::addColumn<QStringList>("arguments"); QTest::addColumn<bool>("hasModules"); - QTest::newRow("cpp") << QString("grpc_cpp.qbs") << QStringList() << false; - - QStringList pkgConfigArgs("project.qbsModuleProviders:qbspkgconfig"); + QStringList pkgConfigArgs({"project.qbsModuleProviders:qbspkgconfig"}); // on macOS, openSSL is hidden from pkg-config by default if (qbs::Internal::HostOsInfo::isMacosHost()) { pkgConfigArgs << "moduleProviders.qbspkgconfig.extraPaths:/usr/local/opt/openssl@1.1/lib/pkgconfig"; } QTest::newRow("cpp-pkgconfig") << QString("grpc_cpp.qbs") << pkgConfigArgs << true; + QStringList conanArgs( + {"project.qbsModuleProviders:conan", "moduleProviders.conan.installDirectory:build"}); + QTest::newRow("cpp-conan") << QString("grpc_cpp.qbs") << conanArgs << true; } void TestBlackbox::grpc() @@ -8446,6 +8795,11 @@ void TestBlackbox::grpc() QFETCH(bool, hasModules); rmDirR(relativeBuildDir()); + if (QTest::currentDataTag() == QLatin1String("cpp-conan")) { + if (!prepareAndRunConan()) + QSKIP("conan is not prepared, check messages above"); + } + QbsRunParameters resolveParams("resolve", QStringList{"-f", projectFile}); resolveParams.arguments << arguments; QCOMPARE(runQbs(resolveParams), 0); diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h index ea3a8597d..3f817b481 100644 --- a/tests/auto/blackbox/tst_blackbox.h +++ b/tests/auto/blackbox/tst_blackbox.h @@ -60,6 +60,8 @@ private slots: void bomSources(); void buildDataOfDisabledProduct(); void buildDirectories(); + void buildDirPlaceholders_data(); + void buildDirPlaceholders(); void buildEnvChange(); void buildGraphVersions(); void buildVariantDefaults_data(); @@ -82,7 +84,6 @@ private slots: void combinedSources(); void commandFile(); void compilerDefinesByLanguage(); - void concurrentExecutor(); void conditionalExport(); void conditionalFileTagger(); void configure(); @@ -91,13 +92,18 @@ private slots: void cxxLanguageVersion_data(); void conanfileProbe_data(); void conanfileProbe(); + void conflictingPropertyValues_data(); + void conflictingPropertyValues(); void cpuFeatures(); + void dateProperty(); void dependenciesProperty(); void dependencyScanningLoop(); void deprecatedProperty(); + void deprecatedProperty_data(); void disappearedProfile(); void discardUnusedData(); void discardUnusedData_data(); + void dotDotPcFile(); void driverLinkerFlags(); void driverLinkerFlags_data(); void dynamicLibraryInModule(); @@ -122,11 +128,15 @@ private slots: void exportedPropertyInDisabledProduct_data(); void exportRule(); void exportToOutsideSearchPath(); + void exportsCMake(); + void exportsCMake_data(); void exportsPkgconfig(); void exportsQbs(); void externalLibs(); void fileDependencies(); void fileTagsFilterMerging(); + void flatbuf(); + void flatbuf_data(); void freedesktop(); void generatedArtifactAsInputToDynamicRule(); void generateLinkerMapFile(); @@ -159,6 +169,8 @@ private slots: void installPackage(); void installRootFromProjectFile(); void installTree(); + void invalidArtifactPath_data(); + void invalidArtifactPath(); void invalidCommandProperty_data(); void invalidCommandProperty(); void invalidExtensionInstantiation(); @@ -194,9 +206,6 @@ private slots: void makefileGenerator(); void maximumCLanguageVersion(); void maximumCxxLanguageVersion(); - void moduleProviders(); - void fallbackModuleProvider_data(); - void fallbackModuleProvider(); void minimumSystemVersion(); void minimumSystemVersion_data(); void missingBuildGraph(); @@ -206,6 +215,7 @@ private slots: void missingOverridePrefix(); void moduleConditions(); void movedFileDependency(); + void msvcAsmLinkerFlags(); void multipleChanges(); void multipleConfigurations(); void multiplexedTool(); @@ -228,6 +238,7 @@ private slots: void overrideProjectProperties(); void pathProbe_data(); void pathProbe(); + void pathListInProbe(); void pchChangeTracking(); void perGroupDefineInExportItem(); void pkgConfigProbe(); @@ -241,13 +252,11 @@ private slots: void probeProperties(); void probesAndShadowProducts(); void probeInExportedModule(); - void probeInModuleProvider(); void probesAndArrayProperties(); void probesInNestedModules(); void productDependenciesByType(); void productInExportedModule(); void productProperties(); - void propertyAssignmentOnNonPresentModule(); void propertyAssignmentInFailedModule(); void propertyChanges(); void propertyEvaluationContext(); @@ -257,18 +266,16 @@ private slots: void protobuf_data(); void protobuf(); void protobufLibraryInstall(); - void providersProperties(); void pseudoMultiplexing(); void qbsConfig(); void qbsConfigAddProfile(); void qbsConfigAddProfile_data(); - void qbsModuleProviders(); - void qbsModuleProviders_data(); - void qbsModuleProvidersCliOverride(); - void qbsModuleProvidersCliOverride_data(); - void qbsModuleProvidersCompatibility(); - void qbsModuleProvidersCompatibility_data(); - void qbspkgconfigModuleProvider(); + void qbsConfigImport(); + void qbsConfigImport_data(); + void qbsConfigExport(); + void qbsConfigExport_data(); + void qbsLanguageServer_data(); + void qbsLanguageServer(); void qbsSession(); void qbsVersion(); void qtBug51237(); @@ -282,15 +289,16 @@ private slots: void reproducibleBuild(); void reproducibleBuild_data(); void require(); - void requireDeprecated(); void rescueTransformerData(); void responseFiles(); void retaggedOutputArtifact(); + void rpathlinkDeduplication(); void ruleConditions(); void ruleConnectionWithExcludedInputs(); void ruleCycle(); void ruleWithNoInputs(); void ruleWithNonRequiredInputs(); + void runMultiplexed(); void sanitizer_data(); void sanitizer(); void scannerItem(); @@ -345,6 +353,8 @@ private slots: void wholeArchive(); void wholeArchive_data(); void wildCardsAndRules(); + void wildCardsAndChangeTracking_data(); + void wildCardsAndChangeTracking(); void wildcardRenaming(); void zip(); void zip_data(); @@ -355,6 +365,7 @@ private: QMap<QString, QString> findNodejs(int *status); QMap<QString, QString> findTypeScript(int *status); QString findArchiver(const QString &fileName, int *status = nullptr); + bool prepareAndRunConan(); static bool lexYaccExist(); static qbs::Version bisonVersion(); }; diff --git a/tests/auto/blackbox/tst_blackboxandroid.cpp b/tests/auto/blackbox/tst_blackboxandroid.cpp index 06027a100..a74d9415d 100644 --- a/tests/auto/blackbox/tst_blackboxandroid.cpp +++ b/tests/auto/blackbox/tst_blackboxandroid.cpp @@ -131,7 +131,7 @@ void TestBlackboxAndroid::android() buildParams.buildDirectory = buildSubDir; buildParams.profile = p.name(); QCOMPARE(runQbs(buildParams), 0); - for (const QString &productName : qAsConst(productNames)) { + for (const QString &productName : std::as_const(productNames)) { const QByteArray tag(QTest::currentDataTag()); QCOMPARE(m_qbsStdout.count("generating BuildConfig.java"), isIncrementalBuild ? 0 : productNames.size()); @@ -262,7 +262,7 @@ void TestBlackboxAndroid::android_data() QByteArray base( aabPackage ? "base/" : ""); for (const QByteArray &entry : lst) { if (entry.contains(archPlaceHolder)) { - for (const QByteArray &arch : qAsConst(archs)) + for (const QByteArray &arch : std::as_const(archs)) result << (base + QByteArray(entry).replace(archPlaceHolder, arch)); } else { result << (base + entry); @@ -309,7 +309,6 @@ void TestBlackboxAndroid::android_data() return QString("modules.Android.sdk.dexCompilerName:") + (enableD8 ? "d8" : "dx"); }; bool enableD8 = true; - auto qtAppExpectedFiles = [&](bool generateAab, bool enableAapt2, bool codeSign = true, QString keyAlias="androiddebugkey") { QByteArrayList expectedFile; @@ -357,6 +356,11 @@ void TestBlackboxAndroid::android_data() "lib/${ARCH}/libplugins_imageformats_qtiff_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qwbmp_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qwebp_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 5)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libQt6Svg_${ARCH}.so", + "lib/${ARCH}/libplugins_iconengines_qsvgicon_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qsvg_${ARCH}.so"}, generateAab); if (!enableAapt2 && version < qbs::Version(6, 0)) expectedFile << "res/layout/splash.xml"; return expectedFile; @@ -613,13 +617,25 @@ void TestBlackboxAndroid::android_data() "lib/${ARCH}/libplugins_imageformats_qtiff_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qwbmp_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qwebp_${ARCH}.so"}, generateAab); - if (version >= qbs::Version(6, 0)) + if (version >= qbs::Version(6, 5)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libQt6Svg_${ARCH}.so", + "lib/${ARCH}/libplugins_iconengines_qsvgicon_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qsvg_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 0)) { expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libQt6OpenGL_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_Models_modelsplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_WorkerScript_workerscriptplugin_${ARCH}.so", - "lib/${ARCH}/libqml_QtQml_qmlplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_qtquick2plugin_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 5)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQml_Base_qmlplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_qmlmetaplugin_${ARCH}.so"}, generateAab); + else + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQml_qmlplugin_${ARCH}.so"}, generateAab); + } if (version >= qbs::Version(6, 2)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libplugins_networkinformation_qandroidnetworkinformation_${ARCH}.so", @@ -627,6 +643,7 @@ void TestBlackboxAndroid::android_data() "lib/${ARCH}/libplugins_tls_qopensslbackend_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Window_quickwindowplugin_${ARCH}.so", }, generateAab); + if (version >= qbs::Version(6, 0) && version < qbs::Version(6, 3)) { expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libQt6QuickControls2Impl_${ARCH}.so", @@ -669,8 +686,8 @@ void TestBlackboxAndroid::android_data() "lib/${ARCH}/libqml_QtQuick_Dialogs_qtquickdialogsplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_Dialogs_quickimpl_qtquickdialogs2quickimplplugin_${ARCH}.so"}, generateAab); - else - expectedFile << expandArchs(ndkArchsForQt, { + else + expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libqml_QtQuick_Window_quickwindow_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_tooling_quicktooling_${ARCH}.so"}, generateAab); } @@ -774,13 +791,25 @@ void TestBlackboxAndroid::android_data() "lib/${ARCH}/libplugins_imageformats_qtiff_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qwbmp_${ARCH}.so", "lib/${ARCH}/libplugins_imageformats_qwebp_${ARCH}.so"}, generateAab); - if (version >= qbs::Version(6, 0)) + if (version >= qbs::Version(6, 5)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libQt6Svg_${ARCH}.so", + "lib/${ARCH}/libplugins_iconengines_qsvgicon_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qsvg_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 0)) { expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libQt6OpenGL_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_Models_modelsplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQml_WorkerScript_workerscriptplugin_${ARCH}.so", - "lib/${ARCH}/libqml_QtQml_qmlplugin_${ARCH}.so", "lib/${ARCH}/libqml_QtQuick_qtquick2plugin_${ARCH}.so"}, generateAab); + if (version >= qbs::Version(6, 5)) + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQml_Base_qmlplugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQml_qmlmetaplugin_${ARCH}.so"}, generateAab); + else + expectedFile << expandArchs(ndkArchsForQt, { + "lib/${ARCH}/libqml_QtQml_qmlplugin_${ARCH}.so"}, generateAab); + } if (version >= qbs::Version(6, 2)) expectedFile << expandArchs(ndkArchsForQt, { "lib/${ARCH}/libplugins_networkinformation_qandroidnetworkinformation_${ARCH}.so", @@ -967,14 +996,14 @@ void TestBlackboxAndroid::android_data() << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; enableAapt2 = true; - QTest::newRow("aidl") << "aidl" << QStringList("io.qbs.aidltest") + QTest::newRow("aidl aapt2") << "aidl" << QStringList("io.qbs.aidltest") << (QList<QByteArrayList>() << (QByteArrayList() << commonFiles(generateAab) << "resources.arsc")) << QStringList{aaptVersion(enableAapt2), packageType(generateAab)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; generateAab = true; - QTest::newRow("aidl") << "aidl" << QStringList("io.qbs.aidltest") + QTest::newRow("aidl aab") << "aidl" << QStringList("io.qbs.aidltest") << (QList<QByteArrayList>() << (QByteArrayList() << commonFiles(generateAab) << "base/resources.pb")) @@ -1031,6 +1060,7 @@ void TestBlackboxAndroid::android_data() << QStringList{aaptVersion(enableAapt2), packageType(generateAab), dexCompilerVersion(enableD8)} << enableAapt2 << generateAab << isIncrementalBuild << enableD8; + enableAapt2 = false; generateAab = false; auto expectedFiles1 = [&](bool generateAab) { @@ -1054,7 +1084,6 @@ void TestBlackboxAndroid::android_data() cxxLibPath("libstlport_shared.so", false)}, generateAab); return expectedFile; }; - QTest::newRow("multiple apks") << "multiple-apks-per-project" << (QStringList() << "twolibs1" << "twolibs2") diff --git a/tests/auto/blackbox/tst_blackboxapple.cpp b/tests/auto/blackbox/tst_blackboxapple.cpp index 2744f907e..30e20a1c9 100644 --- a/tests/auto/blackbox/tst_blackboxapple.cpp +++ b/tests/auto/blackbox/tst_blackboxapple.cpp @@ -191,10 +191,12 @@ void TestBlackboxApple::initTestCase() void TestBlackboxApple::appleMultiConfig() { const auto xcodeVersion = findXcodeVersion(); + if (!xcodeVersion) + QSKIP("requires Xcode profile"); QDir::setCurrent(testDataDir + "/apple-multiconfig"); QCOMPARE(runQbs(QbsRunParameters(QStringList{ "qbs.installPrefix:''", - QStringLiteral("project.xcodeVersion:") + xcodeVersion.toString()})), 0); + QStringLiteral("project.xcodeVersion:") + xcodeVersion->toString()})), 0); if (m_qbsStdout.contains("isShallow: false")) { QVERIFY(QFileInfo2(defaultInstallRoot + "/singleapp.app/Contents/MacOS/singleapp").isExecutable()); @@ -304,6 +306,10 @@ void TestBlackboxApple::appleMultiConfig() void TestBlackboxApple::aggregateDependencyLinking() { const auto xcodeVersion = findXcodeVersion(); + + if (!xcodeVersion) + QSKIP("requires Xcode profile"); + // XCode 11 produces warning about deprecation of 32-bit apps, but still works const bool hasX86Mac = xcodeVersion < qbs::Version(12); const bool hasArmMac = xcodeVersion >= qbs::Version(12, 2); @@ -359,15 +365,16 @@ void TestBlackboxApple::assetCatalog() { QFETCH(bool, flatten); - const auto xcodeVersion = findXcodeVersion(); QDir::setCurrent(testDataDir + QLatin1String("/ib/assetcatalog")); rmDirR(relativeBuildDir()); + if (!findXcode()) + QSKIP("requires Xcode profile"); + QbsRunParameters params; - const auto v = HostOsInfo::hostOsVersion(); const QString flattens = "modules.ib.flatten:" + QString(flatten ? "true" : "false"); - const QString macosTarget = "modules.cpp.minimumMacosVersion:'" + v.toString() + "'"; + const QString macosTarget = "modules.cpp.minimumMacosVersion:'10.15'"; // Make sure a dry run does not write anything params.arguments = QStringList() << "-f" << "assetcatalogempty.qbs" << "--dry-run" @@ -383,39 +390,12 @@ void TestBlackboxApple::assetCatalog() QCOMPARE(runQbs(params), 0); // empty asset catalogs must still produce output - if (xcodeVersion >= qbs::Version(5)) - QVERIFY((bool)m_qbsStdout.contains("compiling empty.xcassets")); - - // should additionally produce raw assets since deployment target will be < 10.9 - // older versions of ibtool generated either raw assets OR .car files; - // newer versions always generate the .car file regardless of the deployment target - if (v < qbs::Version(10, 9)) { - QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") - + "/assetcatalogempty.app/Contents/Resources/other.png")); - QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") - + "/assetcatalogempty.app/Contents/Resources/other@2x.png")); - } - - rmDirR(relativeBuildDir()); - params.arguments.push_back("modules.cpp.minimumMacosVersion:'10.10'"); // force CAR generation - QCOMPARE(runQbs(params), 0); + QVERIFY((bool)m_qbsStdout.contains("compiling empty.xcassets")); // empty asset catalogs must still produce output - if (xcodeVersion >= qbs::Version(5)) { - QVERIFY((bool)m_qbsStdout.contains("compiling empty.xcassets")); - // No matter what, we need a 10.9 host to build CAR files - if (HostOsInfo::hostOsVersion() >= qbs::Version(10, 9)) { - QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") - + "/assetcatalogempty.app/Contents/Resources/Assets.car")); - } else { - QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") - + "/assetcatalogempty.app/Contents/Resources/empty.icns")); - QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") - + "/assetcatalogempty.app/Contents/Resources/other.png")); - QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") - + "/assetcatalogempty.app/Contents/Resources/other@2x.png")); - } - } + QVERIFY((bool)m_qbsStdout.contains("compiling empty.xcassets")); + QVERIFY(regularFileExists(relativeProductBuildDir("assetcatalogempty") + + "/assetcatalogempty.app/Contents/Resources/Assets.car")); // this asset catalog happens to have an embedded icon set, // but this should NOT be built since it is not in the files list @@ -713,30 +693,53 @@ void TestBlackboxApple::bundleStructure_data() QTest::newRow("G") << "G" << "com.apple.product-type.in-app-purchase-content"; } +void TestBlackboxApple::byteArrayInfoPlist() +{ + QDir::setCurrent(testDataDir + "/byteArrayInfoPlist"); + + QCOMPARE(runQbs(), 0); + + const auto infoPlistPath = getInfoPlistPath( + relativeProductBuildDir("byteArrayInfoPlist") + "/byteArrayInfoPlist.app"); + QVERIFY(QFile::exists(infoPlistPath)); + const auto outFilePath = + relativeProductBuildDir("byteArrayInfoPlist") + "/bytearrayInfoPlist-Info.plist.out"; + QFile file(outFilePath); + QVERIFY(file.exists()); + QVERIFY(file.open(QIODevice::ReadOnly)); + QCOMPARE(file.readAll(), "The data value"); +} + void TestBlackboxApple::codesign() { + QFETCH(int, expectedCount); QFETCH(bool, isBundle); QFETCH(bool, enableSigning); QFETCH(bool, multiArch); + QFETCH(bool, multiVariant); const auto xcodeVersion = findXcodeVersion(); + if (!xcodeVersion) + QSKIP("requires Xcode profile"); + QDir::setCurrent(testDataDir + "/codesign"); QbsRunParameters params(QStringList{"qbs.installPrefix:''"}); - params.arguments - << QStringLiteral("project.isBundle:%1").arg(isBundle ? "true" : "false"); - params.arguments - << QStringLiteral("project.enableSigning:%1").arg(enableSigning ? "true" : "false"); - if (multiArch) - params.arguments << QStringLiteral("project.xcodeVersion:") + xcodeVersion.toString(); + // the test can't use xcode module to determine version itself + params.arguments << QStringLiteral("project.xcodeVersion:") + xcodeVersion->toString(); + params.arguments << QStringLiteral("project.isBundle:%1").arg(isBundle ? "true" : "false"); + params.arguments << QStringLiteral("project.enableSigning:%1") + .arg(enableSigning ? "true" : "false"); + params.arguments << QStringLiteral("project.multiArch:%1").arg(multiArch ? "true" : "false"); + params.arguments << QStringLiteral("project.multiVariant:%1") + .arg(multiVariant ? "true" : "false"); rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); const int codeSignCount = QString::fromUtf8(m_qbsStdout).count(QStringLiteral("codesign")); - // We have 3 products, we have to sign each exactly once, even in the multiplexed case - QCOMPARE(codeSignCount, enableSigning ? 3 : 0); + QCOMPARE(codeSignCount, expectedCount); const auto appName = isBundle ? QStringLiteral("A.app") : QStringLiteral("A"); const auto appPath = defaultInstallRoot + "/" + appName; @@ -781,16 +784,25 @@ void TestBlackboxApple::codesign() void TestBlackboxApple::codesign_data() { + QTest::addColumn<int>("expectedCount"); QTest::addColumn<bool>("isBundle"); QTest::addColumn<bool>("enableSigning"); QTest::addColumn<bool>("multiArch"); - - QTest::newRow("bundle, unsigned") << true << false << false; - QTest::newRow("standalone, unsigned") << false << false << false; - QTest::newRow("bundle, signed") << true << true << false; - QTest::newRow("standalone, signed") << false << true << false; - QTest::newRow("bundle, signed, multiarch") << true << true << true; - QTest::newRow("standalone, signed, multiarch") << false << true << true; + QTest::addColumn<bool>("multiVariant"); + + QTest::newRow("standalone, unsigned") << 0 << false << false << false << false; + QTest::newRow("bundle, unsigned") << 0 << true << false << false << false; + QTest::newRow("standalone, signed") << 3 << false << true << false << false; + QTest::newRow("bundle, signed") << 3 << true << true << false << false; + // here we only sign the resulting lipo artifact + QTest::newRow("standalone, signed, multiarch") << 3 << false << true << true << false; + QTest::newRow("bundle, signed, multiarch") << 3 << true << true << true << false; + // here we sign all artifacts + QTest::newRow("standalone, signed, multivariant") << 15 << false << true << false << true; + QTest::newRow("bundle, signed, multivariant") << 15 << true << true << false << true; + QTest::newRow("standalone, signed, multiarch, multivariant") + << 15 << false << true << true << true; + QTest::newRow("bundle, signed, multiarch, multivariant") << 15 << true << true << true << true; } void TestBlackboxApple::deploymentTarget() @@ -803,6 +815,9 @@ void TestBlackboxApple::deploymentTarget() QDir::setCurrent(testDataDir + "/deploymentTarget"); + if (!findXcode()) + QSKIP("requires Xcode profile"); + QbsRunParameters params; params.arguments = QStringList() << "--command-echo-mode" @@ -1023,6 +1038,7 @@ void TestBlackboxApple::infoPlist() if (!content.contains(QStringLiteral("SDKROOT"))) { // macOS-specific values QCOMPARE(content.value("LSMinimumSystemVersion"), QStringLiteral("10.7")); QCOMPARE(content.value("NSPrincipalClass"), QStringLiteral("NSApplication")); + QCOMPARE(content.value(QStringLiteral("NSSupportsAutomaticGraphicsSwitching")), true); } else { // QBS-1447: UIDeviceFamily was set to a string instead of an array const auto family = content.value(QStringLiteral("UIDeviceFamily")); @@ -1108,6 +1124,9 @@ void TestBlackboxApple::overrideInfoPlist() void TestBlackboxApple::xcode() { + if (!findXcode()) + QSKIP("requires Xcode profile"); + QProcess xcodeSelect; xcodeSelect.start("xcode-select", QStringList() << "--print-path"); QVERIFY2(xcodeSelect.waitForStarted(), qPrintable(xcodeSelect.errorString())); @@ -1124,7 +1143,7 @@ void TestBlackboxApple::xcode() QVERIFY2(xcodebuildShowSdks.exitCode() == 0, qPrintable(xcodebuildShowSdks.readAllStandardError().constData())); const auto lines = QString::fromLocal8Bit(xcodebuildShowSdks.readAllStandardOutput().trimmed()) - .split('\n', QBS_SKIP_EMPTY_PARTS); + .split('\n', Qt::SkipEmptyParts); for (const QString &line : lines) { static const std::regex regexp("^.+\\s+\\-sdk\\s+([a-z]+)([0-9]+\\.[0-9]+)$"); const auto ln = line.toStdString(); @@ -1160,7 +1179,7 @@ void TestBlackboxApple::xcode() QTEST_MAIN(TestBlackboxApple) -QVariantMap TestBlackboxApple::findXcode(int *status) +std::optional<QVariantMap> TestBlackboxApple::findXcode(int *status) { QTemporaryDir temp; QbsRunParameters params = QStringList({"-f", testDataDir + "/find/find-xcode.qbs"}); @@ -1172,10 +1191,16 @@ QVariantMap TestBlackboxApple::findXcode(int *status) + "/xcode.json"); if (!file.open(QIODevice::ReadOnly)) return {}; - return QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); + auto result = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); + if (!result["present"].toBool()) + return {}; + return result; } -qbs::Version TestBlackboxApple::findXcodeVersion() +std::optional<qbs::Version> TestBlackboxApple::findXcodeVersion() { - return qbs::Version::fromString(findXcode().value("version").toString()); + const auto xcode = findXcode(); + if (!xcode) + return {}; + return qbs::Version::fromString(xcode->value("version").toString()); } diff --git a/tests/auto/blackbox/tst_blackboxapple.h b/tests/auto/blackbox/tst_blackboxapple.h index 32eee2432..a51414917 100644 --- a/tests/auto/blackbox/tst_blackboxapple.h +++ b/tests/auto/blackbox/tst_blackboxapple.h @@ -31,6 +31,8 @@ #include "tst_blackboxbase.h" +#include <optional> + namespace qbs { class Version; } // namespace qbs @@ -55,6 +57,7 @@ private slots: void assetCatalogsMultiple(); void bundleStructure(); void bundleStructure_data(); + void byteArrayInfoPlist(); void codesign(); void codesign_data(); void deploymentTarget(); @@ -71,8 +74,8 @@ private slots: void xcode(); private: - QVariantMap findXcode(int *status = nullptr); - qbs::Version findXcodeVersion(); + std::optional<QVariantMap> findXcode(int *status = nullptr); + std::optional<qbs::Version> findXcodeVersion(); }; #endif // TST_BLACKBOXAPPLE_H diff --git a/tests/auto/blackbox/tst_blackboxbase.cpp b/tests/auto/blackbox/tst_blackboxbase.cpp index ed0b90b55..317a6b663 100644 --- a/tests/auto/blackbox/tst_blackboxbase.cpp +++ b/tests/auto/blackbox/tst_blackboxbase.cpp @@ -104,6 +104,8 @@ int TestBlackboxBase::runQbs(const QbsRunParameters ¶ms) qDebug("%s", qPrintable(process.errorString())); } exitCode = -1; + } else if (m_qbsStdout.contains("Memory leak:")) { + exitCode = 27; } else { exitCode = process.exitCode(); } @@ -219,7 +221,7 @@ void TestBlackboxBase::validateTestProfile() QString TestBlackboxBase::findExecutable(const QStringList &fileNames) { const QStringList path = QString::fromLocal8Bit(qgetenv("PATH")) - .split(HostOsInfo::pathListSeparator(), QBS_SKIP_EMPTY_PARTS); + .split(HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts); for (const QString &fileName : fileNames) { QFileInfo fi(fileName); @@ -272,3 +274,16 @@ qbs::Version TestBlackboxBase::qmakeVersion(const QString &qmakeFilePath) qDebug() << "qmake '" << qmakeFilePath << "' version is not valid."; return version; } + +bool waitForProcessSuccess(QProcess &p, int msecs) +{ + if (!p.waitForStarted(msecs) || !p.waitForFinished(msecs)) { + qDebug() << p.errorString(); + return false; + } + if (p.exitCode() != 0) { + qDebug() << p.readAllStandardError(); + return false; + } + return true; +} diff --git a/tests/auto/blackbox/tst_blackboxbase.h b/tests/auto/blackbox/tst_blackboxbase.h index d020b7cd9..5733cacd7 100644 --- a/tests/auto/blackbox/tst_blackboxbase.h +++ b/tests/auto/blackbox/tst_blackboxbase.h @@ -90,6 +90,8 @@ public: public slots: virtual void initTestCase(); + static QString findExecutable(const QStringList &fileNames); + protected: virtual void validateTestProfile(); @@ -99,7 +101,6 @@ protected: static QByteArray unifiedLineEndings(const QByteArray &ba); static void sanitizeOutput(QByteArray *ba); 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); @@ -113,4 +114,6 @@ protected: int m_needsQt = false; }; +bool waitForProcessSuccess(QProcess &p, int msecs = 30000); + #endif // TST_BLACKBOXBASE_H diff --git a/tests/auto/blackbox/tst_blackboxexamples.cpp b/tests/auto/blackbox/tst_blackboxexamples.cpp index b6a26b7f3..13ccb7796 100644 --- a/tests/auto/blackbox/tst_blackboxexamples.cpp +++ b/tests/auto/blackbox/tst_blackboxexamples.cpp @@ -82,6 +82,7 @@ void TestBlackboxExamples::examples_data() auto examples = collectExamples(testDataDir); examples.append(collectExamples(testDataDir + "/protobuf")); + examples.append(collectExamples(testDataDir + "/flatbuffers")); std::sort(examples.begin(), examples.end()); for (const auto &example: examples) { diff --git a/tests/auto/blackbox/tst_blackboxjava.cpp b/tests/auto/blackbox/tst_blackboxjava.cpp index 9495ab1b7..4ddd6cdda 100644 --- a/tests/auto/blackbox/tst_blackboxjava.cpp +++ b/tests/auto/blackbox/tst_blackboxjava.cpp @@ -39,7 +39,9 @@ using qbs::Internal::HostOsInfo; using qbs::Profile; -TestBlackboxJava::TestBlackboxJava() : TestBlackboxBase (SRCDIR "/testdata-java", "blackbox-java") +TestBlackboxJava::TestBlackboxJava() + : TestBlackboxBase (SRCDIR "/testdata-java", "blackbox-java"), + m_blacklistedJdks(qgetenv("QBS_AUTOTEST_JDK_BLACKLIST")) { } @@ -96,7 +98,7 @@ void TestBlackboxJava::java() // Now check whether we correctly predicted the class file output paths. QCOMPARE(runQbs(QbsRunParameters("clean")), 0); - for (const QString &classFile : qAsConst(classFiles1)) { + for (const QString &classFile : std::as_const(classFiles1)) { QVERIFY2(!regularFileExists(classFile), qPrintable(classFile)); } @@ -148,8 +150,11 @@ void TestBlackboxJava::javaDependencyTracking() QDir::setCurrent(testDataDir + "/java"); QbsRunParameters rp; rp.arguments.push_back("--check-outputs"); - if (!jdkPath.isEmpty()) + if (!jdkPath.isEmpty()) { + if (m_blacklistedJdks.contains(jdkPath)) + QSKIP("skipping blacklisted JDK"); rp.arguments << ("modules.java.jdkPath:" + jdkPath); + } if (!javaVersion.isEmpty()) rp.arguments << ("modules.java.languageVersion:'" + javaVersion + "'"); rmDirR(relativeBuildDir()); @@ -170,7 +175,7 @@ void TestBlackboxJava::javaDependencyTracking_data() auto getSpecificJdkVersion = [](const QString &jdkVersion) -> QString { if (HostOsInfo::isMacosHost()) { QProcess java_home; - java_home.start("/usr/libexec/java_home", QStringList() << "--version" << jdkVersion); + java_home.start("/usr/libexec/java_home", {"--version", jdkVersion, "--failfast"}); java_home.waitForFinished(); if (java_home.exitStatus() == QProcess::NormalExit && java_home.exitCode() == 0) return QString::fromLocal8Bit(java_home.readAllStandardOutput().trimmed()); diff --git a/tests/auto/blackbox/tst_blackboxjava.h b/tests/auto/blackbox/tst_blackboxjava.h index 68d8a7f80..e770306df 100644 --- a/tests/auto/blackbox/tst_blackboxjava.h +++ b/tests/auto/blackbox/tst_blackboxjava.h @@ -43,6 +43,9 @@ private slots: void javaDependencyTracking(); void javaDependencyTracking_data(); void javaDependencyTrackingInnerClass(); + +private: + const QStringList m_blacklistedJdks; }; #endif // TST_BLACKBOX_H diff --git a/tests/auto/blackbox/tst_blackboxproviders.cpp b/tests/auto/blackbox/tst_blackboxproviders.cpp new file mode 100644 index 000000000..cf6594229 --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxproviders.cpp @@ -0,0 +1,443 @@ +/**************************************************************************** +** +** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** 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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "tst_blackboxproviders.h" + +#include "../shared.h" + +// #include <tools/hostosinfo.h> +// #include <tools/profile.h> +// #include <tools/qttools.h> + +// #include <QtCore/qdir.h> +// #include <QtCore/qregularexpression.h> + +// using qbs::Internal::HostOsInfo; +// using qbs::Profile; + +#define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) + +TestBlackboxProviders::TestBlackboxProviders() + : TestBlackboxBase(SRCDIR "/testdata-providers", "blackbox-providers") +{ +} + +void TestBlackboxProviders::allowedValues() +{ + QFETCH(QStringList, arguments); + QFETCH(bool, expectFailure); + + QDir::setCurrent(testDataDir + "/allowed-values"); + rmDirR(relativeBuildDir()); + QbsRunParameters params; + params.arguments = arguments; + params.expectFailure = expectFailure; + + QVERIFY2(runQbs(params) == int(expectFailure), m_qbsStderr); +} + +void TestBlackboxProviders::allowedValues_data() +{ + QTest::addColumn<QStringList>("arguments"); + QTest::addColumn<bool>("expectFailure"); + + QTest::newRow("invalid js value") << QStringList{} << true; + QTest::newRow("invalid variant value") + << QStringList{"moduleProviders.provider.aProperty:three"} << true; + QTest::newRow("valid variant value") + << QStringList{"moduleProviders.provider.aProperty:one"} << false; +} + +void TestBlackboxProviders::brokenProvider() +{ + QDir::setCurrent(testDataDir + "/broken-provider"); + QbsRunParameters params; + params.expectFailure = true; + QVERIFY(runQbs(params) != 0); + + QVERIFY(m_qbsStderr.contains("Error executing provider for module 'qbsothermodule'")); + QVERIFY(m_qbsStderr.contains("Error executing provider for module 'qbsmetatestmodule'")); + QCOMPARE(m_qbsStderr.count("This provider is broken"), 2); +} + +void TestBlackboxProviders::conanProvider() +{ + QFETCH(bool, generateConanFiles); + QFETCH(bool, successExpected); + + const auto executable = findExecutable({"conan"}); + if (executable.isEmpty()) + QSKIP("conan is not installed or not available in PATH."); + + const auto generator = QDir::homePath() + "/.conan2/extensions/generators/qbsdeps.py"; + if (!QFileInfo(generator).exists()) { + QSKIP( + "qbsdeps.py is not installed, call 'conan config install src/conan/ from qbs source'."); + } + + const auto profilePath = QDir::homePath() + "/.conan2/profiles/qbs-test"; + if (!QFileInfo(profilePath).exists()) + QSKIP("conan profile is not installed, run './scripts/setup-conan-profiles.sh'."); + + // install testlibdep first + QProcess conan; + QDir::setCurrent(testDataDir + "/conan-provider/testlibdep"); + conan.start(executable, {"create", ".", "--profile:all=qbs-test"}); + QVERIFY(waitForProcessSuccess(conan)); + + // install testlib second + QDir::setCurrent(testDataDir + "/conan-provider/testlib"); + conan.start(executable, {"create", ".", "--profile:all=qbs-test"}); + QVERIFY(waitForProcessSuccess(conan)); + + // install header lib third + QDir::setCurrent(testDataDir + "/conan-provider/testlibheader"); + conan.start(executable, {"create", ".", "--profile:all=qbs-test"}); + QVERIFY(waitForProcessSuccess(conan)); + + // now build an app using those libs + QDir::setCurrent(testDataDir + "/conan-provider"); + + rmDirR(relativeBuildDir()); + rmDirR("build"); + + if (generateConanFiles) { + QStringList arguments{ + "install", ".", "-g=QbsDeps", "--profile:all=qbs-test", "--output-folder=build"}; + QProcess conan; + conan.start(executable, arguments); + QVERIFY(waitForProcessSuccess(conan)); + } + + QbsRunParameters buildParams( + "build", + {"--force-probe-execution", + "moduleProviders.conan.installDirectory:" + QDir::currentPath() + "/build"}); + buildParams.expectFailure = !successExpected; + QCOMPARE(runQbs(buildParams) == 0, successExpected); +} + +void TestBlackboxProviders::conanProvider_data() +{ + QTest::addColumn<bool>("generateConanFiles"); + QTest::addColumn<bool>("successExpected"); + + QTest::addRow("no conan files generated") << false << false; + QTest::addRow("conan files generated") << true << true; +} + +void TestBlackboxProviders::moduleProviders() +{ + QDir::setCurrent(testDataDir + "/module-providers"); + + // Resolving in dry-run mode must not leave any data behind. + QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("-n"))), 0); + if (m_qbsStdout.contains("targetPlatform differs from hostPlatform")) + QSKIP("Cannot run binaries in cross-compiled build"); + QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 2); + QVERIFY(!QFile::exists(relativeBuildDir())); + + // Initial build. + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); + QVERIFY(QFile::exists(relativeBuildDir())); + QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 2); + QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("The MY_DEFINE is app1"), m_qbsStdout.constData()); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are Z and Y"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("The MY_DEFINE is app2"), m_qbsStdout.constData()); + + // Rebuild with overridden module provider config. The output for product 2 must change, + // but no setup script must be re-run, because both config values have already been + // handled in the first run. + const QStringList resolveArgs("moduleProviders.mygenerator.chooseLettersFrom:beginning"); + QCOMPARE(runQbs(QbsRunParameters("resolve", resolveArgs)), 0); + QVERIFY2(!m_qbsStdout.contains("Running setup script"), m_qbsStdout.constData()); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); + + // Forcing Probe execution triggers a re-run of the setup script. But only once, + // because the module provider config is the same now. + QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList(resolveArgs) + << "--force-probe-execution")), 0); + QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 1); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); + + // Now re-run without the module provider config override. Again, the setup script must + // run once, for the config value that was not present in the last run. + QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); + QCOMPARE(m_qbsStdout.count("Running setup script for mygenerator"), 1); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app1"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are A and B"), m_qbsStdout.constData()); + QCOMPARE(runQbs(QbsRunParameters("run", QStringList{"-p", "app2"})), 0); + QVERIFY2(m_qbsStdout.contains("The letters are Z and Y"), m_qbsStdout.constData()); +} + +// Checks regression - when loading 2 modules from the same provider, the second module should +// come from provider cache +void TestBlackboxProviders::moduleProvidersCache() +{ + QDir::setCurrent(testDataDir + "/module-providers-cache"); + + QbsRunParameters params("resolve", {"-v"}); + QCOMPARE(runQbs(params), 0); + const auto qbsmetatestmoduleMessage = "Re-checking for module \"qbsmetatestmodule\" with " + "newly added search paths from module provider"; + const auto qbsothermoduleMessage = "Re-checking for module \"qbsothermodule\" with " + "newly added search paths from module provider"; + QCOMPARE(m_qbsStderr.count(qbsmetatestmoduleMessage), 1); + QCOMPARE(m_qbsStderr.count(qbsothermoduleMessage), 1); + QCOMPARE(m_qbsStderr.count("Re-using provider \"provider_a\" from cache"), 1); + + // We didn't change providers, so both modules should come from cache. + params.arguments << "project.dummyProp:value"; + QCOMPARE(runQbs(params), 0); + QCOMPARE(m_qbsStderr.count(qbsmetatestmoduleMessage), 1); + QCOMPARE(m_qbsStderr.count(qbsothermoduleMessage), 1); + QCOMPARE(m_qbsStderr.count("Re-using provider \"provider_a\" from cache"), 2); +} + +void TestBlackboxProviders::nonEagerModuleProvider() +{ + QDir::setCurrent(testDataDir + "/non-eager-provider"); + + QbsRunParameters params("resolve"); + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains(("Running setup script for qbsmetatestmodule")), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("Running setup script for qbsothermodule")), m_qbsStdout); + QVERIFY2(!m_qbsStdout.contains(("Running setup script for nonexistentmodule")), m_qbsStdout); + + QVERIFY2(m_qbsStdout.contains(("p1.qbsmetatestmodule.prop: from_provider_a")), + m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("p1.qbsothermodule.prop: from_provider_a")), + m_qbsStdout); +} + +void TestBlackboxProviders::probeInModuleProvider() +{ + QDir::setCurrent(testDataDir + "/probe-in-module-provider"); + + QbsRunParameters params; + params.command = "build"; + params.arguments << "--force-probe-execution"; + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains("Running probe"), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.boolProp: true"), m_qbsStdout); + WAIT_FOR_NEW_TIMESTAMP(); + touch("probe-in-module-provider.qbs"); + QCOMPARE(runQbs(), 0); + QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.boolProp: true"), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.prop: \"value\""), m_qbsStdout); + QVERIFY2(!m_qbsStdout.contains("Running probe"), m_qbsStdout); +} + +// Tests whether it is possible to set providers properties in a Product or from command-line +void TestBlackboxProviders::providersProperties() +{ + QDir::setCurrent(testDataDir + "/providers-properties"); + + QbsRunParameters params("build"); + params.arguments = QStringList("moduleProviders.provider_b.someProp: \"first,second\""); + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains("p.qbsmetatestmodule.listProp: [\"someValue\"]"), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains( + "p.qbsothermodule.listProp: [\"first\",\"second\"]"), m_qbsStdout); +} + +// checks that we can set qbs module properties in providers and provider cache works corectly +void TestBlackboxProviders::qbsModulePropertiesInProviders() +{ + QDir::setCurrent(testDataDir + "/qbs-module-properties-in-providers"); + + QbsRunParameters params("resolve"); + + QCOMPARE(runQbs(params), 0); + + // We have 2 products in 2 configurations, but second product should use the cached value + // so we should have only 2 copies of the module, not 4. + QCOMPARE(m_qbsStdout.count("Running setup script for qbsmetatestmodule"), 2); + + // Check that products get correct values from modules + QVERIFY2(m_qbsStdout.contains(("product1.qbsmetatestmodule.prop: /sysroot1")), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("product1.qbsmetatestmodule.prop: /sysroot2")), m_qbsStdout); + + QVERIFY2(m_qbsStdout.contains(("product2.qbsmetatestmodule.prop: /sysroot1")), m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("product2.qbsmetatestmodule.prop: /sysroot2")), m_qbsStdout); +} + +void TestBlackboxProviders::qbsModuleProviders_data() +{ + QTest::addColumn<QStringList>("arguments"); + QTest::addColumn<QString>("firstProp"); + QTest::addColumn<QString>("secondProp"); + + QTest::newRow("default") << QStringList() << "from_provider_a" << "undefined"; + QTest::newRow("override") + << QStringList("projects.project.qbsModuleProviders:provider_b") + << "from_provider_b" + << "from_provider_b"; + QTest::newRow("override list a") + << QStringList("projects.project.qbsModuleProviders:provider_a,provider_b") + << "from_provider_a" + << "from_provider_b"; + QTest::newRow("override list b") + << QStringList("projects.project.qbsModuleProviders:provider_b,provider_a") + << "from_provider_b" + << "from_provider_b"; +} + +// Tests whether it is possible to set qbsModuleProviders in Product and Project items +// and that the order of providers results in correct priority +void TestBlackboxProviders::qbsModuleProviders() +{ + QFETCH(QStringList, arguments); + QFETCH(QString, firstProp); + QFETCH(QString, secondProp); + + QDir::setCurrent(testDataDir + "/qbs-module-providers"); + + QbsRunParameters params("resolve"); + params.arguments = arguments; + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains(("p1.qbsmetatestmodule.prop: " + firstProp).toUtf8()), + m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("p1.qbsothermodule.prop: " + secondProp).toUtf8()), + m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("p2.qbsmetatestmodule.prop: " + firstProp).toUtf8()), + m_qbsStdout); + QVERIFY2(m_qbsStdout.contains(("p2.qbsothermodule.prop: " + secondProp).toUtf8()), + m_qbsStdout); +} + +void TestBlackboxProviders::qbsModuleProvidersCliOverride_data() +{ + QTest::addColumn<QStringList>("arguments"); + QTest::addColumn<QString>("propertyValue"); + + QTest::newRow("default") << QStringList() << "undefined"; + QTest::newRow("project-wide") + << QStringList("project.qbsModuleProviders:provider_a") + << "from_provider_a"; + QTest::newRow("concrete project") + << QStringList("projects.innerProject.qbsModuleProviders:provider_a") + << "from_provider_a"; + QTest::newRow("concrete product") + << QStringList("products.product.qbsModuleProviders:provider_a") + << "from_provider_a"; + QTest::newRow("concrete project override project-wide") + << QStringList({ + "project.qbsModuleProviders:provider_a", + "projects.innerProject.qbsModuleProviders:provider_b"}) + << "from_provider_b"; + QTest::newRow("concrete product override project-wide") + << QStringList({ + "project.qbsModuleProviders:provider_a", + "products.product.qbsModuleProviders:provider_b"}) + << "from_provider_b"; +} + +// Tests possible use-cases how to override providers from command-line +void TestBlackboxProviders::qbsModuleProvidersCliOverride() +{ + QFETCH(QStringList, arguments); + QFETCH(QString, propertyValue); + + QDir::setCurrent(testDataDir + "/qbs-module-providers-cli-override"); + + QbsRunParameters params("resolve"); + params.arguments = arguments; + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains(("qbsmetatestmodule.prop: " + propertyValue).toUtf8()), + m_qbsStdout); +} + +void TestBlackboxProviders::qbsModuleProvidersCompatibility_data() +{ + QTest::addColumn<QStringList>("arguments"); + QTest::addColumn<QString>("propertyValue"); + + QTest::newRow("default") << QStringList() << "from_scoped_provider"; + QTest::newRow("scoped by name") << QStringList("project.qbsModuleProviders:qbsmetatestmodule") << "from_scoped_provider"; + QTest::newRow("named") << QStringList("project.qbsModuleProviders:named_provider") << "from_named_provider"; +} + +// Tests whether scoped providers can be used as named, i.e. new provider machinery +// is compatible with the old one +void TestBlackboxProviders::qbsModuleProvidersCompatibility() +{ + QFETCH(QStringList, arguments); + QFETCH(QString, propertyValue); + + QDir::setCurrent(testDataDir + "/qbs-module-providers-compatibility"); + + QbsRunParameters params("resolve"); + params.arguments = arguments; + QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStdout.contains(("qbsmetatestmodule.prop: " + propertyValue).toUtf8()), + m_qbsStdout); +} + +void TestBlackboxProviders::qbspkgconfigModuleProvider() +{ + QDir::setCurrent(testDataDir + "/qbspkgconfig-module-provider/libs"); + rmDirR(relativeBuildDir()); + + const auto commonParams = QbsRunParameters(QStringLiteral("install"), { + QStringLiteral("--install-root"), + QStringLiteral("install-root") + }); + auto dynamicParams = commonParams; + dynamicParams.arguments << "config:library" << "projects.libs.isBundle:false"; + QCOMPARE(runQbs(dynamicParams), 0); + + QDir::setCurrent(testDataDir + "/qbspkgconfig-module-provider"); + rmDirR(relativeBuildDir()); + + const auto sysroot = testDataDir + "/qbspkgconfig-module-provider/libs/install-root"; + + QbsRunParameters params; + params.arguments << "moduleProviders.qbspkgconfig.sysroot:" + sysroot; + QCOMPARE(runQbs(params), 0); +} + +void TestBlackboxProviders::removalVersion() +{ + QDir::setCurrent(testDataDir + "/removal-version"); + QCOMPARE(runQbs(), 0); + QVERIFY(m_qbsStderr.contains( + "Property 'deprecated' was scheduled for removal in version 2.2.0, but is still present")); +} + +QTEST_MAIN(TestBlackboxProviders) diff --git a/tests/auto/blackbox/tst_blackboxproviders.h b/tests/auto/blackbox/tst_blackboxproviders.h new file mode 100644 index 000000000..088cea6a3 --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxproviders.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2023 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** 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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef TST_BLACKBOXPROVIDERS_H +#define TST_BLACKBOXPROVIDERS_H + +#include "tst_blackboxbase.h" + +class TestBlackboxProviders : public TestBlackboxBase +{ + Q_OBJECT + +public: + TestBlackboxProviders(); + +private slots: + void allowedValues(); + void allowedValues_data(); + void brokenProvider(); + void conanProvider(); + void conanProvider_data(); + void moduleProviders(); + void moduleProvidersCache(); + void nonEagerModuleProvider(); + void probeInModuleProvider(); + void providersProperties(); + void qbsModulePropertiesInProviders(); + void qbsModuleProviders_data(); + void qbsModuleProviders(); + void qbsModuleProvidersCliOverride(); + void qbsModuleProvidersCliOverride_data(); + void qbsModuleProvidersCompatibility(); + void qbsModuleProvidersCompatibility_data(); + void qbspkgconfigModuleProvider(); + void removalVersion(); +}; + +#endif // TST_BLACKBOXPROVIDERS_H diff --git a/tests/auto/blackbox/tst_blackboxqt.cpp b/tests/auto/blackbox/tst_blackboxqt.cpp index 620cd2fa7..b083a97e8 100644 --- a/tests/auto/blackbox/tst_blackboxqt.cpp +++ b/tests/auto/blackbox/tst_blackboxqt.cpp @@ -38,7 +38,6 @@ #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) using qbs::Internal::HostOsInfo; -using qbs::Profile; TestBlackboxQt::TestBlackboxQt() : TestBlackboxBase (SRCDIR "/testdata-qt", "blackbox-qt") { @@ -240,7 +239,7 @@ void TestBlackboxQt::mixedBuildVariants() { QDir::setCurrent(testDataDir + "/mixed-build-variants"); const SettingsPtr s = settings(); - Profile profile(profileName(), s.get()); + qbs::Profile profile(profileName(), s.get()); if (profileToolchain(profile).contains("msvc")) { QbsRunParameters params; params.arguments << "qbs.buildVariant:debug"; @@ -376,6 +375,7 @@ void TestBlackboxQt::pkgconfigQt() QbsRunParameters params("build", {"-f", "pkgconfig-qt.qbs"}); // need to override prefix for the downloaded Qt params.environment.insert("PKG_CONFIG_QT5CORE_PREFIX", prefix); + params.environment.insert("PKG_CONFIG_QT6CORE_PREFIX", prefix); params.arguments << "moduleProviders.qbspkgconfig.extraPaths:" + pkgConfigPath; params.arguments << arguments; @@ -392,6 +392,22 @@ void TestBlackboxQt::pkgconfigQt_data() QTest::newRow("pkgconfig") << QStringList() << true; QTest::newRow("dummy") << QStringList({"products.p.qbsModuleProviders:dummyProvider"}) << false; + QTest::newRow("cross-compiling") + << QStringList({"moduleProviders.qbspkgconfig.sysroot:/some/fake/sysroot"}) << false; +} + +void TestBlackboxQt::pkgconfigNoQt() +{ + QDir::setCurrent(testDataDir + "/pkgconfig-qt"); + rmDirR(relativeBuildDir()); + QbsRunParameters params("build", {"-f", "pkgconfig-qt.qbs"}); + params.arguments << "moduleProviders.qbspkgconfig.libDirs:nonexistent"; + params.expectFailure = true; + + QCOMPARE(runQbs(params) == 0, false); + QVERIFY2(m_qbsStderr.contains("Dependency 'Qt.core' not found for product 'p'"), m_qbsStderr); + // QBS-1777: basic check for JS exceptions in case of missing Qt + QVERIFY2(!m_qbsStderr.contains("Error executing provider for module 'Qt.core'"), m_qbsStderr); } void TestBlackboxQt::pluginMetaData() @@ -467,22 +483,36 @@ void TestBlackboxQt::pluginSupport() } } +void TestBlackboxQt::qdoc() +{ + QDir::setCurrent(testDataDir + "/qdoc"); + QCOMPARE(runQbs(QbsRunParameters("resolve")), 0); + if (m_qbsStdout.contains("Qt is too old")) + QSKIP("Skip test since qdoc3 does not work properly"); + QCOMPARE(runQbs(), 0); + QVERIFY(QFileInfo(relativeProductBuildDir("QDoc Test") + "/qdoctest.qch").exists()); +} + void TestBlackboxQt::qmlDebugging() { QDir::setCurrent(testDataDir + "/qml-debugging"); QCOMPARE(runQbs(), 0); - const SettingsPtr s = settings(); - Profile profile(profileName(), s.get()); - if (!profileToolchain(profile).contains("gcc")) - return; + + const bool isGcc = m_qbsStdout.contains("is gcc: true"); + const bool isNotGcc = m_qbsStdout.contains("is gcc: false"); + if (isNotGcc) + QSKIP("The remainder of this test only applies to gcc"); + QVERIFY(isGcc); + QProcess nm; nm.start("nm", QStringList(relativeExecutableFilePath("debuggable-app"))); - if (nm.waitForStarted()) { // Let's ignore hosts without nm. - QVERIFY2(nm.waitForFinished(), qPrintable(nm.errorString())); - QVERIFY2(nm.exitCode() == 0, nm.readAllStandardError().constData()); - const QByteArray output = nm.readAllStandardOutput(); - QVERIFY2(output.toLower().contains("debugginghelper"), output.constData()); - } + if (!nm.waitForStarted()) + QSKIP("The remainder of this test requires nm"); + + QVERIFY2(nm.waitForFinished(), qPrintable(nm.errorString())); + QVERIFY2(nm.exitCode() == 0, nm.readAllStandardError().constData()); + const QByteArray output = nm.readAllStandardOutput(); + QVERIFY2(output.toLower().contains("debugginghelper"), output.constData()); } void TestBlackboxQt::qobjectInObjectiveCpp() @@ -611,10 +641,10 @@ void TestBlackboxQt::staticQtPluginLinking() QDir::setCurrent(testDataDir + "/static-qt-plugin-linking"); QCOMPARE(runQbs(QStringList("products.p.type:application")), 0); const bool isStaticQt = m_qbsStdout.contains("Qt is static"); - QVERIFY2(m_qbsStdout.contains("Creating static import") == isStaticQt, m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("creating static import") == isStaticQt, m_qbsStdout.constData()); QCOMPARE(runQbs(QbsRunParameters("resolve", QStringList("products.p.type:staticlibrary"))), 0); QCOMPARE(runQbs(), 0); - QVERIFY2(!m_qbsStdout.contains("Creating static import"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("creating static import"), m_qbsStdout.constData()); } void TestBlackboxQt::trackAddMocInclude() diff --git a/tests/auto/blackbox/tst_blackboxqt.h b/tests/auto/blackbox/tst_blackboxqt.h index 0ea8dd60b..da395b7d4 100644 --- a/tests/auto/blackbox/tst_blackboxqt.h +++ b/tests/auto/blackbox/tst_blackboxqt.h @@ -62,9 +62,11 @@ private slots: void pkgconfig(); void pkgconfigQt(); void pkgconfigQt_data(); + void pkgconfigNoQt(); void pluginMetaData(); void pluginSupport_data(); void pluginSupport(); + void qdoc(); void qmlDebugging(); void qobjectInObjectiveCpp(); void qmlTypeRegistrar_data(); diff --git a/tests/auto/blackbox/tst_blackboxtutorial.cpp b/tests/auto/blackbox/tst_blackboxtutorial.cpp new file mode 100644 index 000000000..49de448a1 --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxtutorial.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** 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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "tst_blackboxtutorial.h" + +#include <QtCore/qdir.h> +#include <QtCore/qdiriterator.h> + +static QStringList collectProjects(const QString &dirPath) +{ + QStringList result; + QDir dir(dirPath); + const auto subDirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); + for (const auto &subDir : subDirs) { + const auto path = dir.filePath(subDir); + if (!QFileInfo::exists(path + "/myproject.qbs")) + continue; + result.append(dir.relativeFilePath(path)); + } + return result; +} + +TestBlackboxTutorial::TestBlackboxTutorial() + : TestBlackboxBase(SRCDIR "/../../../tutorial/", "blackbox-tutorial") +{} + +void TestBlackboxTutorial::tutorial_data() +{ + QTest::addColumn<QString>("project"); + + const auto projects = collectProjects(testDataDir); + for (const auto &project : projects) { + QTest::newRow(project.toUtf8().data()) << project; + } +} + +void TestBlackboxTutorial::tutorial() +{ + QFETCH(QString, project); + + QVERIFY(QDir::setCurrent(testDataDir + "/" + project)); + QCOMPARE(runQbs(), 0); +} + +QTEST_MAIN(TestBlackboxTutorial) diff --git a/tests/auto/blackbox/tst_blackboxtutorial.h b/tests/auto/blackbox/tst_blackboxtutorial.h new file mode 100644 index 000000000..2e84d6a96 --- /dev/null +++ b/tests/auto/blackbox/tst_blackboxtutorial.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** 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 http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef TST_BLACKBOXTUTORIAL_H +#define TST_BLACKBOXTUTORIAL_H + +#include "tst_blackboxbase.h" + +class TestBlackboxTutorial : public TestBlackboxBase +{ + Q_OBJECT + +public: + TestBlackboxTutorial(); + +private slots: + void tutorial_data(); + void tutorial(); +}; + +#endif // TST_BLACKBOXTUTORIAL_H diff --git a/tests/auto/blackbox/tst_blackboxwindows.cpp b/tests/auto/blackbox/tst_blackboxwindows.cpp index 94257c062..57bd7f947 100644 --- a/tests/auto/blackbox/tst_blackboxwindows.cpp +++ b/tests/auto/blackbox/tst_blackboxwindows.cpp @@ -228,9 +228,9 @@ static bool haveWiX(const Profile &profile) << QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows Installer XML\\"); QStringList paths = QProcessEnvironment::systemEnvironment().value("PATH") - .split(HostOsInfo::pathListSeparator(), QBS_SKIP_EMPTY_PARTS); + .split(HostOsInfo::pathListSeparator(), Qt::SkipEmptyParts); - for (const QString &key : qAsConst(regKeys)) { + for (const QString &key : std::as_const(regKeys)) { const QStringList versions = QSettings(key, QSettings::NativeFormat).childGroups(); for (const QString &version : versions) { QSettings settings(key + version, QSettings::NativeFormat); @@ -240,7 +240,7 @@ static bool haveWiX(const Profile &profile) } } - for (const QString &path : qAsConst(paths)) { + for (const QString &path : std::as_const(paths)) { if (regularFileExists(QDir::fromNativeSeparators(path) + HostOsInfo::appendExecutableSuffix(QStringLiteral("/candle"))) && regularFileExists(QDir::fromNativeSeparators(path) + diff --git a/tests/auto/buildgraph/CMakeLists.txt b/tests/auto/buildgraph/CMakeLists.txt index 3d9d0348d..d8a9a4bbe 100644 --- a/tests/auto/buildgraph/CMakeLists.txt +++ b/tests/auto/buildgraph/CMakeLists.txt @@ -3,5 +3,5 @@ add_qbs_test(buildgraph tst_buildgraph.cpp tst_buildgraph.h DEPENDS - qbsscriptengine + qbsquickjsheaders ) diff --git a/tests/auto/buildgraph/buildgraph.pro b/tests/auto/buildgraph/buildgraph.pro deleted file mode 100644 index 9230bb748..000000000 --- a/tests/auto/buildgraph/buildgraph.pro +++ /dev/null @@ -1,13 +0,0 @@ -TARGET = tst_buildgraph - -SOURCES = tst_buildgraph.cpp -HEADERS = tst_buildgraph.h - -include(../auto.pri) -include(../../../src/app/shared/logging/logging.pri) -include(../../../src/lib/bundledlibs.pri) - -qbs_use_bundled_qtscript { - CONFIG += qbs_do_not_link_bundled_qtscript - include(../../../src/lib/scriptengine/use_scriptengine.pri) -} diff --git a/tests/auto/cmdlineparser/cmdlineparser.pro b/tests/auto/cmdlineparser/cmdlineparser.pro deleted file mode 100644 index a95676be5..000000000 --- a/tests/auto/cmdlineparser/cmdlineparser.pro +++ /dev/null @@ -1,7 +0,0 @@ -TARGET = tst_cmdlineparser - -SOURCES = tst_cmdlineparser.cpp ../../../src/app/qbs/qbstool.cpp - -include(../auto.pri) -include(../../../src/app/qbs/parser/parser.pri) -include(../../../src/app/shared/logging/logging.pri) diff --git a/tests/auto/cmdlineparser/tst_cmdlineparser.cpp b/tests/auto/cmdlineparser/tst_cmdlineparser.cpp index f617d41c7..6a8b44f89 100644 --- a/tests/auto/cmdlineparser/tst_cmdlineparser.cpp +++ b/tests/auto/cmdlineparser/tst_cmdlineparser.cpp @@ -26,6 +26,8 @@ ** ****************************************************************************/ +#include "../shared.h" + #include <app/qbs/parser/commandlineparser.h> #include <app/shared/logging/consolelogger.h> #include <tools/buildoptions.h> @@ -55,6 +57,25 @@ private slots: m_fileArgs = QStringList() << "-f" << m_projectFile.fileName(); } + void testResolve_data() + { + QTest::addColumn<QStringList>("args"); + QTest::addColumn<int>("expectedJobCount"); + + QTest::newRow("default job count") << QStringList() << BuildOptions::defaultMaxJobCount(); + QTest::newRow("explicit job count") << QStringList("-j5") << 5; + } + void testResolve() + { + QFETCH(QStringList, args); + QFETCH(int, expectedJobCount); + + CommandLineParser parser; + QVERIFY(parser.parseCommandLine(QStringList("resolve") << args << m_fileArgs)); + QCOMPARE(parser.command(), ResolveCommandType); + QCOMPARE(parser.jobCount(profileName()), expectedJobCount); + } + void testValidCommandLine() { QStringList args; diff --git a/tests/auto/language/CMakeLists.txt b/tests/auto/language/CMakeLists.txt index b008f52d7..9c04b6c8d 100644 --- a/tests/auto/language/CMakeLists.txt +++ b/tests/auto/language/CMakeLists.txt @@ -2,7 +2,8 @@ add_qbs_test(language DEFINES "QBS_VERSION=\"${QBS_VERSION}\"" DEPENDS - qbsscriptengine + qbsquickjsheaders + Qt6Core5Compat SOURCES tst_language.cpp tst_language.h diff --git a/tests/auto/language/language.pro b/tests/auto/language/language.pro deleted file mode 100644 index cdb067195..000000000 --- a/tests/auto/language/language.pro +++ /dev/null @@ -1,24 +0,0 @@ -TARGET = tst_language - -SOURCES = tst_language.cpp -HEADERS = tst_language.h - -include(../auto.pri) -include(../../../src/app/shared/logging/logging.pri) -include(../../../src/lib/bundledlibs.pri) - -!qbs_use_bundled_qtscript: QT += script - -DATA_DIRS = testdata - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES - -qbs_use_bundled_qtscript { - include(../../../src/lib/scriptengine/use_scriptengine.pri) -} diff --git a/tests/auto/language/testdata/additional-product-types.qbs b/tests/auto/language/testdata/additional-product-types.qbs index 686650f42..f84397da3 100644 --- a/tests/auto/language/testdata/additional-product-types.qbs +++ b/tests/auto/language/testdata/additional-product-types.qbs @@ -5,8 +5,8 @@ Product { Depends { name: "dummy" } Depends { name: "dummy2" } - property bool hasTag1: type.contains("tag1") - property bool hasTag2: type.contains("tag2") - property bool hasTag3: type.contains("tag3") - property bool hasTag4: type.contains("tag4") + property bool hasTag1: type.includes("tag1") + property bool hasTag2: type.includes("tag2") + property bool hasTag3: type.includes("tag3") + property bool hasTag4: type.includes("tag4") } diff --git a/tests/auto/language/testdata/erroneous/duplicate-multiplex-value.qbs b/tests/auto/language/testdata/duplicate-multiplex-value.qbs index 965fd36f7..24b246604 100644 --- a/tests/auto/language/testdata/erroneous/duplicate-multiplex-value.qbs +++ b/tests/auto/language/testdata/duplicate-multiplex-value.qbs @@ -1,5 +1,3 @@ -import qbs // FIXME: Don't remove this import because then the test fails! - Product { name: "p" multiplexByQbsProperties: "architectures" diff --git a/tests/auto/language/testdata/erroneous/duplicate-multiplex-value2.qbs b/tests/auto/language/testdata/duplicate-multiplex-value2.qbs index e6ed35d42..d6c057a9e 100644 --- a/tests/auto/language/testdata/erroneous/duplicate-multiplex-value2.qbs +++ b/tests/auto/language/testdata/duplicate-multiplex-value2.qbs @@ -1,5 +1,3 @@ -import qbs // FIXME: Don't remove this import because then the test fails! - Product { name: "p" multiplexByQbsProperties: ["architectures", "buildVariants", "architectures"] diff --git a/tests/auto/language/testdata/erroneous/dependency_cycle3a.qbs b/tests/auto/language/testdata/erroneous/dependency_cycle3a.qbs new file mode 100644 index 000000000..a0660c074 --- /dev/null +++ b/tests/auto/language/testdata/erroneous/dependency_cycle3a.qbs @@ -0,0 +1,11 @@ +Project { + Product { + name: "B" + Depends { productTypes: ["a"] } + } + Product { + type: ["a"] + name: "A" + Depends { name: "B" } + } +} diff --git a/tests/auto/language/testdata/erroneous/frozen-object-list.qbs b/tests/auto/language/testdata/erroneous/frozen-object-list.qbs new file mode 100644 index 000000000..8bbd2b413 --- /dev/null +++ b/tests/auto/language/testdata/erroneous/frozen-object-list.qbs @@ -0,0 +1,17 @@ + +Product { + Probe { + id: probe + property varList output + configure: { + output = [{"key": "value"}]; + found = true; + } + } + + property var test: { + var result = probe.output; + result.push({}); + return result; + } +} diff --git a/tests/auto/language/testdata/erroneous/frozen-object.qbs b/tests/auto/language/testdata/erroneous/frozen-object.qbs new file mode 100644 index 000000000..0f891d04b --- /dev/null +++ b/tests/auto/language/testdata/erroneous/frozen-object.qbs @@ -0,0 +1,18 @@ + +Product { + Probe { + id: probe + property var output + configure: { + output = {"key": "value"} + found = true + } + } + + property var test: { + "use strict" + var result = probe.output; + result.key = "newValue"; + return result; + } +} diff --git a/tests/auto/language/testdata/erroneous/missing-js-file.qbs b/tests/auto/language/testdata/erroneous/missing-js-file.qbs new file mode 100644 index 000000000..a3274a35b --- /dev/null +++ b/tests/auto/language/testdata/erroneous/missing-js-file.qbs @@ -0,0 +1,3 @@ +Product { + Depends { name: "missing-js-file-module" } +} diff --git a/tests/auto/language/testdata/erroneous/module-property-binding-in-project.qbs b/tests/auto/language/testdata/erroneous/module-property-binding-in-project.qbs new file mode 100644 index 000000000..667088c17 --- /dev/null +++ b/tests/auto/language/testdata/erroneous/module-property-binding-in-project.qbs @@ -0,0 +1,3 @@ +Project { + qbs.sysroot: "/" +} diff --git a/tests/auto/language/testdata/erroneous/module-with-id.qbs b/tests/auto/language/testdata/erroneous/module-with-id.qbs new file mode 100644 index 000000000..5b980100f --- /dev/null +++ b/tests/auto/language/testdata/erroneous/module-with-id.qbs @@ -0,0 +1,4 @@ +Product { + name: "p" + Depends { name: "module-with-id" } +} diff --git a/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file-module.qbs b/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file-module.qbs new file mode 100644 index 000000000..31302b5c2 --- /dev/null +++ b/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file-module.qbs @@ -0,0 +1,3 @@ +import "missing-js-file.js" as MissingJsFile + +Module { } diff --git a/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file.js b/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file.js new file mode 100644 index 000000000..b66048a8f --- /dev/null +++ b/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file.js @@ -0,0 +1 @@ +var userfile = require("javascriptfile.js") diff --git a/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithId.qbs b/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithId.qbs new file mode 100644 index 000000000..d20b96784 --- /dev/null +++ b/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithId.qbs @@ -0,0 +1 @@ +ModuleWithIdParent { id: foo } diff --git a/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithIdParent.qbs b/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithIdParent.qbs new file mode 100644 index 000000000..5e45122de --- /dev/null +++ b/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithIdParent.qbs @@ -0,0 +1 @@ +Module {} diff --git a/tests/auto/language/testdata/erroneous/original-in-export-item.qbs b/tests/auto/language/testdata/erroneous/original-in-export-item.qbs index 06adeb111..c83601cfb 100644 --- a/tests/auto/language/testdata/erroneous/original-in-export-item.qbs +++ b/tests/auto/language/testdata/erroneous/original-in-export-item.qbs @@ -1,5 +1,3 @@ -import qbs // FIXME: Don't remove this import because then the test fails! - Project { Product { name: "a" diff --git a/tests/auto/language/testdata/erroneous/original-in-export-item2.qbs b/tests/auto/language/testdata/erroneous/original-in-export-item2.qbs index 68b83118f..1c9f3de4b 100644 --- a/tests/auto/language/testdata/erroneous/original-in-export-item2.qbs +++ b/tests/auto/language/testdata/erroneous/original-in-export-item2.qbs @@ -1,5 +1,3 @@ -import qbs // FIXME: Don't remove this import because then the test fails! - Project { Product { name: "a" diff --git a/tests/auto/language/testdata/erroneous/original-in-export-item3.qbs b/tests/auto/language/testdata/erroneous/original-in-export-item3.qbs index 30b30dd0e..d23ad0a08 100644 --- a/tests/auto/language/testdata/erroneous/original-in-export-item3.qbs +++ b/tests/auto/language/testdata/erroneous/original-in-export-item3.qbs @@ -1,5 +1,3 @@ -import qbs // FIXME: Don't remove this import because then the test fails! - Project { Product { name: "a" diff --git a/tests/auto/language/testdata/erroneous/properties-item-with-invalid-condition.qbs b/tests/auto/language/testdata/erroneous/properties-item-with-invalid-condition.qbs index 5b1a41f1b..0b48731ae 100644 --- a/tests/auto/language/testdata/erroneous/properties-item-with-invalid-condition.qbs +++ b/tests/auto/language/testdata/erroneous/properties-item-with-invalid-condition.qbs @@ -1,7 +1,7 @@ Product { Depends { name: "cpp" } Properties { - condition: cpp.nonexistingproperty.contains("somevalue") + condition: cpp.nonexistingproperty.includes("somevalue") cpp.defines: ["ABC"] } } diff --git a/tests/auto/language/testdata/getNativeSetting.qbs b/tests/auto/language/testdata/getNativeSetting.qbs index c8126bb10..73af01316 100644 --- a/tests/auto/language/testdata/getNativeSetting.qbs +++ b/tests/auto/language/testdata/getNativeSetting.qbs @@ -7,11 +7,11 @@ Project { Product { name: "p1" targetName: { - if (Host.os().contains("macos")) { + if (Host.os().includes("macos")) { return Utilities.getNativeSetting("/System/Library/CoreServices/SystemVersion.plist", "ProductName"); - } else if (Host.os().contains("windows")) { + } else if (Host.os().includes("windows")) { var productName = Utilities.getNativeSetting("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion", "ProductName"); - if (productName.contains("Windows")) { + if (productName.includes("Windows")) { return "Windows"; } return undefined; diff --git a/tests/auto/language/testdata/groupconditions.qbs b/tests/auto/language/testdata/groupconditions.qbs index b7f383d45..4f55db9cd 100644 --- a/tests/auto/language/testdata/groupconditions.qbs +++ b/tests/auto/language/testdata/groupconditions.qbs @@ -43,7 +43,7 @@ Project { Product { name: "condition_accessing_module_property" Group { - condition: qbs.targetOS.contains("narf") + condition: qbs.targetOS.includes("narf") files: ["main.cpp"] qbs.install: false } diff --git a/tests/auto/language/testdata/invalid-prop-on-non-required-module/invalid-prop-on-non-required-module.qbs b/tests/auto/language/testdata/invalid-prop-on-non-required-module/invalid-prop-on-non-required-module.qbs new file mode 100644 index 000000000..80ae6ad93 --- /dev/null +++ b/tests/auto/language/testdata/invalid-prop-on-non-required-module/invalid-prop-on-non-required-module.qbs @@ -0,0 +1,19 @@ +Project { + property bool useExistingModule + + Product { + name: "a" + condition: project.useExistingModule + Depends { name: "deploader" } + Depends { name: "dep" } + dep.nosuchprop: true + } + + Product { + name: "b" + condition: !project.useExistingModule + Depends { name: "deploader" } + Depends { name: "random"; required: false } + random.nosuchprop: true + } +} diff --git a/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/dep/dep.qbs b/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/dep/dep.qbs new file mode 100644 index 000000000..5e45122de --- /dev/null +++ b/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/dep/dep.qbs @@ -0,0 +1 @@ +Module {} diff --git a/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/deploader/deploader.qbs b/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/deploader/deploader.qbs new file mode 100644 index 000000000..15a1b5309 --- /dev/null +++ b/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/deploader/deploader.qbs @@ -0,0 +1,7 @@ +Module { + // This indirection exists to properly model QBS-1776. + // "deploader" corresponds to "bundle", and "dep" corresponds to "codesign" + Depends { condition: project.useExistingModule; name: "dep"; required: false } + + Depends { condition: !project.useExistingModule; name: "random"; required: false } +} diff --git a/tests/auto/language/testdata/jsextensions.js b/tests/auto/language/testdata/jsextensions.js index df74a263b..5c5821e86 100644 --- a/tests/auto/language/testdata/jsextensions.js +++ b/tests/auto/language/testdata/jsextensions.js @@ -57,9 +57,9 @@ var a = ["one", "two", "three"]; initTestContext("Array.prototype.contains"); for (var k in a) verify(k !== "contains"); -verify(a.contains("one")); -verify(a.contains("two")); -verify(a.contains("three")); -verify(!a.contains("four")); +verify(a.includes("one")); +verify(a.includes("two")); +verify(a.includes("three")); +verify(!a.includes("four")); })() // END function wrapper diff --git a/tests/auto/language/testdata/local-profile-as-top-level-profile.qbs b/tests/auto/language/testdata/local-profile-as-top-level-profile.qbs new file mode 100644 index 000000000..9bca3c599 --- /dev/null +++ b/tests/auto/language/testdata/local-profile-as-top-level-profile.qbs @@ -0,0 +1,7 @@ +Product { + Profile { + name: "test-profile" + qbs.architecture: "arm" + qbs.targetPlatform: "macos" + } +} diff --git a/tests/auto/language/testdata/erroneous/module-depends-on-product.qbs b/tests/auto/language/testdata/module-depends-on-product.qbs index a7db9e036..a7db9e036 100644 --- a/tests/auto/language/testdata/erroneous/module-depends-on-product.qbs +++ b/tests/auto/language/testdata/module-depends-on-product.qbs diff --git a/tests/auto/language/testdata/module-name-collisions/complex-collision.qbs b/tests/auto/language/testdata/module-name-collisions/complex-collision.qbs new file mode 100644 index 000000000..cd55aa946 --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/complex-collision.qbs @@ -0,0 +1,4 @@ +Product { + Depends { name: "prefix1.middle1" } + Depends { name: "prefix1.middle1.suffix1" } +} diff --git a/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/middle1.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/middle1.qbs new file mode 100644 index 000000000..5e45122de --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/middle1.qbs @@ -0,0 +1 @@ +Module {} diff --git a/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix1/suffix1.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix1/suffix1.qbs new file mode 100644 index 000000000..5e45122de --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix1/suffix1.qbs @@ -0,0 +1 @@ +Module {} diff --git a/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix2/suffix2.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix2/suffix2.qbs new file mode 100644 index 000000000..5e45122de --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix2/suffix2.qbs @@ -0,0 +1 @@ +Module {} diff --git a/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle2/suffix/suffix.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle2/suffix/suffix.qbs new file mode 100644 index 000000000..5e45122de --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle2/suffix/suffix.qbs @@ -0,0 +1 @@ +Module {} diff --git a/tests/auto/language/testdata/module-name-collisions/modules/prefix1/prefix1.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/prefix1.qbs new file mode 100644 index 000000000..84957060c --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/prefix1.qbs @@ -0,0 +1,2 @@ +Module { +} diff --git a/tests/auto/language/testdata/erroneous/modules/prefix1/suffix/suffix.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/suffix/suffix.qbs index 218a4feb7..218a4feb7 100644 --- a/tests/auto/language/testdata/erroneous/modules/prefix1/suffix/suffix.qbs +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/suffix/suffix.qbs diff --git a/tests/auto/language/testdata/module-name-collisions/modules/prefix2/prefix2.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix2/prefix2.qbs new file mode 100644 index 000000000..a5aaa6f8b --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix2/prefix2.qbs @@ -0,0 +1,3 @@ +Module { + Depends { name: "prefix2.suffix" } +} diff --git a/tests/auto/language/testdata/module-name-collisions/modules/prefix2/suffix/suffix.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix2/suffix/suffix.qbs new file mode 100644 index 000000000..84957060c --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix2/suffix/suffix.qbs @@ -0,0 +1,2 @@ +Module { +} diff --git a/tests/auto/language/testdata/module-name-collisions/no-collision1.qbs b/tests/auto/language/testdata/module-name-collisions/no-collision1.qbs new file mode 100644 index 000000000..e5a94ad66 --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/no-collision1.qbs @@ -0,0 +1,4 @@ +Product { + Depends { name: "prefix1.middle1.suffix1" } + Depends { name: "prefix1.middle1.suffix2" } +} diff --git a/tests/auto/language/testdata/module-name-collisions/no-collision2.qbs b/tests/auto/language/testdata/module-name-collisions/no-collision2.qbs new file mode 100644 index 000000000..664ec1729 --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/no-collision2.qbs @@ -0,0 +1,4 @@ +Product { + Depends { name: "prefix1.middle1" } + Depends { name: "prefix1.middle2.suffix" } +} diff --git a/tests/auto/language/testdata/erroneous/same-module-prefix1.qbs b/tests/auto/language/testdata/module-name-collisions/simple-collision1.qbs index 8aba31c2a..8aba31c2a 100644 --- a/tests/auto/language/testdata/erroneous/same-module-prefix1.qbs +++ b/tests/auto/language/testdata/module-name-collisions/simple-collision1.qbs diff --git a/tests/auto/language/testdata/erroneous/same-module-prefix2.qbs b/tests/auto/language/testdata/module-name-collisions/simple-collision2.qbs index 6679091c2..6679091c2 100644 --- a/tests/auto/language/testdata/erroneous/same-module-prefix2.qbs +++ b/tests/auto/language/testdata/module-name-collisions/simple-collision2.qbs diff --git a/tests/auto/language/testdata/module-parameters/module-parameters.qbs b/tests/auto/language/testdata/module-parameters/module-parameters.qbs new file mode 100644 index 000000000..48169d601 --- /dev/null +++ b/tests/auto/language/testdata/module-parameters/module-parameters.qbs @@ -0,0 +1,35 @@ +Project { + property bool overrideFromModule + property bool overrideFromExport + property bool overrideFromProduct + + Product { + name: "dep" + Export { + Depends { + name: "higher"; + condition: project.overrideFromExport + lower.param: "fromExportDepends" + } + Parameters { lower.param: "fromParameters" } + } + } + Product { + name: "main" + + Depends { + name: "dep" + condition: project.overrideFromProduct + lower.param: "fromProductDepends" + } + Depends { + name: "higher" + condition: project.overrideFromProduct + lower.param: "fromProductDepends" + } + Depends { name: "dep"; condition: !project.overrideFromProduct } + Depends { name: "higher"; condition: !project.overrideFromProduct } + Depends { name: "highest" } + Depends { name: "broken"; required: false } + } +} diff --git a/tests/auto/language/testdata/module-parameters/modules/broken/broken.qbs b/tests/auto/language/testdata/module-parameters/modules/broken/broken.qbs new file mode 100644 index 000000000..ae7b4c4ef --- /dev/null +++ b/tests/auto/language/testdata/module-parameters/modules/broken/broken.qbs @@ -0,0 +1,4 @@ +Module { + Depends { name: "higher"; lower.param: "shouldNeverAppear" } + validate: { throw "As the name indicates, this module is broken."; } +} diff --git a/tests/auto/language/testdata/module-parameters/modules/higher/higher.qbs b/tests/auto/language/testdata/module-parameters/modules/higher/higher.qbs new file mode 100644 index 000000000..006e05a93 --- /dev/null +++ b/tests/auto/language/testdata/module-parameters/modules/higher/higher.qbs @@ -0,0 +1,4 @@ +Module { + Depends { name: "lower" } + Parameters { lower.param: "fromParameters" } +} diff --git a/tests/auto/language/testdata/module-parameters/modules/highest/highest.qbs b/tests/auto/language/testdata/module-parameters/modules/highest/highest.qbs new file mode 100644 index 000000000..83b0a0a03 --- /dev/null +++ b/tests/auto/language/testdata/module-parameters/modules/highest/highest.qbs @@ -0,0 +1,7 @@ +Module { + Depends { + name: "higher" + condition: project.overrideFromModule + lower.param: "fromModuleDepends" + } +} diff --git a/tests/auto/language/testdata/module-parameters/modules/lower/lower.qbs b/tests/auto/language/testdata/module-parameters/modules/lower/lower.qbs new file mode 100644 index 000000000..11436ecd8 --- /dev/null +++ b/tests/auto/language/testdata/module-parameters/modules/lower/lower.qbs @@ -0,0 +1,3 @@ +Module { + Parameter { property string param: "origin" } +} diff --git a/tests/auto/language/testdata/modulepropertiesingroups.qbs b/tests/auto/language/testdata/modulepropertiesingroups.qbs index e3857bdf4..49f24c0ca 100644 --- a/tests/auto/language/testdata/modulepropertiesingroups.qbs +++ b/tests/auto/language/testdata/modulepropertiesingroups.qbs @@ -80,4 +80,13 @@ Project { } } } + + Product { + name: "module-property-in-group-condition" + Depends { name: "cpp" } + Group { + condition: qbs.architecture === "x86_64" + cpp.includePaths: "." + } + } } diff --git a/tests/auto/language/testdata/modules/broken/broken.qbs b/tests/auto/language/testdata/modules/broken/broken.qbs index 302573bbf..a80547340 100644 --- a/tests/auto/language/testdata/modules/broken/broken.qbs +++ b/tests/auto/language/testdata/modules/broken/broken.qbs @@ -1,5 +1,3 @@ -import qbs // FIXME: Don't remove this import because then the test fails! - Module { Probe { id: theProbe diff --git a/tests/auto/language/testdata/modules/dummy/dummy.qbs b/tests/auto/language/testdata/modules/dummy/dummy.qbs index b1791ac96..623abc413 100644 --- a/tests/auto/language/testdata/modules/dummy/dummy.qbs +++ b/tests/auto/language/testdata/modules/dummy/dummy.qbs @@ -16,7 +16,7 @@ DummyBase { property string zort: "zort in dummy" property pathList includePaths property path somePath - property stringList listProp: product.type.contains("blubb") ? ["123"] : ["456"] + property stringList listProp: product.type.includes("blubb") ? ["123"] : ["456"] property bool controllingProp: false property stringList listProp2: controllingProp diff --git a/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs b/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs index 746c7e37b..2764af9c2 100644 --- a/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs +++ b/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs @@ -1,11 +1,10 @@ Module { - id: qtcore property int versionMajor: 5 property int versionMinor: 0 property int versionPatch: 0 property string version: versionMajor.toString() + "." + versionMinor.toString() + "." + versionPatch.toString() property string coreProperty: "coreProperty" - property string coreVersion: qtcore.version + property string coreVersion: version property string zort: "zort in dummyqt.core" Depends { name: "dummy" } diff --git a/tests/auto/language/testdata/erroneous/modules/module-with-product-dependency/module-with-product-dependency.qbs b/tests/auto/language/testdata/modules/module-with-product-dependency/module-with-product-dependency.qbs index 5781bd6de..5781bd6de 100644 --- a/tests/auto/language/testdata/erroneous/modules/module-with-product-dependency/module-with-product-dependency.qbs +++ b/tests/auto/language/testdata/modules/module-with-product-dependency/module-with-product-dependency.qbs diff --git a/tests/auto/language/testdata/modules/multiple_backends/backend1.qbs b/tests/auto/language/testdata/modules/multiple_backends/backend1.qbs index 794c67827..4f78a89ae 100644 --- a/tests/auto/language/testdata/modules/multiple_backends/backend1.qbs +++ b/tests/auto/language/testdata/modules/multiple_backends/backend1.qbs @@ -1,4 +1,4 @@ Module { - condition: qbs.targetOS.contains("os1") + condition: qbs.targetOS.includes("os1") property string prop: "backend 1" } diff --git a/tests/auto/language/testdata/modules/multiple_backends/backend2.qbs b/tests/auto/language/testdata/modules/multiple_backends/backend2.qbs index 2073c4d0b..e7a44d4c7 100644 --- a/tests/auto/language/testdata/modules/multiple_backends/backend2.qbs +++ b/tests/auto/language/testdata/modules/multiple_backends/backend2.qbs @@ -1,5 +1,5 @@ Module { - condition: qbs.targetOS.contains("os2") + condition: qbs.targetOS.includes("os2") property string prop: "backend 2" property string backend2Prop } diff --git a/tests/auto/language/testdata/modules/multiple_backends/backend3.qbs b/tests/auto/language/testdata/modules/multiple_backends/backend3.qbs index 16228108b..762c12f20 100644 --- a/tests/auto/language/testdata/modules/multiple_backends/backend3.qbs +++ b/tests/auto/language/testdata/modules/multiple_backends/backend3.qbs @@ -1,5 +1,5 @@ Module { - condition: qbs.targetOS.contains("os2") && qbs.toolchain.contains("tc") + condition: qbs.targetOS.includes("os2") && qbs.toolchain.includes("tc") priority: 1 property string backend3Prop } diff --git a/tests/auto/language/testdata/probes-and-multiplexing.qbs b/tests/auto/language/testdata/probes-and-multiplexing.qbs new file mode 100644 index 000000000..38de08aee --- /dev/null +++ b/tests/auto/language/testdata/probes-and-multiplexing.qbs @@ -0,0 +1,15 @@ +Product { + multiplexByQbsProperties: "architectures" + qbs.architectures: ["x86", "x86_64", "arm"] + property string archFromProbe: theProbe.archOut + Probe { + id: theProbe + property string archIn: qbs.architecture + property string archOut + configure: { archOut = archIn; } + } + Group { + name: "theGroup" + qbs.sysroot: "/" + theProbe.archOut + } +} diff --git a/tests/auto/language/testdata/qbs-properties-in-project-condition.qbs b/tests/auto/language/testdata/qbs-properties-in-project-condition.qbs index 31f648233..9d27df254 100644 --- a/tests/auto/language/testdata/qbs-properties-in-project-condition.qbs +++ b/tests/auto/language/testdata/qbs-properties-in-project-condition.qbs @@ -1,5 +1,5 @@ Project { - condition: qbs.targetOS.contains("whatever") + condition: qbs.targetOS.includes("whatever") Product { name: "never reached" diff --git a/tests/auto/language/testdata/rfc1034identifier.qbs b/tests/auto/language/testdata/rfc1034identifier.qbs index 4d320f899..e52dcc6b2 100644 --- a/tests/auto/language/testdata/rfc1034identifier.qbs +++ b/tests/auto/language/testdata/rfc1034identifier.qbs @@ -3,7 +3,7 @@ import qbs.Utilities CppApplication { name: Utilities.rfc1034Identifier("this!has@special#characters$uh-oh,Undersc0r3s_Are.Bad") Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.infoPlist: { return {"CFBundleIdentifier": "$(PRODUCT_NAME:rfc1034identifier)"}; } } } diff --git a/tests/auto/language/testdata/throw.qbs b/tests/auto/language/testdata/throw.qbs new file mode 100644 index 000000000..e9a97efb5 --- /dev/null +++ b/tests/auto/language/testdata/throw.qbs @@ -0,0 +1,16 @@ +Project { + property string throwType + property bool dummy: { + if (throwType === "bool") + throw true; + if (throwType === "int") + throw 43; + if (throwType === "string") + throw "an error"; + if (throwType === "list") + throw ["an", "error"]; + if (throwType === "object") + throw { result: "crash", reason: "overheating" }; + throw "type missing"; + } +} diff --git a/tests/auto/language/tst_language.cpp b/tests/auto/language/tst_language.cpp index cdcff99bd..6a3344842 100644 --- a/tests/auto/language/tst_language.cpp +++ b/tests/auto/language/tst_language.cpp @@ -53,6 +53,7 @@ #include <language/propertymapinternal.h> #include <language/scriptengine.h> #include <language/value.h> +#include <loader/projectresolver.h> #include <parser/qmljslexer_p.h> #include <parser/qmljsparser_p.h> #include <tools/scripttools.h> @@ -65,6 +66,7 @@ #include <tools/settings.h> #include <tools/stlutils.h> +#include <QtCore/qjsonobject.h> #include <QtCore/qprocess.h> #include <algorithm> @@ -84,6 +86,27 @@ static QString testProject(const char *fileName) { return testDataDir() + QLatin1Char('/') + QLatin1String(fileName); } +class JSSourceValueCreator +{ + FileContextPtr m_fileContext; + std::vector<std::unique_ptr<QString>> m_strings; +public: + JSSourceValueCreator(const FileContextPtr &fileContext) + : m_fileContext(fileContext) + { + } + + JSSourceValuePtr create(const QString &sourceCode) + { + JSSourceValuePtr value = JSSourceValue::create(); + value->setFile(m_fileContext); + auto str = std::make_unique<QString>(sourceCode); + value->setSourceCode(*str.get()); + m_strings.push_back(std::move(str)); + return value; + } +}; + TestLanguage::TestLanguage(ILogSink *logSink, Settings *settings) : m_logSink(logSink) , m_settings(settings) @@ -91,14 +114,9 @@ TestLanguage::TestLanguage(ILogSink *logSink, Settings *settings) { m_rand.seed(QTime::currentTime().msec()); qRegisterMetaType<QList<bool> >("QList<bool>"); - defaultParameters.setBuildRoot(m_tempDir.path() + "/buildroot"); - defaultParameters.setPropertyCheckingMode(ErrorHandlingMode::Strict); - defaultParameters.setSettingsDirectory(m_settings->baseDirectory()); } -TestLanguage::~TestLanguage() -{ -} +TestLanguage::~TestLanguage() = default; QHash<QString, ResolvedProductPtr> TestLanguage::productsFromProject(ResolvedProjectPtr project) { @@ -142,8 +160,7 @@ void TestLanguage::handleInitCleanupDataTags(const char *projectFileName, bool * *handled = true; bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject(projectFileName)); - project = loader->loadProject(defaultParameters); + resolveProject(projectFileName); QVERIFY(!!project); } catch (const ErrorInfo &e) { exceptionCaught = true; @@ -158,9 +175,31 @@ void TestLanguage::handleInitCleanupDataTags(const char *projectFileName, bool * } } +TopLevelProjectPtr TestLanguage::resolveProject(const char *relProjectFilePath) +{ + if (relProjectFilePath) + defaultParameters.setProjectFilePath(testProject(relProjectFilePath)); + defaultParameters.expandBuildConfiguration(); + ProjectResolver resolver(defaultParameters, m_engine.get(), m_logger); + return project = resolver.resolve(); +} + void TestLanguage::init() { + // clear caches, otherwise StoredVariantValues may end up being at the same address + // as the destroyed value + m_engine->reset(); m_logSink->setLogLevel(LoggerInfo); + defaultParameters = {}; + defaultParameters.setBuildRoot(m_tempDir.path() + "/buildroot"); + defaultParameters.setPropertyCheckingMode(ErrorHandlingMode::Strict); + defaultParameters.setSettingsDirectory(m_settings->baseDirectory()); + defaultParameters.setTopLevelProfile(profileName()); + defaultParameters.setMaxJobCount(1); + defaultParameters.setConfigurationName("default"); + defaultParameters.setEnvironment(QProcessEnvironment::systemEnvironment()); + defaultParameters.setSearchPaths({SRCDIR "/../../../share/qbs"}); + QVERIFY(m_tempDir.isValid()); } @@ -176,27 +215,15 @@ void TestLanguage::initTestCase() { m_logger = Logger(m_logSink); m_engine = ScriptEngine::create(m_logger, EvalContext::PropertyEvaluation); - loader = new Loader(m_engine.get(), m_logger); - loader->setSearchPaths(QStringList() - << (testDataDir() + "/../../../../share/qbs")); - defaultParameters.setTopLevelProfile(profileName()); - defaultParameters.setConfigurationName("default"); - defaultParameters.expandBuildConfiguration(); - defaultParameters.setEnvironment(QProcessEnvironment::systemEnvironment()); - QVERIFY(QFileInfo(m_wildcardsTestDirPath).isAbsolute()); -} -void TestLanguage::cleanupTestCase() -{ - delete loader; + QVERIFY(QFileInfo(m_wildcardsTestDirPath).isAbsolute()); } void TestLanguage::additionalProductTypes() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("additional-product-types.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("additional-product-types.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); const ResolvedProductConstPtr product = products.value("p"); @@ -217,8 +244,7 @@ void TestLanguage::baseProperty() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("baseproperty.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("baseproperty.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); @@ -235,10 +261,8 @@ void TestLanguage::baseProperty() void TestLanguage::baseValidation() { - qbs::SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("base-validate/base-validate.qbs")); try { - project = loader->loadProject(params); + resolveProject("base-validate/base-validate.qbs"); QVERIFY2(false, "exception expected"); } catch (const qbs::ErrorInfo &e) { QVERIFY2(e.toString().contains("Parent succeeded, child failed."), @@ -248,11 +272,9 @@ void TestLanguage::baseValidation() void TestLanguage::brokenDependencyCycle() { - qbs::SetupProjectParameters params = defaultParameters; QFETCH(QString, projectFileName); - params.setProjectFilePath(testProject(qPrintable(projectFileName))); try { - project = loader->loadProject(params); + resolveProject(qPrintable(projectFileName)); } catch (const qbs::ErrorInfo &e) { QVERIFY2(false, qPrintable(e.toString())); } @@ -269,12 +291,10 @@ void TestLanguage::buildConfigStringListSyntax() { bool exceptionCaught = false; try { - SetupProjectParameters parameters = defaultParameters; QVariantMap overriddenValues; overriddenValues.insert("project.someStrings", "foo,bar,baz"); - parameters.setOverriddenValues(overriddenValues); - parameters.setProjectFilePath(testProject("buildconfigstringlistsyntax.qbs")); - project = loader->loadProject(parameters); + defaultParameters.setOverriddenValues(overriddenValues); + resolveProject("buildconfigstringlistsyntax.qbs"); QVERIFY(!!project); QCOMPARE(project->projectProperties().value("someStrings").toStringList(), QStringList() << "foo" << "bar" << "baz"); @@ -289,9 +309,7 @@ void TestLanguage::builtinFunctionInSearchPathsProperty() { bool exceptionCaught = false; try { - SetupProjectParameters parameters = defaultParameters; - parameters.setProjectFilePath(testProject("builtinFunctionInSearchPathsProperty.qbs")); - QVERIFY(!!loader->loadProject(parameters)); + QVERIFY(resolveProject("builtinFunctionInSearchPathsProperty.qbs")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); @@ -303,11 +321,12 @@ void TestLanguage::chainedProbes() { bool exceptionCaught = false; try { - SetupProjectParameters parameters = defaultParameters; - parameters.setProjectFilePath(testProject("chained-probes/chained-probes.qbs")); - const TopLevelProjectConstPtr project = loader->loadProject(parameters); + resolveProject("chained-probes/chained-probes.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); + const QString prop1Val = project->products.front()->moduleProperties + ->moduleProperty("m", "prop1").toString(); + QCOMPARE(prop1Val, QLatin1String("probe1Val")); const QString prop2Val = project->products.front()->moduleProperties ->moduleProperty("m", "prop2").toString(); QCOMPARE(prop2Val, QLatin1String("probe1Valprobe2Val")); @@ -323,9 +342,7 @@ void TestLanguage::versionCompare() { bool exceptionCaught = false; try { - SetupProjectParameters parameters = defaultParameters; - parameters.setProjectFilePath(testProject("versionCompare.qbs")); - QVERIFY(!!loader->loadProject(parameters)); + QVERIFY(resolveProject("versionCompare.qbs")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); @@ -337,8 +354,7 @@ void TestLanguage::canonicalArchitecture() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("canonicalArchitecture.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("canonicalArchitecture.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value(QStringLiteral("x86")); @@ -354,8 +370,7 @@ void TestLanguage::rfc1034Identifier() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("rfc1034identifier.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("rfc1034identifier.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value(QStringLiteral("this-has-special-characters-" @@ -368,17 +383,47 @@ void TestLanguage::rfc1034Identifier() QCOMPARE(exceptionCaught, false); } +void TestLanguage::throwThings_data() +{ + QTest::addColumn<QString>("type"); + QTest::addColumn<QString>("result"); + QTest::addRow("bool") << "bool" << "true"; + QTest::addRow("int") << "int" << "43"; + QTest::addRow("string") << "string" << "an error"; + QTest::addRow("list") << "list" << R"([ + "an", + "error" +])"; + QTest::addRow("object") << "object" << R"({ + "reason": "overheating", + "result": "crash" +})"; +} + +void TestLanguage::throwThings() +{ + QFETCH(QString, type); + QFETCH(QString, result); + bool exceptionCaught = false; + try { + defaultParameters.setOverriddenValues({{"project.throwType", type}}); + resolveProject("throw.qbs"); + } catch (const ErrorInfo &e) { + exceptionCaught = true; + QVERIFY2(e.toString().contains(result), qPrintable(e.toString())); + } + QVERIFY(exceptionCaught); +} + void TestLanguage::conditionalDepends() { bool exceptionCaught = false; ResolvedProductPtr product; ResolvedModuleConstPtr dependency; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("conditionaldepends.qbs")); - params.setOverriddenValues({std::make_pair(QString("products." + defaultParameters.setOverriddenValues({std::make_pair(QString("products." "multilevel_module_props_overridden.dummy3.loadDummy"), true)}); - project = loader->loadProject(params); + resolveProject("conditionaldepends.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); @@ -477,17 +522,38 @@ void TestLanguage::conditionalDepends() QCOMPARE(exceptionCaught, false); } +void TestLanguage::convertStringList() +{ + FileContextPtr fileContext = FileContext::create(); + fileContext->setFilePath("/dev/null"); + JSSourceValueCreator sourceValueCreator(fileContext); + ItemPool pool; + Item *scope = Item::create(&pool, ItemType::Scope); + scope->setProperty("x", sourceValueCreator.create("[\"a\", \"b\"]")); + + Evaluator evaluator(m_engine.get()); + auto variantValue = evaluator.variantValue(scope, "x"); + // despite we have a stringList prop, we evaluate it as a QVariantList + QCOMPARE(variantValue.userType(), QMetaType::Type::QVariantList); + // and we have to convert it explicitly +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + variantValue.convert(QMetaType(QMetaType::QStringList)); +#else + variantValue.convert(QMetaType::QStringList); +#endif + QCOMPARE(variantValue.userType(), QMetaType::Type::QStringList); + QCOMPARE(variantValue, QStringList({"a", "b"})); +} + void TestLanguage::delayedError() { QFETCH(bool, productEnabled); try { QFETCH(QString, projectFileName); - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject(projectFileName.toLatin1())); QVariantMap overriddenValues; overriddenValues.insert("project.enableProduct", productEnabled); - params.setOverriddenValues(overriddenValues); - project = loader->loadProject(params); + defaultParameters.setOverriddenValues(overriddenValues); + resolveProject(projectFileName.toLatin1()); QCOMPARE(productEnabled, false); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); @@ -519,8 +585,6 @@ void TestLanguage::dependencyOnAllProfiles() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("dependencyOnAllProfiles.qbs")); TemporaryProfile p1("p1", m_settings); p1.p.setValue("qbs.architecture", "arch1"); TemporaryProfile p2("p2", m_settings); @@ -528,8 +592,8 @@ void TestLanguage::dependencyOnAllProfiles() QVariantMap overriddenValues; overriddenValues.insert("project.profile1", "p1"); overriddenValues.insert("project.profile2", "p2"); - params.setOverriddenValues(overriddenValues); - project = loader->loadProject(params); + defaultParameters.setOverriddenValues(overriddenValues); + resolveProject("dependencyOnAllProfiles.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(3)); const ResolvedProductConstPtr mainProduct = productsFromProject(project).value("main"); @@ -550,9 +614,7 @@ void TestLanguage::derivedSubProject() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("derived-sub-project/project.qbs")); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("derived-sub-project/project.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -567,9 +629,7 @@ void TestLanguage::disabledSubProject() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("disabled-subproject.qbs")); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("disabled-subproject.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 0); @@ -598,16 +658,14 @@ void TestLanguage::dottedNames() { QFETCH(bool, expectSuccess); try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("dotted-names/dotted-names.qbs")); QFETCH(bool, useProduct); QFETCH(bool, useModule); const QVariantMap overridden{ std::make_pair("projects.theProject.includeDottedProduct", useProduct), std::make_pair("projects.theProject.includeDottedModule", useModule) }; - params.setOverriddenValues(overridden); - TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(overridden); + resolveProject("dotted-names/dotted-names.qbs"); QVERIFY(expectSuccess); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); @@ -624,13 +682,44 @@ void TestLanguage::dottedNames() } } +void TestLanguage::duplicateMultiplexValues_data() +{ + QTest::addColumn<bool>("dummy"); + QTest::newRow("duplicate-multiplex-value") << true; + QTest::newRow("duplicate-multiplex-value2") << true; +} + +void TestLanguage::duplicateMultiplexValues() +{ + bool exceptionCaught = false; + try { + resolveProject(qPrintable(QString::fromLocal8Bit(QTest::currentDataTag()) + + QLatin1String(".qbs"))); + QVERIFY(project); + const std::vector<ResolvedProductPtr> products = project->allProducts(); + QCOMPARE(products.size(), 2); + bool x86 = false; + bool arm = false; + for (const ResolvedProductPtr &p : products) { + if (p->moduleProperties->moduleProperty("qbs", "architecture").toString() == "x86") + x86 = true; + else if (p->moduleProperties->moduleProperty("qbs", "architecture").toString() == "arm") + arm = true; + } + QVERIFY(x86); + QVERIFY(arm); + } catch (const ErrorInfo &e) { + exceptionCaught = true; + qDebug() << e.toString(); + } + QVERIFY(!exceptionCaught); +} + void TestLanguage::emptyJsFile() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("empty-js-file.qbs")); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("empty-js-file.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -645,14 +734,12 @@ void TestLanguage::enumerateProjectProperties() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("enum-project-props.qbs")); - auto project = loader->loadProject(params); + resolveProject("enum-project-props.qbs"); QVERIFY(!!project); auto products = productsFromProject(project); QCOMPARE(products.size(), 1); auto product = products.values().front(); - auto files = product->groups.front()->allFiles(); + auto files = product->groups.front()->files; QCOMPARE(product->groups.size(), size_t(1)); QCOMPARE(files.size(), size_t(1)); auto fileName = FileInfo::fileName(files.front()->absoluteFilePath); @@ -670,7 +757,7 @@ void TestLanguage::evalErrorInNonPresentModule_data() QTest::addColumn<QString>("errorMessage"); QTest::newRow("module required") - << true << "broken.qbs:4:5 Element at index 0 of list property 'broken' " + << true << "broken.qbs:2:5 Element at index 0 of list property 'broken' " "does not have string type"; QTest::newRow("module not required") << false << QString(); } @@ -680,19 +767,16 @@ void TestLanguage::evalErrorInNonPresentModule() QFETCH(bool, moduleRequired); QFETCH(QString, errorMessage); try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("eval-error-in-non-present-module.qbs")); QVariantMap overridden{std::make_pair("products.p.moduleRequired", moduleRequired)}; - params.setOverriddenValues(overridden); - TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(overridden); + resolveProject("eval-error-in-non-present-module.qbs"); QVERIFY(errorMessage.isEmpty()); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); const ResolvedProductPtr product = products.value("p"); QVERIFY(!!product); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { QVERIFY(!errorMessage.isEmpty()); QVERIFY2(e.toString().contains(errorMessage), qPrintable(e.toString())); } @@ -702,14 +786,12 @@ void TestLanguage::defaultValue() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("defaultvalue/egon.qbs")); QFETCH(QString, prop1Value); QVariantMap overridden; if (!prop1Value.isEmpty()) overridden.insert("modules.lower.prop1", prop1Value); - params.setOverriddenValues(overridden); - TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(overridden); + resolveProject("defaultvalue/egon.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 2); @@ -723,8 +805,7 @@ void TestLanguage::defaultValue() propertyValue = product->moduleProperties->property(propertyName); QFETCH(QVariant, expectedListPropValue); QCOMPARE(propertyValue.toStringList(), expectedListPropValue.toStringList()); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -759,10 +840,7 @@ void TestLanguage::environmentVariable() QProcessEnvironment origEnv = defaultParameters.environment(); // store orig environment defaultParameters.setEnvironment(env); - defaultParameters.setProjectFilePath(testProject("environmentvariable.qbs")); - project = loader->loadProject(defaultParameters); - - defaultParameters.setEnvironment(origEnv); // reset environment + resolveProject("environmentvariable.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); @@ -779,9 +857,7 @@ void TestLanguage::errorInDisabledProduct() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("error-in-disabled-product.qbs")); - auto project = loader->loadProject(params); + resolveProject("error-in-disabled-product.qbs"); QVERIFY(!!project); auto products = productsFromProject(project); QCOMPARE(products.size(), 5); @@ -805,11 +881,11 @@ void TestLanguage::erroneousFiles_data() QTest::newRow("importloop1") << "Loop detected when importing"; QTest::newRow("nonexistentouter") - << "Can't find variable: outer"; + << "'outer' is not defined"; QTest::newRow("invalid_file") << "does not exist"; QTest::newRow("invalid-parameter-rhs") - << "ReferenceError: Can't find variable: access"; + << "'access' is not defined"; QTest::newRow("invalid-parameter-type") << "Value assigned to property 'stringParameter' does not have type 'string'."; QTest::newRow("invalid_property_type") @@ -826,6 +902,8 @@ void TestLanguage::erroneousFiles_data() << "Cyclic dependencies detected."; QTest::newRow("dependency_cycle3") << "Cyclic dependencies detected."; + QTest::newRow("dependency_cycle3a") + << "Cyclic dependencies detected."; QTest::newRow("dependency_cycle4") << "Cyclic dependencies detected."; QTest::newRow("references_cycle") @@ -874,14 +952,10 @@ void TestLanguage::erroneousFiles_data() QTest::newRow("wrongQbsVersionFormat") << "The value '.*' of Project.minimumQbsVersion is not a valid version string."; QTest::newRow("properties-item-with-invalid-condition") - << "properties-item-with-invalid-condition.qbs:4:19.*TypeError: Result of expression " - "'cpp.nonexistingproperty'"; + << "properties-item-with-invalid-condition.qbs:4:19.*" + "cannot read property 'includes' of undefined"; QTest::newRow("misused-inherited-property") << "Binding to non-item property"; QTest::newRow("undeclared_property_in_Properties_item") << "Item 'blubb' is not declared"; - QTest::newRow("same-module-prefix1") << "The name of module 'prefix1' is equal to the first " - "component of the name of module 'prefix1.suffix'"; - QTest::newRow("same-module-prefix2") << "The name of module 'prefix2' is equal to the first " - "component of the name of module 'prefix2.suffix'"; QTest::newRow("conflicting-properties-in-export-items") << "Export item in inherited item redeclares property 'theProp' with different type."; QTest::newRow("invalid-property-option") @@ -889,15 +963,13 @@ void TestLanguage::erroneousFiles_data() QTest::newRow("missing-colon") << "Invalid item 'dummy.cxxFlags'. Did you mean to set a module property?"; QTest::newRow("syntax-error-in-probe") - << "syntax-error-in-probe.qbs:4:20.*ReferenceError"; + << "syntax-error-in-probe.qbs:4:20.*'fngkgsdjfgklkf' is not defined"; QTest::newRow("wrong-toplevel-item") << "wrong-toplevel-item.qbs:1:1.*The top-level item must be of type 'Project' or " "'Product', but it is of type 'Artifact'."; QTest::newRow("conflicting-module-instances") << "There is more than one equally prioritized candidate for module " "'conflicting-instances'."; - QTest::newRow("module-depends-on-product") - << "module-with-product-dependency.qbs:2:5.*Modules cannot depend on products."; QTest::newRow("overwrite-inherited-readonly-property") << "overwrite-inherited-readonly-property.qbs" ":2:21.*Cannot set read-only property 'readOnlyString'."; @@ -914,10 +986,10 @@ void TestLanguage::erroneousFiles_data() << "module-with-invalid-original.qbs:2:24.*The special value 'original' cannot be used " "on the right-hand side of a property declaration."; QTest::newRow("original-in-export-item") - << "original-in-export-item.qbs:7:32.*The special value 'original' cannot be used " + << "original-in-export-item.qbs:5:32.*The special value 'original' cannot be used " "on the right-hand side of a property declaration."; QTest::newRow("original-in-export-item2") - << "original-in-export-item2.qbs:6:9.*Item 'x.y' is not declared. Did you forget " + << "original-in-export-item2.qbs:4:9.*Item 'x.y' is not declared. Did you forget " "to add a Depends item"; QTest::newRow("original-in-export-item3") << "original-in-export-item3.qbs:6:9.*Item 'x.y' is not declared. Did you forget " @@ -937,13 +1009,15 @@ void TestLanguage::erroneousFiles_data() 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") - << "duplicate-multiplex-value2.qbs:3:1.*Duplicate entry 'architecture' in " - "Product.multiplexByQbsProperties."; QTest::newRow("invalid-references") << "invalid-references.qbs:2:17.*Cannot open '.*nosuchproject.qbs'"; + QTest::newRow("missing-js-file") + << "missing-js-file-module.qbs.*Cannot open '.*javascriptfile.js'"; + QTest::newRow("frozen-object") << "'key' is read-only"; + QTest::newRow("frozen-object-list") << "object is not extensible"; + QTest::newRow("module-property-binding-in-project") + << "Module properties cannot be set in Project items"; + QTest::newRow("module-with-id") << "Module items cannot have an id property"; } void TestLanguage::erroneousFiles() @@ -951,8 +1025,7 @@ void TestLanguage::erroneousFiles() QFETCH(QString, errorMessage); QString fileName = QString::fromLocal8Bit(QTest::currentDataTag()) + QLatin1String(".qbs"); try { - defaultParameters.setProjectFilePath(testProject("/erroneous/") + fileName); - loader->loadProject(defaultParameters); + resolveProject(qPrintable("/erroneous/" + fileName)); } catch (const ErrorInfo &e) { const QRegularExpression reg(errorMessage, QRegularExpression::DotMatchesEverythingOption); if (!e.toString().contains(reg)) { @@ -971,8 +1044,7 @@ void TestLanguage::exports() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("exports.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("exports.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 22); @@ -1017,6 +1089,7 @@ void TestLanguage::exports() product = products.value("B"); QVERIFY(!!product); QVERIFY(product->dependencies.empty()); + QCOMPARE(product->exportedModule.productDependencies, std::vector<QString>{"C"}); product = products.value("C"); QVERIFY(!!product); QVERIFY(product->dependencies.empty()); @@ -1085,8 +1158,7 @@ void TestLanguage::exports() || m->name == QString("broken_cycle2"), qPrintable(m->name)); } - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1097,8 +1169,7 @@ void TestLanguage::fileContextProperties() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("filecontextproperties.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("filecontextproperties.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); @@ -1144,14 +1215,12 @@ void TestLanguage::fileInProductAndModule() QFETCH(bool, addFileToProduct); QFETCH(bool, successExpected); try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("file-in-product-and-module.qbs")); - params.setOverriddenValues(QVariantMap{ + defaultParameters.setOverriddenValues(QVariantMap{ std::make_pair("modules.module_with_file.file1IsTarget", file1IsTarget), std::make_pair("modules.module_with_file.file2IsTarget", file2IsTarget), std::make_pair("products.p.addFileToProduct", addFileToProduct), }); - project = loader->loadProject(params); + resolveProject("file-in-product-and-module.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -1166,8 +1235,7 @@ void TestLanguage::getNativeSetting() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("getNativeSetting.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("getNativeSetting.qbs"); QString expectedTargetName; if (HostOsInfo::isMacosHost()) { @@ -1242,8 +1310,7 @@ void TestLanguage::groupName() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("groupname.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("groupname.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 2); @@ -1270,8 +1337,7 @@ void TestLanguage::groupName() group = product->groups.at(2); QVERIFY(!!group); QCOMPARE(group->name, QString("Group 2")); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1281,8 +1347,7 @@ void TestLanguage::groupName() void TestLanguage::homeDirectory() { try { - defaultParameters.setProjectFilePath(testProject("homeDirectory.qbs")); - ResolvedProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("homeDirectory.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -1307,8 +1372,7 @@ void TestLanguage::homeDirectory() FileInfo::resolvePath(product->sourceDirectory, QStringLiteral("a/~/bb"))); QCOMPARE(product->productProperties.value("user").toString(), FileInfo::resolvePath(product->sourceDirectory, QStringLiteral("~foo/bar"))); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { qDebug() << e.toString(); } } @@ -1387,8 +1451,7 @@ void TestLanguage::idUsage() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("idusage.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("idusage.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 5); @@ -1412,8 +1475,7 @@ void TestLanguage::idUsage() QVERIFY(!!product5); QCOMPARE(product5->moduleProperties->moduleProperty("deepdummy.deep.moat", "zort") .toString(), QString("zort in dummy")); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1424,10 +1486,8 @@ void TestLanguage::idUniqueness() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("id-uniqueness.qbs")); - loader->loadProject(defaultParameters); - } - catch (const ErrorInfo &e) { + resolveProject("id-uniqueness.qbs"); + } catch (const ErrorInfo &e) { exceptionCaught = true; const QList<ErrorItem> items = e.items(); QCOMPARE(items.size(), 3); @@ -1442,15 +1502,13 @@ void TestLanguage::importCollection() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("import-collection/project.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("import-collection/project.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); const ResolvedProductConstPtr product = products.value("da product"); QCOMPARE(product->productProperties.value("targetName").toString(), QLatin1String("C1f1C1f2C2f1C2f2")); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1469,19 +1527,15 @@ void TestLanguage::inheritedPropertiesItems() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; QFETCH(QString, buildVariant); QFETCH(QString, productName); - params.setProjectFilePath - (testProject("inherited-properties-items/inherited-properties-items.qbs")); - params.setOverriddenValues(QVariantMap{std::make_pair("qbs.buildVariant", buildVariant)}); - TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(QVariantMap{std::make_pair("qbs.buildVariant", buildVariant)}); + resolveProject("inherited-properties-items/inherited-properties-items.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); QVERIFY(!!products.value(productName)); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1492,13 +1546,11 @@ void TestLanguage::invalidBindingInDisabledItem() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("invalidBindingInDisabledItem.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("invalidBindingInDisabledItem.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 2); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1512,13 +1564,10 @@ void TestLanguage::invalidOverrides() const bool successExpected = expectedErrorMessage.isEmpty(); bool exceptionCaught = false; try { - qbs::SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("invalid-overrides.qbs")); - params.setOverriddenValues(QVariantMap{std::make_pair(key, true)}); - const TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(QVariantMap{std::make_pair(key, true)}); + resolveProject("invalid-overrides.qbs"); QVERIFY(!!project); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; if (successExpected) qDebug() << e.toString(); @@ -1562,31 +1611,32 @@ void TestLanguage::invalidOverrides_data() << "products.MyOtherProduct.cpp.useRPaths" << QString(); } -class JSSourceValueCreator +void TestLanguage::invalidPropOnNonRequiredModule_data() { - FileContextPtr m_fileContext; - QList<QString *> m_strings; -public: - JSSourceValueCreator(const FileContextPtr &fileContext) - : m_fileContext(fileContext) - { - } + QTest::addColumn<bool>("useExistingModule"); + QTest::addColumn<bool>("errorExpected"); - ~JSSourceValueCreator() - { - qDeleteAll(m_strings); - } + QTest::newRow("existing module") << true << true; + QTest::newRow("non-existing module") << false << false; +} - JSSourceValuePtr create(const QString &sourceCode) - { - JSSourceValuePtr value = JSSourceValue::create(); - value->setFile(m_fileContext); - const auto str = new QString(sourceCode); - m_strings.push_back(str); - value->setSourceCode(QStringRef(str)); - return value; +void TestLanguage::invalidPropOnNonRequiredModule() +{ + QFETCH(bool, useExistingModule); + QFETCH(bool, errorExpected); + + try { + defaultParameters.setOverriddenValues( + {std::make_pair("project.useExistingModule", useExistingModule)}); + resolveProject("invalid-prop-on-non-required-module"); + QVERIFY(!errorExpected); + } catch (const ErrorInfo &e) { + const QString errorString = e.toString(); + QVERIFY2(errorExpected, qPrintable(errorString)); + QVERIFY2(errorString.contains("Property 'nosuchprop' is not declared"), + qPrintable(errorString)); } -}; +} void TestLanguage::itemPrototype() { @@ -1603,12 +1653,13 @@ void TestLanguage::itemPrototype() item->setProperty("z", sourceValueCreator.create("2")); Evaluator evaluator(m_engine.get()); - QCOMPARE(evaluator.property(proto, "x").toVariant().toInt(), 1); - QCOMPARE(evaluator.property(proto, "y").toVariant().toInt(), 1); - QVERIFY(!evaluator.property(proto, "z").isValid()); - QCOMPARE(evaluator.property(item, "x").toVariant().toInt(), 1); - QCOMPARE(evaluator.property(item, "y").toVariant().toInt(), 2); - QCOMPARE(evaluator.property(item, "z").toVariant().toInt(), 2); + JSContext * const ctx = m_engine->context(); + QCOMPARE(getJsVariant(ctx, evaluator.property(proto, "x")).toInt(), 1); + QCOMPARE(getJsVariant(ctx, evaluator.property(proto, "y")).toInt(), 1); + QVERIFY(JS_IsUndefined(evaluator.property(proto, "z"))); + QCOMPARE(getJsVariant(ctx, evaluator.property(item, "x")).toInt(), 1); + QCOMPARE(getJsVariant(ctx, evaluator.property(item, "y")).toInt(), 2); + QCOMPARE(getJsVariant(ctx, evaluator.property(item, "z")).toInt(), 2); } void TestLanguage::itemScope() @@ -1627,10 +1678,11 @@ void TestLanguage::itemScope() item->setProperty("z", sourceValueCreator.create("x + y")); Evaluator evaluator(m_engine.get()); - QCOMPARE(evaluator.property(scope1, "x").toVariant().toInt(), 1); - QCOMPARE(evaluator.property(scope2, "y").toVariant().toInt(), 2); - QVERIFY(!evaluator.property(scope2, "x").isValid()); - QCOMPARE(evaluator.property(item, "z").toVariant().toInt(), 3); + JSContext * const ctx = m_engine->context(); + QCOMPARE(getJsVariant(ctx, evaluator.property(scope1, "x")).toInt(), 1); + QCOMPARE(getJsVariant(ctx, evaluator.property(scope2, "y")).toInt(), 2); + QVERIFY(JS_IsUndefined(evaluator.property(scope2, "x"))); + QCOMPARE(getJsVariant(ctx, evaluator.property(item, "z")).toInt(), 3); } void TestLanguage::jsExtensions() @@ -1640,10 +1692,10 @@ void TestLanguage::jsExtensions() QTextStream ts(&file); QString code = ts.readAll(); QVERIFY(!code.isEmpty()); - QScriptValue evaluated = m_engine->evaluate(code, file.fileName(), 1); - if (m_engine->hasErrorOrException(evaluated)) { - qDebug() << m_engine->uncaughtExceptionBacktrace(); - QFAIL(qPrintable(m_engine->lastErrorString(evaluated))); + m_engine->evaluate(JsValueOwner::Caller, code, file.fileName(), 1); + if (JsException ex = m_engine->checkAndClearException({})) { + qDebug() << ex.stackTrace(); + QFAIL(qPrintable(ex.message())); } } @@ -1662,35 +1714,45 @@ void TestLanguage::jsImportUsedInMultipleScopes() bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("jsimportsinmultiplescopes.qbs")); - params.setOverriddenValues({std::make_pair(QStringLiteral("qbs.buildVariant"), - buildVariant)}); - params.expandBuildConfiguration(); - TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues({std::make_pair(QStringLiteral("qbs.buildVariant"), + buildVariant)}); + resolveProject("jsimportsinmultiplescopes.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product = products.values().front(); QVERIFY(!!product); QCOMPARE(product->name, expectedProductName); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } +void TestLanguage::localProfileAsTopLevelProfile() +{ + bool exceptionCaught = false; + try { + defaultParameters.setTopLevelProfile("test-profile"); + resolveProject("local-profile-as-top-level-profile.qbs"); + QVERIFY(!!project); + QCOMPARE(int(project->products.size()), 1); + const PropertyMapConstPtr &props = project->products.front()->moduleProperties; + QCOMPARE(props->qbsPropertyValue("architecture"), "arm"); + QCOMPARE(props->qbsPropertyValue("targetPlatform"), "macos"); + } catch (const ErrorInfo &e) { + exceptionCaught = true; + qDebug() << e.toString(); + } + QCOMPARE(exceptionCaught, false); +} + void TestLanguage::moduleMergingVariantValues() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath - (testProject("module-merging-variant-values/module-merging-variant-values.qbs")); - params.expandBuildConfiguration(); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("module-merging-variant-values/module-merging-variant-values.qbs"); QVERIFY(!!project); QCOMPARE(int(project->products.size()), 2); } catch (const ErrorInfo &e) { @@ -1700,6 +1762,185 @@ void TestLanguage::moduleMergingVariantValues() QCOMPARE(exceptionCaught, false); } +void TestLanguage::moduleNameCollisions_data() +{ + QTest::addColumn<QString>("projectFile"); + QTest::addColumn<bool>("collisionExpected"); + + QTest::newRow("simple collision (one order)") << "simple-collision1.qbs" << true; + QTest::newRow("simple collision (other order)") << "simple-collision2.qbs" << true; + QTest::newRow("collision with more components") << "complex-collision.qbs" << true; + QTest::newRow("no collision (same length)") << "no-collision1.qbs" << false; + QTest::newRow("no collision (different length)") << "no-collision2.qbs" << false; +} + +void TestLanguage::moduleNameCollisions() +{ + QFETCH(QString, projectFile); + QFETCH(bool, collisionExpected); + + try { + const QString compositeProjectFilePath = QString("module-name-collisions/") + projectFile; + QVERIFY(resolveProject(qPrintable(compositeProjectFilePath))); + QVERIFY(!collisionExpected); + } catch (const ErrorInfo &e) { + const QString errorString = e.toString(); + QVERIFY2(collisionExpected, qPrintable(errorString)); + QVERIFY2(errorString.contains("not allowed"), qPrintable(errorString)); + } +} + +void TestLanguage::moduleParameters_data() +{ + QTest::addColumn<QVariantMap>("inputProperties"); + QTest::addColumn<QVariantMap>("expectedModuleParameters"); + QTest::addColumn<bool>("errorExpected"); + + QTest::newRow("no overrides") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "false"), + std::make_pair("project.overrideFromExport", "false"), + std::make_pair("project.overrideFromProduct", "false")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromParameters")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromParameters")})})} + << false; + QTest::newRow("override from product") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "false"), + std::make_pair("project.overrideFromExport", "false"), + std::make_pair("project.overrideFromProduct", "true")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})})} + << false; + QTest::newRow("override from export") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "false"), + std::make_pair("project.overrideFromExport", "true"), + std::make_pair("project.overrideFromProduct", "false")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromExportDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromParameters")})})} + << false; + QTest::newRow("override from export and product") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "false"), + std::make_pair("project.overrideFromExport", "true"), + std::make_pair("project.overrideFromProduct", "true")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})})} + << false; + QTest::newRow("override from module") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "true"), + std::make_pair("project.overrideFromExport", "false"), + std::make_pair("project.overrideFromProduct", "false")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromModuleDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromParameters")})})} + << false; + QTest::newRow("override from module and product") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "true"), + std::make_pair("project.overrideFromExport", "false"), + std::make_pair("project.overrideFromProduct", "true")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})})} + << false; + QTest::newRow("override from module and export") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "true"), + std::make_pair("project.overrideFromExport", "true"), + std::make_pair("project.overrideFromProduct", "false")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromExportDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromParameters")})})} + << true; + QTest::newRow("override from module, export and product") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "true"), + std::make_pair("project.overrideFromExport", "true"), + std::make_pair("project.overrideFromProduct", "true")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})})} + << false; +} + +void TestLanguage::moduleParameters() +{ + QFETCH(QVariantMap, inputProperties); + QFETCH(QVariantMap, expectedModuleParameters); + QFETCH(bool, errorExpected); + + try { + defaultParameters.setOverriddenValues(inputProperties); + resolveProject("module-parameters/module-parameters.qbs"); + QVERIFY(!errorExpected); + QVERIFY(project); + QCOMPARE(int(project->products.size()), 2); + const ResolvedProductPtr mainProduct = productsFromProject(project).value("main"); + QVERIFY(mainProduct); + QCOMPARE(int(mainProduct->moduleParameters.size()), 2); + for (auto it = expectedModuleParameters.cbegin(); it != expectedModuleParameters.cend(); + ++it) { + const auto findInProduct = [&](const QString &moduleName) { + for (auto it = mainProduct->moduleParameters.cbegin(); + it != mainProduct->moduleParameters.cend(); ++it) { + if (it.key()->name == moduleName) + return it.value(); + } + return QVariantMap(); + }; + const QVariantMap actual = findInProduct(it.key()); + const QVariantMap expected = it.value().toMap(); + const bool same = qVariantMapsEqual(actual, expected); + if (!same) { + qDebug().noquote() << "---" << expected; + qDebug().noquote() << "+++" << actual; + } + QVERIFY(same); + } + } catch (const ErrorInfo &e) { + QVERIFY2(errorExpected, qPrintable(e.toString())); + } +} + void TestLanguage::modulePrioritizationBySearchPath_data() { QTest::addColumn<QStringList>("searchPaths"); @@ -1715,12 +1956,10 @@ void TestLanguage::modulePrioritizationBySearchPath() bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("module-prioritization-by-search-path/project.qbs")); - params.setOverriddenValues({std::make_pair(QStringLiteral("project.qbsSearchPaths"), - searchPaths)}); - params.expandBuildConfiguration(); - TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues( + {std::make_pair(QStringLiteral("project.qbsSearchPaths"), + searchPaths)}); + resolveProject("module-prioritization-by-search-path/project.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -1729,8 +1968,7 @@ void TestLanguage::modulePrioritizationBySearchPath() const QString actualVariant = product->moduleProperties->moduleProperty ("conflicting-instances", "moduleVariant").toString(); QCOMPARE(actualVariant, expectedVariant); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1796,7 +2034,7 @@ void TestLanguage::modulePropertiesInGroups() defaultParameters.setProjectFilePath(testProject("modulepropertiesingroups.qbs")); bool exceptionCaught = false; try { - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject(); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value("grouptest"); @@ -1924,7 +2162,7 @@ void TestLanguage::modulePropertiesInGroups() QCOMPARE(g2Gmod1List1, QStringList() << "gmod1_list1_proto" << "g2"); const auto &g2Gmod1List2 = moduleProperty(g2Props, "gmod.gmod1", "gmod1_list2") .toStringList(); - QCOMPARE(g2Gmod1List2, QStringList() << "grouptest" << "g2" << "gmod1_list2_proto"); + QCOMPARE(g2Gmod1List2, QStringList() << "grouptest" << "gmod1_string_proto" << "gmod1_list2_proto"); const int g2P0 = moduleProperty(g2Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g2P0, 6); const int g2DepProp = moduleProperty(g2Props, "gmod.gmod1", "depProp").toInt(); @@ -2008,17 +2246,14 @@ void TestLanguage::modulePropertyOverridesPerProduct() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setOverriddenValues({ + defaultParameters.setOverriddenValues({ std::make_pair("modules.dummy.rpaths", QStringList({"/usr/lib"})), std::make_pair("modules.dummy.someString", "m"), std::make_pair("products.b.dummy.someString", "b"), std::make_pair("products.c.dummy.someString", "c"), std::make_pair("products.c.dummy.rpaths", QStringList({"/home", "/tmp"})) }); - params.setProjectFilePath( - testProject("module-property-overrides-per-product.qbs")); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("module-property-overrides-per-product.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 3); @@ -2051,8 +2286,7 @@ void TestLanguage::modulePropertyOverridesPerProduct() QCOMPARE(listPropertyValue(a), productPropertyValue(a)); QCOMPARE(listPropertyValue(b), productPropertyValue(b)); QCOMPARE(listPropertyValue(c), productPropertyValue(c)); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2064,7 +2298,7 @@ void TestLanguage::moduleScope() bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("modulescope.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject(); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -2084,13 +2318,30 @@ void TestLanguage::moduleScope() QCOMPARE(intModuleValue("f"), 2); // overridden QCOMPARE(intModuleValue("g"), 156); // overridden, dependent on product properties QCOMPARE(intModuleValue("h"), 158); // overridden, base dependent on product properties - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); +} +void TestLanguage::moduleWithProductDependency() +{ + bool exceptionCaught = false; + try { + defaultParameters.setProjectFilePath(testProject("module-depends-on-product.qbs")); + resolveProject(); + QVERIFY(project); + QHash<QString, ResolvedProductPtr> products = productsFromProject(project); + QCOMPARE(products.size(), 2); + ResolvedProductPtr product = products.value("p1"); + QVERIFY(product); + QCOMPARE(int(product->dependencies.size()), 1); + } catch (const ErrorInfo &e) { + exceptionCaught = true; + qDebug() << e.toString(); + } + QCOMPARE(exceptionCaught, false); } void TestLanguage::modules_data() @@ -2149,9 +2400,7 @@ void TestLanguage::multiplexedExports() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("multiplexed-exports.qbs")); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("multiplexed-exports.qbs"); QVERIFY(!!project); const auto products = project->allProducts(); QCOMPARE(products.size(), size_t(4)); @@ -2185,11 +2434,9 @@ void TestLanguage::multiplexingByProfile() { QFETCH(QString, projectFileName); QFETCH(bool, successExpected); - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testDataDir() + "/multiplexing-by-profile/" + projectFileName); try { - params.setDryRun(true); - const TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setDryRun(true); + resolveProject(qPrintable("/multiplexing-by-profile/" + projectFileName)); QVERIFY(successExpected); QVERIFY(!!project); } catch (const ErrorInfo &e) { @@ -2213,11 +2460,9 @@ void TestLanguage::nonApplicableModulePropertyInProfile() QFETCH(QString, toolchain); QFETCH(bool, successExpected); try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("non-applicable-module-property-in-profile.qbs")); - params.setOverriddenValues(QVariantMap{std::make_pair("project.targetOS", targetOS), + defaultParameters.setOverriddenValues({std::make_pair("project.targetOS", targetOS), std::make_pair("project.toolchain", toolchain)}); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("non-applicable-module-property-in-profile.qbs"); QVERIFY(!!project); QVERIFY(successExpected); } catch (const ErrorInfo &e) { @@ -2247,8 +2492,6 @@ void TestLanguage::nonRequiredProducts() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("non-required-products.qbs")); QFETCH(bool, subProjectEnabled); QFETCH(bool, dependeeEnabled); QVariantMap overriddenValues; @@ -2256,8 +2499,8 @@ void TestLanguage::nonRequiredProducts() overriddenValues.insert("projects.subproject.condition", false); else if (!dependeeEnabled) overriddenValues.insert("products.dependee.condition", false); - params.setOverriddenValues(overriddenValues); - const TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(overriddenValues); + resolveProject("non-required-products.qbs"); QVERIFY(!!project); const auto products = productsFromProject(project); QCOMPARE(products.size(), 4 + !!subProjectEnabled); @@ -2276,8 +2519,7 @@ void TestLanguage::nonRequiredProducts() QVERIFY2(product, name); QVERIFY2(!product->enabled, name); } - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2298,7 +2540,7 @@ void TestLanguage::outerInGroup() bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("outerInGroup.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject(); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -2319,8 +2561,7 @@ void TestLanguage::outerInGroup() artifact = group->files.front(); installDir = artifact->properties->qbsPropertyValue("installDir"); QCOMPARE(installDir.toString(), QString("/somewhere/else")); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2333,16 +2574,14 @@ void TestLanguage::overriddenPropertiesAndPrototypes() try { QFETCH(QString, osName); QFETCH(QString, backendName); - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("overridden-properties-and-prototypes.qbs")); - params.setOverriddenValues({std::make_pair("modules.qbs.targetPlatform", osName)}); - TopLevelProjectConstPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues({std::make_pair("modules.qbs.targetPlatform", + osName)}); + resolveProject("overridden-properties-and-prototypes.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); QCOMPARE(project->products.front()->moduleProperties->moduleProperty( "multiple_backends", "prop").toString(), backendName); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2361,11 +2600,9 @@ void TestLanguage::overriddenVariantProperty() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; const QVariantMap objectValue{std::make_pair("x", 1), std::make_pair("y", 2)}; - params.setOverriddenValues({std::make_pair("products.p.myObject", objectValue)}); - params.setProjectFilePath(testProject("overridden-variant-property.qbs")); - TopLevelProjectConstPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues({std::make_pair("products.p.myObject", objectValue)}); + resolveProject("overridden-variant-property.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); QCOMPARE(project->products.front()->productProperties.value("myObject").toMap(), @@ -2382,9 +2619,8 @@ void TestLanguage::parameterTypes() bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("parameter-types.qbs")); - loader->loadProject(defaultParameters); - } - catch (const ErrorInfo &e) { + resolveProject(); + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2395,8 +2631,7 @@ void TestLanguage::pathProperties() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("pathproperties.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("pathproperties.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); @@ -2422,6 +2657,35 @@ void TestLanguage::pathProperties() QCOMPARE(exceptionCaught, false); } +void TestLanguage::probesAndMultiplexing() +{ + bool exceptionCaught = false; + try { + resolveProject("probes-and-multiplexing.qbs"); + QVERIFY(project); + QCOMPARE(int(project->products.size()), 3); + QStringList architectures{"x86", "x86_64", "arm"}; + for (const ResolvedProductPtr &product : project->products) { + const QString arch = product->moduleProperties->moduleProperty("qbs", "architecture") + .toString(); + QVERIFY2(architectures.removeOne(arch), qPrintable(arch)); + QCOMPARE(product->productProperties.value("archFromProbe").toString(), arch); + bool foundGroup = false; + for (const GroupPtr &group : product->groups) { + if (group->name == "theGroup") { + foundGroup = true; + QCOMPARE(group->properties->moduleProperty("qbs", "sysroot"), "/" + arch); + } + } + QVERIFY(foundGroup); + } + } catch (const ErrorInfo &e) { + exceptionCaught = true; + qDebug() << e.toString(); + } + QCOMPARE(exceptionCaught, false); +} + void TestLanguage::profileValuesAndOverriddenValues() { bool exceptionCaught = false; @@ -2432,14 +2696,11 @@ void TestLanguage::profileValuesAndOverriddenValues() profile.setValue("dummy.cFlags", "IN_PROFILE"); profile.setValue("dummy.cxxFlags", "IN_PROFILE"); profile.setValue("qbs.architecture", "x86"); - SetupProjectParameters parameters = defaultParameters; - parameters.setTopLevelProfile(profile.name()); + defaultParameters.setTopLevelProfile(profile.name()); QVariantMap overriddenValues; overriddenValues.insert("modules.dummy.cFlags", "OVERRIDDEN"); - parameters.setOverriddenValues(overriddenValues); - parameters.setProjectFilePath(testProject("profilevaluesandoverriddenvalues.qbs")); - parameters.expandBuildConfiguration(); - project = loader->loadProject(parameters); + defaultParameters.setOverriddenValues(overriddenValues); + resolveProject("profilevaluesandoverriddenvalues.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); @@ -2469,7 +2730,7 @@ void TestLanguage::projectFileLookup() try { SetupProjectParameters params; params.setProjectFilePath(projectFileInput); - Loader::setupProjectFilePath(params); + params.finalizeProjectFilePath(); QVERIFY(!failureExpected); QCOMPARE(params.projectFilePath(), projectFileOutput); } catch (const ErrorInfo &) { @@ -2500,8 +2761,7 @@ void TestLanguage::productConditions() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("productconditions.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("productconditions.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 6); @@ -2529,8 +2789,7 @@ void TestLanguage::productConditions() product = products.value("product_probe_condition_true"); QVERIFY(!!product); QVERIFY(product->enabled); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2541,8 +2800,7 @@ void TestLanguage::productDirectories() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("productdirectories.qbs")); - ResolvedProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("productdirectories.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -2553,8 +2811,7 @@ void TestLanguage::productDirectories() QCOMPARE(config.value(QStringLiteral("buildDirectory")).toString(), product->buildDirectory()); QCOMPARE(config.value(QStringLiteral("sourceDirectory")).toString(), testDataDir()); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2700,8 +2957,7 @@ void TestLanguage::propertiesBlockInGroup() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("properties-block-in-group.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("properties-block-in-group.qbs"); QVERIFY(!!project); QCOMPARE(project->allProducts().size(), size_t(1)); const ResolvedProductConstPtr product = project->allProducts().front(); @@ -2725,9 +2981,7 @@ void TestLanguage::propertiesItemInModule() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath( - testProject("properties-item-in-module.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("properties-item-in-module.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 2); @@ -2746,9 +3000,7 @@ void TestLanguage::propertyAssignmentInExportedGroup() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath( - testProject("property-assignment-in-exported-group.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("property-assignment-in-exported-group.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 2); @@ -2775,8 +3027,7 @@ void TestLanguage::qbs1275() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("qbs1275.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("qbs1275.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.count(), 5); @@ -2791,10 +3042,9 @@ void TestLanguage::qbsPropertiesInProjectCondition() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath( - testProject("qbs-properties-in-project-condition.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("qbs-properties-in-project-condition.qbs"); QVERIFY(!!project); + QVERIFY(!project->enabled); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 0); } catch (const ErrorInfo &e) { @@ -2808,16 +3058,14 @@ void TestLanguage::qbsPropertyConvenienceOverride() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("qbs-property-convenience-override.qbs")); - params.setOverriddenValues({std::make_pair("qbs.installPrefix", "/opt")}); - TopLevelProjectConstPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues({std::make_pair("qbs.installPrefix", "/opt")}); + resolveProject("qbs-property-convenience-override.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); QCOMPARE(project->products.front()->moduleProperties->qbsPropertyValue("installPrefix") .toString(), QString("/opt")); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { + exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); @@ -2828,11 +3076,9 @@ void TestLanguage::relaxedErrorMode() m_logSink->setLogLevel(LoggerMinLevel); QFETCH(bool, strictMode); try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("relaxed-error-mode/relaxed-error-mode.qbs")); - params.setProductErrorMode(strictMode ? ErrorHandlingMode::Strict - : ErrorHandlingMode::Relaxed); - const TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setProductErrorMode(strictMode ? ErrorHandlingMode::Strict + : ErrorHandlingMode::Relaxed); + resolveProject("relaxed-error-mode/relaxed-error-mode.qbs"); QVERIFY(!strictMode); const auto productMap = productsFromProject(project); const ResolvedProductConstPtr brokenProduct = productMap.value("broken"); @@ -2855,7 +3101,7 @@ void TestLanguage::relaxedErrorMode() QVERIFY(missingFile->enabled); QCOMPARE(missingFile->groups.size(), size_t(1)); QVERIFY(missingFile->groups.front()->enabled); - QCOMPARE(missingFile->groups.front()->allFiles().size(), size_t(2)); + QCOMPARE(missingFile->groups.front()->files.size(), size_t(2)); const ResolvedProductConstPtr fine = productMap.value("fine"); QVERIFY(fine->enabled); QCOMPARE(fine->allFiles().size(), size_t(1)); @@ -2877,10 +3123,7 @@ void TestLanguage::requiredAndNonRequiredDependencies() QFETCH(QString, projectFile); QFETCH(bool, exceptionExpected); try { - SetupProjectParameters params = defaultParameters; - const QString projectFilePath = "required-and-nonrequired-dependencies/" + projectFile; - params.setProjectFilePath(testProject(projectFilePath.toLocal8Bit())); - const TopLevelProjectConstPtr project = loader->loadProject(params); + resolveProject(qPrintable("required-and-nonrequired-dependencies/" + projectFile)); QVERIFY(!!project); QVERIFY(!exceptionExpected); } catch (const ErrorInfo &e) { @@ -2907,10 +3150,7 @@ void TestLanguage::requiredAndNonRequiredDependencies_data() void TestLanguage::suppressedAndNonSuppressedErrors() { try { - SetupProjectParameters params = defaultParameters; - const QString projectFilePath = "suppressed-and-non-suppressed-errors.qbs"; - params.setProjectFilePath(testProject(projectFilePath.toLocal8Bit())); - const TopLevelProjectConstPtr project = loader->loadProject(params); + resolveProject("suppressed-and-non-suppressed-errors.qbs"); QFAIL("failure expected"); } catch (const ErrorInfo &e) { QVERIFY2(e.toString().contains("easter bunny"), qPrintable(e.toString())); @@ -2922,12 +3162,10 @@ void TestLanguage::throwingProbe() { QFETCH(bool, enableProbe); try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("throwing-probe.qbs")); QVariantMap properties; properties.insert(QStringLiteral("products.theProduct.enableProbe"), enableProbe); - params.setOverriddenValues(properties); - const TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(properties); + resolveProject("throwing-probe.qbs"); QVERIFY(!!project); QVERIFY(!enableProbe); } catch (const ErrorInfo &e) { @@ -2969,9 +3207,7 @@ void TestLanguage::recursiveProductDependencies() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath( - testProject("recursive-dependencies/recursive-dependencies.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("recursive-dependencies/recursive-dependencies.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 4); @@ -3031,10 +3267,8 @@ void TestLanguage::fileTags() void TestLanguage::useInternalProfile() { const QString profile(QStringLiteral("theprofile")); - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("use-internal-profile.qbs")); - params.setTopLevelProfile(profile); - TopLevelProjectConstPtr project = loader->loadProject(params); + defaultParameters.setTopLevelProfile(profile); + resolveProject("use-internal-profile.qbs"); QVERIFY(!!project); QCOMPARE(project->profile(), profile); QCOMPARE(project->products.size(), size_t(1)); @@ -3230,7 +3464,7 @@ void TestLanguage::wildcards() } // create files - for (QString filePath : qAsConst(filesToCreate)) { + for (QString filePath : std::as_const(filesToCreate)) { filePath.prepend(m_wildcardsTestDirPath + '/'); QFileInfo fi(filePath); if (!QDir(fi.path()).exists()) @@ -3244,7 +3478,7 @@ void TestLanguage::wildcards() ResolvedProductPtr product; try { defaultParameters.setProjectFilePath(projectFilePath); - project = loader->loadProject(defaultParameters); + resolveProject(); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); product = products.value("MyProduct"); @@ -3263,10 +3497,10 @@ void TestLanguage::wildcards() group = product->groups.front(); } QVERIFY(!!group); - QCOMPARE(group->files.size(), size_t(0)); + QCOMPARE(group->files.size(), expected.size()); // we assume all files are wildcards QVERIFY(!!group->wildcards); QStringList actualFilePaths; - for (const SourceArtifactPtr &artifact : group->wildcards->files) { + for (const SourceArtifactPtr &artifact : group->files) { QString str = artifact->absoluteFilePath; int idx = str.indexOf(m_wildcardsTestDirPath); if (idx != -1) @@ -3290,4 +3524,3 @@ int main(int argc, char *argv[]) TestLanguage tl(ConsoleLogger::instance().logSink(), s.get()); return QTest::qExec(&tl, argc, argv); } - diff --git a/tests/auto/language/tst_language.h b/tests/auto/language/tst_language.h index 4fe2752e4..870b7d1f8 100644 --- a/tests/auto/language/tst_language.h +++ b/tests/auto/language/tst_language.h @@ -41,8 +41,9 @@ #define TST_LANGUAGE_H #include <language/forward_decls.h> -#include <language/loader.h> +#include <language/scriptengine.h> #include <logging/ilogsink.h> +#include <logging/logger.h> #include <tools/setupprojectparameters.h> #include <QtCore/qrandom.h> @@ -56,27 +57,9 @@ public: TestLanguage(qbs::ILogSink *logSink, qbs::Settings *settings); ~TestLanguage(); -private: - qbs::ILogSink *m_logSink; - qbs::Settings * const m_settings; - qbs::Internal::Logger m_logger; - std::unique_ptr<qbs::Internal::ScriptEngine> m_engine; - qbs::Internal::Loader *loader; - qbs::Internal::TopLevelProjectPtr project; - qbs::SetupProjectParameters defaultParameters; - const QString m_wildcardsTestDirPath; - - QHash<QString, qbs::Internal::ResolvedProductPtr> productsFromProject( - qbs::Internal::ResolvedProjectPtr project); - qbs::Internal::ResolvedModuleConstPtr findModuleByName( - qbs::Internal::ResolvedProductPtr product, const QString &name); - QVariant productPropertyValue(qbs::Internal::ResolvedProductPtr product, QString propertyName); - void handleInitCleanupDataTags(const char *projectFileName, bool *handled); - private slots: void init(); void initTestCase(); - void cleanupTestCase(); void additionalProductTypes(); void baseProperty(); @@ -88,6 +71,7 @@ private slots: void chainedProbes(); void canonicalArchitecture(); void conditionalDepends(); + void convertStringList(); void delayedError(); void delayedError_data(); void dependencyOnAllProfiles(); @@ -95,6 +79,8 @@ private slots: void disabledSubProject(); void dottedNames_data(); void dottedNames(); + void duplicateMultiplexValues_data(); + void duplicateMultiplexValues(); void emptyJsFile(); void enumerateProjectProperties(); void evalErrorInNonPresentModule_data(); @@ -124,12 +110,19 @@ private slots: void invalidBindingInDisabledItem(); void invalidOverrides(); void invalidOverrides_data(); + void invalidPropOnNonRequiredModule_data(); + void invalidPropOnNonRequiredModule(); void itemPrototype(); void itemScope(); void jsExtensions(); void jsImportUsedInMultipleScopes_data(); void jsImportUsedInMultipleScopes(); + void localProfileAsTopLevelProfile(); void moduleMergingVariantValues(); + void moduleNameCollisions_data(); + void moduleNameCollisions(); + void moduleParameters_data(); + void moduleParameters(); void modulePrioritizationBySearchPath_data(); void modulePrioritizationBySearchPath(); void moduleProperties_data(); @@ -137,6 +130,7 @@ private slots: void modulePropertiesInGroups(); void modulePropertyOverridesPerProduct(); void moduleScope(); + void moduleWithProductDependency(); void modules_data(); void modules(); void multiplexedExports(); @@ -152,6 +146,7 @@ private slots: void overriddenVariantProperty(); void parameterTypes(); void pathProperties(); + void probesAndMultiplexing(); void productConditions(); void productDirectories(); void profileValuesAndOverriddenValues(); @@ -177,12 +172,29 @@ private slots: void qualifiedId(); void recursiveProductDependencies(); void rfc1034Identifier(); + void throwThings_data(); + void throwThings(); void useInternalProfile(); void versionCompare(); void wildcards_data(); void wildcards(); private: + QHash<QString, qbs::Internal::ResolvedProductPtr> productsFromProject( + qbs::Internal::ResolvedProjectPtr project); + qbs::Internal::ResolvedModuleConstPtr findModuleByName( + qbs::Internal::ResolvedProductPtr product, const QString &name); + QVariant productPropertyValue(qbs::Internal::ResolvedProductPtr product, QString propertyName); + void handleInitCleanupDataTags(const char *projectFileName, bool *handled); + qbs::Internal::TopLevelProjectPtr resolveProject(const char *relProjectFilePath = nullptr); + + qbs::ILogSink * const m_logSink; + qbs::Settings * const m_settings; + qbs::Internal::Logger m_logger; + std::unique_ptr<qbs::Internal::ScriptEngine> m_engine; + qbs::Internal::TopLevelProjectPtr project; + qbs::SetupProjectParameters defaultParameters; + const QString m_wildcardsTestDirPath; QTemporaryDir m_tempDir; QRandomGenerator m_rand; }; diff --git a/tests/auto/pkgconfig/CMakeLists.txt b/tests/auto/pkgconfig/CMakeLists.txt index 4d60491ba..74a13a8ab 100644 --- a/tests/auto/pkgconfig/CMakeLists.txt +++ b/tests/auto/pkgconfig/CMakeLists.txt @@ -4,5 +4,5 @@ add_qbs_test(pkgconfig tst_pkgconfig.h DEPENDS qbspkgconfig - qbsscriptengine + qbsquickjsheaders ) diff --git a/tests/auto/pkgconfig/testdata/lib/pkgconfig/prefix.pc b/tests/auto/pkgconfig/testdata/lib/pkgconfig/prefix.pc new file mode 100644 index 000000000..64b980803 --- /dev/null +++ b/tests/auto/pkgconfig/testdata/lib/pkgconfig/prefix.pc @@ -0,0 +1,13 @@ +prefix=/usr +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=/usr/include +usrdir=/usrdir + +Name: Prefix test +Description: This tests prefix auto detection +Version: 1.0.0 +Requires: +Libs: -lprefix +Libs.private: -lm +Cflags: -I${includedir} diff --git a/tests/auto/pkgconfig/testdata/requires-test-merged-static.json b/tests/auto/pkgconfig/testdata/requires-test-merged-static.json deleted file mode 100644 index 2c43b2d40..000000000 --- a/tests/auto/pkgconfig/testdata/requires-test-merged-static.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "Name": "Requires test package", - "Description": "Dummy pkgconfig test package for testing Requires/Requires.private", - "Version": "1.0.0", - "Libs": [ - {"Type": "LibraryPath", "Value": "/public-dep/lib"}, - {"Type": "LibraryName", "Value": "public-dep"}, - {"Type": "LibraryPath", "Value": "/private-dep/lib"}, - {"Type": "LibraryName", "Value": "private-dep"}, - {"Type": "LibraryPath", "Value": "/requires-test/lib"}, - {"Type": "LibraryName", "Value": "requires-test"} - ], - "Cflags": [ - {"Type": "IncludePath", "Value": "/public-dep/include"}, - {"Type": "IncludePath", "Value": "/private-dep/include"}, - {"Type": "IncludePath", "Value": "/requires-test/include"} - ], - "Requires": [ - ], - "RequiresPrivate": [ - ] -} diff --git a/tests/auto/pkgconfig/testdata/requires-test-merged.json b/tests/auto/pkgconfig/testdata/requires-test-merged.json deleted file mode 100644 index 88114ba30..000000000 --- a/tests/auto/pkgconfig/testdata/requires-test-merged.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "Name": "Requires test package", - "Description": "Dummy pkgconfig test package for testing Requires/Requires.private", - "Version": "1.0.0", - "Libs": [ - {"Type": "LibraryPath", "Value": "/public-dep/lib"}, - {"Type": "LibraryName", "Value": "public-dep"}, - {"Type": "LibraryPath", "Value": "/requires-test/lib"}, - {"Type": "LibraryName", "Value": "requires-test"} - ], - "Cflags": [ - {"Type": "IncludePath", "Value": "/public-dep/include"}, - {"Type": "IncludePath", "Value": "/requires-test/include"} - ], - "Requires": [ - ], - "RequiresPrivate": [ - ] -} diff --git a/tests/auto/pkgconfig/tst_pkgconfig.cpp b/tests/auto/pkgconfig/tst_pkgconfig.cpp index 220e54e7a..86d954259 100644 --- a/tests/auto/pkgconfig/tst_pkgconfig.cpp +++ b/tests/auto/pkgconfig/tst_pkgconfig.cpp @@ -33,6 +33,7 @@ #include <tools/fileinfo.h> #include <tools/hostosinfo.h> #include <pkgconfig.h> +#include <pcparser.h> #include <jsextensions/pkgconfigjs.h> #include <QJsonArray> @@ -58,6 +59,48 @@ void TestPkgConfig::initTestCase() qPrintable(errorMessage)); } +void TestPkgConfig::fileName() +{ + QCOMPARE(qbs::Internal::fileName(""), ""); + QCOMPARE(qbs::Internal::fileName("file.txt"), "file.txt"); + QCOMPARE(qbs::Internal::fileName("/home/user/file.txt"), "file.txt"); + QCOMPARE(qbs::Internal::fileName("/"), ""); +#if defined(Q_OS_WIN) + QCOMPARE(qbs::Internal::fileName("c:file.txt"), "file.txt"); + QCOMPARE(qbs::Internal::fileName("c:"), ""); +#endif +} + +void TestPkgConfig::completeBaseName() +{ + QCOMPARE(qbs::Internal::completeBaseName(""), ""); + QCOMPARE(qbs::Internal::completeBaseName("file.txt"), "file"); + QCOMPARE(qbs::Internal::completeBaseName("archive.tar.gz"), "archive.tar"); + QCOMPARE(qbs::Internal::completeBaseName("/home/user/file.txt"), "file"); +#if defined(Q_OS_WIN) + QCOMPARE(qbs::Internal::completeBaseName("c:file.txt"), "file"); + QCOMPARE(qbs::Internal::completeBaseName("c:archive.tar.gz"), "archive.tar"); + QCOMPARE(qbs::Internal::completeBaseName("c:"), ""); +#endif +} + +void TestPkgConfig::parentPath() +{ + QCOMPARE(qbs::Internal::parentPath(""), ""); + QCOMPARE(qbs::Internal::parentPath("file.txt"), "."); + QCOMPARE(qbs::Internal::parentPath("/home/user/file.txt"), "/home/user"); + QCOMPARE(qbs::Internal::parentPath("/home/user/"), "/home/user"); + QCOMPARE(qbs::Internal::parentPath("/home"), "/"); + QCOMPARE(qbs::Internal::parentPath("/"), "/"); +#if defined(Q_OS_WIN) + QCOMPARE(qbs::Internal::parentPath("c:/folder/file.txt"), "c:/folder"); + QCOMPARE(qbs::Internal::parentPath("c:/folder/"), "c:/folder"); + QCOMPARE(qbs::Internal::parentPath("c:/folder"), "c:/"); + QCOMPARE(qbs::Internal::parentPath("c:/"), "c:/"); + QCOMPARE(qbs::Internal::parentPath("c:"), "c:"); +#endif +} + void TestPkgConfig::pkgConfig() { QFETCH(QString, pcFileName); @@ -67,9 +110,6 @@ void TestPkgConfig::pkgConfig() if (jsonFileName.isEmpty()) jsonFileName = pcFileName; - if (!optionsMap.contains("mergeDependencies")) - optionsMap["mergeDependencies"] = false; - Options options = qbs::Internal::PkgConfigJs::convertOptions( QProcessEnvironment::systemEnvironment(), optionsMap); options.libDirs.push_back(m_workingDataDir.toStdString()); @@ -176,14 +216,6 @@ void TestPkgConfig::pkgConfig_data() << QStringLiteral("simple") << QString() << QVariantMap(); QTest::newRow("requires-test") << QStringLiteral("requires-test") << QString() << QVariantMap(); - QTest::newRow("requires-test-merged") - << QStringLiteral("requires-test") - << QStringLiteral("requires-test-merged") - << QVariantMap({{"mergeDependencies", true}}); - QTest::newRow("requires-test-merged-static") - << QStringLiteral("requires-test") - << QStringLiteral("requires-test-merged-static") - << QVariantMap({{"mergeDependencies", true}, {"staticMode", true}}); QTest::newRow("special-flags") << QStringLiteral("special-flags") << QString() << QVariantMap(); QTest::newRow("system") @@ -194,10 +226,6 @@ void TestPkgConfig::pkgConfig_data() << QStringLiteral("tilde") << QString() << QVariantMap(); QTest::newRow("variables") << QStringLiteral("variables") << QString() << QVariantMap(); - QTest::newRow("variables-merged") - << QStringLiteral("variables") - << QString() - << QVariantMap({{"mergeDependencies", true}}); QTest::newRow("whitespace") << QStringLiteral("whitespace") << QString() << QVariantMap(); QTest::newRow("base.name") @@ -214,4 +242,25 @@ void TestPkgConfig::benchSystem() } } +void TestPkgConfig::prefix() +{ + const auto prefixDir = m_workingDataDir; + const auto libDir = m_workingDataDir + "/lib"; + const auto includeDir = m_workingDataDir + "/include"; + const auto pkgconfigDir = libDir + "/pkgconfig"; + Options options = qbs::Internal::PkgConfigJs::convertOptions( + QProcessEnvironment::systemEnvironment(), {}); + options.definePrefix = true; + options.libDirs.push_back(pkgconfigDir.toStdString()); + PkgConfig pkgConfig(std::move(options)); + const auto &packageOr = pkgConfig.getPackage("prefix"); + QVERIFY(packageOr.isValid()); + const auto &package = packageOr.asPackage(); + QCOMPARE(package.variables.at("prefix"), prefixDir.toStdString()); + QCOMPARE(package.variables.at("exec_prefix"), prefixDir.toStdString()); + QCOMPARE(package.variables.at("libdir"), libDir.toStdString()); + QCOMPARE(package.variables.at("includedir"), includeDir.toStdString()); + QCOMPARE(package.variables.at("usrdir"), "/usrdir"); +} + QTEST_MAIN(TestPkgConfig) diff --git a/tests/auto/pkgconfig/tst_pkgconfig.h b/tests/auto/pkgconfig/tst_pkgconfig.h index 687411862..47654e1ec 100644 --- a/tests/auto/pkgconfig/tst_pkgconfig.h +++ b/tests/auto/pkgconfig/tst_pkgconfig.h @@ -41,9 +41,13 @@ public: private slots: void initTestCase(); + void fileName(); + void completeBaseName(); + void parentPath(); void pkgConfig(); void pkgConfig_data(); void benchSystem(); + void prefix(); private: const QString m_sourceDataDir; diff --git a/tests/auto/shared.h b/tests/auto/shared.h index 53ff364fb..408594be0 100644 --- a/tests/auto/shared.h +++ b/tests/auto/shared.h @@ -158,7 +158,7 @@ inline QByteArray diffText(const QByteArray &actual, const QByteArray &expected) n++; } auto addLines = [&result, &n] (const QList<QByteArray> &lines) { - for (const QByteArray &line : qAsConst(lines)) { + for (const QByteArray &line : std::as_const(lines)) { result += QStringLiteral("%1: %2\n") .arg(n) .arg(QString::fromUtf8(line)) diff --git a/tests/auto/tools/tools.pro b/tests/auto/tools/tools.pro deleted file mode 100644 index ba293f417..000000000 --- a/tests/auto/tools/tools.pro +++ /dev/null @@ -1,6 +0,0 @@ -TARGET = tst_tools - -SOURCES = tst_tools.cpp ../../../src/app/qbs/qbstool.cpp -HEADERS = tst_tools.h - -include(../auto.pri) diff --git a/tests/auto/tools/tst_tools.cpp b/tests/auto/tools/tst_tools.cpp index a872bdd0d..b856192f9 100644 --- a/tests/auto/tools/tst_tools.cpp +++ b/tests/auto/tools/tst_tools.cpp @@ -1207,87 +1207,6 @@ void TestTools::stringutils_join_char_data() << std::string("a b c"); } -void TestTools::stringutils_startsWith() -{ - std::string a; - a = "AB"; - QVERIFY( startsWith(a, "A") ); - QVERIFY( startsWith(a, "AB") ); - QVERIFY( !startsWith(a, "C") ); - QVERIFY( !startsWith(a, "ABCDEF") ); - QVERIFY( startsWith(a, "") ); - QVERIFY( startsWith(a, 'A') ); - QVERIFY( !startsWith(a, 'C') ); - QVERIFY( !startsWith(a, char()) ); - - QVERIFY( startsWith(a, "A") ); - QVERIFY( startsWith(a, "AB") ); - QVERIFY( !startsWith(a, "C") ); - QVERIFY( !startsWith(a, "ABCDEF") ); - QVERIFY( startsWith(a, "") ); - - a = ""; - QVERIFY( startsWith(a, "") ); - QVERIFY( !startsWith(a, "ABC") ); - - QVERIFY( startsWith(a, "") ); - QVERIFY( !startsWith(a, "ABC") ); - - QVERIFY( !startsWith(a, 'x') ); - QVERIFY( !startsWith(a, char()) ); - - a = std::string(); - QVERIFY( startsWith(a, "") ); // different from QString::startsWith - QVERIFY( !startsWith(a, "ABC") ); - - QVERIFY( !startsWith(a, 'x') ); - QVERIFY( !startsWith(a, char()) ); - - a = u8"\xc3\xa9"; - QVERIFY( startsWith(a, u8"\xc3\xa9") ); - QVERIFY( !startsWith(a, u8"\xc3\xa1") ); -} - -void TestTools::stringutils_endsWith() -{ - std::string a; - a = "AB"; - QVERIFY( endsWith(a, "B") ); - QVERIFY( endsWith(a, "AB") ); - QVERIFY( !endsWith(a, "C") ); - QVERIFY( !endsWith(a, "ABCDEF") ); - QVERIFY( endsWith(a, "") ); - QVERIFY( endsWith(a, 'B') ); - QVERIFY( !endsWith(a, 'C') ); - QVERIFY( !endsWith(a, char()) ); - - QVERIFY( endsWith(a, "B") ); - QVERIFY( endsWith(a, "AB") ); - QVERIFY( !endsWith(a, "C") ); - QVERIFY( !endsWith(a, "ABCDEF") ); - QVERIFY( endsWith(a, "") ); - - a = ""; - QVERIFY( endsWith(a, "") ); - QVERIFY( !endsWith(a, "ABC") ); - QVERIFY( !endsWith(a, 'x') ); - QVERIFY( !endsWith(a, char()) ); - - QVERIFY( endsWith(a, "") ); - QVERIFY( !endsWith(a, "ABC") ); - - a = std::string(); - QVERIFY( endsWith(a, "") ); // different from QString::endsWith - QVERIFY( !endsWith(a, "ABC") ); - - QVERIFY( !endsWith(a, 'x') ); - QVERIFY( !endsWith(a, char()) ); - - a = u8"\xc3\xa9"; - QVERIFY( endsWith(a, u8"\xc3\xa9") ); - QVERIFY( !endsWith(a, u8"\xc3\xa1") ); -} - void TestTools::stringutils_trimmed() { std::string a; diff --git a/tests/auto/tools/tst_tools.h b/tests/auto/tools/tst_tools.h index 619174976..e1b2261b2 100644 --- a/tests/auto/tools/tst_tools.h +++ b/tests/auto/tools/tst_tools.h @@ -96,8 +96,6 @@ private slots: void stringutils_join_empty(); void stringutils_join_char(); void stringutils_join_char_data(); - void stringutils_startsWith(); - void stringutils_endsWith(); void stringutils_trimmed(); void hash_tuple(); diff --git a/tests/benchmarker/benchmarker-main.cpp b/tests/benchmarker/benchmarker-main.cpp index 2aa379372..4dfe053cc 100644 --- a/tests/benchmarker/benchmarker-main.cpp +++ b/tests/benchmarker/benchmarker-main.cpp @@ -41,7 +41,7 @@ static bool hasRegression = false; static int relativeChange(qint64 oldVal, qint64 newVal) { - return newVal == 0 ? 0 : newVal * 100 / oldVal - 100; + return newVal == 0 ? 0 : (newVal - oldVal) * 100 / oldVal; } static QByteArray relativeChangeString(int change) diff --git a/tests/benchmarker/benchmarker.pro b/tests/benchmarker/benchmarker.pro deleted file mode 100644 index 875cf1de0..000000000 --- a/tests/benchmarker/benchmarker.pro +++ /dev/null @@ -1,20 +0,0 @@ -TARGET = qbs_benchmarker -DESTDIR = ../../bin -CONFIG += console -CONFIG -= app_bundle -CONFIG += c++17 -QT += concurrent -SOURCES = \ - benchmarker-main.cpp \ - benchmarker.cpp \ - commandlineparser.cpp \ - runsupport.cpp \ - valgrindrunner.cpp - -HEADERS = \ - activities.h \ - benchmarker.h \ - commandlineparser.h \ - exception.h \ - runsupport.h \ - valgrindrunner.h diff --git a/tests/clang-format-test/CMakeLists.txt b/tests/clang-format-test/CMakeLists.txt new file mode 100644 index 000000000..e84b539a7 --- /dev/null +++ b/tests/clang-format-test/CMakeLists.txt @@ -0,0 +1,4 @@ +add_qbs_app(clang-format-test + DEPENDS Qt${QT_VERSION_MAJOR}::Core + SOURCES clang-format.cpp +) diff --git a/tests/clang-format-test/clang-format-test.qbs b/tests/clang-format-test/clang-format-test.qbs new file mode 100644 index 000000000..3c34b5962 --- /dev/null +++ b/tests/clang-format-test/clang-format-test.qbs @@ -0,0 +1,5 @@ +QtApplication { + Depends { name: "Qt.core" } + files: "clang-format.cpp" + cpp.warningLevel: "none" +} diff --git a/tests/clang-format-test/clang-format.cpp b/tests/clang-format-test/clang-format.cpp new file mode 100644 index 000000000..3d952f11c --- /dev/null +++ b/tests/clang-format-test/clang-format.cpp @@ -0,0 +1,681 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +// +// KEEP THIS FILE COMPILABLE TO ENSURE THAT WE TEST AGAINST VALID CODE. +// + +// NOTE: Nice, includes are sorted +#include <QCoreApplication> +#include <QFile> +#include <QLoggingCategory> +#include <QObject> +#include <QVector> + +#include <functional> +#include <iostream> +#include <vector> + +static int aGlobalInt = 3; + +// ------------------------------------------------------------------------------------------------- +// Preprocessor +// ------------------------------------------------------------------------------------------------- + +// NOTE: Ops, preprocessor branches are not indented ("#define" vs "# define") +#if defined(TEXTEDITOR_LIBRARY) +#define TEXTEDITOR_EXPORT Q_DECL_EXPORT +#else +#define TEXTEDITOR_EXPORT Q_DECL_IMPORT +#endif + +// ------------------------------------------------------------------------------------------------- +// Macros +// ------------------------------------------------------------------------------------------------- + +#define QTCREATOR_UTILS_EXPORT + +// qtcassert.h: +namespace Utils { +void writeAssertLocation(const char *msg) +{ + std::printf("%s", msg); +} +} // namespace Utils + +#define QTC_ASSERT_STRINGIFY_HELPER(x) #x +#define QTC_ASSERT_STRINGIFY(x) QTC_ASSERT_STRINGIFY_HELPER(x) +#define QTC_ASSERT_STRING(cond) \ + ::Utils::writeAssertLocation("\"" cond "\" in file " __FILE__ \ + ", line " QTC_ASSERT_STRINGIFY(__LINE__)) + +// NOTE: Ops, macro definitions: are more verbose +#define QTC_ASSERT(cond, action) \ + if (cond) { \ + } else { \ + QTC_ASSERT_STRING(#cond); \ + action; \ + } \ + do { \ + } while (0) +#define QTC_CHECK(cond) \ + if (cond) { \ + } else { \ + QTC_ASSERT_STRING(#cond); \ + } \ + do { \ + } while (0) +#define QTC_GUARD(cond) ((cond) ? true : (QTC_ASSERT_STRING(#cond), false)) + +void lala(int foo) +{ + Q_UNUSED(foo) + Q_UNUSED(foo); + QTC_ASSERT(true, return); // NOTE: Ops, extra space with QTC_ASSERT macro and return keyword + QTC_ASSERT(true, return;); + while (true) + QTC_ASSERT(true, break); // ...but this is fine +} + +// ------------------------------------------------------------------------------------------------- +// Namespaces +// ------------------------------------------------------------------------------------------------- + +namespace N { +namespace C { + +struct Foo +{}; + +struct Bar +{}; + +namespace { +class ClassInUnnamedNamespace +{}; +} // namespace + +// NOTE: Nice, namespace end comments are added/updated automatically +} // namespace C + +struct Baz +{}; + +} // namespace N +namespace N2 {} + +// ------------------------------------------------------------------------------------------------- +// Forward declarations +// ------------------------------------------------------------------------------------------------- + +// NOTE: Ops, no one-liner anymore: forward declarations within namespace +namespace N { +struct Baz; +} + +class SourceLocation; +class SourceRange; +class ClangString; + +QT_BEGIN_NAMESPACE +class QString; +QT_END_NAMESPACE + +QT_FORWARD_DECLARE_CLASS(QTextDocument) +QT_FORWARD_DECLARE_CLASS(QTextBlock); + +// ------------------------------------------------------------------------------------------------- +// Using declarations, using directives, using alias, typedefs +// ------------------------------------------------------------------------------------------------- + +// NOTE: OK, using directives are not sorted +using namespace std; +using namespace N2; +using namespace N; + +// NOTE: Nice, using declarations are sorted +using N::C::Bar; +using N::C::Foo; + +// NOTE: OK, typedefs are not sorted +typedef N::C::Foo TypedefedFoor; +typedef N::C::Bar TypedefedBar; + +// NOTE: OK, using aliases are not sorted +using AliasedFoor = N::C::Foo; +using AliasedBar = N::C::Bar; + +// ------------------------------------------------------------------------------------------------- +// Comments +// ------------------------------------------------------------------------------------------------- + +// NOTE: OK, reflowing/wrapping of comments is turned off for now. +// This is a fancy comment that might be reflowed or not or not or not or not or not or not or not or not or not. + +// NOTE: Nice, comments after declarations are aligned +int foo; // fancy comment describing foo +int superDuperFoo; // fancy comment describing superDuperFoo +int lalaFoo; // fancy comment describing lalaFoo + +// ------------------------------------------------------------------------------------------------- +// Function declarations +// ------------------------------------------------------------------------------------------------- + +void f(); + +void f2() {} + +void f3(int parameter1, int parameter2, int parameter3); + +// NOTE: Ops, awkward placement of parameter list, there is no equivalent of +// PenaltyBreakBeforeFirstCallParameter for parameter list +void f3( + int parameter1, int parameter2, int parameter3, int parameter4, int parameter5, int parameter6); + +void f3( + int parameter1, + int parameter2, + int parameter3, + int parameter4, + int parameter5, + int parameter6, + int parrameter7, + int p = aGlobalInt); + +bool operator==(N::Baz, N::Baz); + +template<class T> +void fancyTemplateFunction(); + +template<typename... Type> +void variadicTemplateFunction(Type *...arg); + +// ------------------------------------------------------------------------------------------------- +// Inside functions +// ------------------------------------------------------------------------------------------------- + +int myfunction(int parameter1, int parameter2) +{ + // Function calls + myfunction(parameter1, parameter2); + + // Casts + int value = 3; + int z = (int) value; + int a = static_cast<int>(value + z); + + // Pointer/references alignment + int *p = nullptr; + int &r = *p; + + // Operators + int result = parameter1 + parameter1 + parameter1 + parameter1 + parameter1 + parameter1 + + parameter1 + parameter1; + + // Long expressions + int someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt = -1; + bool condition1 = false; + bool condition2 = false; + // NOTE: Ops, alignment of readable, boolean and complex expressions will be reverted + if (condition1 || condition2 + || someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt) { + return value; + } + + // Initializer lists + vector<int> x{1, 2, 3, 4}; + vector<Foo> y{{}, {}, {}, {}}; + new int[3]{1, 2, 3}; + + // Streams + // NOTE: OK, there is a heuristic (endl, '\n') to wrap statements with stream operators. + cout << "Hello" << parameter1 << endl + << parameter2 << endl + << result << endl + << condition1 << someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt; + cout << "Hello" << parameter1 << '\n' + << parameter2 << '\n' + << a << '\n' + << condition1 << someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt; + // ...but here not: + cout << "Hello" << parameter1 << '\t' << parameter2 << '\t' << z << '\t' << condition1 + << someVeryLooooooooooooooooooooooooooooooooooooooooooooooooooongInt << r; + + return 1; +} + +// ------------------------------------------------------------------------------------------------- +// Ternary Operator +// ------------------------------------------------------------------------------------------------- + +bool ternary() +{ + bool someWhatLongerName; + bool someWhatLongerName2; + bool isThatReallyReallyReallyReallyReallyReallyReallyReallyTrue = false; + bool isThatReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyTrue = false; + + bool yesno = true ? true : false; + bool sino = isThatReallyReallyReallyReallyReallyReallyReallyReallyTrue ? someWhatLongerName + : someWhatLongerName2; + bool danet = isThatReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyTrue + ? someWhatLongerName + : someWhatLongerName2; + + return yesno && sino && danet; +} + +// ------------------------------------------------------------------------------------------------- +// Penalty Test +// ------------------------------------------------------------------------------------------------- + +int functionToCall(int parameter1) +{ + return 1; +} + +int functionToCall(int paramter1, int parameter2) +{ + return 1; +} + +int functionToCall(int paramter1, int parameter2, int parameter3) +{ + return 1; +} + +int functionToCall(int paramter1, int parameter2, int parameter3, int parameter4, int parameter5) +{ + return 1; +} + +int functionToCall( + int paramter1, int parameter2, int parameter3, int parameter4, int parameter5, int paramete6) +{ + return 1; +} + +int functionToCall( + int paramter1, + int parameter2, + int parameter3, + int parameter4, + int parameter5, + int paramete6, + int parameter6) +{ + return 1; +} + +bool functionToCallSt(const QString ¶mter1, const QStringList &list) +{ + return 1; +} + +void emitAddOutput(const QString &text, int priority) {} +void emitAddOutput(const QString &text, int priority, int category) {} + +void penaltyTests(bool isThatTrue) +{ + int valueX = 3; + int valueY = 1; + int valueZ = 1; + int valueXTimesY = valueX * valueY; + int unbelievableBigValue = 1000000; + int unlimitedValueunbelievableBigValue = 1000000; + QString arguments; + QString argumentsVeryLong; + + const QFile::OpenMode openMode = isThatTrue ? QIODevice::ReadOnly + : (QIODevice::ReadOnly | QIODevice::Text); + + const auto someValue10 = functionToCall(valueX, valueY, valueXTimesY); + const auto someValue11 = functionToCall( + valueX, valueY, valueXTimesY, unbelievableBigValue, unbelievableBigValue); + const auto someValue12 = functionToCall( + valueX, + valueY, + valueXTimesY, + unbelievableBigValue, + unbelievableBigValue * unbelievableBigValue, + unbelievableBigValue); + + const auto someValue13 = functionToCall( + valueX, + valueY, + valueXTimesY, + unbelievableBigValue, + functionToCall(functionToCall(valueX), functionToCall(valueY)), + unbelievableBigValue); + + const auto someValue14WithAnOutstandingLongName = functionToCall( + valueX, + valueY, + valueXTimesY, + unbelievableBigValue, + functionToCall(functionToCall(valueX), functionToCall(valueY)), + unbelievableBigValue); + + const bool someValue20 = functionToCall(valueX, valueY, valueXTimesY) || functionToCall(3); + const bool someValue21 = functionToCall(valueX, valueY, valueXTimesY) + || functionToCall(valueX, valueY); + + emitAddOutput( + QCoreApplication::tr("Starting: \"%1\" %2") + .arg("/some/very/very/very/very/long/path/to/an/executable", arguments), + functionToCall(3), + functionToCall(3) | valueX); + + emitAddOutput( + QCoreApplication::tr("Starting: \"%1\" %2") + .arg("/some/very/very/very/very/long/path/to/an/executable", argumentsVeryLong), + functionToCall(3), + functionToCall(3) | unlimitedValueunbelievableBigValue + | unlimitedValueunbelievableBigValue); + + const QString path; + const bool someLongerNameNNNNNNNNNN = functionToCallSt( + path, QStringList(QLatin1String("-print-env"))); +} + +// ------------------------------------------------------------------------------------------------- +// Classes and member functions +// ------------------------------------------------------------------------------------------------- + +class Base1 +{}; +class Base2 +{}; + +class MyClass : public QObject, public Base1, public Base2 +{ + Q_OBJECT + +public: + friend class FriendX; // for X::foo() + friend class OtherFriendY; // for Y::bar() + + MyClass() {} + + MyClass(int d1) + : data1(d1) + {} + + MyClass(int d1, int d2) + : data1(d1) + , data2(d2) + , data3(d2) + {} + + MyClass( + int initialData1, + int initialData2, + int initialData3, + int initialData4, + int initialData5, + int initialData6) + : data1(initialData1) + , data2(initialData2) + , data3(initialData3) + , data4(initialData4) + , data5(initialData5) + , data6(initialData6) + { + // NOTE: Ops, manual alignment of QObject::connect() arguments is reverted + // (we tend to write emitter/receiver on separate lines) + connect(this, &MyClass::inlineZeroStatements, this, &MyClass::nonInlineSingleStatement); + } + + void inlineZeroStatements() {} + void inlineSingleStatement() { aGlobalInt = 2; } + void inlineMultipleStatements() + { + aGlobalInt = 2; + aGlobalInt = 3; + } + + void nonInlineZeroStatements(); + void nonInlineSingleStatement(); + void nonInlineMultipleStatements(); + + virtual void shortVirtual(int parameter1, int parameter2, int parameter3) = 0; + + // NOTE: Ops, awkward placement of "= 0;" + virtual void longerVirtual( + int parameter1, int parameter2, int parameter3, int parameter4, int parameter5) + = 0; + + int someGetter() const; + +private: + int data1 = 0; + int data2 = 0; + int data3 = 0; + int data4 = 0; + int data5 = 0; + int data6 = 0; +}; + +void MyClass::nonInlineZeroStatements() {} + +void MyClass::nonInlineSingleStatement() +{ + aGlobalInt = 2; +} + +void MyClass::nonInlineMultipleStatements() +{ + aGlobalInt = 2; + aGlobalInt = 2; +} + +template<class T> +class TemplateClass +{}; + +// ------------------------------------------------------------------------------------------------- +// Enums +// ------------------------------------------------------------------------------------------------- + +// NOTE: OK, enums: one-liner are possible +enum MyEnum { SourceFiles = 0x1, GeneratedFiles = 0x2, AllFiles = SourceFiles | GeneratedFiles }; + +// NOTE: OK, enums: a comment breaks one-liners +enum MyEnumX { + OSourceFiles = 0x1 // fancy +}; + +// NOTE: OK, enums: longer ones are wrapped +enum MyOtherEnum { + XSourceFiles = 0x1, + XGeneratedFiles = 0x2, + XAllFiles = XSourceFiles | XGeneratedFiles +}; + +enum { + Match_None, + Match_TooManyArgs, + Match_TooFewArgs, + Match_Ok +} matchType + = Match_None; // NOTE: Ops, awkward placement of "= value;" at enum definition+use + +// ------------------------------------------------------------------------------------------------- +// Lambdas +// ------------------------------------------------------------------------------------------------- + +void takeLambda(std::function<int()>) {} +void takeLambdaWithSomeLongerNameHa(std::function<int()>) {} +bool UtilsFiltered(QVector<N::Baz>, std::function<int(const N::Baz &)>) +{ + return true; +} + +void lambda() +{ + auto shortLambda = []() { return 1; }; + auto longLambda = []() { + aGlobalInt = 3; + return; + }; + + takeLambda([]() { return true; }); + takeLambda([]() { + aGlobalInt = 3; + return aGlobalInt; + }); + + // NOTE: Ops, lambda: capture and parameter list should be on separate line + int thisCouldBeSomeLongerFunctionCallExpressionOrSoSoSo; + takeLambdaWithSomeLongerNameHa( + [&]() { return thisCouldBeSomeLongerFunctionCallExpressionOrSoSoSo; }); + + QVector<N::Baz> myClasses; + UtilsFiltered(myClasses, [](const N::Baz &) { return 1; }); + + // NOTE: Ops, lambda: lambda not started on new line in if-condition + if (UtilsFiltered(myClasses, [](const N::Baz &) { return 1; })) { + ++aGlobalInt; + } +} + +// ------------------------------------------------------------------------------------------------- +// Control flow +// ------------------------------------------------------------------------------------------------- + +int fn(int, int, int) +{ + return 1; +} + +void controlFlow(int x) +{ + int y = -1; + + // if + if (true) + fn(1, 2, 3); + + int value = 3; + if (value) { + value += value + 1; + --value; + } + + if (x == y) + fn(1, 2, 3); + else if (x > y) + fn(1, 2, 3); + else + fn(1, 2, 3); + + if (x == y) { + fn(1, 2, 3); + return; + } else if (x > y) { + fn(1, 2, 3); + } else { + fn(1, 2, 3); + } + + // switch + switch (x) { + case 0: + ++aGlobalInt; + return; + case 1: + fn(1, 2, 3); + ++aGlobalInt; + break; + case 2: + fn(1, 2, 3); + break; + default: + break; + } + + // do-while + do { + value += value + 1; + ++value; + } while (true); + + // for + QVector<int> myVector; + for (int i = 0; i < myVector.size(); ++i) + ++aGlobalInt; + + for (QVector<int>::const_iterator i = myVector.begin(); i != myVector.end(); ++i) + ++aGlobalInt; + + QVector<int> myVectorWithLongName; + for (QVector<int>::const_iterator i = myVectorWithLongName.begin(), + ei = myVectorWithLongName.end(); + i != ei; + ++i) { + } + + forever { + ++aGlobalInt; + --aGlobalInt; + } +} + +// ------------------------------------------------------------------------------------------------- +// Function declarations and calls - extreme cases +// ------------------------------------------------------------------------------------------------- + +void extremeFunction(const char[]) {} +void extremeFunction( + int uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunbelievableLongParameter) +{ + extremeFunction( + uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunbelievableLongParameter); + + int uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunbelievableLongValue + = 3; + ++uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunbelievableLongValue; + + extremeFunction( + "some super duper super duper super duper super duper super duper super duper long"); + + // BreakStringLiterals splits the string. + extremeFunction("some super duper super duper super duper super duper super duper super duper " + "super duper long"); +} + +void extremeFunction2( + int parameter1, + int parameter2, + int parameter3WithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVerVeryVeryLong) +{ + extremeFunction2( + parameter1, + parameter2, + parameter3WithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVerVeryVeryLong); +} + +void extremeFunction3( + int parameter1, + int parameter2, + int parameter3WithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVerVeryVeryLongNameX) +{ + extremeFunction3( + parameter1, + parameter2, + parameter3WithAVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVerVeryVeryLongNameX); +} + +// ------------------------------------------------------------------------------------------------- +// Misc +// ------------------------------------------------------------------------------------------------- + +static Q_LOGGING_CATEGORY(log, "qtc.cpptools.builtineditordocumentprocessor", QtWarningMsg) + + int hello; // NOTE: Ops, awkward placement of next token after Q_LOGGING_CATEGORY (semicolon helps) + +// ------------------------------------------------------------------------------------------------- + +int main() {} + +#include "clang-format.moc" diff --git a/tests/fuzzy-test/fuzzy-test.pro b/tests/fuzzy-test/fuzzy-test.pro deleted file mode 100644 index 97083ef7a..000000000 --- a/tests/fuzzy-test/fuzzy-test.pro +++ /dev/null @@ -1,11 +0,0 @@ -TARGET = qbs_fuzzy-test -DESTDIR = ../../bin -CONFIG += console -CONFIG -= app_bundle -SOURCES = main.cpp \ - commandlineparser.cpp \ - fuzzytester.cpp - -HEADERS += \ - commandlineparser.h \ - fuzzytester.h diff --git a/tests/fuzzy-test/fuzzytester.cpp b/tests/fuzzy-test/fuzzytester.cpp index f38ad4736..e601e006f 100644 --- a/tests/fuzzy-test/fuzzytester.cpp +++ b/tests/fuzzy-test/fuzzytester.cpp @@ -151,12 +151,7 @@ QStringList FuzzyTester::findAllCommits(const QString &startCommit) QString allCommitsString; runGit(QStringList() << "log" << (startCommit + "~1.." + m_headCommit) << "--format=format:%h", &allCommitsString); - return allCommitsString.simplified().split(QLatin1Char(' '), -#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0)) - QString::SkipEmptyParts); -#else - Qt::SkipEmptyParts); -#endif + return allCommitsString.simplified().split(QLatin1Char(' '), Qt::SkipEmptyParts); } QString FuzzyTester::findWorkingStartCommit(const QString &startCommit) diff --git a/tests/lspclient/CMakeLists.txt b/tests/lspclient/CMakeLists.txt new file mode 100644 index 000000000..ba6f3dbdc --- /dev/null +++ b/tests/lspclient/CMakeLists.txt @@ -0,0 +1,8 @@ +add_qbs_app(qbs_lspclient + DEPENDS + Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Network + qbscore + qtclsp + SOURCES lspclient.cpp + ) diff --git a/tests/lspclient/lspclient.cpp b/tests/lspclient/lspclient.cpp new file mode 100644 index 000000000..40adc9288 --- /dev/null +++ b/tests/lspclient/lspclient.cpp @@ -0,0 +1,434 @@ +/**************************************************************************** +** +** Copyright (C) 2023 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <lsp/clientcapabilities.h> +#include <lsp/completion.h> +#include <lsp/initializemessages.h> +#include <lsp/languagefeatures.h> +#include <lsp/textsynchronization.h> + +#include <QBuffer> +#include <QCommandLineOption> +#include <QCommandLineParser> +#include <QCoreApplication> +#include <QLocalSocket> + +#include <cstdlib> +#include <iostream> + +enum class Command { + GotoDefinition, + Completion, +}; + +class LspClient : public QObject +{ +public: + LspClient(Command command, const QString &socketPath, const QString &codeToInsert, + int insertLine, int insertColumn, + const QString &filePath, int line, int column); + void start(); + +private: + void finishWithError(const QString &msg); + void exit(int code); + void initiateProtocol(); + void handleIncomingData(); + void sendMessage(const lsp::JsonObject &msg); + void sendMessage(const lsp::JsonRpcMessage &msg); + void handleCurrentMessage(); + void handleInitializeReply(); + void openDocument(); + void insertCode(); + void sendRequest(); + void handleResponse(); + void sendGotoDefinitionRequest(); + void handleGotoDefinitionResponse(); + void sendCompletionRequest(); + void handleCompletionResponse(); + lsp::DocumentUri uri() const; + lsp::DocumentUri::PathMapper mapper() const; + + const Command m_command; + const QString m_socketPath; + const QString m_codeToInsert; + const int m_insertLine; + const int m_insertColumn; + const QString m_filePath; + int m_line; + int m_column; + QLocalSocket m_socket; + QBuffer m_incomingData; + lsp::BaseMessage m_currentMessage; + QJsonObject m_messageObject; + + enum class State { Inactive, Connecting, Initializing, RunningCommand } + m_state = State::Inactive; +}; + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + + const QCommandLineOption socketOption({"socket", "s"}, "The server socket to connect to.", + "socket"); + const QCommandLineOption gotoDefinitionOption( + {"goto-def", "g"}, "Go to definition from the specified location."); + const QCommandLineOption completionOption( + {"completion", "c"}, "Request completion at the specified location."); + const QCommandLineOption insertCodeOption("insert-code", + "A piece of code to insert before doing the actual " + "operation.", + "code"); + const QCommandLineOption insertLocationOption("insert-location", + "The location at which to insert the code.", + "<line>:<column>"); + QCommandLineParser parser; + parser.addOptions( + {socketOption, + insertCodeOption, + insertLocationOption, + gotoDefinitionOption, + completionOption}); + parser.addHelpOption(); + parser.addPositionalArgument("location", "The location at which to operate.", + "<file>:<line>:<column>"); + parser.process(app); + + const auto complainAndExit = [&](const char *text) { + std::cerr << text << std::endl; + parser.showHelp(EXIT_FAILURE); + }; + + if (!parser.isSet(socketOption)) + complainAndExit("Socket must be specified."); + + // Initialized to suppress warning. TODO: In C++23, mark lambdas as noreturn instead. + Command command = Command::GotoDefinition; + + if (parser.isSet(gotoDefinitionOption)) + command = Command::GotoDefinition; + else if (parser.isSet(completionOption)) + command = Command::Completion; + else + complainAndExit("Don't know what to do."); + + if (parser.positionalArguments().size() != 1) + complainAndExit("Need location."); + const auto complainAboutLocationString = [&] { complainAndExit("Invalid location."); }; + const QString loc = parser.positionalArguments().first(); + int sep1 = loc.indexOf(':'); + if (sep1 <= 0) + complainAboutLocationString(); + if (qbs::Internal::HostOsInfo::isWindowsHost()) { + sep1 = loc.indexOf(':', sep1 + 1); + if (sep1 < 0) + complainAboutLocationString(); + } + const int sep2 = loc.indexOf(':', sep1 + 1); + if (sep2 == -1 || sep2 == loc.size() - 1) + complainAboutLocationString(); + const auto extractNumber = [&](const QString &s) { + bool ok; + const int n = s.toInt(&ok); + if (!ok || n <= 0) + complainAboutLocationString(); + return n; + }; + const int line = extractNumber(loc.mid(sep1 + 1, sep2 - sep1 - 1)); + const int column = extractNumber(loc.mid(sep2 + 1)); + + const QString insertLoc = parser.value(insertLocationOption); + int insertLine = -1; + int insertColumn = -1; + if (insertLoc.isEmpty()) { + insertLine = line; + insertColumn = column; + } else { + const int sep = insertLoc.indexOf(':'); + if (sep <= 0) + complainAboutLocationString(); + insertLine = extractNumber(insertLoc.left(sep)); + insertColumn = extractNumber(insertLoc.mid(sep + 1)); + } + + LspClient client(command, parser.value(socketOption), parser.value(insertCodeOption), + insertLine, insertColumn, + QDir::fromNativeSeparators(loc.left(sep1)), line, column); + QMetaObject::invokeMethod(&client, &LspClient::start, Qt::QueuedConnection); + + return app.exec(); +} + +LspClient::LspClient(Command command, const QString &socketPath, const QString &codeToInsert, + int insertLine, int insertColumn, + const QString &filePath, int line, int column) + : m_command(command), m_socketPath(socketPath), m_codeToInsert(codeToInsert), + m_insertLine(insertLine), m_insertColumn(insertColumn), + m_filePath(filePath), m_line(line), m_column(column) +{ + connect(&m_socket, &QLocalSocket::disconnected, this, [this] { + finishWithError("Server disconnected unexpectedly."); + }); + connect(&m_socket, &QLocalSocket::errorOccurred, this, [this] { + finishWithError(QString::fromLatin1("Socket error: %1").arg(m_socket.errorString())); + }); + connect(&m_socket, &QLocalSocket::connected, this, &LspClient::initiateProtocol); + connect(&m_socket, &QLocalSocket::readyRead, this, &LspClient::handleIncomingData); +} + +void LspClient::start() +{ + m_state = State::Connecting; + m_incomingData.open(QIODevice::ReadWrite | QIODevice::Append); + m_socket.connectToServer(m_socketPath); +} + +void LspClient::finishWithError(const QString &msg) +{ + std::cerr << qPrintable(msg) << std::endl; + m_socket.disconnectFromServer(); + exit(EXIT_FAILURE); +} + +void LspClient::exit(int code) +{ + m_socket.disconnect(this); + qApp->exit(code); +} + +void LspClient::initiateProtocol() +{ + if (m_state != State::Connecting) { + finishWithError(QString::fromLatin1("State should be %1, was %2.") + .arg(int(State::Connecting), int(m_state))); + return; + } + m_state = State::Initializing; + + lsp::DynamicRegistrationCapabilities definitionCaps; + definitionCaps.setDynamicRegistration(false); + lsp::TextDocumentClientCapabilities docCaps; + docCaps.setDefinition(definitionCaps); + lsp::ClientCapabilities clientCaps; + clientCaps.setTextDocument(docCaps); + lsp::InitializeParams initParams; + initParams.setCapabilities(clientCaps); + sendMessage(lsp::InitializeRequest(initParams)); +} + +void LspClient::handleIncomingData() +{ + const int pos = m_incomingData.pos(); + m_incomingData.write(m_socket.readAll()); + m_incomingData.seek(pos); + QString parseError; + lsp::BaseMessage::parse(&m_incomingData, parseError, m_currentMessage); + if (!parseError.isEmpty()) { + return finishWithError(QString::fromLatin1("Error parsing server message: %1.") + .arg(parseError)); + } + if (m_currentMessage.isComplete()) { + m_incomingData.buffer().remove(0, m_incomingData.pos()); + m_incomingData.seek(0); + handleCurrentMessage(); + m_currentMessage = {}; + m_messageObject = {}; + if (m_socket.state() == QLocalSocket::ConnectedState) + handleIncomingData(); + } +} + +void LspClient::sendMessage(const lsp::JsonObject &msg) +{ + sendMessage(lsp::JsonRpcMessage(msg)); +} + +void LspClient::sendMessage(const lsp::JsonRpcMessage &msg) +{ + lsp::BaseMessage baseMsg = msg.toBaseMessage(); + m_socket.write(baseMsg.header()); + m_socket.write(baseMsg.content); +} + +void LspClient::handleCurrentMessage() +{ + m_messageObject = lsp::JsonRpcMessage(m_currentMessage).toJsonObject(); + switch (m_state) { + case State::Inactive: + case State::Connecting: + finishWithError("Received message in non-connected state."); + break; + case State::Initializing: + handleInitializeReply(); + openDocument(); + insertCode(); + sendRequest(); + break; + case State::RunningCommand: + handleResponse(); + break; + } +} + +void LspClient::handleInitializeReply() +{ + lsp::ServerCapabilities serverCaps = lsp::InitializeRequest::Response( + m_messageObject).result().value_or(lsp::InitializeResult()).capabilities(); + const auto defProvider = serverCaps.definitionProvider(); + if (!defProvider) + return finishWithError("Expected definition provider."); + const bool * const defProviderValue = std::get_if<bool>(&(*defProvider)); + if (!defProviderValue || !*defProviderValue) + return finishWithError("Expected definition provider."); + sendMessage(lsp::InitializeNotification(lsp::InitializedParams())); +} + +void LspClient::openDocument() +{ + QFile file(m_filePath); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + return finishWithError(QString::fromLatin1("Could not open '%1': %2") + .arg(m_filePath, file.errorString())); + } + lsp::TextDocumentItem item; + item.setUri(uri()); + item.setVersion(0); + item.setText(QString::fromUtf8(file.readAll())); + item.setLanguageId("application/x-qt.qbs+qml"); + sendMessage(lsp::DidOpenTextDocumentNotification(lsp::DidOpenTextDocumentParams(item))); +} + +void LspClient::insertCode() +{ + if (m_codeToInsert.isEmpty()) + return; + + lsp::VersionedTextDocumentIdentifier docId; + docId.setUri(uri()); + docId.setVersion(1); + lsp::DidChangeTextDocumentParams params(docId); + lsp::DidChangeTextDocumentParams::TextDocumentContentChangeEvent change; + const lsp::Position insertPos(m_insertLine - 1, m_insertColumn- 1); + change.setRange({insertPos, insertPos}); + change.setText(m_codeToInsert); + params.setContentChanges({change}); + sendMessage(lsp::DidChangeTextDocumentNotification(params)); + + if (m_insertLine > m_line || (m_insertLine == m_line && m_insertColumn > m_column)) + return; + + const int newlineCount = m_codeToInsert.count('\n'); + m_line += newlineCount; + m_column += m_codeToInsert.size() - (newlineCount == 0 ? 0 : m_codeToInsert.lastIndexOf('\n')); +} + +void LspClient::sendRequest() +{ + m_state = State::RunningCommand; + switch (m_command) { + case Command::GotoDefinition: + return sendGotoDefinitionRequest(); + case Command::Completion: + return sendCompletionRequest(); + } +} + +void LspClient::handleResponse() +{ + const QString error = m_messageObject.value(lsp::errorKey).toObject() + .value("message").toString(); + if (!error.isEmpty()) + return finishWithError(error); + + switch (m_command) { + case Command::GotoDefinition: + return handleGotoDefinitionResponse(); + case Command::Completion: + return handleCompletionResponse(); + } +} + +void LspClient::sendGotoDefinitionRequest() +{ + const lsp::TextDocumentIdentifier doc(uri()); + const lsp::Position pos(m_line - 1, m_column - 1); + sendMessage(lsp::GotoDefinitionRequest({doc, pos})); +} + +void LspClient::handleGotoDefinitionResponse() +{ + const lsp::GotoResult result(lsp::GotoDefinitionRequest::Response(m_messageObject) + .result().value_or(lsp::GotoResult())); + QList<lsp::Utils::Link> links; + const auto loc2Link = [this](const lsp::Location &loc) { return loc.toLink(mapper()); }; + if (const auto loc = std::get_if<lsp::Location>(&result)) { + links << loc2Link(*loc); + } else if (const auto locs = std::get_if<QList<lsp::Location>>(&result)) { + links = lsp::Utils::transform(*locs, loc2Link); + } + for (const lsp::Utils::Link &link : std::as_const(links)) { + std::cout << qPrintable(link.targetFilePath) << ':' << link.targetLine << ':' + << (link.targetColumn + 1) << std::endl; + } + exit(EXIT_SUCCESS); +} + +void LspClient::sendCompletionRequest() +{ + const lsp::TextDocumentIdentifier doc(uri()); + const lsp::Position pos(m_line - 1, m_column - 1); + sendMessage(lsp::CompletionRequest({doc, pos})); +} + +void LspClient::handleCompletionResponse() +{ + const lsp::CompletionResult result(lsp::CompletionRequest::Response(m_messageObject) + .result() + .value_or(lsp::CompletionResult())); + if (const auto items = std::get_if<QList<lsp::CompletionItem>>(&result)) { + for (const lsp::CompletionItem &item : *items) { + std::cout << qPrintable(item.label()); + if (item.detail()) + std::cout << ' ' << qPrintable(*item.detail()); + std::cout << std::endl; + } + } + exit(EXIT_SUCCESS); +} + +lsp::DocumentUri LspClient::uri() const +{ + return lsp::DocumentUri::fromFilePath(lsp::Utils::FilePath::fromUserInput(m_filePath), + mapper()); +} + +lsp::DocumentUri::PathMapper LspClient::mapper() const +{ + return [](const lsp::Utils::FilePath &fp) { return fp; }; +} diff --git a/tests/lspclient/lspclient.qbs b/tests/lspclient/lspclient.qbs new file mode 100644 index 000000000..c89b9e0c0 --- /dev/null +++ b/tests/lspclient/lspclient.qbs @@ -0,0 +1,10 @@ +QbsApp { + name: "qbs_lspclient" + + Depends { name: "qtclsp" } + Depends { name: "Qt.network" } + + cpp.defines: base.filter(function(d) { return d !== "QT_NO_CAST_FROM_ASCII"; }) + + files: "lspclient.cpp" +} diff --git a/tests/tests.pro b/tests/tests.pro deleted file mode 100644 index e454771e4..000000000 --- a/tests/tests.pro +++ /dev/null @@ -1,4 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = auto fuzzy-test - -qtHaveModule(concurrent): SUBDIRS += benchmarker diff --git a/tests/tests.qbs b/tests/tests.qbs index 3cc757c8a..3478ce8aa 100644 --- a/tests/tests.qbs +++ b/tests/tests.qbs @@ -4,7 +4,9 @@ Project { references: [ "auto/auto.qbs", "benchmarker/benchmarker.qbs", + "clang-format-test/clang-format-test.qbs", "fuzzy-test/fuzzy-test.qbs", + "lspclient/lspclient.qbs", ] AutotestRunner { |