diff options
Diffstat (limited to 'tests/auto/blackbox')
129 files changed, 2212 insertions, 263 deletions
diff --git a/tests/auto/blackbox/CMakeLists.txt b/tests/auto/blackbox/CMakeLists.txt index 1d90ec95b..88e19acdf 100644 --- a/tests/auto/blackbox/CMakeLists.txt +++ b/tests/auto/blackbox/CMakeLists.txt @@ -80,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-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/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-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-baremetal/external-static-libraries/external-static-libraries.qbs b/tests/auto/blackbox/testdata-baremetal/external-static-libraries/external-static-libraries.qbs index 7e7427561..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,7 +2,7 @@ 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 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-providers/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-providers/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-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 index 8a7c7d6ed..476a83143 100644 --- 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 @@ -1,16 +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"); + 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", undefined, undefined, found); + Helpers.writeModule(outputBaseDir, "qbsmetatestmodule", theValue, undefined, found); + if (sysroot !== qbs.sysroot) + throw "this is unexpected"; return ""; } } diff --git a/tests/auto/blackbox/testdata-providers/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-providers/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/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/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/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/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/external-libs/external-libs.qbs b/tests/auto/blackbox/testdata/external-libs/external-libs.qbs index 610df0507..326bf5dae 100644 --- a/tests/auto/blackbox/testdata/external-libs/external-libs.qbs +++ b/tests/auto/blackbox/testdata/external-libs/external-libs.qbs @@ -1,7 +1,7 @@ import qbs.TextFile Project { - property string libDir: sourceDirectory + "/libs" + property string libDir: buildDirectory + "/libs" StaticLibrary { name: "lib1" destinationDirectory: project.libDir 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/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 dd2184c7e..d1bdd5d60 100644 --- a/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs +++ b/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs @@ -12,16 +12,18 @@ CppApplication { Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++17" - cpp.minimumMacosVersion: "10.8" + 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/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/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/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 9934efb04..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"] 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/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/blackbox/testdata/lsp/modules/Prefix/m2/m2.qbs b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m2/m2.qbs new file mode 100644 index 000000000..84957060c --- /dev/null +++ b/tests/auto/blackbox/testdata/lsp/modules/Prefix/m2/m2.qbs @@ -0,0 +1,2 @@ +Module { +} 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/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/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/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/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/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/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/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/separate-debug-info/separate-debug-info.qbs b/tests/auto/blackbox/testdata/separate-debug-info/separate-debug-info.qbs index 9f57b7f01..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.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")); } } } 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/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/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 424d08642..dbabfb311 100644 --- a/tests/auto/blackbox/tst_blackbox.cpp +++ b/tests/auto/blackbox/tst_blackbox.cpp @@ -63,7 +63,6 @@ #define WAIT_FOR_NEW_TIMESTAMP() waitForNewTimestamp(testDataDir) using qbs::Internal::HostOsInfo; -using qbs::Profile; class MacosTarHealer { public: @@ -139,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() @@ -299,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; } @@ -699,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")), @@ -708,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"); @@ -794,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() @@ -1387,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")); @@ -1594,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); @@ -1926,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."); @@ -2068,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") @@ -2151,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"; @@ -2165,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")); @@ -2222,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); @@ -2271,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; @@ -2569,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())); @@ -2592,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)); @@ -2653,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"); @@ -2737,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"); @@ -3141,6 +3256,12 @@ 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"); @@ -3457,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"); @@ -3802,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; @@ -3823,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( @@ -3923,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"; @@ -3988,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())); @@ -4058,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"); @@ -4115,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. @@ -4219,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()) @@ -4473,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"); @@ -4564,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"); @@ -4832,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() @@ -4840,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() @@ -4946,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() @@ -5079,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; @@ -5159,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); @@ -5930,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() @@ -5956,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")) @@ -6105,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); } } @@ -6169,6 +6440,92 @@ void TestBlackbox::qbsConfigAddProfile_data() << QString("Profile properties must be key/value pairs"); } +void TestBlackbox::qbsConfigImport() +{ + QFETCH(QString, format); + + QDir::setCurrent(testDataDir + "/qbs-config-import-export"); + + 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); + 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::qbsConfigImport_data() +{ + QTest::addColumn<QString>("format"); + + QTest::newRow("text") << QStringLiteral("txt"); + QTest::newRow("json") << QStringLiteral("json"); +} + +void TestBlackbox::qbsConfigExport() +{ + QFETCH(QString, format); + + 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; + + QCOMPARE(runQbs(params), 0); + + QVERIFY(QFileInfo(filePath).canonicalPath() != QFileInfo(fileName).canonicalPath()); + + QFile exported(filePath); + QFile expected(fileName); + + QVERIFY(exported.open(QIODevice::ReadOnly | QIODevice::Text)); + QVERIFY(expected.open(QIODevice::ReadOnly | QIODevice::Text)); + + QCOMPARE(exported.readAll(), expected.readAll()); +} + +void TestBlackbox::qbsConfigExport_data() +{ + QTest::addColumn<QString>("format"); + + QTest::newRow("text") << QStringLiteral("txt"); + QTest::newRow("json") << QStringLiteral("json"); +} + static QJsonObject getNextSessionPacket(QProcess &session, QByteArray &data) { int totalSize = -1; @@ -6205,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"); @@ -6221,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) { @@ -6249,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(), 3); + QCOMPARE(receivedMessage.value("api-level").toInt(), 5); QCOMPARE(receivedMessage.value("api-compat-level").toInt(), 2); // Resolve & verify structure @@ -6265,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"})); @@ -7188,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); @@ -7197,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); @@ -7207,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() @@ -7338,7 +7827,7 @@ 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 : std::as_const(regKeys)) { QSettings settings(key, QSettings::NativeFormat); @@ -7576,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); @@ -7617,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); @@ -7784,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")); @@ -8104,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()) @@ -8225,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")); @@ -8250,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() @@ -8269,14 +8795,12 @@ void TestBlackbox::grpc() QFETCH(bool, hasModules); rmDirR(relativeBuildDir()); - QbsRunParameters resolveParams("resolve", QStringList{"-f", projectFile}); - if (QTest::currentDataTag() == QLatin1String("cpp")) { - if (const QString extraLibs = qEnvironmentVariable("QBS_EXTRA_GRPC_LIBS"); - !extraLibs.isEmpty()) { - resolveParams.arguments << (QLatin1String("modules.protobuf.cpp._extraGrpcLibs:") - + extraLibs); - } + 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); const bool withGrpc = m_qbsStdout.contains("has grpc: true"); diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h index 4f8e898aa..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(); @@ -126,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(); @@ -163,6 +169,8 @@ private slots: void installPackage(); void installRootFromProjectFile(); void installTree(); + void invalidArtifactPath_data(); + void invalidArtifactPath(); void invalidCommandProperty_data(); void invalidCommandProperty(); void invalidExtensionInstantiation(); @@ -207,6 +215,7 @@ private slots: void missingOverridePrefix(); void moduleConditions(); void movedFileDependency(); + void msvcAsmLinkerFlags(); void multipleChanges(); void multipleConfigurations(); void multiplexedTool(); @@ -229,6 +238,7 @@ private slots: void overrideProjectProperties(); void pathProbe_data(); void pathProbe(); + void pathListInProbe(); void pchChangeTracking(); void perGroupDefineInExportItem(); void pkgConfigProbe(); @@ -247,7 +257,6 @@ private slots: void productDependenciesByType(); void productInExportedModule(); void productProperties(); - void propertyAssignmentOnNonPresentModule(); void propertyAssignmentInFailedModule(); void propertyChanges(); void propertyEvaluationContext(); @@ -261,6 +270,12 @@ private slots: void qbsConfig(); void qbsConfigAddProfile(); void qbsConfigAddProfile_data(); + void qbsConfigImport(); + void qbsConfigImport_data(); + void qbsConfigExport(); + void qbsConfigExport_data(); + void qbsLanguageServer_data(); + void qbsLanguageServer(); void qbsSession(); void qbsVersion(); void qtBug51237(); @@ -277,11 +292,13 @@ private slots: 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(); @@ -336,6 +353,8 @@ private slots: void wholeArchive(); void wholeArchive_data(); void wildCardsAndRules(); + void wildCardsAndChangeTracking_data(); + void wildCardsAndChangeTracking(); void wildcardRenaming(); void zip(); void zip_data(); @@ -346,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_blackboxapple.cpp b/tests/auto/blackbox/tst_blackboxapple.cpp index 01446c815..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); @@ -363,6 +369,9 @@ void TestBlackboxApple::assetCatalog() rmDirR(relativeBuildDir()); + if (!findXcode()) + QSKIP("requires Xcode profile"); + QbsRunParameters params; const QString flattens = "modules.ib.flatten:" + QString(flatten ? "true" : "false"); const QString macosTarget = "modules.cpp.minimumMacosVersion:'10.15'"; @@ -703,28 +712,34 @@ void TestBlackboxApple::byteArrayInfoPlist() 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; @@ -769,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() @@ -791,6 +815,9 @@ void TestBlackboxApple::deploymentTarget() QDir::setCurrent(testDataDir + "/deploymentTarget"); + if (!findXcode()) + QSKIP("requires Xcode profile"); + QbsRunParameters params; params.arguments = QStringList() << "--command-echo-mode" @@ -1097,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())); @@ -1113,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(); @@ -1149,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"}); @@ -1161,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 9c329e961..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 @@ -72,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 8e85640db..317a6b663 100644 --- a/tests/auto/blackbox/tst_blackboxbase.cpp +++ b/tests/auto/blackbox/tst_blackboxbase.cpp @@ -221,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); @@ -274,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 05bd99078..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")) { } @@ -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 index ceb413510..cf6594229 100644 --- a/tests/auto/blackbox/tst_blackboxproviders.cpp +++ b/tests/auto/blackbox/tst_blackboxproviders.cpp @@ -49,60 +49,110 @@ TestBlackboxProviders::TestBlackboxProviders() { } -void TestBlackboxProviders::fallbackModuleProvider_data() +void TestBlackboxProviders::allowedValues() { - 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; + 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::fallbackModuleProvider() +void TestBlackboxProviders::conanProvider() { - QFETCH(bool, fallbacksEnabledInProduct); - QFETCH(bool, fallbacksEnabledGlobally); - QFETCH(QStringList, pkgConfigLibDirs); + QFETCH(bool, generateConanFiles); 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; + 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"); @@ -179,6 +229,22 @@ void TestBlackboxProviders::moduleProvidersCache() 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"); @@ -193,6 +259,7 @@ void TestBlackboxProviders::probeInModuleProvider() 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); } @@ -365,4 +432,12 @@ void TestBlackboxProviders::qbspkgconfigModuleProvider() 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 index 017cc1c5e..088cea6a3 100644 --- a/tests/auto/blackbox/tst_blackboxproviders.h +++ b/tests/auto/blackbox/tst_blackboxproviders.h @@ -41,10 +41,14 @@ public: TestBlackboxProviders(); private slots: - void fallbackModuleProvider_data(); - void fallbackModuleProvider(); + void allowedValues(); + void allowedValues_data(); + void brokenProvider(); + void conanProvider(); + void conanProvider_data(); void moduleProviders(); void moduleProvidersCache(); + void nonEagerModuleProvider(); void probeInModuleProvider(); void providersProperties(); void qbsModulePropertiesInProviders(); @@ -55,6 +59,7 @@ private slots: 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 6bb7838f6..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"; @@ -397,6 +396,20 @@ void TestBlackboxQt::pkgconfigQt_data() << 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() { QDir::setCurrent(testDataDir + "/plugin-meta-data"); @@ -470,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() 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 1c487bc52..57bd7f947 100644 --- a/tests/auto/blackbox/tst_blackboxwindows.cpp +++ b/tests/auto/blackbox/tst_blackboxwindows.cpp @@ -228,7 +228,7 @@ 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 : std::as_const(regKeys)) { const QStringList versions = QSettings(key, QSettings::NativeFormat).childGroups(); |