diff options
Diffstat (limited to 'tests/auto/blackbox')
98 files changed, 1888 insertions, 272 deletions
diff --git a/tests/auto/blackbox/find/find-android.qbs b/tests/auto/blackbox/find/find-android.qbs index 26dedc60f..de5c78d10 100644 --- a/tests/auto/blackbox/find/find-android.qbs +++ b/tests/auto/blackbox/find/find-android.qbs @@ -3,12 +3,23 @@ import qbs.TextFile Product { property string packageName: "" qbs.targetPlatform: "android" + multiplexByQbsProperties: ["architectures"] + + Properties { + condition: qbs.architectures && qbs.architectures.length > 1 + aggregate: true + multiplexedType: "json_arch" + } Depends { name: "Android.sdk"; required: false } Depends { name: "Android.ndk"; required: false } type: ["json"] + Rule { multiplex: true + property stringList inputTags: "json_arch" + inputsFromDependencies: inputTags + inputs: product.aggregate ? [] : inputTags Artifact { filePath: ["android.json"] fileTags: ["json"] @@ -18,17 +29,50 @@ Product { cmd.description = output.filePath; cmd.sourceCode = function() { var tools = {}; + + for (var i in inputs["json_arch"]) { + var tf = new TextFile(inputs["json_arch"][i].filePath, TextFile.ReadOnly); + var json = JSON.parse(tf.readAll()); + tools["ndk"] = json["ndk"]; + tools["ndk-samples"] = json["ndk-samples"]; + tf.close(); + } + if (product.moduleProperty("Android.sdk", "present")) { tools["sdk"] = product.moduleProperty("Android.sdk", "sdkDir"); tools["sdk-build-tools-dx"] = product.Android.sdk.dxFilePath; } + if (product.java && product.java.present) + tools["jar"] = product.java.jarFilePath; + + var tf; + try { + tf = new TextFile(output.filePath, TextFile.WriteOnly); + tf.writeLine(JSON.stringify(tools, undefined, 4)); + } finally { + if (tf) + tf.close(); + } + }; + return cmd; + } + } + Rule { + multiplex: true + Artifact { + filePath: ["android_arch.json"] + fileTags: ["json_arch"] + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = output.filePath; + cmd.sourceCode = function() { + var tools = {}; if (product.moduleProperty("Android.ndk", "present")) { tools["ndk"] = product.moduleProperty("Android.ndk", "ndkDir"); tools["ndk-samples"] = product.Android.ndk.ndkSamplesDir; } - if (product.java && product.java.present) - tools["jar"] = product.java.jarFilePath; var tf; try { @@ -43,3 +87,4 @@ Product { } } } + diff --git a/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c b/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c index 6b625858b..f49b4f90f 100644 --- a/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c +++ b/tests/auto/blackbox/testdata-android/minimal-native/src/main/native/native.c @@ -4,5 +4,6 @@ jstring Java_minimalnative_MinimalNative_stringFromNative(JNIEnv* env, jobject thiz) { + (void)thiz; return (*env)->NewStringUTF(env, "This message comes from native code."); } diff --git a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xml index 289969409..272fe55de 100644 --- a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xml +++ b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product1/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.qt.dummy1" android:versionCode="1" android:versionName="1.0"> - <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="19"/> + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/> <uses-feature android:glEsVersion="0x00020000"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:hasCode="true"> diff --git a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xml index ef0fbe54f..871aadbe6 100644 --- a/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xml +++ b/tests/auto/blackbox/testdata-android/multiple-apks-per-project/product2/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.qt.dummy2" android:versionCode="1" android:versionName="1.0"> - <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="19"/> + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/> <uses-feature android:glEsVersion="0x00020000"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:hasCode="true"> diff --git a/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xml index 6694afc18..f184a8f1f 100644 --- a/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xml +++ b/tests/auto/blackbox/testdata-android/multiple-libs-per-apk/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ <?xml version="1.0"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.qt.dummy" android:versionCode="1" android:versionName="1.0"> - <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="19"/> + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/> <uses-feature android:glEsVersion="0x00020000"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:hasCode="true"> diff --git a/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml b/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml index 066ec0a63..542794825 100644 --- a/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml +++ b/tests/auto/blackbox/testdata-android/qml-app/src/main/AndroidManifest.xml @@ -67,7 +67,7 @@ </application> - <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16"/> + <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28"/> <supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/> <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application. diff --git a/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbs b/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbs index e7c8867bd..a65dcd023 100644 --- a/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbs +++ b/tests/auto/blackbox/testdata-apple/aggregateDependencyLinking/aggregateDependencyLinking.qbs @@ -14,6 +14,7 @@ Project { // This will generate 2 multiplex configs and an aggregate. qbs.architectures: ["x86", "x86_64"] qbs.buildVariant: "debug" + cpp.minimumMacosVersion: "10.8" } CppApplication { @@ -30,6 +31,7 @@ Project { qbs.architecture: "x86_64" qbs.buildVariant: "debug" + cpp.minimumMacosVersion: "10.8" multiplexByQbsProperties: [] } } diff --git a/tests/auto/blackbox/testdata-apple/overrideInfoPlist/Override-Info.plist b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/Override-Info.plist new file mode 100644 index 000000000..f2621e983 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/Override-Info.plist @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>DefaultValue</key> + <string>The default value</string> + <key>OverriddenValue</key> + <string>The default value</string> +</dict> +</plist> diff --git a/tests/auto/blackbox/testdata-apple/overrideInfoPlist/main.c b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/main.c new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/main.c @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs new file mode 100644 index 000000000..e70584ed8 --- /dev/null +++ b/tests/auto/blackbox/testdata-apple/overrideInfoPlist/overrideInfoPlist.qbs @@ -0,0 +1,16 @@ +CppApplication { + Depends { name: "bundle" } + cpp.minimumMacosVersion: "10.7" + files: ["main.c", "Override-Info.plist"] + + Properties { + condition: qbs.targetOS.contains("darwin") + bundle.isBundle: true + bundle.identifierPrefix: "com.test" + + bundle.infoPlist: ({ + "CFBundleName": "My Bundle", + "OverriddenValue": "The overridden value", + }) + } +} diff --git a/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs b/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs index fbab6d0b1..fa4c67b96 100644 --- a/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs +++ b/tests/auto/blackbox/testdata-apple/xcode/xcode-project.qbs @@ -43,8 +43,11 @@ Project { } for (var i = 0; i < a.length; ++i) { - if (a[i] !== b[i]) { - throw msg; + var version1 = a[i].split('.'); + var version2 = b[i].split('.'); + for (var j = 0; j < version1.length; ++j) { + if (version1[j] !== version2[j]) + throw msg; } } } diff --git a/tests/auto/blackbox/testdata-qt/metatypes/metatypes.qbs b/tests/auto/blackbox/testdata-qt/metatypes/metatypes.qbs new file mode 100644 index 000000000..bbc98c934 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/metatypes/metatypes.qbs @@ -0,0 +1,28 @@ +import qbs.Utilities + +StaticLibrary { + name: "mylib" + + Depends { name: "Qt.core" } + + qbs.installPrefix: "some-prefix" + + Probe { + id: capabilitiesChecker + property string version: Qt.core.version + configure: { + if (Utilities.versionCompare(version, "5.15") >= 0) + console.info("can generate"); + else + console.info("cannot generate"); + found = true; + } + } + + files: [ + "mocableclass1.cpp", + "mocableclass1.h", + "mocableclass2.cpp", + "unmocableclass.cpp", + ] +} diff --git a/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.cpp b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.cpp new file mode 100644 index 000000000..06adc8ca5 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.cpp @@ -0,0 +1,3 @@ +#include "mocableclass1.h" + +MocableClass1::MocableClass1(QObject *parent) : QObject(parent) {} diff --git a/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.h b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.h new file mode 100644 index 000000000..020c15179 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass1.h @@ -0,0 +1,8 @@ +#include <QObject> + +class MocableClass1 : public QObject +{ + Q_OBJECT +public: + MocableClass1(QObject *parent = nullptr); +}; diff --git a/tests/auto/blackbox/testdata-qt/metatypes/mocableclass2.cpp b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass2.cpp new file mode 100644 index 000000000..bf538913a --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/metatypes/mocableclass2.cpp @@ -0,0 +1,10 @@ +#include <QObject> + +class MocableClass2 : public QObject +{ + Q_OBJECT +public: + MocableClass2(QObject *parent) : QObject(parent) {} +}; + +#include <mocableclass2.moc> diff --git a/tests/auto/blackbox/testdata-qt/metatypes/unmocableclass.cpp b/tests/auto/blackbox/testdata-qt/metatypes/unmocableclass.cpp new file mode 100644 index 000000000..34330d189 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/metatypes/unmocableclass.cpp @@ -0,0 +1,7 @@ +#include <QObject> + +class UnmocableClass : public QObject +{ +public: + UnmocableClass(QObject *parent) : QObject(parent) {} +}; diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/example.qml b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/example.qml new file mode 100644 index 000000000..ef97df12d --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/example.qml @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// ![0] +import People 1.0 + +Person { + name: "Bob Jones" + shoeSize: 12 +} +// ![0] diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/main.cpp b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/main.cpp new file mode 100644 index 000000000..6c3920f04 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QCoreApplication> +#include <QQmlEngine> +#include <QQmlComponent> +#include <QDebug> +#include "person.h" + +int main(int argc, char ** argv) +{ + QCoreApplication app(argc, argv); + + QQmlEngine engine; + QQmlComponent component(&engine, QUrl("qrc:example.qml")); + auto *person = qobject_cast<Person *>(component.create()); + if (person) { + qWarning() << "The person's name is" << person->name(); + qWarning() << "They wear a" << person->shoeSize() << "sized shoe"; + } else { + qWarning() << component.errors(); + } + + return EXIT_SUCCESS; +} diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.cpp b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.cpp new file mode 100644 index 000000000..de4a33dd0 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "person.h" + +// ![0] +Person::Person(QObject *parent) +: QObject(parent), m_shoeSize(0) +{ +} + +QString Person::name() const +{ + return m_name; +} + +void Person::setName(const QString &n) +{ + m_name = n; +} + +int Person::shoeSize() const +{ + return m_shoeSize; +} + +void Person::setShoeSize(int s) +{ + m_shoeSize = s; +} + +// ![0] diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.h b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.h new file mode 100644 index 000000000..530c335de --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/person.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef PERSON_H +#define PERSON_H + +#include <QObject> +#include <QtQml/qqml.h> + +//![0] +class Person : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(int shoeSize READ shoeSize WRITE setShoeSize) + QML_ELEMENT +public: + Person(QObject *parent = nullptr); + + QString name() const; + void setName(const QString &); + + int shoeSize() const; + void setShoeSize(int); + +private: + QString m_name; + int m_shoeSize; +}; +//![0] + +#endif // PERSON_H diff --git a/tests/auto/blackbox/testdata-qt/qmltyperegistrar/qmltyperegistrar.qbs b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/qmltyperegistrar.qbs new file mode 100644 index 000000000..68dc83743 --- /dev/null +++ b/tests/auto/blackbox/testdata-qt/qmltyperegistrar/qmltyperegistrar.qbs @@ -0,0 +1,33 @@ +import qbs.Utilities + +CppApplication { + name: "myapp" + Depends { name: "Qt.qml" } + + Qt.qml.importVersion: "1" + cpp.includePaths: sourceDirectory + qbs.installPrefix: "" + + files: [ + "main.cpp", + "person.cpp", + "person.h", + ] + + Group { + files: "example.qml" + fileTags: "qt.core.resource_data" + } + + Probe { + id: versionProbe + property string version: Qt.core.version + configure: { + if (Utilities.versionCompare(version, "5.15") >= 0) + console.info("has registrar"); + else + console.info("does not have registrar"); + found = true; + } + } +} diff --git a/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs b/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs index 38ed5fac9..90b968ec9 100644 --- a/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs +++ b/tests/auto/blackbox/testdata-qt/qtscxml/qtscxml.qbs @@ -39,18 +39,22 @@ Project { prepare: { var cmd = new Command(input.filePath); cmd.description = "running " + input.filePath; - var pathVar; - var pathValue; + + var envVars = {}; if (product.qbs.hostOS.contains("windows")) { - pathVar = "PATH"; - pathValue = FileInfo.toWindowsSeparators(input["Qt.core"].binPath); + envVars["PATH"] = FileInfo.toWindowsSeparators(input["Qt.core"].binPath); + } else if (product.qbs.hostOS.contains("macos")) { + envVars["DYLD_LIBRARY_PATH"] = input["Qt.core"].libPath; + envVars["DYLD_FRAMEWORK_PATH"] = input["Qt.core"].libPath; } else { - pathVar = "LD_LIBRARY_PATH"; - pathValue = input["Qt.core"].libPath; + envVars["LD_LIBRARY_PATH"] = input["Qt.core"].libPath; + } + for (var varName in envVars) { + var oldValue = Environment.getEnv(varName) || ""; + var newValue = envVars[varName] + product.qbs.pathListSeparator + oldValue; + cmd.environment.push(varName + '=' + newValue); } - var oldValue = Environment.getEnv(pathVar) || ""; - var newValue = pathValue + product.qbs.pathListSeparator + oldValue; - cmd.environment = [pathVar + '=' + newValue]; + return [cmd]; } } diff --git a/tests/auto/blackbox/testdata/build-variant-defaults/build-variant-defaults.qbs b/tests/auto/blackbox/testdata/build-variant-defaults/build-variant-defaults.qbs new file mode 100644 index 000000000..4015817ca --- /dev/null +++ b/tests/auto/blackbox/testdata/build-variant-defaults/build-variant-defaults.qbs @@ -0,0 +1,16 @@ +CppApplication { + property bool validate: { + var valid = true; + if (qbs.buildVariant === "release") { + valid = !qbs.enableDebugCode && !qbs.debugInformation && qbs.optimization === "fast"; + } else if (qbs.buildVariant === "debug") { + valid = qbs.enableDebugCode && qbs.debugInformation && qbs.optimization === "none"; + } else if (qbs.buildVariant === "profiling") { + valid = !qbs.enableDebugCode && qbs.debugInformation && qbs.optimization === "fast"; + } + + if (!valid) + throw "Invalid defaults"; + return valid; + } +} diff --git a/tests/auto/blackbox/testdata/build-variant-defaults/main.cpp b/tests/auto/blackbox/testdata/build-variant-defaults/main.cpp new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata/build-variant-defaults/main.cpp @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile-probe-project.qbs b/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile-probe-project.qbs new file mode 100644 index 000000000..ab1c68385 --- /dev/null +++ b/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile-probe-project.qbs @@ -0,0 +1,22 @@ +import qbs.Probes +import qbs.TextFile + +Project { + + Probes.ConanfileProbe { + id: conan + conanfilePath: path + "/conanfile.py" + options: ({opt: "True"}) + settings: ({os: "AIX"}) + } + + property var check: { + tf = new TextFile(buildDirectory + "/results.json", TextFile.WriteOnly); + var o = { + json: conan.json.deps_env_info["ENV_VAR"], + dependencies: conan.dependencies["testlib"].libs, + generatedFilesPath: conan.generatedFilesPath + }; + tf.write(JSON.stringify(o)); + } +} diff --git a/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile.py b/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile.py new file mode 100644 index 000000000..630cf0283 --- /dev/null +++ b/tests/auto/blackbox/testdata/conanfile-probe/testapp/conanfile.py @@ -0,0 +1,25 @@ +from conans import ConanFile + +class TestApp(ConanFile): + name = "testapp" + description = "Our project package, to be inspected by the Qbs ConanfileProbe" + license = "none" + version = "6.6.6" + + settings = "os" + options = {"opt": [True, False]} + default_options = {"opt": False} + + requires = "testlib/1.2.3@qbs/testing" + + def configure(self): + self.options["testlib"].opt = self.options.opt + + def source(self): + pass + + def build(self): + pass + + def package(self): + pass diff --git a/tests/auto/blackbox/testdata/conanfile-probe/testlib/conanfile.py b/tests/auto/blackbox/testdata/conanfile-probe/testlib/conanfile.py new file mode 100644 index 000000000..983c22599 --- /dev/null +++ b/tests/auto/blackbox/testdata/conanfile-probe/testlib/conanfile.py @@ -0,0 +1,25 @@ +from conans import ConanFile + +class Testlib(ConanFile): + name = "testlib" + description = "Represents an arbitrary package, for instance on bintray" + license = "none" + version = "1.2.3" + + settings = "os" + options = {"opt": [True, False]} + default_options = {"opt": False} + + def source(self): + pass + + def build(self): + pass + + def package(self): + pass + + def package_info(self): + self.cpp_info.libs = ["testlib1","testlib2"] + self.env_info.ENV_VAR = "TESTLIB_ENV_VAL" + self.user_info.user_var = "testlib_user_val" diff --git a/tests/auto/blackbox/testdata/dependency-profile-mismatch/dependency-profile-mismatch.qbs b/tests/auto/blackbox/testdata/dependency-profile-mismatch/dependency-profile-mismatch.qbs deleted file mode 100644 index 8a6f733c0..000000000 --- a/tests/auto/blackbox/testdata/dependency-profile-mismatch/dependency-profile-mismatch.qbs +++ /dev/null @@ -1,12 +0,0 @@ -Project { - property string mainProfile - property string depProfile - Product { - name: "dep" - qbs.profiles: [project.depProfile] - } - Product { - name: "main" - Depends { name: "dep"; profiles: [project.mainProfile]; } - } -} diff --git a/tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs b/tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs new file mode 100644 index 000000000..ac8e7258c --- /dev/null +++ b/tests/auto/blackbox/testdata/dependency-scanning-loop/dependency-scanning-loop.qbs @@ -0,0 +1,34 @@ +import qbs.FileInfo +import qbs.TextFile + +CppApplication { + name: "app" + cpp.includePaths: buildDirectory + Group { + files: "main.cpp" + fileTags: ["cpp", "custom.in"] + } + Rule { + inputs: "custom.in" + Artifact { + filePath: FileInfo.completeBaseName(input.filePath) + ".h" + fileTags: "hpp" + } + Artifact { + filePath: "custom.txt" + fileTags: "whatever" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "generating " + outputs.hpp[0].fileName; + cmd.sourceCode = function() { + var f = new TextFile(outputs.hpp[0].filePath, TextFile.WriteOnly); + f.writeLine("int main() {}"); + f.close(); + f = new TextFile(outputs.whatever[0].filePath, TextFile.WriteOnly); + f.close(); + } + return cmd; + } + } +} diff --git a/tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp b/tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp new file mode 100644 index 000000000..5e8dda41b --- /dev/null +++ b/tests/auto/blackbox/testdata/dependency-scanning-loop/main.cpp @@ -0,0 +1 @@ +#include <main.h> diff --git a/tests/auto/blackbox/testdata/empty-profile/empty-profile.qbs b/tests/auto/blackbox/testdata/empty-profile/empty-profile.qbs new file mode 100644 index 000000000..da7536315 --- /dev/null +++ b/tests/auto/blackbox/testdata/empty-profile/empty-profile.qbs @@ -0,0 +1,3 @@ +CppApplication { + files: ["main.cpp"] +} diff --git a/tests/auto/blackbox/testdata/empty-profile/main.cpp b/tests/auto/blackbox/testdata/empty-profile/main.cpp new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata/empty-profile/main.cpp @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs b/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs new file mode 100644 index 000000000..60c3d304f --- /dev/null +++ b/tests/auto/blackbox/testdata/freedesktop/freedesktop.qbs @@ -0,0 +1,25 @@ +import qbs 1.0 + +Project { + CppApplication { + name: "main" + install: true + files: [ + "main.cpp", + "myapp.desktop", + "myapp.appdata.xml", + ] + + Depends { name: "freedesktop" } + + freedesktop.name: "My App" + freedesktop.desktopKeys: ({ + 'Icon': "myapp.png" + }) + + Group { + files: "myapp.png" + fileTags: "freedesktop.appIcon" + } + } +} diff --git a/tests/auto/blackbox/testdata/freedesktop/main.cpp b/tests/auto/blackbox/testdata/freedesktop/main.cpp new file mode 100644 index 000000000..905869dfa --- /dev/null +++ b/tests/auto/blackbox/testdata/freedesktop/main.cpp @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml b/tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml new file mode 100644 index 000000000..3cf0a5641 --- /dev/null +++ b/tests/auto/blackbox/testdata/freedesktop/myapp.appdata.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component type="desktop"> + <id>myapp.desktop</id> + <metadata_license>CC0</metadata_license> + <name>MyApp</name> + <summary>The coolest app ever</summary> + + <description> + <p>This is a cool application.</p> + </description> + + <url type="homepage">https://software.house/myapp</url> + <project_license>GPL-2.0+</project_license> + <developer_name>Coding Wizard</developer_name> +</component> diff --git a/tests/auto/blackbox/testdata/freedesktop/myapp.desktop b/tests/auto/blackbox/testdata/freedesktop/myapp.desktop new file mode 100644 index 000000000..dac3014c3 --- /dev/null +++ b/tests/auto/blackbox/testdata/freedesktop/myapp.desktop @@ -0,0 +1,4 @@ +[Desktop Entry] +GenericName=Image Editor +Comment=Create images and edit photographs +Icon=overridden.png diff --git a/tests/auto/blackbox/testdata/freedesktop/myapp.png b/tests/auto/blackbox/testdata/freedesktop/myapp.png new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/auto/blackbox/testdata/freedesktop/myapp.png diff --git a/tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs b/tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs index 815e64853..8c971a747 100644 --- a/tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs +++ b/tests/auto/blackbox/testdata/generate-linker-map-file/generate-linker-map-file.qbs @@ -2,11 +2,14 @@ Project { CppApplication { name: "app-map" files: ["main.cpp"] + // lld-link has different flag for map files, test it by switching to "lld" linkerVariant + Properties { condition: qbs.toolchain.contains("clang-cl"); cpp.linkerVariant: "lld" } cpp.generateLinkerMapFile: true } CppApplication { name: "app-nomap" files: ["main.cpp"] + Properties { condition: qbs.toolchain.contains("clang-cl"); cpp.linkerVariant: "lld" } cpp.generateLinkerMapFile: false } CppApplication { diff --git a/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs b/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs index 8ee3dd9c9..b7a594c13 100644 --- a/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs +++ b/tests/auto/blackbox/testdata/grpc/grpc_cpp.qbs @@ -7,6 +7,7 @@ CppApplication { Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.8" cpp.warningLevel: "none" Depends { name: "protobuf.cpp"; required: false } diff --git a/tests/auto/blackbox/testdata/host-os-properties/host-os-properties.qbs b/tests/auto/blackbox/testdata/host-os-properties/host-os-properties.qbs new file mode 100644 index 000000000..b6b862d1c --- /dev/null +++ b/tests/auto/blackbox/testdata/host-os-properties/host-os-properties.qbs @@ -0,0 +1,8 @@ +CppApplication { + consoleApplication: true + cpp.defines: [ + 'HOST_ARCHITECTURE="' + qbs.hostArchitecture + '"', + 'HOST_PLATFORM="' + qbs.hostPlatform + '"' + ] + files: "main.cpp" +} diff --git a/tests/auto/blackbox/testdata/host-os-properties/main.cpp b/tests/auto/blackbox/testdata/host-os-properties/main.cpp new file mode 100644 index 000000000..b0c239e20 --- /dev/null +++ b/tests/auto/blackbox/testdata/host-os-properties/main.cpp @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main() { + printf("HOST_ARCHITECTURE = %s\n", HOST_ARCHITECTURE); + printf("HOST_PLATFORM = %s\n", HOST_PLATFORM); + return 0; +} diff --git a/tests/auto/blackbox/testdata/install-locations/install-locations.qbs b/tests/auto/blackbox/testdata/install-locations/install-locations.qbs index ed0e1810a..722b233c4 100644 --- a/tests/auto/blackbox/testdata/install-locations/install-locations.qbs +++ b/tests/auto/blackbox/testdata/install-locations/install-locations.qbs @@ -13,7 +13,9 @@ Project { CppApplication { name: "theapp" install: true + installDebugInformation: true files: "main.cpp" + cpp.separateDebugInformation: true Group { fileTagsFilter: "application" fileTags: "some-tag" @@ -23,7 +25,17 @@ Project { name: "thelib" install: true installImportLib: true + installDebugInformation: true Depends { name: "cpp" } + cpp.separateDebugInformation: true files: "thelib.cpp" } + LoadableModule { + name: "theplugin" + install: true + installDebugInformation: true + Depends { name: "cpp" } + cpp.separateDebugInformation: true + files: "theplugin.cpp" + } } diff --git a/tests/auto/blackbox/testdata/install-locations/theplugin.cpp b/tests/auto/blackbox/testdata/install-locations/theplugin.cpp new file mode 100644 index 000000000..ac1ede090 --- /dev/null +++ b/tests/auto/blackbox/testdata/install-locations/theplugin.cpp @@ -0,0 +1,3 @@ +#include "../dllexport.h" + +DLL_EXPORT void pluginFunc() {} diff --git a/tests/auto/blackbox/testdata/last-module-candidate-broken/last-module-candidate-broken.qbs b/tests/auto/blackbox/testdata/last-module-candidate-broken/last-module-candidate-broken.qbs new file mode 100644 index 000000000..db7dc2265 --- /dev/null +++ b/tests/auto/blackbox/testdata/last-module-candidate-broken/last-module-candidate-broken.qbs @@ -0,0 +1,5 @@ +CppApplication { + qbsSearchPaths: "qbs" + Depends { name: "Foo" } + files: "main.cpp" +} diff --git a/tests/auto/blackbox/testdata/last-module-candidate-broken/main.cpp b/tests/auto/blackbox/testdata/last-module-candidate-broken/main.cpp new file mode 100644 index 000000000..76e819701 --- /dev/null +++ b/tests/auto/blackbox/testdata/last-module-candidate-broken/main.cpp @@ -0,0 +1 @@ +int main() { return 0; } diff --git a/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo1.qbs b/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo1.qbs new file mode 100644 index 000000000..ba08b862b --- /dev/null +++ b/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo1.qbs @@ -0,0 +1,3 @@ +Module { + condition: false +} diff --git a/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo2.qbs b/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo2.qbs new file mode 100644 index 000000000..0bc383b86 --- /dev/null +++ b/tests/auto/blackbox/testdata/last-module-candidate-broken/qbs/modules/Foo/Foo2.qbs @@ -0,0 +1,2 @@ +Group { +} diff --git a/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs b/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs index c7462676d..c47a40aea 100644 --- a/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs +++ b/tests/auto/blackbox/testdata/list-property-order/modules/lower/lower.qbs @@ -1,5 +1,5 @@ Module { - property stringList listProp + property stringList listProp: [ "lower" ] Rule { inputs: ["intype"] @@ -10,7 +10,7 @@ Module { prepare: { var cmd = new JavaScriptCommand(); cmd.sourceCode = function() { - console.info("listProp = " + JSON.stringify(product.lower.listProp)); + console.warn("listProp = " + JSON.stringify(product.lower.listProp)); }; cmd.silent = true; return [cmd]; diff --git a/tests/auto/blackbox/testdata/list-property-order/product.qbs b/tests/auto/blackbox/testdata/list-property-order/product.qbs index e92494693..bec122214 100644 --- a/tests/auto/blackbox/testdata/list-property-order/product.qbs +++ b/tests/auto/blackbox/testdata/list-property-order/product.qbs @@ -4,6 +4,7 @@ Product { Depends { name: "higher1" } Depends { name: "higher2" } Depends { name: "higher3" } + lower.listProp: ["product"] Group { files: ["dummy.txt"] fileTags: ["intype"] diff --git a/tests/auto/blackbox/testdata/path-probe/BaseApp.qbs b/tests/auto/blackbox/testdata/path-probe/BaseApp.qbs index 84c00c240..93172579f 100644 --- a/tests/auto/blackbox/testdata/path-probe/BaseApp.qbs +++ b/tests/auto/blackbox/testdata/path-probe/BaseApp.qbs @@ -28,6 +28,7 @@ ** ****************************************************************************/ +import qbs.FileInfo import qbs.Probes CppApplication { @@ -40,6 +41,7 @@ CppApplication { property var inputCandidateFilter property stringList outputFilePaths + property var outputCandidatePaths Probes.PathProbe { id: probe @@ -49,6 +51,7 @@ CppApplication { nameFilter: inputNameFilter candidateFilter: inputCandidateFilter searchPaths: inputSearchPaths + platformSearchPaths: [] } property bool validate: { @@ -56,19 +59,72 @@ CppApplication { if (lhs.length !== rhs.length) return false; for (var i = 0; i < lhs.length; ++i) { - if (lhs[i] !== rhs[i]) + if (Array.isArray(lhs[i]) && Array.isArray(rhs[i])) { + if (!compareArrays(lhs[i], rhs[i])) + return false; + } else if (lhs[i] !== rhs[i]) { return false; + } } return true; }; - if (!probe.found) + if (outputCandidatePaths) { + var actual = probe.allResults.map(function(file) { return file.candidatePaths; }); + if (!compareArrays(actual, outputCandidatePaths)) { + throw "Invalid canndidatePaths: actual = " + JSON.stringify(actual) + + ", expected = " + JSON.stringify(outputCandidatePaths); + } + } + + if (!probe.found) { + if (probe.filePath) { + throw "Invalid filePath: actual = " + JSON.stringify(probe.filePath) + + ", expected = 'undefined'"; + } + if (probe.fileName) { + throw "Invalid fileName: actual = " + JSON.stringify(probe.fileName) + + ", expected = 'undefined'"; + } + if (probe.path) { + throw "Invalid path: actual = " + JSON.stringify(probe.path) + + ", expected = 'undefined'"; + } + throw "Probe failed to find files"; + } if (outputFilePaths) { var actual = probe.allResults.map(function(file) { return file.filePath; }); - if (!compareArrays(actual, outputFilePaths)) - throw "Invalid filePaths: actual = " + actual + ", expected = " + outputFilePaths; + if (!compareArrays(actual, outputFilePaths)) { + throw "Invalid filePaths: actual = " + JSON.stringify(actual) + + ", expected = " + JSON.stringify(outputFilePaths); + } + } + + if (probe.allResults.length !== 1) + return; + + // check that single-file interface matches the first value in allResults + var expectedFilePath = probe.allResults[0].filePath; + if (probe.filePath !== expectedFilePath) { + throw "Invalid filePath: actual = " + probe.filePath + + ", expected = " + expectedFilePath; + } + var expectedFileName = probe.allResults[0].fileName; + if (probe.fileName !== expectedFileName) { + throw "Invalid fileName: actual = " + probe.fileName + + ", expected = " + expectedFileName; + } + var expectedPath = probe.allResults[0].path; + if (probe.path !== expectedPath) { + throw "Invalid path: actual = " + probe.path + + ", expected = " + expectedPath; + } + var expectedCandidatePaths = probe.allResults[0].candidatePaths; + if (!compareArrays(probe.candidatePaths, expectedCandidatePaths)) { + throw "Invalid candidatePaths: actual = " + JSON.stringify(probe.candidatePaths) + + ", expected = " + JSON.stringify(expectedCandidatePaths); } } diff --git a/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs b/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs index a65256a68..c40f22736 100644 --- a/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs +++ b/tests/auto/blackbox/testdata/path-probe/candidate-filter.qbs @@ -3,10 +3,11 @@ import qbs.FileInfo BaseApp { inputNames: ["tool.1", "tool.2"] inputSearchPaths: "bin" - outputFilePaths: ["bin/tool.2"] inputCandidateFilter: { return function(f) { return FileInfo.fileName(f) == "tool.2"; } } + outputFilePaths: ["bin/tool.2"] + outputCandidatePaths: [["bin/tool.1", "bin/tool.2"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs b/tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs index b112db44d..33656d4e6 100644 --- a/tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs +++ b/tests/auto/blackbox/testdata/path-probe/mult-files-mult-suffixes.qbs @@ -1,8 +1,9 @@ BaseApp { inputSelectors: [ - {names : "tool", nameSuffixes: [".1", ".2"]}, + {names : "tool", nameSuffixes: [".0", ".1", ".2"]}, {names : "super-tool", nameSuffixes: [".1"]}, ] inputSearchPaths: "bin" outputFilePaths: ["bin/tool.1", "bin/super-tool.1"] + outputCandidatePaths: [["bin/tool.0", "bin/tool.1"], ["bin/super-tool.1"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs b/tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs index 60c56e6b4..dd0b58aa2 100644 --- a/tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs +++ b/tests/auto/blackbox/testdata/path-probe/mult-files-mult-variants.qbs @@ -1,9 +1,10 @@ BaseApp { inputSelectors: [ "tool", - ["tool.1", "tool.2"], + ["tool.0", "tool.1", "tool.2"], {names : ["tool.3", "tool.4"]}, ] inputSearchPaths: "bin" outputFilePaths: ["bin/tool", "bin/tool.1", "bin/tool.3"] + outputCandidatePaths: [["bin/tool"], ["bin/tool.0", "bin/tool.1"], ["bin/tool.3"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs b/tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs index 5e4fc27ca..7ae78de24 100644 --- a/tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs +++ b/tests/auto/blackbox/testdata/path-probe/mult-files-suffixes.qbs @@ -5,4 +5,5 @@ BaseApp { ] inputSearchPaths: "bin" outputFilePaths: ["bin/tool.2", "bin/super-tool.1"] + outputCandidatePaths: [["bin/tool.2"], ["bin/super-tool.1"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/mult-files.qbs b/tests/auto/blackbox/testdata/path-probe/mult-files.qbs index 08727ac01..aa08befc8 100644 --- a/tests/auto/blackbox/testdata/path-probe/mult-files.qbs +++ b/tests/auto/blackbox/testdata/path-probe/mult-files.qbs @@ -7,4 +7,5 @@ BaseApp { ] inputSearchPaths: "bin" outputFilePaths: ["bin/tool.1", "bin/tool.2", "bin/tool.3", "bin/tool.4"] + outputCandidatePaths: [["bin/tool.1"], ["bin/tool.2"], ["bin/tool.3"], ["bin/tool.4"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/name-filter.qbs b/tests/auto/blackbox/testdata/path-probe/name-filter.qbs index 406988fed..b2840443b 100644 --- a/tests/auto/blackbox/testdata/path-probe/name-filter.qbs +++ b/tests/auto/blackbox/testdata/path-probe/name-filter.qbs @@ -7,4 +7,5 @@ BaseApp { }; } outputFilePaths: ["bin/tool.2"] + outputCandidatePaths: [["bin/tool.2"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs b/tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs index aaa27042c..aabb0fe7b 100644 --- a/tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs +++ b/tests/auto/blackbox/testdata/path-probe/non-existent-selector.qbs @@ -5,4 +5,5 @@ BaseApp { "tool.2", ] inputSearchPaths: "bin" + outputCandidatePaths: [["bin/tool.1"], ["bin/nonexistent"], ["bin/tool.2"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/non-existent.qbs b/tests/auto/blackbox/testdata/path-probe/non-existent.qbs index f0c58fa6c..aad01c31b 100644 --- a/tests/auto/blackbox/testdata/path-probe/non-existent.qbs +++ b/tests/auto/blackbox/testdata/path-probe/non-existent.qbs @@ -1,4 +1,5 @@ BaseApp { inputNames: "nonexistent" inputSearchPaths: "bin" + outputCandidatePaths: [["bin/nonexistent"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs b/tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs index 992a0bea4..98f5b141a 100644 --- a/tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs +++ b/tests/auto/blackbox/testdata/path-probe/single-file-mult-variants.qbs @@ -2,4 +2,5 @@ BaseApp { inputNames: ["tool.1", "tool.2"] inputSearchPaths: "bin" outputFilePaths: ["bin/tool.1"] + outputCandidatePaths: [["bin/tool.1"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs b/tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs index 697665242..292df4add 100644 --- a/tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs +++ b/tests/auto/blackbox/testdata/path-probe/single-file-selector-array.qbs @@ -2,4 +2,5 @@ BaseApp { inputSelectors: ["tool"] inputSearchPaths: "bin" outputFilePaths: ["bin/tool"] + outputCandidatePaths: [["bin/tool"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs b/tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs index d57700baf..cf7cfe436 100644 --- a/tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs +++ b/tests/auto/blackbox/testdata/path-probe/single-file-selector.qbs @@ -2,4 +2,5 @@ BaseApp { inputSelectors: "tool" inputSearchPaths: "bin" outputFilePaths: ["bin/tool"] + outputCandidatePaths: [["bin/tool"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs b/tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs index 4442e719a..3436a49c3 100644 --- a/tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs +++ b/tests/auto/blackbox/testdata/path-probe/single-file-suffixes.qbs @@ -1,6 +1,7 @@ BaseApp { inputNames: "tool" inputSearchPaths: "bin" - inputNameSuffixes: [".1", ".2"] + inputNameSuffixes: [".0", ".1", ".2"] outputFilePaths: ["bin/tool.1"] + outputCandidatePaths: [["bin/tool.0", "bin/tool.1"]] } diff --git a/tests/auto/blackbox/testdata/path-probe/single-file.qbs b/tests/auto/blackbox/testdata/path-probe/single-file.qbs index 3590e7664..e22d7ba0d 100644 --- a/tests/auto/blackbox/testdata/path-probe/single-file.qbs +++ b/tests/auto/blackbox/testdata/path-probe/single-file.qbs @@ -2,4 +2,5 @@ BaseApp { inputNames: "tool" inputSearchPaths: "bin" outputFilePaths: ["bin/tool"] + outputCandidatePaths: [["bin/tool"]] } diff --git a/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs b/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs index 9846eacef..ce89d11f4 100644 --- a/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs +++ b/tests/auto/blackbox/testdata/probeProperties/probeProperties.qbs @@ -1,29 +1,40 @@ import qbs.Probes -CppApplication { - Probes.PathProbe { - id: probe1 - names: ["bin/tool"] - platformSearchPaths: [product.sourceDirectory] - } +Project { - Probes.PathProbe { - id: probe2 - names: ["tool"] - platformSearchPaths: [product.sourceDirectory + "/bin"] - } + CppApplication { + Probes.PathProbe { + id: probe1 + names: ["bin/tool"] + platformSearchPaths: [product.sourceDirectory] + } - targetName: { - console.info("probe1.fileName=" + probe1.fileName); - console.info("probe1.path=" + probe1.path); - console.info("probe1.filePath=" + probe1.filePath); + Probes.PathProbe { + id: probe2 + names: ["tool"] + platformSearchPaths: [product.sourceDirectory + "/bin"] + } - console.info("probe2.fileName=" + probe2.fileName); - console.info("probe2.path=" + probe2.path); - console.info("probe2.filePath=" + probe2.filePath); + targetName: { + console.info("probe1.fileName=" + probe1.fileName); + console.info("probe1.path=" + probe1.path); + console.info("probe1.filePath=" + probe1.filePath); - return name; + console.info("probe2.fileName=" + probe2.fileName); + console.info("probe2.path=" + probe2.path); + console.info("probe2.filePath=" + probe2.filePath); + + console.info("probe3.fileName=" + probe3.fileName); + console.info("probe3.path=" + probe3.path); + console.info("probe3.filePath=" + probe3.filePath); + return name; + } + } + + Probes.PathProbe { + id: probe3 + names: ["tool"] + platformSearchPaths: [project.sourceDirectory + "/bin"] } - files: ["main.c"] } diff --git a/tests/auto/blackbox/testdata/property-evaluation-context/modules/base/base.qbs b/tests/auto/blackbox/testdata/property-evaluation-context/modules/base/base.qbs new file mode 100644 index 000000000..a97538751 --- /dev/null +++ b/tests/auto/blackbox/testdata/property-evaluation-context/modules/base/base.qbs @@ -0,0 +1,4 @@ +Module { + property string productInBase: product.name + property string productInTop: "" +} diff --git a/tests/auto/blackbox/testdata/property-evaluation-context/modules/top/top.qbs b/tests/auto/blackbox/testdata/property-evaluation-context/modules/top/top.qbs new file mode 100644 index 000000000..fa073ff78 --- /dev/null +++ b/tests/auto/blackbox/testdata/property-evaluation-context/modules/top/top.qbs @@ -0,0 +1,6 @@ +Module { + Depends { name: "base" } + base.productInTop: product.name + property string productInTop: product.name + property string productInExport: "" +} diff --git a/tests/auto/blackbox/testdata/property-evaluation-context/property-evaluation-context.qbs b/tests/auto/blackbox/testdata/property-evaluation-context/property-evaluation-context.qbs new file mode 100644 index 000000000..28216c150 --- /dev/null +++ b/tests/auto/blackbox/testdata/property-evaluation-context/property-evaluation-context.qbs @@ -0,0 +1,34 @@ +Project { + qbsSearchPaths: [ path ] + Product { + name: "mylib" + Export { + Depends { name: "top" } + top.productInExport: product.name + } + } + + Product { + type: "rule-output" + name: "myapp" + Depends { name: "mylib" } + + Rule { + alwaysRun: true + multiplex: true + requiresInputs: false + outputFileTags: "rule-output" + prepare: { + var cmd = new JavaScriptCommand(); + cmd.silent = true; + cmd.sourceCode = function() { + console.info("base.productInBase evaluated in: " + product.base.productInBase); + console.info("base.productInTop evaluated in: " + product.base.productInTop); + console.info("top.productInExport evaluated in: " + product.top.productInExport); + console.info("top.productInTop evaluated in: " + product.top.productInTop); + } + return [cmd]; + } + } + } +} diff --git a/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs b/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs index f09706b47..5e6ffc508 100644 --- a/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs +++ b/tests/auto/blackbox/testdata/protobuf/addressbook_cpp.qbs @@ -12,6 +12,7 @@ CppApplication { Depends { name: "cpp" } cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.8" Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { diff --git a/tests/auto/blackbox/testdata/protobuf/import.qbs b/tests/auto/blackbox/testdata/protobuf/import.qbs index 59a094dce..ef4e80c1b 100644 --- a/tests/auto/blackbox/testdata/protobuf/import.qbs +++ b/tests/auto/blackbox/testdata/protobuf/import.qbs @@ -13,6 +13,7 @@ CppApplication { protobuf.cpp.importPaths: [sourceDirectory] cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.8" Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { diff --git a/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs b/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs index 475c1c6c7..493632a0e 100644 --- a/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs +++ b/tests/auto/blackbox/testdata/protobuf/needs-import-dir.qbs @@ -14,6 +14,7 @@ CppApplication { protobuf.cpp.importPaths: (theImportDir ? [theImportDir] : []).concat([sourceDirectory]) cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.8" Depends { name: "protobuf.cpp"; required: false } property bool hasProtobuf: { diff --git a/tests/auto/blackbox/testdata/response-files/response-files.qbs b/tests/auto/blackbox/testdata/response-files/response-files.qbs index efed1dc9f..168cdf66a 100644 --- a/tests/auto/blackbox/testdata/response-files/response-files.qbs +++ b/tests/auto/blackbox/testdata/response-files/response-files.qbs @@ -44,6 +44,9 @@ Project { Product { name: "lotsofobjects" type: ["dynamiclibrary"] + // clang-cl does not use response file internally, thus linker complains that command is + // too long. This can be worked around by calling the linker directly + cpp.linkerMode: qbs.toolchain.contains("clang-cl") ? "manual" : original Depends { name: "cpp" } Rule { multiplex: true diff --git a/tests/auto/blackbox/testdata/sanitizer/sanitizer.cpp b/tests/auto/blackbox/testdata/sanitizer/sanitizer.cpp new file mode 100644 index 000000000..4a7c3ee32 --- /dev/null +++ b/tests/auto/blackbox/testdata/sanitizer/sanitizer.cpp @@ -0,0 +1,4 @@ +int main(int argc, char *argv[]) +{ + return 0; +} diff --git a/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs b/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs new file mode 100644 index 000000000..7b5054316 --- /dev/null +++ b/tests/auto/blackbox/testdata/sanitizer/sanitizer.qbs @@ -0,0 +1,30 @@ +CppApplication { + property string sanitizer + + property bool supportsSanitizer: { + if (qbs.toolchain.contains("clang-cl")) + // only these are supported + return sanitizer === "address" || sanitizer === "undefined"; + if (!qbs.toolchain.contains("gcc")) + return false; + if (qbs.toolchain.contains("mingw")) + return false; + return true; + } + + condition: { + if (!sanitizer) + return true; + if (!supportsSanitizer) + console.info("Compiler does not support sanitizer"); + return supportsSanitizer; + } + qbs.buildVariant: "release" + cpp.cxxLanguageVersion: "c++11" + cpp.minimumMacosVersion: "10.8" + consoleApplication: true + cpp.runtimeLibrary: "static" + cpp.driverFlags: sanitizer ? ["-fsanitize=" + sanitizer] : [] + cpp.debugInformation: true + files: "sanitizer.cpp" +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.h b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.h new file mode 100644 index 000000000..a82b12fbd --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.h @@ -0,0 +1 @@ +#include "lib.h" diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.qbs b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.qbs new file mode 100644 index 000000000..e931b853c --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/app.qbs @@ -0,0 +1,4 @@ +CppApplication { + cpp.includePaths: project.sourceDirectory + "/lib" + files: "main.cpp" +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/main.cpp b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/main.cpp new file mode 100644 index 000000000..2e7bedac8 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/app/main.cpp @@ -0,0 +1,3 @@ +#include "app.h" + +int main() { } diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/lib/lib.h b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/lib/lib.h new file mode 100644 index 000000000..af6f627b7 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/lib/lib.h @@ -0,0 +1,3 @@ +#pragma once + +void lib1_foo();
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/other/other.qbs b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/other/other.qbs new file mode 100644 index 000000000..29682da1c --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/other/other.qbs @@ -0,0 +1,24 @@ +import qbs.TextFile + +Product { + type: "testproduct" + files: "../lib/lib.h" + + Rule { + multiplex: true + Artifact { + fileTags: ["testproduct"] + filePath: "fubar" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "generating text file"; + cmd.sourceCode = function() { + var tf = new TextFile(output.filePath, TextFile.WriteOnly); + tf.writeLine("blubb"); + tf.close(); + } + return cmd; + } + } +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-non-dependency/p.qbs b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/p.qbs new file mode 100644 index 000000000..bcbd5ebce --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-non-dependency/p.qbs @@ -0,0 +1,6 @@ +Project { + references: [ + "app/app.qbs", + "other/other.qbs", + ] +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.h b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.h new file mode 100644 index 000000000..a82b12fbd --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.h @@ -0,0 +1 @@ +#include "lib.h" diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.qbs b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.qbs new file mode 100644 index 000000000..984e9aca9 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/app.qbs @@ -0,0 +1,4 @@ +CppApplication { + Depends { name: "lib" } + files: "main.cpp" +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/app/main.cpp b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/main.cpp new file mode 100644 index 000000000..2e7bedac8 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/app/main.cpp @@ -0,0 +1,3 @@ +#include "app.h" + +int main() { } diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.h b/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.h new file mode 100644 index 000000000..af6f627b7 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.h @@ -0,0 +1,3 @@ +#pragma once + +void lib1_foo();
\ No newline at end of file diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.qbs b/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.qbs new file mode 100644 index 000000000..fe2916714 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/lib/lib.qbs @@ -0,0 +1,7 @@ +Product { + files: "lib.h" + Export { + Depends { name: "cpp" } + cpp.includePaths: product.sourceDirectory + } +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/other/other.qbs b/tests/auto/blackbox/testdata/scan-result-in-other-product/other/other.qbs new file mode 100644 index 000000000..29682da1c --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/other/other.qbs @@ -0,0 +1,24 @@ +import qbs.TextFile + +Product { + type: "testproduct" + files: "../lib/lib.h" + + Rule { + multiplex: true + Artifact { + fileTags: ["testproduct"] + filePath: "fubar" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "generating text file"; + cmd.sourceCode = function() { + var tf = new TextFile(output.filePath, TextFile.WriteOnly); + tf.writeLine("blubb"); + tf.close(); + } + return cmd; + } + } +} diff --git a/tests/auto/blackbox/testdata/scan-result-in-other-product/p.qbs b/tests/auto/blackbox/testdata/scan-result-in-other-product/p.qbs new file mode 100644 index 000000000..fedf84989 --- /dev/null +++ b/tests/auto/blackbox/testdata/scan-result-in-other-product/p.qbs @@ -0,0 +1,7 @@ +Project { + references: [ + "app/app.qbs", + "lib/lib.qbs", + "other/other.qbs", + ] +} diff --git a/tests/auto/blackbox/testdata/undefined-target-platform/undefined-target-platform.qbs b/tests/auto/blackbox/testdata/undefined-target-platform/undefined-target-platform.qbs new file mode 100644 index 000000000..2b3724c26 --- /dev/null +++ b/tests/auto/blackbox/testdata/undefined-target-platform/undefined-target-platform.qbs @@ -0,0 +1,13 @@ +import qbs.File +import qbs.FileInfo + +Product { + name: "undefined-target-platform" + qbs.targetPlatform: undefined + + readonly property bool _validate: { + if (Array.isArray(qbs.targetOS) && qbs.targetOS.length === 0) + return true; + throw "Invalid qbs.targetOS value: " + qbs.targetOS; + } +} diff --git a/tests/auto/blackbox/tst_blackbox.cpp b/tests/auto/blackbox/tst_blackbox.cpp index 861790acd..25e36816c 100644 --- a/tests/auto/blackbox/tst_blackbox.cpp +++ b/tests/auto/blackbox/tst_blackbox.cpp @@ -713,6 +713,25 @@ void TestBlackbox::buildGraphVersions() QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } +void TestBlackbox::buildVariantDefaults_data() +{ + QTest::addColumn<QString>("buildVariant"); + QTest::newRow("default") << QString(); + QTest::newRow("debug") << QStringLiteral("debug"); + QTest::newRow("release") << QStringLiteral("release"); + QTest::newRow("profiling") << QStringLiteral("profiling"); +} + +void TestBlackbox::buildVariantDefaults() +{ + QFETCH(QString, buildVariant); + QDir::setCurrent(testDataDir + "/build-variant-defaults"); + QbsRunParameters params{QStringLiteral("resolve")}; + if (!buildVariant.isEmpty()) + params.arguments << ("modules.qbs.buildVariant:" + buildVariant); + QCOMPARE(runQbs(params), 0); +} + void TestBlackbox::changedFiles_data() { QTest::addColumn<bool>("useChangedFilesForInitialBuild"); @@ -942,20 +961,11 @@ void TestBlackbox::dependenciesProperty() QCOMPARE(product2_cpp_defines.first().toString(), QLatin1String("DIGEDAG")); } -void TestBlackbox::dependencyProfileMismatch() +void TestBlackbox::dependencyScanningLoop() { - QDir::setCurrent(testDataDir + "/dependency-profile-mismatch"); - const SettingsPtr s = settings(); - qbs::Internal::TemporaryProfile depProfile("qbs_autotests_profileMismatch", s.get()); - depProfile.p.setValue("qbs.architecture", "x86"); // Profiles must not be empty... - s->sync(); - QbsRunParameters params(QStringList() << ("project.mainProfile:" + profileName()) - << ("project.depProfile:" + depProfile.p.name())); - params.expectFailure = true; - QVERIFY2(runQbs(params) != 0, m_qbsStderr.constData()); - QVERIFY2(m_qbsStderr.contains(profileName().toLocal8Bit()) - && m_qbsStderr.contains("', which does not exist"), - m_qbsStderr.constData()); + QDir::setCurrent(testDataDir + "/dependency-scanning-loop"); + QCOMPARE(runQbs(), 0); + QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); } void TestBlackbox::deprecatedProperty() @@ -1442,7 +1452,7 @@ void TestBlackbox::versionScript() { const SettingsPtr s = settings(); Profile buildProfile(profileName(), s.get()); - QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); + QStringList toolchain = profileToolchain(buildProfile); if (!toolchain.contains("gcc") || targetOs() != HostOsInfo::HostOsLinux) QSKIP("version script test only applies to Linux"); QDir::setCurrent(testDataDir + "/versionscript"); @@ -1765,6 +1775,40 @@ void TestBlackbox::cxxLanguageVersion_data() std::make_pair(QString("msvc-new"), QString("/std:"))}); } +void TestBlackbox::conanfileProbe() +{ + QString executable = findExecutable({"conan"}); + if (executable.isEmpty()) + QSKIP("conan is not installed or not available in PATH."); + + // We first build a dummy package testlib and use that as dependency + // in the testapp package. + QDir::setCurrent(testDataDir + "/conanfile-probe/testlib"); + QStringList arguments { "create", "-o", "opt=True", "-s", "os=AIX", ".", + "testlib/1.2.3@qbs/testing" }; + QProcess conan; + conan.start(executable, arguments); + QVERIFY(waitForProcessSuccess(conan)); + + QDir::setCurrent(testDataDir + "/conanfile-probe/testapp"); + QCOMPARE(runQbs(QbsRunParameters("resolve", {"--force-probe-execution"})), 0); + + QFile file(relativeBuildDir() + "/results.json"); + QVERIFY(file.open(QIODevice::ReadOnly)); + QVariantMap actualResults = QJsonDocument::fromJson(file.readAll()).toVariant().toMap(); + const auto generatedFilesPath = actualResults.take("generatedFilesPath").toString(); + // We want to make sure that generatedFilesPath is under the project directory, + // but we don't care about the actual name. + QVERIFY(directoryExists(relativeBuildDir() + "/genconan/" + + QFileInfo(generatedFilesPath).baseName())); + + const QVariantMap expectedResults = { + { "json", "TESTLIB_ENV_VAL" }, + { "dependencies", QVariantList{"testlib1", "testlib2"} }, + }; + QCOMPARE(actualResults, expectedResults); +} + void TestBlackbox::cpuFeatures() { QDir::setCurrent(testDataDir + "/cpu-features"); @@ -1832,7 +1876,7 @@ void TestBlackbox::separateDebugInfo() const SettingsPtr s = settings(); Profile buildProfile(profileName(), s.get()); - QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); + QStringList toolchain = profileToolchain(buildProfile); if (isDarwin) { QVERIFY(directoryExists(relativeProductBuildDir("app1") + "/app1.app.dSYM")); QVERIFY(regularFileExists(relativeProductBuildDir("app1") @@ -2035,7 +2079,7 @@ void TestBlackbox::trackExternalProductChanges() rmDirR(relativeBuildDir()); const SettingsPtr s = settings(); const Profile profile(profileName(), s.get()); - const QStringList toolchainTypes = profile.value("qbs.toolchain").toStringList(); + const QStringList toolchainTypes = profileToolchain(profile); if (!toolchainTypes.contains("gcc")) QSKIP("Need GCC-like compiler to run this test"); params.environment = QProcessEnvironment::systemEnvironment(); @@ -2332,9 +2376,11 @@ void TestBlackbox::reproducibleBuild() { const SettingsPtr s = settings(); const Profile profile(profileName(), s.get()); - const QStringList toolchains = profile.value("qbs.toolchain").toStringList(); - if (!toolchains.contains("gcc") || toolchains.contains("clang")) + 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); @@ -2495,6 +2541,36 @@ void TestBlackbox::ruleWithNonRequiredInputs() QVERIFY2(m_qbsStdout.contains("Generating"), m_qbsStdout.constData()); } +void TestBlackbox::sanitizer_data() +{ + QTest::addColumn<QString>("sanitizer"); + QTest::newRow("none") << QString(); + QTest::newRow("address") << QStringLiteral("address"); + QTest::newRow("undefined") << QStringLiteral("undefined"); + QTest::newRow("thread") << QStringLiteral("thread"); +} + +void TestBlackbox::sanitizer() +{ + QFETCH(QString, sanitizer); + QDir::setCurrent(testDataDir + "/sanitizer"); + rmDirR(relativeBuildDir()); + QbsRunParameters params("build", {"--command-echo-mode", "command-line"}); + if (!sanitizer.isEmpty()) { + params.arguments.append( + {QStringLiteral("products.sanitizer.sanitizer:\"") + sanitizer + "\""}); + } + QCOMPARE(runQbs(params), 0); + if (m_qbsStdout.contains(QByteArrayLiteral("Compiler does not support sanitizer"))) + QSKIP("Compiler does not support the specified sanitizer"); + if (!sanitizer.isEmpty()) { + QVERIFY2(m_qbsStdout.contains(QByteArrayLiteral("-fsanitize=") + sanitizer.toLatin1()), + qPrintable(m_qbsStdout)); + } else { + QVERIFY2(!m_qbsStdout.contains(QByteArrayLiteral("-fsanitize=")), qPrintable(m_qbsStdout)); + } +} + void TestBlackbox::scannerItem() { QDir::setCurrent(testDataDir + "/scanner-item"); @@ -2513,6 +2589,47 @@ void TestBlackbox::scannerItem() QVERIFY2(m_qbsStdout.contains("handling file2.in"), m_qbsStdout.constData()); } +void TestBlackbox::scanResultInOtherProduct() +{ + QDir::setCurrent(testDataDir + "/scan-result-in-other-product"); + QCOMPARE(runQbs(QStringList("-vv")), 0); + QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStderr.contains("The file dependency might get lost during change tracking"), + m_qbsStderr.constData()); + WAIT_FOR_NEW_TIMESTAMP(); + REPLACE_IN_FILE("other/other.qbs", "blubb", "blubb2"); + QCOMPARE(runQbs(), 0); + QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); + WAIT_FOR_NEW_TIMESTAMP(); + touch("lib/lib.h"); + QCOMPARE(runQbs(), 0); + QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); +} + +void TestBlackbox::scanResultInNonDependency() +{ + QDir::setCurrent(testDataDir + "/scan-result-in-non-dependency"); + QCOMPARE(runQbs(QStringList("-vv")), 0); + QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStderr.contains("The file dependency might get lost during change tracking"), + m_qbsStderr.constData()); + WAIT_FOR_NEW_TIMESTAMP(); + REPLACE_IN_FILE("other/other.qbs", "blubb", "blubb2"); + QCOMPARE(runQbs(), 0); + QVERIFY2(!m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); + WAIT_FOR_NEW_TIMESTAMP(); + touch("lib/lib.h"); + QCOMPARE(runQbs(), 0); + QEXPECT_FAIL("", "QBS-1532", Continue); + QVERIFY2(m_qbsStdout.contains("compiling main.cpp"), m_qbsStdout.constData()); + QVERIFY2(!m_qbsStdout.contains("generating text file"), m_qbsStdout.constData()); +} + void TestBlackbox::setupBuildEnvironment() { QDir::setCurrent(testDataDir + "/setup-build-environment"); @@ -2821,6 +2938,8 @@ void TestBlackbox::pathProbe() QbsRunParameters buildParams("build", QStringList{"-f", projectFile}); buildParams.expectFailure = !successExpected; QCOMPARE(runQbs(buildParams) == 0, successExpected); + if (!successExpected) + QVERIFY2(m_qbsStderr.contains("Probe failed to find files"), m_qbsStderr); } void TestBlackbox::pchChangeTracking() @@ -3077,6 +3196,9 @@ void TestBlackbox::probeProperties() QVERIFY2(m_qbsStdout.contains("probe2.fileName=tool"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe2.path=" + dir + "/bin"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("probe2.filePath=" + dir + "/bin/tool"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("probe3.fileName=tool"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("probe3.path=" + dir + "/bin"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("probe3.filePath=" + dir + "/bin/tool"), m_qbsStdout.constData()); } void TestBlackbox::probesAndShadowProducts() @@ -3099,7 +3221,7 @@ void TestBlackbox::probeInExportedModule() << QStringLiteral("probe-in-exported-module.qbs"))), 0); QVERIFY2(m_qbsStdout.contains("found: true"), m_qbsStdout.constData()); QVERIFY2(m_qbsStdout.contains("prop: yes"), m_qbsStdout.constData()); - QVERIFY2(m_qbsStdout.contains("listProp: my,myother"), m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains("listProp: myother,my"), m_qbsStdout.constData()); } void TestBlackbox::probesAndArrayProperties() @@ -3368,6 +3490,17 @@ void TestBlackbox::propertyChanges() QVERIFY(m_qbsStdout.contains("Making output from other output")); } +void TestBlackbox::propertyEvaluationContext() +{ + const QString testDir = testDataDir + "/property-evaluation-context"; + QDir::setCurrent(testDir); + QCOMPARE(runQbs(), 0); + QCOMPARE(m_qbsStdout.count("base.productInBase evaluated in: myapp"), 1); + QCOMPARE(m_qbsStdout.count("base.productInTop evaluated in: myapp"), 1); + QCOMPARE(m_qbsStdout.count("top.productInExport evaluated in: mylib"), 1); + QCOMPARE(m_qbsStdout.count("top.productInTop evaluated in: myapp"), 1); +} + void TestBlackbox::qtBug51237() { const QString profileName = "profile-qtBug51237"; @@ -3452,6 +3585,42 @@ void TestBlackbox::dynamicRuleOutputs() QVERIFY(!QFile::exists(sourceFile2)); } +void TestBlackbox::emptyProfile() +{ + QDir::setCurrent(testDataDir + "/empty-profile"); + + const SettingsPtr s = settings(); + const Profile buildProfile(profileName(), s.get()); + bool isMsvc = false; + auto toolchainType = buildProfile.value(QStringLiteral("qbs.toolchainType")).toString(); + QbsRunParameters params; + params.profile = "none"; + + if (toolchainType.isEmpty()) { + const auto toolchain = buildProfile.value(QStringLiteral("qbs.toolchain")).toStringList(); + if (!toolchain.isEmpty()) + toolchainType = toolchain.first(); + } + if (!toolchainType.isEmpty()) { + params.arguments = QStringList{QStringLiteral("qbs.toolchainType:") + toolchainType}; + isMsvc = toolchainType == "msvc" || toolchainType == "clang-cl"; + } + + if (!isMsvc) { + const auto tcPath = + QDir::toNativeSeparators( + buildProfile.value(QStringLiteral("cpp.toolchainInstallPath")).toString()); + auto paths = params.environment.value(QStringLiteral("PATH")) + .split(HostOsInfo::pathListSeparator(), QString::SkipEmptyParts); + if (!tcPath.isEmpty() && !paths.contains(tcPath)) { + paths.prepend(tcPath); + params.environment.insert( + QStringLiteral("PATH"), paths.join(HostOsInfo::pathListSeparator())); + } + } + QCOMPARE(runQbs(params), 0); +} + void TestBlackbox::erroneousFiles_data() { QTest::addColumn<QString>("errorMessage"); @@ -3544,9 +3713,11 @@ void TestBlackbox::escapedLinkerFlags() { const SettingsPtr s = settings(); const Profile buildProfile(profileName(), s.get()); - const QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); - if (!toolchain.contains("gcc") || targetOs() == HostOsInfo::HostOsMacos) + 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")); QCOMPARE(runQbs(params), 0); @@ -3836,6 +4007,40 @@ void TestBlackbox::fileTagsFilterMerging() QVERIFY2(QFile::exists(otherOutput), qPrintable(otherOutput)); } +void TestBlackbox::freedesktop() +{ + if (!HostOsInfo::isAnyUnixHost()) + QSKIP("only applies on Unix"); + if (HostOsInfo::isMacosHost()) + QSKIP("Does not apply on macOS"); + QDir::setCurrent(testDataDir + "/freedesktop"); + QCOMPARE(runQbs(), 0); + + // Check desktop file + QString desktopFilePath = + defaultInstallRoot + "/usr/local/share/applications/myapp.desktop"; + QVERIFY(QFile::exists(desktopFilePath)); + QFile desktopFile(desktopFilePath); + QVERIFY2(desktopFile.open(QIODevice::ReadOnly), qPrintable(desktopFile.errorString())); + QByteArrayList lines = desktopFile.readAll().split('\n'); + // Automatically filled line: + QVERIFY(lines.contains("Exec=main")); + // Name specified in `freedesktop.name` property + QVERIFY(lines.contains("Name=My App")); + // Overridden line: + QVERIFY(lines.contains("Icon=myapp.png")); + // Untouched line: + QVERIFY(lines.contains("Terminal=false")); + + // Check AppStream file + QVERIFY(QFile::exists(defaultInstallRoot + + "/usr/local/share/metainfo/myapp.appdata.xml")); + + // Check icon file + QVERIFY(QFile::exists(defaultInstallRoot + + "/usr/local/share/icons/hicolor/scalable/apps/myapp.png")); +} + void TestBlackbox::installedTransformerOutput() { QDir::setCurrent(testDataDir + "/installed-transformer-output"); @@ -3849,8 +4054,16 @@ void TestBlackbox::installLocations_data() QTest::addColumn<QString>("binDir"); QTest::addColumn<QString>("dllDir"); QTest::addColumn<QString>("libDir"); - QTest::newRow("explicit values") << QString("bindir") << QString("dlldir") << QString("libdir"); - QTest::newRow("default values") << QString() << QString() << QString(); + QTest::addColumn<QString>("pluginDir"); + QTest::addColumn<QString>("dsymDir"); + QTest::newRow("explicit values") + << QString("bindir") + << QString("dlldir") + << QString("libdir") + << QString("pluginDir") + << QString("dsymDir"); + QTest::newRow("default values") + << QString() << QString() << QString() << QString() << QString(); } void TestBlackbox::installLocations() @@ -3859,6 +4072,8 @@ void TestBlackbox::installLocations() QFETCH(QString, binDir); QFETCH(QString, dllDir); QFETCH(QString, libDir); + QFETCH(QString, pluginDir); + QFETCH(QString, dsymDir); QbsRunParameters params("resolve"); if (!binDir.isEmpty()) params.arguments.push_back("products.theapp.installDir:" + binDir); @@ -3866,6 +4081,13 @@ void TestBlackbox::installLocations() params.arguments.push_back("products.thelib.installDir:" + dllDir); if (!libDir.isEmpty()) params.arguments.push_back("products.thelib.importLibInstallDir:" + libDir); + if (!pluginDir.isEmpty()) + params.arguments.push_back("products.theplugin.installDir:" + pluginDir); + if (!dsymDir.isEmpty()) { + params.arguments.push_back("products.theapp.debugInformationInstallDir:" + dsymDir); + params.arguments.push_back("products.thelib.debugInformationInstallDir:" + dsymDir); + params.arguments.push_back("products.theplugin.debugInformationInstallDir:" + dsymDir); + } QCOMPARE(runQbs(params), 0); const bool isWindows = m_qbsStdout.contains("is windows"); const bool isDarwin = m_qbsStdout.contains("is darwin"); @@ -3873,33 +4095,77 @@ void TestBlackbox::installLocations() const bool isUnix = m_qbsStdout.contains("is unix"); QVERIFY(isWindows || isDarwin || isUnix); QCOMPARE(runQbs(QbsRunParameters(QStringList("--clean-install-root"))), 0); - const QString dllFileName = - isWindows ? "thelib.dll" : isDarwin ? "thelib" : "libthelib.so"; - const QString appFileName = isWindows ? "theapp.exe" : "theapp"; - if (binDir.isEmpty()) - binDir = isDarwin ? "/Applications" : "/bin"; - if (dllDir.isEmpty()) - dllDir = isDarwin ? "/Library/Frameworks" : isWindows ? "/bin" : "/lib"; - if (libDir.isEmpty()) - libDir = "/lib"; - if (isDarwin) { - if (isMac) - binDir += "/theapp.app/Contents/MacOS"; - else - binDir += "/theapp.app/"; - dllDir += "/thelib.framework"; - } + + struct BinaryInfo + { + QString fileName; + QString installDir; + QString subDir; + + QString absolutePath(const QString &prefix) const + { + return QDir::cleanPath(prefix + '/' + installDir + '/' + subDir + '/' + fileName); + } + }; + + const BinaryInfo dll = { + isWindows ? "thelib.dll" : isDarwin ? "thelib" : "libthelib.so", + dllDir.isEmpty() + ? (isDarwin ? "/Library/Frameworks" : (isWindows ? "/bin" : "/lib")) + : dllDir, + isDarwin ? "thelib.framework" : "" + }; + const BinaryInfo dllDsym = { + isWindows ? "thelib.pdb" : isDarwin ? "thelib.framework.dSYM" : "libthelib.so.debug", + dsymDir.isEmpty() ? dll.installDir : dsymDir, + {} + }; + const BinaryInfo plugin = { + isWindows ? "theplugin.dll" : isDarwin ? "theplugin" : "libtheplugin.so", + pluginDir.isEmpty() ? dll.installDir : pluginDir, + isDarwin ? (isMac ? "theplugin.bundle/Contents/MacOS" : "theplugin.bundle") : "" + }; + const BinaryInfo pluginDsym = { + isWindows ? "theplugin.pdb" : isDarwin ? "theplugin.bundle.dSYM" : "libtheplugin.so.debug", + dsymDir.isEmpty() ? plugin.installDir : dsymDir, + {} + }; + const BinaryInfo app = { + isWindows ? "theapp.exe" : "theapp", + binDir.isEmpty() ? (isDarwin ? "/Applications" : "/bin") : binDir, + isDarwin ? (isMac ? "theapp.app/Contents/MacOS" : "theapp.app") : "" + }; + const BinaryInfo appDsym = { + isWindows ? "theapp.pdb" : isDarwin ? "theapp.app.dSYM" : "theapp.debug", + dsymDir.isEmpty() ? app.installDir : dsymDir, + {} + }; + const QString installRoot = QDir::currentPath() + "/default/install-root"; const QString installPrefix = isWindows ? QString() : "/usr/local"; const QString fullInstallPrefix = installRoot + '/' + installPrefix + '/'; - const QString appFilePath = fullInstallPrefix + binDir + '/' + appFileName; + const QString appFilePath = app.absolutePath(fullInstallPrefix); QVERIFY2(QFile::exists(appFilePath), qPrintable(appFilePath)); - const QString dllFilePath = fullInstallPrefix + dllDir + '/' + dllFileName; + const QString dllFilePath = dll.absolutePath(fullInstallPrefix); QVERIFY2(QFile::exists(dllFilePath), qPrintable(dllFilePath)); if (isWindows) { - const QString libFilePath = fullInstallPrefix + libDir + "/thelib.lib"; + const BinaryInfo lib = { + "thelib.lib", + libDir.isEmpty() ? "/lib" : libDir, + "" + }; + const QString libFilePath = lib.absolutePath(fullInstallPrefix); QVERIFY2(QFile::exists(libFilePath), qPrintable(libFilePath)); } + const QString pluginFilePath = plugin.absolutePath(fullInstallPrefix); + QVERIFY2(QFile::exists(pluginFilePath), qPrintable(pluginFilePath)); + + const QString appDsymFilePath = appDsym.absolutePath(fullInstallPrefix); + QVERIFY2(QFileInfo(appDsymFilePath).exists(), qPrintable(appDsymFilePath)); + const QString dllDsymFilePath = dllDsym.absolutePath(fullInstallPrefix); + QVERIFY2(QFileInfo(dllDsymFilePath).exists(), qPrintable(dllDsymFilePath)); + const QString pluginDsymFilePath = pluginDsym.absolutePath(fullInstallPrefix); + QVERIFY2(QFile::exists(pluginDsymFilePath), qPrintable(pluginDsymFilePath)); } void TestBlackbox::inputsFromDependencies() @@ -4080,7 +4346,7 @@ void TestBlackbox::cli() const SettingsPtr s = settings(); Profile p("qbs_autotests-cli", s.get()); - const QStringList toolchain = p.value("qbs.toolchain").toStringList(); + const QStringList toolchain = profileToolchain(p); if (!p.exists() || !(toolchain.contains("dotnet") || toolchain.contains("mono"))) QSKIP("No suitable Common Language Infrastructure test profile"); @@ -4311,6 +4577,15 @@ void TestBlackbox::jsExtensionsBinaryFile() QCOMPARE(data.at(7), char(0xFF)); } +void TestBlackbox::lastModuleCandidateBroken() +{ + QDir::setCurrent(testDataDir + "/last-module-candidate-broken"); + QbsRunParameters params; + params.expectFailure = true; + QVERIFY(runQbs(params) != 0); + QVERIFY2(m_qbsStderr.contains("Module Foo could not be loaded"), m_qbsStderr); +} + void TestBlackbox::ld() { QDir::setCurrent(testDataDir + "/ld"); @@ -4549,7 +4824,7 @@ void TestBlackbox::linkerLibraryDuplicates() { const SettingsPtr s = settings(); Profile buildProfile(profileName(), s.get()); - QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); + QStringList toolchain = profileToolchain(buildProfile); if (!toolchain.contains("gcc")) QSKIP("linkerLibraryDuplicates test only applies to GCC toolchain"); @@ -4629,7 +4904,7 @@ void TestBlackbox::linkerScripts() { const SettingsPtr s = settings(); Profile buildProfile(profileName(), s.get()); - QStringList toolchain = buildProfile.value("qbs.toolchain").toStringList(); + QStringList toolchain = profileToolchain(buildProfile); if (!toolchain.contains("gcc") || targetOs() != HostOsInfo::HostOsLinux) QSKIP("linker script test only applies to Linux "); @@ -4743,9 +5018,10 @@ void TestBlackbox::listPropertiesWithOuter() void TestBlackbox::listPropertyOrder() { QDir::setCurrent(testDataDir + "/list-property-order"); - const QbsRunParameters params(QStringList() << "-qq"); + const QbsRunParameters params(QStringList() << "-q"); QCOMPARE(runQbs(params), 0); const QByteArray firstOutput = m_qbsStderr; + QVERIFY(firstOutput.contains("listProp = [\"product\",\"higher3\",\"higher2\",\"higher1\",\"lower\"]")); for (int i = 0; i < 25; ++i) { rmDirR(relativeBuildDir()); QCOMPARE(runQbs(params), 0); @@ -4987,6 +5263,8 @@ void TestBlackbox::propertyPrecedence() // Case 1: [cmdline=0,prod=0,export=0,nonleaf=0,profile=0] QCOMPARE(runQbs(params), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); + QVERIFY2(m_qbsStdout.contains("scalar prop: leaf\n") && m_qbsStdout.contains("list prop: [\"leaf\"]\n"), m_qbsStdout.constData()); @@ -4995,6 +5273,8 @@ void TestBlackbox::propertyPrecedence() // Case 2: [cmdline=0,prod=0,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); + QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: profile\n") && m_qbsStdout.contains("list prop: [\"profile\"]\n"), @@ -5006,6 +5286,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: nonleaf\n") && m_qbsStdout.contains("list prop: [\"nonleaf\",\"leaf\"]\n"), @@ -5014,6 +5295,7 @@ void TestBlackbox::propertyPrecedence() // Case 4: [cmdline=0,prod=0,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: nonleaf\n") && m_qbsStdout.contains("list prop: [\"nonleaf\",\"profile\"]\n"), @@ -5026,6 +5308,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(nonleafFile, false); switchFileContents(depFile, true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"leaf\"]\n"), @@ -5034,15 +5317,21 @@ void TestBlackbox::propertyPrecedence() // Case 6: [cmdline=0,prod=0,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"profile\"]\n"), m_qbsStdout.constData()); + // Case 7: [cmdline=0,prod=0,export=1,nonleaf=1,profile=0] switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.contains("WARNING: Conflicting scalar values at") + && m_qbsStderr.contains("nonleaf.qbs:4:22") + && m_qbsStderr.contains("dep.qbs:6:26"), + m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"nonleaf\",\"leaf\"]\n"), @@ -5051,6 +5340,10 @@ void TestBlackbox::propertyPrecedence() // Case 8: [cmdline=0,prod=0,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.contains("WARNING: Conflicting scalar values at") + && m_qbsStderr.contains("nonleaf.qbs:4:22") + && m_qbsStderr.contains("dep.qbs:6:26"), + m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: export\n") && m_qbsStdout.contains("list prop: [\"export\",\"nonleaf\",\"profile\"]\n"), @@ -5064,6 +5357,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(depFile, false); switchFileContents(productFile, true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"leaf\"]\n"), @@ -5072,6 +5366,7 @@ void TestBlackbox::propertyPrecedence() // Case 10: [cmdline=0,prod=1,export=0,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"profile\"]\n"), @@ -5081,6 +5376,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"nonleaf\",\"leaf\"]\n"), @@ -5089,6 +5385,7 @@ void TestBlackbox::propertyPrecedence() // Case 12: [cmdline=0,prod=1,export=0,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"nonleaf\",\"profile\"]\n"), @@ -5099,6 +5396,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(nonleafFile, false); switchFileContents(depFile, true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"leaf\"]\n"), @@ -5107,6 +5405,7 @@ void TestBlackbox::propertyPrecedence() // Case 14: [cmdline=0,prod=1,export=1,nonleaf=0,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"profile\"]\n"), @@ -5116,6 +5415,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), false); switchFileContents(nonleafFile, true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"nonleaf\",\"leaf\"]\n"), @@ -5124,6 +5424,7 @@ void TestBlackbox::propertyPrecedence() // Case 16: [cmdline=0,prod=1,export=1,nonleaf=1,profile=1] switchProfileContents(profile.p, s.get(), true); QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: product\n") && m_qbsStdout.contains("list prop: [\"product\",\"export\",\"nonleaf\",\"profile\"]\n"), @@ -5137,6 +5438,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(productFile, false); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5146,6 +5448,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5156,6 +5459,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5165,6 +5469,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5176,6 +5481,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(depFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5185,6 +5491,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5195,6 +5502,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5204,6 +5512,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5216,6 +5525,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(productFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5225,6 +5535,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5235,6 +5546,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5244,6 +5556,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5255,6 +5568,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(depFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5264,6 +5578,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5274,6 +5589,7 @@ void TestBlackbox::propertyPrecedence() switchFileContents(nonleafFile, true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5283,6 +5599,7 @@ void TestBlackbox::propertyPrecedence() switchProfileContents(profile.p, s.get(), true); resolveParams.arguments << "modules.leaf.scalarProp:cmdline" << "modules.leaf.listProp:cmdline"; QCOMPARE(runQbs(resolveParams), 0); + QVERIFY2(m_qbsStderr.isEmpty(), m_qbsStderr.constData()); QCOMPARE(runQbs(params), 0); QVERIFY2(m_qbsStdout.contains("scalar prop: cmdline\n") && m_qbsStdout.contains("list prop: [\"cmdline\"]\n"), @@ -5563,8 +5880,8 @@ 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(), 1); - QCOMPARE(receivedMessage.value("api-compat-level").toInt(), 1); + QCOMPARE(receivedMessage.value("api-level").toInt(), 2); + QCOMPARE(receivedMessage.value("api-compat-level").toInt(), 2); // Resolve & verify structure QJsonObject resolveMessage; @@ -5622,7 +5939,7 @@ void TestBlackbox::qbsSession() const QJsonObject group = v.toObject(); const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); - const auto findArtifact = [&sourceArtifacts](const QString fileName) { + const auto findArtifact = [&sourceArtifacts](const QString &fileName) { for (const QJsonValue &v : sourceArtifacts) { const QJsonObject artifact = v.toObject(); if (QFileInfo(artifact.value("file-path").toString()).fileName() @@ -5892,34 +6209,51 @@ void TestBlackbox::qbsSession() qDebug() << error; } QVERIFY(error.isEmpty()); - QJsonObject projectData = receivedMessage.value("project-data").toObject(); - QJsonArray products = projectData.value("products").toArray(); - bool file1 = false; - bool file2 = false; - for (const QJsonValue &v : products) { - const QJsonObject product = v.toObject(); - const QString productName = product.value("full-display-name").toString(); - const QJsonArray groups = product.value("groups").toArray(); - for (const QJsonValue &v : groups) { - const QJsonObject group = v.toObject(); - const QString groupName = group.value("name").toString(); - const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); - for (const QJsonValue &v : sourceArtifacts) { - const QString filePath = v.toObject().value("file-path").toString(); - if (filePath.endsWith("file1.cpp")) { - QCOMPARE(productName, QString("theLib")); - QCOMPARE(groupName, QString("sources")); - file1 = true; - } else if (filePath.endsWith("file2.cpp")) { - QCOMPARE(productName, QString("theLib")); - QCOMPARE(groupName, QString("sources")); - file2 = true; + + receivedReply = false; + sendPacket(resolveMessage); + 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()); + const QJsonObject projectData = receivedMessage.value("project-data").toObject(); + QJsonArray products = projectData.value("products").toArray(); + bool file1 = false; + bool file2 = false; + for (const QJsonValue &v : products) { + const QJsonObject product = v.toObject(); + const QString productName = product.value("full-display-name").toString(); + const QJsonArray groups = product.value("groups").toArray(); + for (const QJsonValue &v : groups) { + const QJsonObject group = v.toObject(); + const QString groupName = group.value("name").toString(); + const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); + for (const QJsonValue &v : sourceArtifacts) { + const QString filePath = v.toObject().value("file-path").toString(); + if (filePath.endsWith("file1.cpp")) { + QCOMPARE(productName, QString("theLib")); + QCOMPARE(groupName, QString("sources")); + file1 = true; + } else if (filePath.endsWith("file2.cpp")) { + QCOMPARE(productName, QString("theLib")); + QCOMPARE(groupName, QString("sources")); + file2 = true; + } + } } } + QVERIFY(file1); + QVERIFY(file2); } } - QVERIFY(file1); - QVERIFY(file2); + QVERIFY(receivedReply); + receivedReply = false; receivedProcessResult = false; bool compiledFile1 = false; @@ -5978,32 +6312,48 @@ void TestBlackbox::qbsSession() if (!error.isEmpty()) qDebug() << error; QVERIFY(error.isEmpty()); - projectData = receivedMessage.value("project-data").toObject(); - products = projectData.value("products").toArray(); - file1 = false; - file2 = false; - for (const QJsonValue &v : products) { - const QJsonObject product = v.toObject(); - const QString productName = product.value("full-display-name").toString(); - const QJsonArray groups = product.value("groups").toArray(); - for (const QJsonValue &v : groups) { - const QJsonObject group = v.toObject(); - const QString groupName = group.value("name").toString(); - const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); - for (const QJsonValue &v : sourceArtifacts) { - const QString filePath = v.toObject().value("file-path").toString(); - if (filePath.endsWith("file1.cpp")) { - file1 = true; - } else if (filePath.endsWith("file2.cpp")) { - QCOMPARE(productName, QString("theLib")); - QCOMPARE(groupName, QString("sources")); - file2 = true; + receivedReply = false; + sendPacket(resolveMessage); + 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()); + const QJsonObject projectData = receivedMessage.value("project-data").toObject(); + QJsonArray products = projectData.value("products").toArray(); + bool file1 = false; + bool file2 = false; + for (const QJsonValue &v : products) { + const QJsonObject product = v.toObject(); + const QString productName = product.value("full-display-name").toString(); + const QJsonArray groups = product.value("groups").toArray(); + for (const QJsonValue &v : groups) { + const QJsonObject group = v.toObject(); + const QString groupName = group.value("name").toString(); + const QJsonArray sourceArtifacts = group.value("source-artifacts").toArray(); + for (const QJsonValue &v : sourceArtifacts) { + const QString filePath = v.toObject().value("file-path").toString(); + if (filePath.endsWith("file1.cpp")) { + file1 = true; + } else if (filePath.endsWith("file2.cpp")) { + QCOMPARE(productName, QString("theLib")); + QCOMPARE(groupName, QString("sources")); + file2 = true; + } + } } } + QVERIFY(!file1); + QVERIFY(file2); } } - QVERIFY(!file1); - QVERIFY(file2); + QVERIFY(receivedReply); + receivedReply = false; receivedProcessResult = false; compiledFile1 = false; @@ -7012,6 +7362,12 @@ void TestBlackbox::typescript() QVERIFY(regularFileExists(relativeProductBuildDir("animals") + "/main.js")); } +void TestBlackbox::undefinedTargetPlatform() +{ + QDir::setCurrent(testDataDir + "/undefined-target-platform"); + QCOMPARE(runQbs(), 0); +} + void TestBlackbox::importInPropertiesCondition() { QDir::setCurrent(testDataDir + "/import-in-properties-condition"); @@ -7776,6 +8132,17 @@ void TestBlackbox::grpc() QCOMPARE(runQbs(runParams), 0); } +void TestBlackbox::hostOsProperties() +{ + QDir::setCurrent(testDataDir + "/host-os-properties"); + QCOMPARE(runQbs(QStringLiteral("run")), 0); + QVERIFY2(m_qbsStdout.contains( + ("HOST_ARCHITECTURE = " + HostOsInfo::hostOSArchitecture()).data()), + m_qbsStdout.constData()); + QVERIFY2(m_qbsStdout.contains(("HOST_PLATFORM = " + HostOsInfo::hostOSIdentifier()).data()), + m_qbsStdout.constData()); +} + void TestBlackbox::ico() { QDir::setCurrent(testDataDir + "/ico"); diff --git a/tests/auto/blackbox/tst_blackbox.h b/tests/auto/blackbox/tst_blackbox.h index 4e2755724..757462b80 100644 --- a/tests/auto/blackbox/tst_blackbox.h +++ b/tests/auto/blackbox/tst_blackbox.h @@ -60,6 +60,8 @@ private slots: void buildDirectories(); void buildEnvChange(); void buildGraphVersions(); + void buildVariantDefaults_data(); + void buildVariantDefaults(); void changedFiles_data(); void changedFiles(); void changedInputsFromDependencies(); @@ -83,9 +85,10 @@ private slots: void conflictingArtifacts(); void cxxLanguageVersion(); void cxxLanguageVersion_data(); + void conanfileProbe(); void cpuFeatures(); void dependenciesProperty(); - void dependencyProfileMismatch(); + void dependencyScanningLoop(); void deprecatedProperty(); void disappearedProfile(); void discardUnusedData(); @@ -96,6 +99,7 @@ private slots: void dynamicMultiplexRule(); void dynamicProject(); void dynamicRuleOutputs(); + void emptyProfile(); void enableExceptions(); void enableExceptions_data(); void enableRtti(); @@ -118,6 +122,7 @@ private slots: void externalLibs(); void fileDependencies(); void fileTagsFilterMerging(); + void freedesktop(); void generatedArtifactAsInputToDynamicRule(); void generateLinkerMapFile(); void generator(); @@ -125,6 +130,7 @@ private slots: void groupsInModules(); void grpc_data(); void grpc(); + void hostOsProperties(); void ico(); void importAssignment(); void importChangeTracking(); @@ -164,6 +170,7 @@ private slots: void jsExtensionsTemporaryDir(); void jsExtensionsTextFile(); void jsExtensionsBinaryFile(); + void lastModuleCandidateBroken(); void ld(); void linkerMode(); void linkerVariant_data(); @@ -236,6 +243,7 @@ private slots: void propertyAssignmentOnNonPresentModule(); void propertyAssignmentInFailedModule(); void propertyChanges(); + void propertyEvaluationContext(); void propertyPrecedence(); void properQuoting(); void propertiesInExportItems(); @@ -265,7 +273,11 @@ private slots: void ruleCycle(); void ruleWithNoInputs(); void ruleWithNonRequiredInputs(); + void sanitizer_data(); + void sanitizer(); void scannerItem(); + void scanResultInOtherProduct(); + void scanResultInNonDependency(); void setupBuildEnvironment(); void setupRunEnvironment(); void smartRelinking(); @@ -301,6 +313,7 @@ private slots: void trackRemoveProduct(); void transitiveOptionalDependencies(); void typescript(); + void undefinedTargetPlatform(); void usingsAsSoleInputsNonMultiplexed(); void variantSuffix(); void variantSuffix_data(); diff --git a/tests/auto/blackbox/tst_blackboxandroid.cpp b/tests/auto/blackbox/tst_blackboxandroid.cpp index e312c4493..eb0303a07 100644 --- a/tests/auto/blackbox/tst_blackboxandroid.cpp +++ b/tests/auto/blackbox/tst_blackboxandroid.cpp @@ -79,7 +79,7 @@ void TestBlackboxAndroid::android() QFETCH(QString, projectDir); QFETCH(QStringList, productNames); QFETCH(QList<QByteArrayList>, expectedFilesLists); - QFETCH(QStringList, customProperties); + QFETCH(QStringList, qmlAppCustomProperties); const SettingsPtr s = settings(); Profile p(theProfileName(projectDir == "qml-app"), s.get()); @@ -110,7 +110,7 @@ void TestBlackboxAndroid::android() auto currentExpectedFilesLists = expectedFilesLists; const QString configArgument = "config:" + configName; QbsRunParameters resolveParams("resolve"); - resolveParams.arguments << configArgument << customProperties; + resolveParams.arguments << configArgument << qmlAppCustomProperties; resolveParams.profile = p.name(); QCOMPARE(runQbs(resolveParams), 0); QbsRunParameters buildParams(QStringList{"--command-echo-mode", "command-line", @@ -206,14 +206,41 @@ void TestBlackboxAndroid::android_data() .toString() == "clang"; return QByteArray("lib/${ARCH}/") + (usesClang ? "libc++_shared.so" : oldcxxLib); }; - const QByteArrayList archsForQt = { pQt.value("qbs.architecture").toString().toUtf8() }; - QByteArrayList ndkArchsForQt = archsForQt; - if (ndkArchsForQt.first() == "armv7a") - ndkArchsForQt.first() = "armeabi-v7a"; - else if (ndkArchsForQt.first() == "armv5te") - ndkArchsForQt.first() = "armeabi"; - else if (ndkArchsForQt.first() == "arm64") - ndkArchsForQt.first() = "arm64-v8a"; + + bool usingOldQt = true; + QStringList qmakeFilePaths = pQt.value(QStringLiteral("moduleProviders.Qt.qmakeFilePaths")). + toStringList(); + if (qmakeFilePaths.size() == 1) { + qbs::Version version = TestBlackboxBase::qmakeVersion(qmakeFilePaths[0]); + if (version.isValid() && version >= qbs::Version(5, 14)) + usingOldQt = false; + } + + QByteArrayList archsForQt; + if (usingOldQt) { + archsForQt = { pQt.value("qbs.architecture").toString().toUtf8() }; + if (archsStringList.empty()) + archsStringList << QStringLiteral("armv7a"); // must match default in common.qbs + } else { + QStringList archsForQtStringList = pQt.value(QStringLiteral("qbs.architectures")) + .toStringList(); + if (archsForQtStringList.empty()) + archsForQtStringList << pQt.value("qbs.architecture").toString(); + std::transform(archsForQtStringList.begin(), + archsForQtStringList.end(), + std::back_inserter(archsForQt), + [] (const QString &s) { + return s.toUtf8(); + }); + } + + QByteArrayList ndkArchsForQt; + std::transform(archsForQt.begin(), archsForQt.end(), std::back_inserter(ndkArchsForQt), + [] (const QString &s) { + return s.toUtf8().replace("armv7a", "armeabi-v7a") + .replace("armv5te", "armeabi") + .replace("arm64", "arm64-v8a"); + }); auto expandArchs = [] (const QByteArrayList &archs, const QByteArrayList &lst) { const QByteArray &archPlaceHolder = "${ARCH}"; @@ -237,7 +264,7 @@ void TestBlackboxAndroid::android_data() QTest::addColumn<QString>("projectDir"); QTest::addColumn<QStringList>("productNames"); QTest::addColumn<QList<QByteArrayList>>("expectedFilesLists"); - QTest::addColumn<QStringList>("customProperties"); + QTest::addColumn<QStringList>("qmlAppCustomProperties"); QTest::newRow("teapot") << "teapot" << QStringList("TeapotNativeActivity") << (QList<QByteArrayList>() << commonFiles + expandArchs(archs, { @@ -257,9 +284,12 @@ void TestBlackboxAndroid::android_data() "lib/${ARCH}/libdependency.so"})) << QStringList{"products.minimalnative.multiplexByQbsProperties:[]", "modules.qbs.architecture:" + archsStringList.first()}; - QTest::newRow("qml app") - << "qml-app" << QStringList("qmlapp") - << (QList<QByteArrayList>() << commonFiles + expandArchs(ndkArchsForQt, { + QByteArrayList qmlAppExpectedFiles; + QByteArrayList qmlAppMinistroExpectedFiles; + QByteArrayList qmlAppCustomMetaDataExpectedFiles; + QStringList qmlAppCustomProperties; + if (usingOldQt) { + qmlAppExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, { "resources.arsc", "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes", "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir", @@ -298,64 +328,157 @@ void TestBlackboxAndroid::android_data() "lib/${ARCH}/libQt5QuickParticles.so", "lib/${ARCH}/libQt5Quick.so", "lib/${ARCH}/libqmlapp.so", - "res/layout/splash.xml"})) - << QStringList{"modules.Android.sdk.automaticSources:false", - "modules.qbs.architecture:" + archsForQt.first()}; - QTest::newRow("qml app using Ministro") - << "qml-app" << QStringList("qmlapp") - << (QList<QByteArrayList>() << commonFiles + expandArchs(ndkArchsForQt, { + "res/layout/splash.xml"}); + qmlAppMinistroExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, { + "resources.arsc", + "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", + "lib/${ARCH}/libgdbserver.so", + cxxLibPath("libgnustl_shared.so", true), + "lib/${ARCH}/libqmlapp.so", + "res/layout/splash.xml"}); + qmlAppCustomMetaDataExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, { + "resources.arsc", + "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes", + "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir", + "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/plugins.qmltypes", + "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/qmldir", + "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", + "assets/dummyasset.txt", + "lib/${ARCH}/libgdbserver.so", + cxxLibPath("libgnustl_shared.so", true), + "lib/${ARCH}/libplugins_bearer_libqandroidbearer.so", + "lib/${ARCH}/libplugins_imageformats_libqgif.so", + "lib/${ARCH}/libplugins_imageformats_libqicns.so", + "lib/${ARCH}/libplugins_imageformats_libqico.so", + "lib/${ARCH}/libplugins_imageformats_libqjpeg.so", + "lib/${ARCH}/libplugins_imageformats_libqtga.so", + "lib/${ARCH}/libplugins_imageformats_libqtiff.so", + "lib/${ARCH}/libplugins_imageformats_libqwbmp.so", + "lib/${ARCH}/libplugins_imageformats_libqwebp.so", + "lib/${ARCH}/libplugins_platforms_android_libqtforandroid.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_debugger.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_inspector.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_local.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_messages.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_native.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_nativedebugger.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_profiler.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_preview.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_quickprofiler.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_server.so", + "lib/${ARCH}/libplugins_qmltooling_libqmldbg_tcp.so", + "lib/${ARCH}/libqml_QtQuick.2_libqtquick2plugin.so", + "lib/${ARCH}/libqml_QtQuick_Window.2_libwindowplugin.so", + "lib/${ARCH}/libQt5Core.so", + "lib/${ARCH}/libQt5Gui.so", + "lib/${ARCH}/libQt5Network.so", + "lib/${ARCH}/libQt5Qml.so", + "lib/${ARCH}/libQt5QuickParticles.so", + "lib/${ARCH}/libQt5Quick.so", + "lib/${ARCH}/libqmlapp.so", + "res/layout/splash.xml"}); + qmlAppCustomProperties = QStringList{"modules.Android.sdk.automaticSources:false", + "modules.qbs.architecture:" + archsForQt.first()}; + } else { + qmlAppExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, { "resources.arsc", - "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", + "assets/android_rcc_bundle.rcc", "lib/${ARCH}/libgdbserver.so", cxxLibPath("libgnustl_shared.so", true), - "lib/${ARCH}/libqmlapp.so", - "res/layout/splash.xml"})) + "lib/${ARCH}/libplugins_bearer_qandroidbearer_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qgif_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qicns_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qico_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qjpeg_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qtga_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qtiff_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qwbmp_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qwebp_${ARCH}.so", + "lib/${ARCH}/libplugins_platforms_qtforandroid_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_debugger_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_inspector_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_local_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_messages_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_native_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_nativedebugger_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_profiler_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_preview_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_quickprofiler_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_server_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_tcp_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick.2_qtquick2plugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Window.2_windowplugin_${ARCH}.so", + "lib/${ARCH}/libQt5Core_${ARCH}.so", + "lib/${ARCH}/libQt5Gui_${ARCH}.so", + "lib/${ARCH}/libQt5Network_${ARCH}.so", + "lib/${ARCH}/libQt5Qml_${ARCH}.so", + "lib/${ARCH}/libQt5QuickParticles_${ARCH}.so", + "lib/${ARCH}/libQt5Quick_${ARCH}.so", + "lib/${ARCH}/libQt5QmlModels_${ARCH}.so", + "lib/${ARCH}/libQt5QmlWorkerScript_${ARCH}.so", + "lib/${ARCH}/libqmlapp_${ARCH}.so", + "res/layout/splash.xml"}); + qmlAppMinistroExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, { + "resources.arsc", + "assets/android_rcc_bundle.rcc", + "lib/${ARCH}/libgdbserver.so", + cxxLibPath("libgnustl_shared.so", true), + "lib/${ARCH}/libqmlapp_${ARCH}.so", + "res/layout/splash.xml"}); + qmlAppCustomMetaDataExpectedFiles << commonFiles + expandArchs(ndkArchsForQt, { + "resources.arsc", + "assets/android_rcc_bundle.rcc", + "assets/dummyasset.txt", + "lib/${ARCH}/libgdbserver.so", + cxxLibPath("libgnustl_shared.so", true), + "lib/${ARCH}/libplugins_bearer_qandroidbearer_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qgif_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qicns_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qico_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qjpeg_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qtga_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qtiff_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qwbmp_${ARCH}.so", + "lib/${ARCH}/libplugins_imageformats_qwebp_${ARCH}.so", + "lib/${ARCH}/libplugins_platforms_qtforandroid_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_debugger_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_inspector_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_local_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_messages_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_native_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_nativedebugger_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_profiler_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_preview_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_quickprofiler_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_server_${ARCH}.so", + "lib/${ARCH}/libplugins_qmltooling_qmldbg_tcp_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick.2_qtquick2plugin_${ARCH}.so", + "lib/${ARCH}/libqml_QtQuick_Window.2_windowplugin_${ARCH}.so", + "lib/${ARCH}/libQt5Core_${ARCH}.so", + "lib/${ARCH}/libQt5Gui_${ARCH}.so", + "lib/${ARCH}/libQt5Network_${ARCH}.so", + "lib/${ARCH}/libQt5Qml_${ARCH}.so", + "lib/${ARCH}/libQt5QuickParticles_${ARCH}.so", + "lib/${ARCH}/libQt5Quick_${ARCH}.so", + "lib/${ARCH}/libQt5QmlModels_${ARCH}.so", + "lib/${ARCH}/libQt5QmlWorkerScript_${ARCH}.so", + "lib/${ARCH}/libqmlapp_${ARCH}.so", + "res/layout/splash.xml"}); + qmlAppCustomProperties = QStringList{"modules.Android.sdk.automaticSources:false"}; + } + QTest::newRow("qml app") + << "qml-app" << QStringList("qmlapp") + << (QList<QByteArrayList>() << qmlAppExpectedFiles) + << qmlAppCustomProperties; + QTest::newRow("qml app using Ministro") + << "qml-app" << QStringList("qmlapp") + << (QList<QByteArrayList>() << qmlAppMinistroExpectedFiles) << QStringList{"modules.Qt.android_support.useMinistro:true", "modules.Android.sdk.automaticSources:false"}; QTest::newRow("qml app with custom metadata") << "qml-app" << QStringList("qmlapp") - << (QList<QByteArrayList>() << commonFiles + expandArchs(ndkArchsForQt, { - "resources.arsc", - "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/plugins.qmltypes", - "assets/--Added-by-androiddeployqt--/qml/QtQuick.2/qmldir", - "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/plugins.qmltypes", - "assets/--Added-by-androiddeployqt--/qml/QtQuick/Window.2/qmldir", - "assets/--Added-by-androiddeployqt--/qt_cache_pregenerated_file_list", - "assets/dummyasset.txt", - "lib/${ARCH}/libgdbserver.so", - cxxLibPath("libgnustl_shared.so", true), - "lib/${ARCH}/libplugins_bearer_libqandroidbearer.so", - "lib/${ARCH}/libplugins_imageformats_libqgif.so", - "lib/${ARCH}/libplugins_imageformats_libqicns.so", - "lib/${ARCH}/libplugins_imageformats_libqico.so", - "lib/${ARCH}/libplugins_imageformats_libqjpeg.so", - "lib/${ARCH}/libplugins_imageformats_libqtga.so", - "lib/${ARCH}/libplugins_imageformats_libqtiff.so", - "lib/${ARCH}/libplugins_imageformats_libqwbmp.so", - "lib/${ARCH}/libplugins_imageformats_libqwebp.so", - "lib/${ARCH}/libplugins_platforms_android_libqtforandroid.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_debugger.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_inspector.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_local.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_messages.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_native.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_nativedebugger.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_profiler.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_preview.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_quickprofiler.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_server.so", - "lib/${ARCH}/libplugins_qmltooling_libqmldbg_tcp.so", - "lib/${ARCH}/libqml_QtQuick.2_libqtquick2plugin.so", - "lib/${ARCH}/libqml_QtQuick_Window.2_libwindowplugin.so", - "lib/${ARCH}/libQt5Core.so", - "lib/${ARCH}/libQt5Gui.so", - "lib/${ARCH}/libQt5Network.so", - "lib/${ARCH}/libQt5Qml.so", - "lib/${ARCH}/libQt5QuickParticles.so", - "lib/${ARCH}/libQt5Quick.so", - "lib/${ARCH}/libqmlapp.so", - "res/layout/splash.xml"})) - << QStringList("modules.Android.sdk.automaticSources:true"); + << (QList<QByteArrayList>() << qmlAppCustomMetaDataExpectedFiles) + << QStringList("modules.Android.sdk.automaticSources:true"); QTest::newRow("no native") << "no-native" << QStringList("com.example.android.basicmediadecoder") @@ -390,7 +513,7 @@ void TestBlackboxAndroid::android_data() "lib/${ARCH}/liblib2.so", cxxLibPath("libstlport_shared.so", false)})) << QStringList(); - QByteArrayList expectedFiles1 = (commonFiles + QByteArrayList expectedFiles1 = qbs::toList(qbs::toSet(commonFiles + expandArchs(QByteArrayList{"armeabi-v7a", "x86"}, { "resources.arsc", "lib/${ARCH}/libgdbserver.so", @@ -400,7 +523,7 @@ void TestBlackboxAndroid::android_data() "resources.arsc", "lib/${ARCH}/libgdbserver.so", "lib/${ARCH}/libp1lib2.so", - cxxLibPath("libstlport_shared.so", false)})).toSet().toList(); + cxxLibPath("libstlport_shared.so", false)}))); QByteArrayList expectedFiles2 = commonFiles + expandArchs(archs, { "lib/${ARCH}/libgdbserver.so", "lib/${ARCH}/libp2lib1.so", diff --git a/tests/auto/blackbox/tst_blackboxapple.cpp b/tests/auto/blackbox/tst_blackboxapple.cpp index cde742f3c..3623dc51b 100644 --- a/tests/auto/blackbox/tst_blackboxapple.cpp +++ b/tests/auto/blackbox/tst_blackboxapple.cpp @@ -60,6 +60,65 @@ static QString getEmbeddedBinaryPlist(const QString &file) return QString::fromUtf8(p.readAllStandardOutput()).trimmed(); } +static QVariantMap readInfoPlistFile(const QString &infoPlistPath) +{ + if (!QFile::exists(infoPlistPath)) { + qWarning() << infoPlistPath << "doesn't exist"; + return {}; + } + + QProcess plutil; + plutil.start("plutil", { + QStringLiteral("-convert"), + QStringLiteral("json"), + infoPlistPath + }); + if (!plutil.waitForStarted()) { + qWarning() << plutil.errorString(); + return {}; + } + if (!plutil.waitForFinished()) { + qWarning() << plutil.errorString(); + return {}; + } + if (plutil.exitCode() != 0) { + qWarning() << plutil.readAllStandardError().constData(); + return {}; + } + + QFile infoPlist(infoPlistPath); + if (!infoPlist.open(QIODevice::ReadOnly)) { + qWarning() << infoPlist.errorString(); + return {}; + } + QJsonParseError error; + const auto json = QJsonDocument::fromJson(infoPlist.readAll(), &error); + if (error.error != QJsonParseError::NoError) { + qWarning() << error.errorString(); + return {}; + } + return json.object().toVariantMap(); +} + +static QString getInfoPlistPath(const QString &bundlePath) +{ + QFileInfo contents(bundlePath + "/Contents"); + if (contents.exists() && contents.isDir()) + return contents.filePath() + "/Info.plist"; // macOS bundle + return bundlePath + "/Info.plist"; +} + +static bool testVariantListType(const QVariant &variant, QMetaType::Type type) +{ + if (variant.userType() != QMetaType::QVariantList) + return false; + for (const auto &value : variant.toList()) { + if (value.userType() != type) + return false; + } + return true; +} + TestBlackboxApple::TestBlackboxApple() : TestBlackboxBase (SRCDIR "/testdata-apple", "blackbox-apple") { @@ -190,8 +249,11 @@ void TestBlackboxApple::appleMultiConfig() void TestBlackboxApple::aggregateDependencyLinking() { - if (HostOsInfo::hostOsVersion() > qbs::Version(10, 13, 4)) - QSKIP("32-bit arch build is no longer supported on macOS versions higher than 10.13.4."); + // XCode 11 produces warning about deprecation of 32-bit apps, so skip the test + // for future XCode versions as well + const auto xcodeVersion = findXcodeVersion(); + if (xcodeVersion >= qbs::Version(11)) + QSKIP("32-bit arch build is no longer supported on macOS higher than 10.13.4."); QDir::setCurrent(testDataDir + "/aggregateDependencyLinking"); QCOMPARE(runQbs(QStringList{"-p", "multi_arch_lib"}), 0); @@ -623,47 +685,47 @@ void TestBlackboxApple::deploymentTarget_data() } QTest::newRow("macos x86_64") << "macosx" << macos << "x86_64" << "-triple x86_64-apple-macosx10.6" - << "-macosx_version_min 10.6"; + << "10.6"; if (xcodeVersion >= qbs::Version(6)) QTest::newRow("macos x86_64h") << "macosx" << macos << "x86_64h" << "-triple x86_64h-apple-macosx10.12" - << "-macosx_version_min 10.12"; + << "10.12"; QTest::newRow("ios armv7a") << "iphoneos" << ios << "armv7a" << "-triple thumbv7-apple-ios6.0" - << "-iphoneos_version_min 6.0"; + << "6.0"; QTest::newRow("ios armv7s") << "iphoneos" <<ios << "armv7s" << "-triple thumbv7s-apple-ios7.0" - << "-iphoneos_version_min 7.0"; + << "7.0"; if (xcodeVersion >= qbs::Version(5)) QTest::newRow("ios arm64") << "iphoneos" <<ios << "arm64" << "-triple arm64-apple-ios7.0" - << "-iphoneos_version_min 7.0"; + << "7.0"; QTest::newRow("ios-simulator x86") << "iphonesimulator" << ios_sim << "x86" << "-triple i386-apple-ios6.0" - << "-ios_simulator_version_min 6.0"; + << "6.0"; if (xcodeVersion >= qbs::Version(5)) QTest::newRow("ios-simulator x86_64") << "iphonesimulator" << ios_sim << "x86_64" << "-triple x86_64-apple-ios7.0" - << "-ios_simulator_version_min 7.0"; + << "7.0"; if (xcodeVersion >= qbs::Version(7)) { if (xcodeVersion >= qbs::Version(7, 1)) { QTest::newRow("tvos arm64") << "appletvos" << tvos << "arm64" << "-triple arm64-apple-tvos9.0" - << "-tvos_version_min 9.0"; + << "9.0"; QTest::newRow("tvos-simulator x86_64") << "appletvsimulator" << tvos_sim << "x86_64" << "-triple x86_64-apple-tvos9.0" - << "-tvos_simulator_version_min 9.0"; + << "9.0"; } QTest::newRow("watchos armv7k") << "watchos" << watchos << "armv7k" << "-triple thumbv7k-apple-watchos2.0" - << "-watchos_version_min 2.0"; + << "2.0"; QTest::newRow("watchos-simulator x86") << "watchsimulator" << watchos_sim << "x86" << "-triple i386-apple-watchos2.0" - << "-watchos_simulator_version_min 2.0"; + << "2.0"; } } @@ -772,37 +834,35 @@ void TestBlackboxApple::infoPlist() params.arguments = QStringList() << "-f" << "infoplist.qbs"; QCOMPARE(runQbs(params), 0); - auto infoplistPath = relativeProductBuildDir("infoplist") - + "/infoplist.app/Contents/Info.plist"; - if (!QFile::exists(infoplistPath)) - infoplistPath = relativeProductBuildDir("infoplist") + "/infoplist.app/Info.plist"; - QVERIFY(QFile::exists(infoplistPath)); - QProcess plutil; - plutil.start("plutil", { - QStringLiteral("-convert"), - QStringLiteral("json"), - infoplistPath - }); - QVERIFY2(plutil.waitForStarted(), qPrintable(plutil.errorString())); - QVERIFY2(plutil.waitForFinished(), qPrintable(plutil.errorString())); - QVERIFY2(plutil.exitCode() == 0, qPrintable(plutil.readAllStandardError().constData())); + const auto infoPlistPath = getInfoPlistPath( + relativeProductBuildDir("infoplist") + "/infoplist.app"); + QVERIFY(QFile::exists(infoPlistPath)); + const auto content = readInfoPlistFile(infoPlistPath); + QVERIFY(!content.isEmpty()); - QFile infoplist(infoplistPath); - QVERIFY(infoplist.open(QIODevice::ReadOnly)); - QJsonParseError error; - const auto json = QJsonDocument::fromJson(infoplist.readAll(), &error); - QCOMPARE(error.error, QJsonParseError::NoError); - QVERIFY(json.isObject()); // common values - QCOMPARE(json.object().value(QStringLiteral("CFBundleIdentifier")), + QCOMPARE(content.value(QStringLiteral("CFBundleIdentifier")), QStringLiteral("org.example.infoplist")); - QCOMPARE(json.object().value(QStringLiteral("CFBundleName")), QStringLiteral("infoplist")); - QCOMPARE(json.object().value(QStringLiteral("CFBundleExecutable")), + QCOMPARE(content.value(QStringLiteral("CFBundleName")), QStringLiteral("infoplist")); + QCOMPARE(content.value(QStringLiteral("CFBundleExecutable")), QStringLiteral("infoplist")); - if (!json.object().contains(QStringLiteral("SDKROOT"))) { // macOS-specific values - QCOMPARE(json.object().value("LSMinimumSystemVersion"), QStringLiteral("10.7")); - QVERIFY(json.object().contains("NSPrincipalClass")); + if (!content.contains(QStringLiteral("SDKROOT"))) { // macOS-specific values + QCOMPARE(content.value("LSMinimumSystemVersion"), QStringLiteral("10.7")); + QCOMPARE(content.value("NSPrincipalClass"), QStringLiteral("NSApplication")); + } else { + // QBS-1447: UIDeviceFamily was set to a string instead of an array + const auto family = content.value(QStringLiteral("UIDeviceFamily")); + if (family.isValid()) { + // int gets converted to a double when exporting plist as JSON + QVERIFY(testVariantListType(family, QMetaType::Double)); + } + const auto caps = content.value(QStringLiteral("UIRequiredDeviceCapabilities")); + if (caps.isValid()) + QVERIFY(testVariantListType(caps, QMetaType::QString)); + const auto orientations = content.value(QStringLiteral("UIRequiredDeviceCapabilities")); + if (orientations.isValid()) + QVERIFY(testVariantListType(orientations, QMetaType::QString)); } } @@ -813,6 +873,31 @@ void TestBlackboxApple::objcArc() QCOMPARE(runQbs(), 0); } +void TestBlackboxApple::overrideInfoPlist() +{ + QDir::setCurrent(testDataDir + "/overrideInfoPlist"); + + QCOMPARE(runQbs(), 0); + + const auto infoPlistPath = getInfoPlistPath( + relativeProductBuildDir("overrideInfoPlist") + "/overrideInfoPlist.app"); + QVERIFY(QFile::exists(infoPlistPath)); + const auto content = readInfoPlistFile(infoPlistPath); + QVERIFY(!content.isEmpty()); + + // test we do not override custom values by default + QCOMPARE(content.value(QStringLiteral("DefaultValue")), + QStringLiteral("The default value")); + // test we can override custom values + QCOMPARE(content.value(QStringLiteral("OverriddenValue")), + QStringLiteral("The overridden value")); + // test we do not override special values set by Qbs by default + QCOMPARE(content.value(QStringLiteral("CFBundleExecutable")), + QStringLiteral("overrideInfoPlist")); + // test we can override special values set by Qbs + QCOMPARE(content.value(QStringLiteral("CFBundleName")), QStringLiteral("My Bundle")); +} + void TestBlackboxApple::xcode() { QProcess xcodeSelect; diff --git a/tests/auto/blackbox/tst_blackboxapple.h b/tests/auto/blackbox/tst_blackboxapple.h index 76711ddf5..be2e5c5b5 100644 --- a/tests/auto/blackbox/tst_blackboxapple.h +++ b/tests/auto/blackbox/tst_blackboxapple.h @@ -63,6 +63,7 @@ private slots: void iconsetApp(); void infoPlist(); void objcArc(); + void overrideInfoPlist(); void xcode(); private: diff --git a/tests/auto/blackbox/tst_blackboxbase.cpp b/tests/auto/blackbox/tst_blackboxbase.cpp index 61b0271f6..90afaabfc 100644 --- a/tests/auto/blackbox/tst_blackboxbase.cpp +++ b/tests/auto/blackbox/tst_blackboxbase.cpp @@ -64,7 +64,7 @@ static bool supportsSettingsDirOption(const QString &command) { TestBlackboxBase::TestBlackboxBase(const QString &testDataSrcDir, const QString &testName) : testDataDir(testWorkDir(testName)), - testSourceDir(QDir::cleanPath(testDataSrcDir)), + testSourceDir(testDataSourceDir(testDataSrcDir)), qbsExecutableFilePath(initQbsExecutableFilePath()), defaultInstallRoot(relativeBuildDir() + QLatin1Char('/') + InstallOptions::defaultInstallRoot()) { @@ -232,3 +232,21 @@ QMap<QString, QString> TestBlackboxBase::findJdkTools(int *status) {"jar", QDir::fromNativeSeparators(tools["jar"].toString())} }; } + +qbs::Version TestBlackboxBase::qmakeVersion(const QString &qmakeFilePath) +{ + QStringList arguments; + arguments << "-query" << "QT_VERSION"; + QProcess qmakeProcess; + qmakeProcess.start(qmakeFilePath, arguments); + if (!qmakeProcess.waitForStarted() || !qmakeProcess.waitForFinished() + || qmakeProcess.exitStatus() != QProcess::NormalExit) { + qDebug() << "qmake '" << qmakeFilePath << "' could not be run."; + return qbs::Version(); + } + QByteArray result = qmakeProcess.readAll().simplified(); + qbs::Version version = qbs::Version::fromString(result); + if (!version.isValid()) + qDebug() << "qmake '" << qmakeFilePath << "' version is not valid."; + return version; +} diff --git a/tests/auto/blackbox/tst_blackboxbase.h b/tests/auto/blackbox/tst_blackboxbase.h index 251f3752d..518cc80d0 100644 --- a/tests/auto/blackbox/tst_blackboxbase.h +++ b/tests/auto/blackbox/tst_blackboxbase.h @@ -42,14 +42,14 @@ public: init(); } - QbsRunParameters(const QString &cmd, const QStringList &args = QStringList()) - : command(cmd), arguments(args) + QbsRunParameters(QString cmd, QStringList args = QStringList()) + : command(std::move(cmd)), arguments(std::move(args)) { init(); } - QbsRunParameters(const QStringList &args) - : arguments(args) + QbsRunParameters(QStringList args) + : arguments(std::move(args)) { init(); } @@ -92,6 +92,7 @@ protected: 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); const QString testDataDir; const QString testSourceDir; diff --git a/tests/auto/blackbox/tst_blackboxjava.cpp b/tests/auto/blackbox/tst_blackboxjava.cpp index f7feb0612..a815a84ff 100644 --- a/tests/auto/blackbox/tst_blackboxjava.cpp +++ b/tests/auto/blackbox/tst_blackboxjava.cpp @@ -119,7 +119,7 @@ void TestBlackboxJava::java() if (process.waitForStarted()) { QVERIFY2(process.waitForFinished(), qPrintable(process.errorString())); const QByteArray stdOut = process.readAllStandardOutput(); - QVERIFY2(stdOut.contains("Class-Path: car_jar.jar random_stuff.jar"), stdOut.constData()); + QVERIFY2(stdOut.contains("Class-Path: random_stuff.jar car_jar.jar"), stdOut.constData()); QVERIFY2(stdOut.contains("Main-Class: Vehicles"), stdOut.constData()); QVERIFY2(stdOut.contains("Some-Property: Some-Value"), stdOut.constData()); QVERIFY2(stdOut.contains("Additional-Property: Additional-Value"), stdOut.constData()); @@ -184,6 +184,7 @@ void TestBlackboxJava::javaDependencyTracking_data() "/usr/lib/jvm/java-" + minorVersion + "-openjdk" + dpkgArch("-"), // Debian "/usr/lib/jvm/java-" + minorVersion + "-openjdk", // Arch "/usr/lib/jvm/jre-1." + minorVersion + ".0-openjdk", // Fedora + "/usr/lib64/jvm/java-1." + minorVersion + ".0-openjdk", // OpenSuSE }; for (const QString &searchPath : searchPaths) { if (QFile::exists(searchPath + "/bin/javac")) diff --git a/tests/auto/blackbox/tst_blackboxqt.cpp b/tests/auto/blackbox/tst_blackboxqt.cpp index 035af959c..595a173a2 100644 --- a/tests/auto/blackbox/tst_blackboxqt.cpp +++ b/tests/auto/blackbox/tst_blackboxqt.cpp @@ -121,7 +121,7 @@ void TestBlackboxQt::combinedMoc() void TestBlackboxQt::createProject() { QDir::setCurrent(testDataDir + "/create-project"); - QVERIFY(QFile::copy(SRCDIR "/../../../examples/helloworld-qt/main.cpp", + QVERIFY(QFile::copy(testSourceDir + "/../../../../examples/helloworld-qt/main.cpp", QDir::currentPath() + "/main.cpp")); QbsRunParameters createParams("create-project"); createParams.profile.clear(); @@ -210,12 +210,48 @@ void TestBlackboxQt::lrelease() QVERIFY(!regularFileExists(relativeProductBuildDir("lrelease-test") + "/hu.qm")); } +void TestBlackboxQt::metaTypes_data() +{ + QTest::addColumn<bool>("generate"); + QTest::addColumn<QString>("installDir"); + QTest::newRow("don't generate") << false << QString(); + QTest::newRow("don't generate with install info") << false << QString("blubb"); + QTest::newRow("generate only") << true << QString(); + QTest::newRow("generate and install") << true << QString("blubb"); +} + +void TestBlackboxQt::metaTypes() +{ + QDir::setCurrent(testDataDir + "/metatypes"); + QFETCH(bool, generate); + QFETCH(QString, installDir); + const QStringList args{"modules.Qt.core.generateMetaTypesFile:" + + QString(generate ? "true" : "false"), + "modules.Qt.core.metaTypesInstallDir:" + installDir, + "-v", "--force-probe-execution"}; + QCOMPARE(runQbs(QbsRunParameters("resolve", args)), 0); + const bool canGenerate = m_qbsStdout.contains("can generate"); + const bool cannotGenerate = m_qbsStdout.contains("cannot generate"); + QVERIFY(canGenerate != cannotGenerate); + const bool expectFiles = generate && canGenerate; + const bool expectInstalledFiles = expectFiles && !installDir.isEmpty(); + QCOMPARE(runQbs(QStringList("--clean-install-root")), 0); + const QString productDir = relativeProductBuildDir("mylib"); + const QString outputDir = productDir + "/qt.headers"; + QVERIFY(!regularFileExists(outputDir + "/moc_unmocableclass.cpp.json")); + QCOMPARE(regularFileExists(outputDir + "/moc_mocableclass1.cpp.json"), expectFiles); + QCOMPARE(regularFileExists(outputDir + "/mocableclass2.moc.json"), expectFiles); + QCOMPARE(regularFileExists(productDir + "/mylib_metatypes.json"), expectFiles); + QCOMPARE(regularFileExists(relativeBuildDir() + "/install-root/some-prefix/" + installDir + + "/mylib_metatypes.json"), expectInstalledFiles); +} + void TestBlackboxQt::mixedBuildVariants() { QDir::setCurrent(testDataDir + "/mixed-build-variants"); const SettingsPtr s = settings(); Profile profile(profileName(), s.get()); - if (profile.value("qbs.toolchain").toStringList().contains("msvc")) { + if (profileToolchain(profile).contains("msvc")) { QbsRunParameters params; params.arguments << "qbs.buildVariant:debug"; params.expectFailure = true; @@ -339,7 +375,7 @@ void TestBlackboxQt::qmlDebugging() QCOMPARE(runQbs(), 0); const SettingsPtr s = settings(); Profile profile(profileName(), s.get()); - if (!profile.value("qbs.toolchain").toStringList().contains("gcc")) + if (!profileToolchain(profile).contains("gcc")) return; QProcess nm; nm.start("nm", QStringList(relativeExecutableFilePath("debuggable-app"))); @@ -360,6 +396,40 @@ void TestBlackboxQt::qobjectInObjectiveCpp() QCOMPARE(runQbs(), 0); } +void TestBlackboxQt::qmlTypeRegistrar_data() +{ + QTest::addColumn<QString>("importName"); + QTest::addColumn<QString>("installDir"); + QTest::newRow("don't generate") << QString() << QString(); + QTest::newRow("don't generate with install info") << QString() << QString("blubb"); + QTest::newRow("generate only") << QString("People") << QString(); + QTest::newRow("generate and install") << QString("People") << QString("blubb"); +} + +void TestBlackboxQt::qmlTypeRegistrar() +{ + QDir::setCurrent(testDataDir + "/qmltyperegistrar"); + QFETCH(QString, importName); + QFETCH(QString, installDir); + rmDirR(relativeBuildDir()); + const QStringList args{"modules.Qt.qml.importName:" + importName, + "modules.Qt.qml.typesInstallDir:" + installDir}; + QCOMPARE(runQbs(QbsRunParameters("resolve", args)), 0); + const bool hasRegistrar = m_qbsStdout.contains("has registrar"); + const bool doesNotHaveRegistrar = m_qbsStdout.contains("does not have registrar"); + QVERIFY(hasRegistrar != doesNotHaveRegistrar); + if (doesNotHaveRegistrar) + QSKIP("Qt version too old"); + QCOMPARE(runQbs(), 0); + const bool enabled = !importName.isEmpty(); + QCOMPARE(m_qbsStdout.contains("running qmltyperegistrar"), enabled); + QCOMPARE(m_qbsStdout.contains("compiling myapp_qmltyperegistrations.cpp"), enabled); + const QString buildDir = relativeProductBuildDir("myapp"); + QCOMPARE(regularFileExists(buildDir + "/myapp.qmltypes"), enabled); + QCOMPARE(regularFileExists(relativeBuildDir() + "/install-root/" + installDir + + "/myapp.qmltypes"), enabled && !installDir.isEmpty()); +} + void TestBlackboxQt::qtKeywords() { QDir::setCurrent(testDataDir + "/qt-keywords"); diff --git a/tests/auto/blackbox/tst_blackboxqt.h b/tests/auto/blackbox/tst_blackboxqt.h index 180f9e0c0..4008b14ca 100644 --- a/tests/auto/blackbox/tst_blackboxqt.h +++ b/tests/auto/blackbox/tst_blackboxqt.h @@ -53,6 +53,8 @@ private slots: void includedMocCpp(); void linkerVariant(); void lrelease(); + void metaTypes_data(); + void metaTypes(); void mixedBuildVariants(); void mocAndCppCombining(); void mocFlags(); @@ -63,6 +65,8 @@ private slots: void pluginSupport(); void qmlDebugging(); void qobjectInObjectiveCpp(); + void qmlTypeRegistrar_data(); + void qmlTypeRegistrar(); void qtKeywords(); void quickCompiler(); void qtScxml(); diff --git a/tests/auto/blackbox/tst_clangdb.cpp b/tests/auto/blackbox/tst_clangdb.cpp index 3a6dd2d92..65e562484 100644 --- a/tests/auto/blackbox/tst_clangdb.cpp +++ b/tests/auto/blackbox/tst_clangdb.cpp @@ -202,9 +202,9 @@ void TestClangDb::checkClangDetectsSourceCodeProblems() // clang-check.exe does not understand MSVC command-line syntax const SettingsPtr s = settings(); qbs::Profile profile(profileName(), s.get()); - if (profile.value("qbs.toolchain").toStringList().contains("msvc")) { + if (profileToolchain(profile).contains("msvc")) { arguments << "-extra-arg-before=--driver-mode=cl"; - } else if (profile.value("qbs.toolchain").toStringList().contains("mingw")) { + } else if (profileToolchain(profile).contains("mingw")) { arguments << "-extra-arg-before=--driver-mode=g++"; } |