diff options
Diffstat (limited to 'tests/auto/language')
88 files changed, 1011 insertions, 502 deletions
diff --git a/tests/auto/language/CMakeLists.txt b/tests/auto/language/CMakeLists.txt new file mode 100644 index 000000000..9c04b6c8d --- /dev/null +++ b/tests/auto/language/CMakeLists.txt @@ -0,0 +1,10 @@ +add_qbs_test(language + DEFINES + "QBS_VERSION=\"${QBS_VERSION}\"" + DEPENDS + qbsquickjsheaders + Qt6Core5Compat + SOURCES + tst_language.cpp + tst_language.h + ) diff --git a/tests/auto/language/language.pro b/tests/auto/language/language.pro deleted file mode 100644 index 86248d926..000000000 --- a/tests/auto/language/language.pro +++ /dev/null @@ -1,25 +0,0 @@ -TARGET = tst_language - -SOURCES = tst_language.cpp -HEADERS = tst_language.h - -include(../auto.pri) -include(../../../src/app/shared/logging/logging.pri) -include(../../../src/lib/bundledlibs.pri) - -!qbs_use_bundled_qtscript: QT += script - -DATA_DIRS = testdata - -for(data_dir, DATA_DIRS) { - files = $$files($$PWD/$$data_dir/*, true) - win32:files ~= s|\\\\|/|g - for(file, files):!exists($$file/*):FILES += $$file -} - -OTHER_FILES += $$FILES - -qbs_use_bundled_qtscript { - CONFIG += qbs_do_not_link_bundled_qtscript - include(../../../src/lib/scriptengine/use_scriptengine.pri) -} diff --git a/tests/auto/language/language.qbs b/tests/auto/language/language.qbs index f43ca0e44..3767477db 100644 --- a/tests/auto/language/language.qbs +++ b/tests/auto/language/language.qbs @@ -1,13 +1,8 @@ -import qbs import qbs.Utilities -QbsAutotest { +QbsUnittest { Depends { name: "qbsversion" } - Depends { - name: "Qt.script" - condition: !qbsbuildconfig.useBundledQtScript - required: false - } + Depends { name: "qbsconsolelogger" } testName: "language" condition: qbsbuildconfig.enableUnitTests diff --git a/tests/auto/language/testdata/ParentWithExport.qbs b/tests/auto/language/testdata/ParentWithExport.qbs index 16f9a2cd1..b16097e69 100644 --- a/tests/auto/language/testdata/ParentWithExport.qbs +++ b/tests/auto/language/testdata/ParentWithExport.qbs @@ -1,6 +1,6 @@ Product { Export { Depends { name: "dummy" } - dummy.defines: [product.name.toUpperCase()] + dummy.defines: [exportingProduct.name.toUpperCase()] } } diff --git a/tests/auto/language/testdata/additional-product-types.qbs b/tests/auto/language/testdata/additional-product-types.qbs index 686650f42..f84397da3 100644 --- a/tests/auto/language/testdata/additional-product-types.qbs +++ b/tests/auto/language/testdata/additional-product-types.qbs @@ -5,8 +5,8 @@ Product { Depends { name: "dummy" } Depends { name: "dummy2" } - property bool hasTag1: type.contains("tag1") - property bool hasTag2: type.contains("tag2") - property bool hasTag3: type.contains("tag3") - property bool hasTag4: type.contains("tag4") + property bool hasTag1: type.includes("tag1") + property bool hasTag2: type.includes("tag2") + property bool hasTag3: type.includes("tag3") + property bool hasTag4: type.includes("tag4") } diff --git a/tests/auto/language/testdata/chained-probes/modules/m/m.qbs b/tests/auto/language/testdata/chained-probes/modules/m/m.qbs index 3c6bcd1c9..bf68e56b6 100644 --- a/tests/auto/language/testdata/chained-probes/modules/m/m.qbs +++ b/tests/auto/language/testdata/chained-probes/modules/m/m.qbs @@ -2,13 +2,13 @@ Module { Probe { id: probe1 property string probe1Prop - configure: { probe1Prop = "probe1Val"; found = true; } + configure: { probe1Prop = "probe1Val"; found = true } } Probe { id: probe2 property string inputProp: prop1 property string probe2Prop - configure: { probe2Prop = inputProp + "probe2Val"; found = true; } + configure: { probe2Prop = inputProp + "probe2Val"; found = true } } property string prop1: probe1.probe1Prop property string prop2: probe2.probe2Prop diff --git a/tests/auto/language/testdata/conditionaldepends.qbs b/tests/auto/language/testdata/conditionaldepends.qbs index 9a499da92..e4f9fae7d 100644 --- a/tests/auto/language/testdata/conditionaldepends.qbs +++ b/tests/auto/language/testdata/conditionaldepends.qbs @@ -14,25 +14,25 @@ Project { Product { name: "product_props_true" property bool someTrueProp: true - Depends { condition: someTrueProp; name: "dummy"} + Depends { condition: someTrueProp; name: "dummy" } } Product { name: "product_props_false" property bool someFalseProp: false - Depends { condition: someFalseProp; name: "dummy"} + Depends { condition: someFalseProp; name: "dummy" } } property bool someTruePrjProp: true Product { name: "project_props_true" - Depends { condition: project.someTruePrjProp; name: "dummy"} + Depends { condition: project.someTruePrjProp; name: "dummy" } } property bool someFalsePrjProp: false Product { name: "project_props_false" - Depends { condition: project.someFalsePrjProp; name: "dummy"} + Depends { condition: project.someFalsePrjProp; name: "dummy" } } Product { diff --git a/tests/auto/language/testdata/conditionaldepends_base.qbs b/tests/auto/language/testdata/conditionaldepends_base.qbs index 5ab5b973a..74eb958d4 100644 --- a/tests/auto/language/testdata/conditionaldepends_base.qbs +++ b/tests/auto/language/testdata/conditionaldepends_base.qbs @@ -1,4 +1,4 @@ -Application { +Product { name: 'conditionaldepends_base' property bool someProp: false Depends { diff --git a/tests/auto/language/testdata/dotted-names/dotted-names.qbs b/tests/auto/language/testdata/dotted-names/dotted-names.qbs index cf5658384..714988f0b 100644 --- a/tests/auto/language/testdata/dotted-names/dotted-names.qbs +++ b/tests/auto/language/testdata/dotted-names/dotted-names.qbs @@ -1,5 +1,3 @@ -import qbs - Project { name: "theProject" property bool includeDottedProduct diff --git a/tests/auto/language/testdata/dotted-names/modules/x/y/xy.qbs b/tests/auto/language/testdata/dotted-names/modules/x/y/xy.qbs index 71cfac9cb..eee46458d 100644 --- a/tests/auto/language/testdata/dotted-names/modules/x/y/xy.qbs +++ b/tests/auto/language/testdata/dotted-names/modules/x/y/xy.qbs @@ -1,5 +1,3 @@ -import qbs - Module { property string z: "default" } diff --git a/tests/auto/language/testdata/erroneous/duplicate-multiplex-value.qbs b/tests/auto/language/testdata/duplicate-multiplex-value.qbs index 56da41af1..24b246604 100644 --- a/tests/auto/language/testdata/erroneous/duplicate-multiplex-value.qbs +++ b/tests/auto/language/testdata/duplicate-multiplex-value.qbs @@ -1,5 +1,3 @@ -import qbs - Product { name: "p" multiplexByQbsProperties: "architectures" diff --git a/tests/auto/language/testdata/erroneous/duplicate-multiplex-value2.qbs b/tests/auto/language/testdata/duplicate-multiplex-value2.qbs index e412e5210..d6c057a9e 100644 --- a/tests/auto/language/testdata/erroneous/duplicate-multiplex-value2.qbs +++ b/tests/auto/language/testdata/duplicate-multiplex-value2.qbs @@ -1,5 +1,3 @@ -import qbs - Product { name: "p" multiplexByQbsProperties: ["architectures", "buildVariants", "architectures"] diff --git a/tests/auto/language/testdata/erroneous/ambiguous-multiplex-dependency.qbs b/tests/auto/language/testdata/erroneous/ambiguous-multiplex-dependency.qbs new file mode 100644 index 000000000..6f60b1faf --- /dev/null +++ b/tests/auto/language/testdata/erroneous/ambiguous-multiplex-dependency.qbs @@ -0,0 +1,14 @@ +Project { + Product { + name: "a" + multiplexByQbsProperties: ["architectures", "buildVariants"] + qbs.architectures: ["x86", "arm"] + qbs.buildVariants: ["debug", "release"] + } + Product { + name: "b" + Depends { name: "a" } + multiplexByQbsProperties: ["architectures"] + qbs.architectures: ["x86", "arm"] + } +} diff --git a/tests/auto/language/testdata/erroneous/conflicting_fileTagsFilter.qbs b/tests/auto/language/testdata/erroneous/conflicting_fileTagsFilter.qbs index 97e11bb9b..3738e0cca 100644 --- a/tests/auto/language/testdata/erroneous/conflicting_fileTagsFilter.qbs +++ b/tests/auto/language/testdata/erroneous/conflicting_fileTagsFilter.qbs @@ -1,10 +1,11 @@ -Application { +Product { + type: "app" Group { - fileTagsFilter: "application" + fileTagsFilter: "app" qbs.install: true } Group { - fileTagsFilter: "application" + fileTagsFilter: "app" qbs.install: false } } diff --git a/tests/auto/language/testdata/erroneous/dependency-profile-mismatch-2.qbs b/tests/auto/language/testdata/erroneous/dependency-profile-mismatch-2.qbs new file mode 100644 index 000000000..d76907a35 --- /dev/null +++ b/tests/auto/language/testdata/erroneous/dependency-profile-mismatch-2.qbs @@ -0,0 +1,17 @@ +Project { + Profile { + name: "profile1" + } + Profile { + name: "profile2" + } + + Product { + name: "dep" + qbs.profiles: ["profile1", "profile2"] + } + Product { + name: "main" + Depends { name: "dep"; profiles: ["profile47"]; } + } +} diff --git a/tests/auto/language/testdata/erroneous/dependency-profile-mismatch.qbs b/tests/auto/language/testdata/erroneous/dependency-profile-mismatch.qbs new file mode 100644 index 000000000..e014fa9b1 --- /dev/null +++ b/tests/auto/language/testdata/erroneous/dependency-profile-mismatch.qbs @@ -0,0 +1,14 @@ +Project { + Profile { + name: "profile1" + } + + Product { + name: "dep" + qbs.profiles: ["profile1"] + } + Product { + name: "main" + Depends { name: "dep"; profiles: ["profile47"]; } + } +} diff --git a/tests/auto/language/testdata/erroneous/dependency_cycle.qbs b/tests/auto/language/testdata/erroneous/dependency_cycle.qbs index 83a6e35f6..80c678f89 100644 --- a/tests/auto/language/testdata/erroneous/dependency_cycle.qbs +++ b/tests/auto/language/testdata/erroneous/dependency_cycle.qbs @@ -1,15 +1,15 @@ Project { - CppApplication { + Product { name: "A" Depends { name: "B" } files: ["main.cpp"] } - CppApplication { + Product { name: "B" Depends { name: "C" } files: ["main.cpp"] } - CppApplication { + Product { name: "C" Depends { name: "A" } files: ["main.cpp"] diff --git a/tests/auto/language/testdata/erroneous/dependency_cycle2.qbs b/tests/auto/language/testdata/erroneous/dependency_cycle2.qbs index 335355480..4aff0b75c 100644 --- a/tests/auto/language/testdata/erroneous/dependency_cycle2.qbs +++ b/tests/auto/language/testdata/erroneous/dependency_cycle2.qbs @@ -1,20 +1,20 @@ Project { - CppApplication { + Product { name: "A" Depends { name: "B" } files: ["main.cpp"] } - CppApplication { + Product { name: "B" Depends { name: "C" } files: ["main.cpp"] } - CppApplication { + Product { name: "C" Depends { name: "A" } files: ["main.cpp"] } - CppApplication { + Product { name: "D" files: ["main.cpp"] } diff --git a/tests/auto/language/testdata/erroneous/dependency_cycle3a.qbs b/tests/auto/language/testdata/erroneous/dependency_cycle3a.qbs new file mode 100644 index 000000000..a0660c074 --- /dev/null +++ b/tests/auto/language/testdata/erroneous/dependency_cycle3a.qbs @@ -0,0 +1,11 @@ +Project { + Product { + name: "B" + Depends { productTypes: ["a"] } + } + Product { + type: ["a"] + name: "A" + Depends { name: "B" } + } +} diff --git a/tests/auto/language/testdata/erroneous/frozen-object-list.qbs b/tests/auto/language/testdata/erroneous/frozen-object-list.qbs new file mode 100644 index 000000000..8bbd2b413 --- /dev/null +++ b/tests/auto/language/testdata/erroneous/frozen-object-list.qbs @@ -0,0 +1,17 @@ + +Product { + Probe { + id: probe + property varList output + configure: { + output = [{"key": "value"}]; + found = true; + } + } + + property var test: { + var result = probe.output; + result.push({}); + return result; + } +} diff --git a/tests/auto/language/testdata/erroneous/frozen-object.qbs b/tests/auto/language/testdata/erroneous/frozen-object.qbs new file mode 100644 index 000000000..0f891d04b --- /dev/null +++ b/tests/auto/language/testdata/erroneous/frozen-object.qbs @@ -0,0 +1,18 @@ + +Product { + Probe { + id: probe + property var output + configure: { + output = {"key": "value"} + found = true + } + } + + property var test: { + "use strict" + var result = probe.output; + result.key = "newValue"; + return result; + } +} diff --git a/tests/auto/language/testdata/erroneous/invalid_file.qbs b/tests/auto/language/testdata/erroneous/invalid_file.qbs index c461b87ef..54ec27410 100644 --- a/tests/auto/language/testdata/erroneous/invalid_file.qbs +++ b/tests/auto/language/testdata/erroneous/invalid_file.qbs @@ -1,3 +1,3 @@ -Application { +Product { files: ["main.cpp", "other.h"] } diff --git a/tests/auto/language/testdata/erroneous/missing-colon.qbs b/tests/auto/language/testdata/erroneous/missing-colon.qbs index e62eb7cfd..6e136bb56 100644 --- a/tests/auto/language/testdata/erroneous/missing-colon.qbs +++ b/tests/auto/language/testdata/erroneous/missing-colon.qbs @@ -1,3 +1,5 @@ -CppApplication { - cpp.dynamicLibraries { } +Product { + Depends { name: "dummy" } + qbsSearchPaths: ".." + dummy.cxxFlags { } } diff --git a/tests/auto/language/testdata/erroneous/missing-js-file.qbs b/tests/auto/language/testdata/erroneous/missing-js-file.qbs new file mode 100644 index 000000000..a3274a35b --- /dev/null +++ b/tests/auto/language/testdata/erroneous/missing-js-file.qbs @@ -0,0 +1,3 @@ +Product { + Depends { name: "missing-js-file-module" } +} diff --git a/tests/auto/language/testdata/erroneous/module-property-binding-in-project.qbs b/tests/auto/language/testdata/erroneous/module-property-binding-in-project.qbs new file mode 100644 index 000000000..667088c17 --- /dev/null +++ b/tests/auto/language/testdata/erroneous/module-property-binding-in-project.qbs @@ -0,0 +1,3 @@ +Project { + qbs.sysroot: "/" +} diff --git a/tests/auto/language/testdata/erroneous/module-with-id.qbs b/tests/auto/language/testdata/erroneous/module-with-id.qbs new file mode 100644 index 000000000..5b980100f --- /dev/null +++ b/tests/auto/language/testdata/erroneous/module-with-id.qbs @@ -0,0 +1,4 @@ +Product { + name: "p" + Depends { name: "module-with-id" } +} diff --git a/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file-module.qbs b/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file-module.qbs new file mode 100644 index 000000000..31302b5c2 --- /dev/null +++ b/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file-module.qbs @@ -0,0 +1,3 @@ +import "missing-js-file.js" as MissingJsFile + +Module { } diff --git a/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file.js b/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file.js new file mode 100644 index 000000000..b66048a8f --- /dev/null +++ b/tests/auto/language/testdata/erroneous/modules/missing-js-file-module/missing-js-file.js @@ -0,0 +1 @@ +var userfile = require("javascriptfile.js") diff --git a/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithId.qbs b/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithId.qbs new file mode 100644 index 000000000..d20b96784 --- /dev/null +++ b/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithId.qbs @@ -0,0 +1 @@ +ModuleWithIdParent { id: foo } diff --git a/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithIdParent.qbs b/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithIdParent.qbs new file mode 100644 index 000000000..5e45122de --- /dev/null +++ b/tests/auto/language/testdata/erroneous/modules/module-with-id/ModuleWithIdParent.qbs @@ -0,0 +1 @@ +Module {} diff --git a/tests/auto/language/testdata/erroneous/original-in-export-item.qbs b/tests/auto/language/testdata/erroneous/original-in-export-item.qbs index 51fedb9a2..c83601cfb 100644 --- a/tests/auto/language/testdata/erroneous/original-in-export-item.qbs +++ b/tests/auto/language/testdata/erroneous/original-in-export-item.qbs @@ -1,5 +1,3 @@ -import qbs - Project { Product { name: "a" diff --git a/tests/auto/language/testdata/erroneous/original-in-export-item2.qbs b/tests/auto/language/testdata/erroneous/original-in-export-item2.qbs index d932d4aee..1c9f3de4b 100644 --- a/tests/auto/language/testdata/erroneous/original-in-export-item2.qbs +++ b/tests/auto/language/testdata/erroneous/original-in-export-item2.qbs @@ -1,5 +1,3 @@ -import qbs - Project { Product { name: "a" diff --git a/tests/auto/language/testdata/erroneous/original-in-export-item3.qbs b/tests/auto/language/testdata/erroneous/original-in-export-item3.qbs index d7bcb322e..d23ad0a08 100644 --- a/tests/auto/language/testdata/erroneous/original-in-export-item3.qbs +++ b/tests/auto/language/testdata/erroneous/original-in-export-item3.qbs @@ -1,5 +1,3 @@ -import qbs - Project { Product { name: "a" diff --git a/tests/auto/language/testdata/erroneous/original-in-module-prototype.qbs b/tests/auto/language/testdata/erroneous/original-in-module-prototype.qbs index e7128092a..00661fb66 100644 --- a/tests/auto/language/testdata/erroneous/original-in-module-prototype.qbs +++ b/tests/auto/language/testdata/erroneous/original-in-module-prototype.qbs @@ -1,5 +1,3 @@ -import qbs - Product { Depends { name: "module-with-invalid-original" } } diff --git a/tests/auto/language/testdata/erroneous/properties-item-with-invalid-condition.qbs b/tests/auto/language/testdata/erroneous/properties-item-with-invalid-condition.qbs index 5b1a41f1b..0b48731ae 100644 --- a/tests/auto/language/testdata/erroneous/properties-item-with-invalid-condition.qbs +++ b/tests/auto/language/testdata/erroneous/properties-item-with-invalid-condition.qbs @@ -1,7 +1,7 @@ Product { Depends { name: "cpp" } Properties { - condition: cpp.nonexistingproperty.contains("somevalue") + condition: cpp.nonexistingproperty.includes("somevalue") cpp.defines: ["ABC"] } } diff --git a/tests/auto/language/testdata/eval-error-in-non-present-module.qbs b/tests/auto/language/testdata/eval-error-in-non-present-module.qbs index c112bc6d4..6882a2216 100644 --- a/tests/auto/language/testdata/eval-error-in-non-present-module.qbs +++ b/tests/auto/language/testdata/eval-error-in-non-present-module.qbs @@ -1,5 +1,3 @@ -import qbs - Product { name: "p" property bool moduleRequired diff --git a/tests/auto/language/testdata/exports.qbs b/tests/auto/language/testdata/exports.qbs index cc86b1e4a..0071aadce 100644 --- a/tests/auto/language/testdata/exports.qbs +++ b/tests/auto/language/testdata/exports.qbs @@ -1,7 +1,8 @@ import "exports_product.qbs" as ProductWithInheritedExportItem Project { - Application { + Product { + type: "app" name: "myapp" Depends { name: "mylib" } Depends { name: "dummy" } @@ -15,30 +16,35 @@ Project { "subdir2/exports-mylib2.qbs" ] - Application { + Product { + type: "app" name: "A" Depends { name: "qbs" } Depends { name: "B" } } - StaticLibrary { + Product { + type: "lib" name: "B" Export { Depends { name: "C" } Depends { name: "qbs" } } } - StaticLibrary { + Product { + type: "lib" name: "C" Export { Depends { name: "D" } Depends { name: "qbs" } } } - StaticLibrary { + Product { + type: "lib" name: "D" } - Application { + Product { + type: "app" name: "myapp2" Depends { name: "productWithInheritedExportItem" } Depends { name: "qbs" } @@ -46,7 +52,7 @@ Project { ProductWithInheritedExportItem { name: "productWithInheritedExportItem" Export { - dummy.cFlags: base.concat("PRODUCT_" + product.name.toUpperCase()) + dummy.cFlags: base.concat("PRODUCT_" + exportingProduct.name.toUpperCase()) dummy.cxxFlags: ["-bar"] Properties { condition: true @@ -54,7 +60,8 @@ Project { } } } - Application { + Product { + type: "app" name: "myapp3" Depends { name: "productWithInheritedExportItem"; versionAtLeast: "2.0" } } @@ -125,7 +132,7 @@ Project { Export { property bool depend: false - property var config: product.config + property var config: exportingProduct.config Depends { condition: depend; name: "cpp" } Properties { condition: depend; cpp.includePaths: ["."] } } @@ -142,8 +149,9 @@ Project { name: "broken_cycle1" Export { property bool depend: true - Depends { name: "broken_cycle3"; condition: depend } } + Depends { name: "broken_cycle3"; condition: depend } } + } Product { name: "broken_cycle2" Export { diff --git a/tests/auto/language/testdata/exports_product.qbs b/tests/auto/language/testdata/exports_product.qbs index dc4c9f462..394d388d9 100644 --- a/tests/auto/language/testdata/exports_product.qbs +++ b/tests/auto/language/testdata/exports_product.qbs @@ -2,7 +2,7 @@ Product { Export { version: "2.0" Depends { name: "dummy" } - dummy.cFlags: ["BASE_" + product.name.toUpperCase()] + dummy.cFlags: ["BASE_" + exportingProduct.name.toUpperCase()] dummy.cxxFlags: ["-foo"] dummy.defines: ["ABC"] } diff --git a/tests/auto/language/testdata/getNativeSetting.qbs b/tests/auto/language/testdata/getNativeSetting.qbs index 975aefebc..73af01316 100644 --- a/tests/auto/language/testdata/getNativeSetting.qbs +++ b/tests/auto/language/testdata/getNativeSetting.qbs @@ -1,15 +1,17 @@ import qbs.FileInfo import qbs.Utilities +import qbs.Host + Project { Product { name: "p1" targetName: { - if (qbs.hostOS.contains("macos")) { + if (Host.os().includes("macos")) { return Utilities.getNativeSetting("/System/Library/CoreServices/SystemVersion.plist", "ProductName"); - } else if (qbs.hostOS.contains("windows")) { + } else if (Host.os().includes("windows")) { var productName = Utilities.getNativeSetting("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion", "ProductName"); - if (productName.contains("Windows")) { + if (productName.includes("Windows")) { return "Windows"; } return undefined; diff --git a/tests/auto/language/testdata/groupconditions.qbs b/tests/auto/language/testdata/groupconditions.qbs index b7f383d45..4f55db9cd 100644 --- a/tests/auto/language/testdata/groupconditions.qbs +++ b/tests/auto/language/testdata/groupconditions.qbs @@ -43,7 +43,7 @@ Project { Product { name: "condition_accessing_module_property" Group { - condition: qbs.targetOS.contains("narf") + condition: qbs.targetOS.includes("narf") files: ["main.cpp"] qbs.install: false } diff --git a/tests/auto/language/testdata/inherited-properties-items/imports/DebugName.qbs b/tests/auto/language/testdata/inherited-properties-items/imports/DebugName.qbs index 5ac15658c..d129dc9db 100644 --- a/tests/auto/language/testdata/inherited-properties-items/imports/DebugName.qbs +++ b/tests/auto/language/testdata/inherited-properties-items/imports/DebugName.qbs @@ -1,5 +1,3 @@ -import qbs - Properties { condition: qbs.buildVariant === "debug" name: "product_debug" diff --git a/tests/auto/language/testdata/inherited-properties-items/imports/ReleaseName.qbs b/tests/auto/language/testdata/inherited-properties-items/imports/ReleaseName.qbs index e33c5652b..57ab96a7e 100644 --- a/tests/auto/language/testdata/inherited-properties-items/imports/ReleaseName.qbs +++ b/tests/auto/language/testdata/inherited-properties-items/imports/ReleaseName.qbs @@ -1,5 +1,3 @@ -import qbs - Properties { condition: qbs.buildVariant === "release" name: "product_release" diff --git a/tests/auto/language/testdata/inherited-properties-items/inherited-properties-items-product.qbs b/tests/auto/language/testdata/inherited-properties-items/inherited-properties-items-product.qbs index c20f045c8..6d148ba53 100644 --- a/tests/auto/language/testdata/inherited-properties-items/inherited-properties-items-product.qbs +++ b/tests/auto/language/testdata/inherited-properties-items/inherited-properties-items-product.qbs @@ -1,5 +1,3 @@ -import qbs - Product { name: "product_default" DebugName {} diff --git a/tests/auto/language/testdata/inherited-properties-items/inherited-properties-items.qbs b/tests/auto/language/testdata/inherited-properties-items/inherited-properties-items.qbs index 40d41c2fb..52f7ffc00 100644 --- a/tests/auto/language/testdata/inherited-properties-items/inherited-properties-items.qbs +++ b/tests/auto/language/testdata/inherited-properties-items/inherited-properties-items.qbs @@ -1,5 +1,3 @@ -import qbs - Project { qbsSearchPaths: sourceDirectory references: "inherited-properties-items-product.qbs" diff --git a/tests/auto/language/testdata/invalid-prop-on-non-required-module/invalid-prop-on-non-required-module.qbs b/tests/auto/language/testdata/invalid-prop-on-non-required-module/invalid-prop-on-non-required-module.qbs new file mode 100644 index 000000000..80ae6ad93 --- /dev/null +++ b/tests/auto/language/testdata/invalid-prop-on-non-required-module/invalid-prop-on-non-required-module.qbs @@ -0,0 +1,19 @@ +Project { + property bool useExistingModule + + Product { + name: "a" + condition: project.useExistingModule + Depends { name: "deploader" } + Depends { name: "dep" } + dep.nosuchprop: true + } + + Product { + name: "b" + condition: !project.useExistingModule + Depends { name: "deploader" } + Depends { name: "random"; required: false } + random.nosuchprop: true + } +} diff --git a/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/dep/dep.qbs b/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/dep/dep.qbs new file mode 100644 index 000000000..5e45122de --- /dev/null +++ b/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/dep/dep.qbs @@ -0,0 +1 @@ +Module {} diff --git a/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/deploader/deploader.qbs b/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/deploader/deploader.qbs new file mode 100644 index 000000000..15a1b5309 --- /dev/null +++ b/tests/auto/language/testdata/invalid-prop-on-non-required-module/modules/deploader/deploader.qbs @@ -0,0 +1,7 @@ +Module { + // This indirection exists to properly model QBS-1776. + // "deploader" corresponds to "bundle", and "dep" corresponds to "codesign" + Depends { condition: project.useExistingModule; name: "dep"; required: false } + + Depends { condition: !project.useExistingModule; name: "random"; required: false } +} diff --git a/tests/auto/language/testdata/jsextensions.js b/tests/auto/language/testdata/jsextensions.js index df74a263b..5c5821e86 100644 --- a/tests/auto/language/testdata/jsextensions.js +++ b/tests/auto/language/testdata/jsextensions.js @@ -57,9 +57,9 @@ var a = ["one", "two", "three"]; initTestContext("Array.prototype.contains"); for (var k in a) verify(k !== "contains"); -verify(a.contains("one")); -verify(a.contains("two")); -verify(a.contains("three")); -verify(!a.contains("four")); +verify(a.includes("one")); +verify(a.includes("two")); +verify(a.includes("three")); +verify(!a.includes("four")); })() // END function wrapper diff --git a/tests/auto/language/testdata/local-profile-as-top-level-profile.qbs b/tests/auto/language/testdata/local-profile-as-top-level-profile.qbs new file mode 100644 index 000000000..9bca3c599 --- /dev/null +++ b/tests/auto/language/testdata/local-profile-as-top-level-profile.qbs @@ -0,0 +1,7 @@ +Product { + Profile { + name: "test-profile" + qbs.architecture: "arm" + qbs.targetPlatform: "macos" + } +} diff --git a/tests/auto/language/testdata/erroneous/module-depends-on-product.qbs b/tests/auto/language/testdata/module-depends-on-product.qbs index a7db9e036..a7db9e036 100644 --- a/tests/auto/language/testdata/erroneous/module-depends-on-product.qbs +++ b/tests/auto/language/testdata/module-depends-on-product.qbs diff --git a/tests/auto/language/testdata/module-name-collisions/complex-collision.qbs b/tests/auto/language/testdata/module-name-collisions/complex-collision.qbs new file mode 100644 index 000000000..cd55aa946 --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/complex-collision.qbs @@ -0,0 +1,4 @@ +Product { + Depends { name: "prefix1.middle1" } + Depends { name: "prefix1.middle1.suffix1" } +} diff --git a/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/middle1.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/middle1.qbs new file mode 100644 index 000000000..5e45122de --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/middle1.qbs @@ -0,0 +1 @@ +Module {} diff --git a/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix1/suffix1.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix1/suffix1.qbs new file mode 100644 index 000000000..5e45122de --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix1/suffix1.qbs @@ -0,0 +1 @@ +Module {} diff --git a/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix2/suffix2.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix2/suffix2.qbs new file mode 100644 index 000000000..5e45122de --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle1/suffix2/suffix2.qbs @@ -0,0 +1 @@ +Module {} diff --git a/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle2/suffix/suffix.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle2/suffix/suffix.qbs new file mode 100644 index 000000000..5e45122de --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/middle2/suffix/suffix.qbs @@ -0,0 +1 @@ +Module {} diff --git a/tests/auto/language/testdata/erroneous/modules/prefix1/prefix1.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/prefix1.qbs index 84957060c..84957060c 100644 --- a/tests/auto/language/testdata/erroneous/modules/prefix1/prefix1.qbs +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/prefix1.qbs diff --git a/tests/auto/language/testdata/erroneous/modules/prefix1/suffix/suffix.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/suffix/suffix.qbs index 218a4feb7..218a4feb7 100644 --- a/tests/auto/language/testdata/erroneous/modules/prefix1/suffix/suffix.qbs +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix1/suffix/suffix.qbs diff --git a/tests/auto/language/testdata/module-name-collisions/modules/prefix2/prefix2.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix2/prefix2.qbs new file mode 100644 index 000000000..a5aaa6f8b --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix2/prefix2.qbs @@ -0,0 +1,3 @@ +Module { + Depends { name: "prefix2.suffix" } +} diff --git a/tests/auto/language/testdata/module-name-collisions/modules/prefix2/suffix/suffix.qbs b/tests/auto/language/testdata/module-name-collisions/modules/prefix2/suffix/suffix.qbs new file mode 100644 index 000000000..84957060c --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/modules/prefix2/suffix/suffix.qbs @@ -0,0 +1,2 @@ +Module { +} diff --git a/tests/auto/language/testdata/module-name-collisions/no-collision1.qbs b/tests/auto/language/testdata/module-name-collisions/no-collision1.qbs new file mode 100644 index 000000000..e5a94ad66 --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/no-collision1.qbs @@ -0,0 +1,4 @@ +Product { + Depends { name: "prefix1.middle1.suffix1" } + Depends { name: "prefix1.middle1.suffix2" } +} diff --git a/tests/auto/language/testdata/module-name-collisions/no-collision2.qbs b/tests/auto/language/testdata/module-name-collisions/no-collision2.qbs new file mode 100644 index 000000000..664ec1729 --- /dev/null +++ b/tests/auto/language/testdata/module-name-collisions/no-collision2.qbs @@ -0,0 +1,4 @@ +Product { + Depends { name: "prefix1.middle1" } + Depends { name: "prefix1.middle2.suffix" } +} diff --git a/tests/auto/language/testdata/erroneous/same-module-prefix1.qbs b/tests/auto/language/testdata/module-name-collisions/simple-collision1.qbs index 8aba31c2a..8aba31c2a 100644 --- a/tests/auto/language/testdata/erroneous/same-module-prefix1.qbs +++ b/tests/auto/language/testdata/module-name-collisions/simple-collision1.qbs diff --git a/tests/auto/language/testdata/erroneous/same-module-prefix2.qbs b/tests/auto/language/testdata/module-name-collisions/simple-collision2.qbs index 6679091c2..6679091c2 100644 --- a/tests/auto/language/testdata/erroneous/same-module-prefix2.qbs +++ b/tests/auto/language/testdata/module-name-collisions/simple-collision2.qbs diff --git a/tests/auto/language/testdata/module-parameters/module-parameters.qbs b/tests/auto/language/testdata/module-parameters/module-parameters.qbs new file mode 100644 index 000000000..48169d601 --- /dev/null +++ b/tests/auto/language/testdata/module-parameters/module-parameters.qbs @@ -0,0 +1,35 @@ +Project { + property bool overrideFromModule + property bool overrideFromExport + property bool overrideFromProduct + + Product { + name: "dep" + Export { + Depends { + name: "higher"; + condition: project.overrideFromExport + lower.param: "fromExportDepends" + } + Parameters { lower.param: "fromParameters" } + } + } + Product { + name: "main" + + Depends { + name: "dep" + condition: project.overrideFromProduct + lower.param: "fromProductDepends" + } + Depends { + name: "higher" + condition: project.overrideFromProduct + lower.param: "fromProductDepends" + } + Depends { name: "dep"; condition: !project.overrideFromProduct } + Depends { name: "higher"; condition: !project.overrideFromProduct } + Depends { name: "highest" } + Depends { name: "broken"; required: false } + } +} diff --git a/tests/auto/language/testdata/module-parameters/modules/broken/broken.qbs b/tests/auto/language/testdata/module-parameters/modules/broken/broken.qbs new file mode 100644 index 000000000..ae7b4c4ef --- /dev/null +++ b/tests/auto/language/testdata/module-parameters/modules/broken/broken.qbs @@ -0,0 +1,4 @@ +Module { + Depends { name: "higher"; lower.param: "shouldNeverAppear" } + validate: { throw "As the name indicates, this module is broken."; } +} diff --git a/tests/auto/language/testdata/module-parameters/modules/higher/higher.qbs b/tests/auto/language/testdata/module-parameters/modules/higher/higher.qbs new file mode 100644 index 000000000..006e05a93 --- /dev/null +++ b/tests/auto/language/testdata/module-parameters/modules/higher/higher.qbs @@ -0,0 +1,4 @@ +Module { + Depends { name: "lower" } + Parameters { lower.param: "fromParameters" } +} diff --git a/tests/auto/language/testdata/module-parameters/modules/highest/highest.qbs b/tests/auto/language/testdata/module-parameters/modules/highest/highest.qbs new file mode 100644 index 000000000..83b0a0a03 --- /dev/null +++ b/tests/auto/language/testdata/module-parameters/modules/highest/highest.qbs @@ -0,0 +1,7 @@ +Module { + Depends { + name: "higher" + condition: project.overrideFromModule + lower.param: "fromModuleDepends" + } +} diff --git a/tests/auto/language/testdata/module-parameters/modules/lower/lower.qbs b/tests/auto/language/testdata/module-parameters/modules/lower/lower.qbs new file mode 100644 index 000000000..11436ecd8 --- /dev/null +++ b/tests/auto/language/testdata/module-parameters/modules/lower/lower.qbs @@ -0,0 +1,3 @@ +Module { + Parameter { property string param: "origin" } +} diff --git a/tests/auto/language/testdata/modulepropertiesingroups.qbs b/tests/auto/language/testdata/modulepropertiesingroups.qbs index e3857bdf4..49f24c0ca 100644 --- a/tests/auto/language/testdata/modulepropertiesingroups.qbs +++ b/tests/auto/language/testdata/modulepropertiesingroups.qbs @@ -80,4 +80,13 @@ Project { } } } + + Product { + name: "module-property-in-group-condition" + Depends { name: "cpp" } + Group { + condition: qbs.architecture === "x86_64" + cpp.includePaths: "." + } + } } diff --git a/tests/auto/language/testdata/modules/broken/broken.qbs b/tests/auto/language/testdata/modules/broken/broken.qbs index b960117cf..a80547340 100644 --- a/tests/auto/language/testdata/modules/broken/broken.qbs +++ b/tests/auto/language/testdata/modules/broken/broken.qbs @@ -1,5 +1,3 @@ -import qbs - Module { Probe { id: theProbe diff --git a/tests/auto/language/testdata/modules/dummy/dummy.qbs b/tests/auto/language/testdata/modules/dummy/dummy.qbs index b1791ac96..623abc413 100644 --- a/tests/auto/language/testdata/modules/dummy/dummy.qbs +++ b/tests/auto/language/testdata/modules/dummy/dummy.qbs @@ -16,7 +16,7 @@ DummyBase { property string zort: "zort in dummy" property pathList includePaths property path somePath - property stringList listProp: product.type.contains("blubb") ? ["123"] : ["456"] + property stringList listProp: product.type.includes("blubb") ? ["123"] : ["456"] property bool controllingProp: false property stringList listProp2: controllingProp diff --git a/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs b/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs index 746c7e37b..2764af9c2 100644 --- a/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs +++ b/tests/auto/language/testdata/modules/dummyqt/core/dummycore.qbs @@ -1,11 +1,10 @@ Module { - id: qtcore property int versionMajor: 5 property int versionMinor: 0 property int versionPatch: 0 property string version: versionMajor.toString() + "." + versionMinor.toString() + "." + versionPatch.toString() property string coreProperty: "coreProperty" - property string coreVersion: qtcore.version + property string coreVersion: version property string zort: "zort in dummyqt.core" Depends { name: "dummy" } diff --git a/tests/auto/language/testdata/erroneous/modules/module-with-product-dependency/module-with-product-dependency.qbs b/tests/auto/language/testdata/modules/module-with-product-dependency/module-with-product-dependency.qbs index 5781bd6de..5781bd6de 100644 --- a/tests/auto/language/testdata/erroneous/modules/module-with-product-dependency/module-with-product-dependency.qbs +++ b/tests/auto/language/testdata/modules/module-with-product-dependency/module-with-product-dependency.qbs diff --git a/tests/auto/language/testdata/modules/multiple_backends/backend1.qbs b/tests/auto/language/testdata/modules/multiple_backends/backend1.qbs index 794c67827..4f78a89ae 100644 --- a/tests/auto/language/testdata/modules/multiple_backends/backend1.qbs +++ b/tests/auto/language/testdata/modules/multiple_backends/backend1.qbs @@ -1,4 +1,4 @@ Module { - condition: qbs.targetOS.contains("os1") + condition: qbs.targetOS.includes("os1") property string prop: "backend 1" } diff --git a/tests/auto/language/testdata/modules/multiple_backends/backend2.qbs b/tests/auto/language/testdata/modules/multiple_backends/backend2.qbs index 2073c4d0b..e7a44d4c7 100644 --- a/tests/auto/language/testdata/modules/multiple_backends/backend2.qbs +++ b/tests/auto/language/testdata/modules/multiple_backends/backend2.qbs @@ -1,5 +1,5 @@ Module { - condition: qbs.targetOS.contains("os2") + condition: qbs.targetOS.includes("os2") property string prop: "backend 2" property string backend2Prop } diff --git a/tests/auto/language/testdata/modules/multiple_backends/backend3.qbs b/tests/auto/language/testdata/modules/multiple_backends/backend3.qbs index 16228108b..762c12f20 100644 --- a/tests/auto/language/testdata/modules/multiple_backends/backend3.qbs +++ b/tests/auto/language/testdata/modules/multiple_backends/backend3.qbs @@ -1,5 +1,5 @@ Module { - condition: qbs.targetOS.contains("os2") && qbs.toolchain.contains("tc") + condition: qbs.targetOS.includes("os2") && qbs.toolchain.includes("tc") priority: 1 property string backend3Prop } diff --git a/tests/auto/language/testdata/multiplexed-exports.qbs b/tests/auto/language/testdata/multiplexed-exports.qbs index f98ceff95..3252145f1 100644 --- a/tests/auto/language/testdata/multiplexed-exports.qbs +++ b/tests/auto/language/testdata/multiplexed-exports.qbs @@ -6,7 +6,7 @@ Project { property string includeDir: qbs.buildVariant === "debug" ? "/d" : "/r" Export { Depends { name: "cpp" } - cpp.includePaths: product.includeDir + cpp.includePaths: exportingProduct.includeDir } } Product { diff --git a/tests/auto/language/testdata/probes-and-multiplexing.qbs b/tests/auto/language/testdata/probes-and-multiplexing.qbs new file mode 100644 index 000000000..38de08aee --- /dev/null +++ b/tests/auto/language/testdata/probes-and-multiplexing.qbs @@ -0,0 +1,15 @@ +Product { + multiplexByQbsProperties: "architectures" + qbs.architectures: ["x86", "x86_64", "arm"] + property string archFromProbe: theProbe.archOut + Probe { + id: theProbe + property string archIn: qbs.architecture + property string archOut + configure: { archOut = archIn; } + } + Group { + name: "theGroup" + qbs.sysroot: "/" + theProbe.archOut + } +} diff --git a/tests/auto/language/testdata/profilevaluesandoverriddenvalues.qbs b/tests/auto/language/testdata/profilevaluesandoverriddenvalues.qbs index 3aaa0cfa9..a0f189403 100644 --- a/tests/auto/language/testdata/profilevaluesandoverriddenvalues.qbs +++ b/tests/auto/language/testdata/profilevaluesandoverriddenvalues.qbs @@ -1,5 +1,5 @@ Project { - Application { + Product { name: "product1" property bool dummyProp: { if (!(dummy.cFlags instanceof Array)) diff --git a/tests/auto/language/testdata/qbs-properties-in-project-condition.qbs b/tests/auto/language/testdata/qbs-properties-in-project-condition.qbs index 31f648233..9d27df254 100644 --- a/tests/auto/language/testdata/qbs-properties-in-project-condition.qbs +++ b/tests/auto/language/testdata/qbs-properties-in-project-condition.qbs @@ -1,5 +1,5 @@ Project { - condition: qbs.targetOS.contains("whatever") + condition: qbs.targetOS.includes("whatever") Product { name: "never reached" diff --git a/tests/auto/language/testdata/rfc1034identifier.qbs b/tests/auto/language/testdata/rfc1034identifier.qbs index 4d320f899..e52dcc6b2 100644 --- a/tests/auto/language/testdata/rfc1034identifier.qbs +++ b/tests/auto/language/testdata/rfc1034identifier.qbs @@ -3,7 +3,7 @@ import qbs.Utilities CppApplication { name: Utilities.rfc1034Identifier("this!has@special#characters$uh-oh,Undersc0r3s_Are.Bad") Properties { - condition: qbs.targetOS.contains("darwin") + condition: qbs.targetOS.includes("darwin") bundle.infoPlist: { return {"CFBundleIdentifier": "$(PRODUCT_NAME:rfc1034identifier)"}; } } } diff --git a/tests/auto/language/testdata/subdir/exports-mylib.qbs b/tests/auto/language/testdata/subdir/exports-mylib.qbs index 92f39483a..68ea30384 100644 --- a/tests/auto/language/testdata/subdir/exports-mylib.qbs +++ b/tests/auto/language/testdata/subdir/exports-mylib.qbs @@ -8,8 +8,8 @@ StaticLibrary { Export { Depends { name: "dummy" } Depends { name: "mylib2" } - dummy.defines: [product.definePrefix + product.name.toUpperCase()] + dummy.defines: [exportingProduct.definePrefix + exportingProduct.name.toUpperCase()] dummy.includePaths: ["./lib"] - dummy.somePath: product.aPath + dummy.somePath: exportingProduct.aPath } } diff --git a/tests/auto/language/testdata/subdir2/exports-mylib2.qbs b/tests/auto/language/testdata/subdir2/exports-mylib2.qbs index ac8b9ebe4..b16b47821 100644 --- a/tests/auto/language/testdata/subdir2/exports-mylib2.qbs +++ b/tests/auto/language/testdata/subdir2/exports-mylib2.qbs @@ -5,7 +5,7 @@ StaticLibrary { property string definePrefix: "USE_" Export { Depends { name: "dummy" } - dummy.defines: [product.definePrefix + product.name.toUpperCase()] + dummy.defines: [exportingProduct.definePrefix + exportingProduct.name.toUpperCase()] dummy.includePaths: ["./lib"] } } diff --git a/tests/auto/language/testdata/suppressed-and-non-suppressed-errors.qbs b/tests/auto/language/testdata/suppressed-and-non-suppressed-errors.qbs index 4d5219157..684cc67b3 100644 --- a/tests/auto/language/testdata/suppressed-and-non-suppressed-errors.qbs +++ b/tests/auto/language/testdata/suppressed-and-non-suppressed-errors.qbs @@ -1,5 +1,5 @@ Project { - CppApplication { + Product { name: "mysterious creature" files: ["easter bunny"] } diff --git a/tests/auto/language/testdata/throw.qbs b/tests/auto/language/testdata/throw.qbs new file mode 100644 index 000000000..e9a97efb5 --- /dev/null +++ b/tests/auto/language/testdata/throw.qbs @@ -0,0 +1,16 @@ +Project { + property string throwType + property bool dummy: { + if (throwType === "bool") + throw true; + if (throwType === "int") + throw 43; + if (throwType === "string") + throw "an error"; + if (throwType === "list") + throw ["an", "error"]; + if (throwType === "object") + throw { result: "crash", reason: "overheating" }; + throw "type missing"; + } +} diff --git a/tests/auto/language/testdata/use-internal-profile.qbs b/tests/auto/language/testdata/use-internal-profile.qbs new file mode 100644 index 000000000..c2e20ff19 --- /dev/null +++ b/tests/auto/language/testdata/use-internal-profile.qbs @@ -0,0 +1,13 @@ +Project { + name: "theproject" + + Profile { + name: "theprofile" + dummy.defines: name + } + + Product { + name: "theproduct" + Depends { name: "dummy" } + } +}
\ No newline at end of file diff --git a/tests/auto/language/tst_language.cpp b/tests/auto/language/tst_language.cpp index 31aebfa3a..6a3344842 100644 --- a/tests/auto/language/tst_language.cpp +++ b/tests/auto/language/tst_language.cpp @@ -43,6 +43,7 @@ #include "../shared.h" +#include <app/shared/logging/consolelogger.h> #include <language/evaluator.h> #include <language/filecontext.h> #include <language/identifiersearch.h> @@ -52,6 +53,7 @@ #include <language/propertymapinternal.h> #include <language/scriptengine.h> #include <language/value.h> +#include <loader/projectresolver.h> #include <parser/qmljslexer_p.h> #include <parser/qmljsparser_p.h> #include <tools/scripttools.h> @@ -64,8 +66,7 @@ #include <tools/settings.h> #include <tools/stlutils.h> -#include "../shared/logging/consolelogger.h" - +#include <QtCore/qjsonobject.h> #include <QtCore/qprocess.h> #include <algorithm> @@ -79,28 +80,43 @@ using namespace qbs; using namespace qbs::Internal; static QString testDataDir() { - return FileInfo::resolvePath(QStringLiteral(SRCDIR), - QStringLiteral("../../../tests/auto/language/testdata")); + return testDataSourceDir(SRCDIR "/testdata"); } static QString testProject(const char *fileName) { return testDataDir() + QLatin1Char('/') + QLatin1String(fileName); } +class JSSourceValueCreator +{ + FileContextPtr m_fileContext; + std::vector<std::unique_ptr<QString>> m_strings; +public: + JSSourceValueCreator(const FileContextPtr &fileContext) + : m_fileContext(fileContext) + { + } + + JSSourceValuePtr create(const QString &sourceCode) + { + JSSourceValuePtr value = JSSourceValue::create(); + value->setFile(m_fileContext); + auto str = std::make_unique<QString>(sourceCode); + value->setSourceCode(*str.get()); + m_strings.push_back(std::move(str)); + return value; + } +}; + TestLanguage::TestLanguage(ILogSink *logSink, Settings *settings) : m_logSink(logSink) , m_settings(settings) , m_wildcardsTestDirPath(QDir::tempPath() + QLatin1String("/_wildcards_test_dir_")) { - qsrand(QTime::currentTime().msec()); + m_rand.seed(QTime::currentTime().msec()); qRegisterMetaType<QList<bool> >("QList<bool>"); - defaultParameters.setBuildRoot(m_tempDir.path() + "/buildroot"); - defaultParameters.setPropertyCheckingMode(ErrorHandlingMode::Strict); - defaultParameters.setSettingsDirectory(m_settings->baseDirectory()); } -TestLanguage::~TestLanguage() -{ -} +TestLanguage::~TestLanguage() = default; QHash<QString, ResolvedProductPtr> TestLanguage::productsFromProject(ResolvedProjectPtr project) { @@ -144,8 +160,7 @@ void TestLanguage::handleInitCleanupDataTags(const char *projectFileName, bool * *handled = true; bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject(projectFileName)); - project = loader->loadProject(defaultParameters); + resolveProject(projectFileName); QVERIFY(!!project); } catch (const ErrorInfo &e) { exceptionCaught = true; @@ -160,9 +175,31 @@ void TestLanguage::handleInitCleanupDataTags(const char *projectFileName, bool * } } +TopLevelProjectPtr TestLanguage::resolveProject(const char *relProjectFilePath) +{ + if (relProjectFilePath) + defaultParameters.setProjectFilePath(testProject(relProjectFilePath)); + defaultParameters.expandBuildConfiguration(); + ProjectResolver resolver(defaultParameters, m_engine.get(), m_logger); + return project = resolver.resolve(); +} + void TestLanguage::init() { + // clear caches, otherwise StoredVariantValues may end up being at the same address + // as the destroyed value + m_engine->reset(); m_logSink->setLogLevel(LoggerInfo); + defaultParameters = {}; + defaultParameters.setBuildRoot(m_tempDir.path() + "/buildroot"); + defaultParameters.setPropertyCheckingMode(ErrorHandlingMode::Strict); + defaultParameters.setSettingsDirectory(m_settings->baseDirectory()); + defaultParameters.setTopLevelProfile(profileName()); + defaultParameters.setMaxJobCount(1); + defaultParameters.setConfigurationName("default"); + defaultParameters.setEnvironment(QProcessEnvironment::systemEnvironment()); + defaultParameters.setSearchPaths({SRCDIR "/../../../share/qbs"}); + QVERIFY(m_tempDir.isValid()); } @@ -177,28 +214,16 @@ void TestLanguage::init() void TestLanguage::initTestCase() { m_logger = Logger(m_logSink); - m_engine = ScriptEngine::create(m_logger, EvalContext::PropertyEvaluation, this); - loader = new Loader(m_engine, m_logger); - loader->setSearchPaths(QStringList() - << QStringLiteral(SRCDIR "/../../../share/qbs")); - defaultParameters.setTopLevelProfile(profileName()); - defaultParameters.setConfigurationName("default"); - defaultParameters.expandBuildConfiguration(); - defaultParameters.setEnvironment(QProcessEnvironment::systemEnvironment()); - QVERIFY(QFileInfo(m_wildcardsTestDirPath).isAbsolute()); -} + m_engine = ScriptEngine::create(m_logger, EvalContext::PropertyEvaluation); -void TestLanguage::cleanupTestCase() -{ - delete loader; + QVERIFY(QFileInfo(m_wildcardsTestDirPath).isAbsolute()); } void TestLanguage::additionalProductTypes() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("additional-product-types.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("additional-product-types.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); const ResolvedProductConstPtr product = products.value("p"); @@ -219,8 +244,7 @@ void TestLanguage::baseProperty() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("baseproperty.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("baseproperty.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); @@ -237,10 +261,8 @@ void TestLanguage::baseProperty() void TestLanguage::baseValidation() { - qbs::SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("base-validate/base-validate.qbs")); try { - project = loader->loadProject(params); + resolveProject("base-validate/base-validate.qbs"); QVERIFY2(false, "exception expected"); } catch (const qbs::ErrorInfo &e) { QVERIFY2(e.toString().contains("Parent succeeded, child failed."), @@ -250,11 +272,9 @@ void TestLanguage::baseValidation() void TestLanguage::brokenDependencyCycle() { - qbs::SetupProjectParameters params = defaultParameters; QFETCH(QString, projectFileName); - params.setProjectFilePath(testProject(qPrintable(projectFileName))); try { - project = loader->loadProject(params); + resolveProject(qPrintable(projectFileName)); } catch (const qbs::ErrorInfo &e) { QVERIFY2(false, qPrintable(e.toString())); } @@ -271,12 +291,10 @@ void TestLanguage::buildConfigStringListSyntax() { bool exceptionCaught = false; try { - SetupProjectParameters parameters = defaultParameters; QVariantMap overriddenValues; overriddenValues.insert("project.someStrings", "foo,bar,baz"); - parameters.setOverriddenValues(overriddenValues); - parameters.setProjectFilePath(testProject("buildconfigstringlistsyntax.qbs")); - project = loader->loadProject(parameters); + defaultParameters.setOverriddenValues(overriddenValues); + resolveProject("buildconfigstringlistsyntax.qbs"); QVERIFY(!!project); QCOMPARE(project->projectProperties().value("someStrings").toStringList(), QStringList() << "foo" << "bar" << "baz"); @@ -291,9 +309,7 @@ void TestLanguage::builtinFunctionInSearchPathsProperty() { bool exceptionCaught = false; try { - SetupProjectParameters parameters = defaultParameters; - parameters.setProjectFilePath(testProject("builtinFunctionInSearchPathsProperty.qbs")); - QVERIFY(!!loader->loadProject(parameters)); + QVERIFY(resolveProject("builtinFunctionInSearchPathsProperty.qbs")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); @@ -305,11 +321,12 @@ void TestLanguage::chainedProbes() { bool exceptionCaught = false; try { - SetupProjectParameters parameters = defaultParameters; - parameters.setProjectFilePath(testProject("chained-probes/chained-probes.qbs")); - const TopLevelProjectConstPtr project = loader->loadProject(parameters); + resolveProject("chained-probes/chained-probes.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); + const QString prop1Val = project->products.front()->moduleProperties + ->moduleProperty("m", "prop1").toString(); + QCOMPARE(prop1Val, QLatin1String("probe1Val")); const QString prop2Val = project->products.front()->moduleProperties ->moduleProperty("m", "prop2").toString(); QCOMPARE(prop2Val, QLatin1String("probe1Valprobe2Val")); @@ -325,9 +342,7 @@ void TestLanguage::versionCompare() { bool exceptionCaught = false; try { - SetupProjectParameters parameters = defaultParameters; - parameters.setProjectFilePath(testProject("versionCompare.qbs")); - QVERIFY(!!loader->loadProject(parameters)); + QVERIFY(resolveProject("versionCompare.qbs")); } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); @@ -339,8 +354,7 @@ void TestLanguage::canonicalArchitecture() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("canonicalArchitecture.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("canonicalArchitecture.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value(QStringLiteral("x86")); @@ -356,8 +370,7 @@ void TestLanguage::rfc1034Identifier() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("rfc1034identifier.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("rfc1034identifier.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value(QStringLiteral("this-has-special-characters-" @@ -370,17 +383,47 @@ void TestLanguage::rfc1034Identifier() QCOMPARE(exceptionCaught, false); } +void TestLanguage::throwThings_data() +{ + QTest::addColumn<QString>("type"); + QTest::addColumn<QString>("result"); + QTest::addRow("bool") << "bool" << "true"; + QTest::addRow("int") << "int" << "43"; + QTest::addRow("string") << "string" << "an error"; + QTest::addRow("list") << "list" << R"([ + "an", + "error" +])"; + QTest::addRow("object") << "object" << R"({ + "reason": "overheating", + "result": "crash" +})"; +} + +void TestLanguage::throwThings() +{ + QFETCH(QString, type); + QFETCH(QString, result); + bool exceptionCaught = false; + try { + defaultParameters.setOverriddenValues({{"project.throwType", type}}); + resolveProject("throw.qbs"); + } catch (const ErrorInfo &e) { + exceptionCaught = true; + QVERIFY2(e.toString().contains(result), qPrintable(e.toString())); + } + QVERIFY(exceptionCaught); +} + void TestLanguage::conditionalDepends() { bool exceptionCaught = false; ResolvedProductPtr product; ResolvedModuleConstPtr dependency; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("conditionaldepends.qbs")); - params.setOverriddenValues({std::make_pair(QString("products." + defaultParameters.setOverriddenValues({std::make_pair(QString("products." "multilevel_module_props_overridden.dummy3.loadDummy"), true)}); - project = loader->loadProject(params); + resolveProject("conditionaldepends.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); @@ -479,17 +522,38 @@ void TestLanguage::conditionalDepends() QCOMPARE(exceptionCaught, false); } +void TestLanguage::convertStringList() +{ + FileContextPtr fileContext = FileContext::create(); + fileContext->setFilePath("/dev/null"); + JSSourceValueCreator sourceValueCreator(fileContext); + ItemPool pool; + Item *scope = Item::create(&pool, ItemType::Scope); + scope->setProperty("x", sourceValueCreator.create("[\"a\", \"b\"]")); + + Evaluator evaluator(m_engine.get()); + auto variantValue = evaluator.variantValue(scope, "x"); + // despite we have a stringList prop, we evaluate it as a QVariantList + QCOMPARE(variantValue.userType(), QMetaType::Type::QVariantList); + // and we have to convert it explicitly +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + variantValue.convert(QMetaType(QMetaType::QStringList)); +#else + variantValue.convert(QMetaType::QStringList); +#endif + QCOMPARE(variantValue.userType(), QMetaType::Type::QStringList); + QCOMPARE(variantValue, QStringList({"a", "b"})); +} + void TestLanguage::delayedError() { QFETCH(bool, productEnabled); try { QFETCH(QString, projectFileName); - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject(projectFileName.toLatin1())); QVariantMap overriddenValues; overriddenValues.insert("project.enableProduct", productEnabled); - params.setOverriddenValues(overriddenValues); - project = loader->loadProject(params); + defaultParameters.setOverriddenValues(overriddenValues); + resolveProject(projectFileName.toLatin1()); QCOMPARE(productEnabled, false); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); @@ -521,8 +585,6 @@ void TestLanguage::dependencyOnAllProfiles() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("dependencyOnAllProfiles.qbs")); TemporaryProfile p1("p1", m_settings); p1.p.setValue("qbs.architecture", "arch1"); TemporaryProfile p2("p2", m_settings); @@ -530,14 +592,14 @@ void TestLanguage::dependencyOnAllProfiles() QVariantMap overriddenValues; overriddenValues.insert("project.profile1", "p1"); overriddenValues.insert("project.profile2", "p2"); - params.setOverriddenValues(overriddenValues); - project = loader->loadProject(params); + defaultParameters.setOverriddenValues(overriddenValues); + resolveProject("dependencyOnAllProfiles.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(3)); const ResolvedProductConstPtr mainProduct = productsFromProject(project).value("main"); QVERIFY(!!mainProduct); QCOMPARE(mainProduct->dependencies.size(), size_t { 2 }); - for (const ResolvedProductConstPtr &p : mainProduct->dependencies) { + for (const ResolvedProductPtr &p : mainProduct->dependencies) { QCOMPARE(p->name, QLatin1String("dep")); QVERIFY(p->profile() == "p1" || p->profile() == "p2"); } @@ -552,9 +614,7 @@ void TestLanguage::derivedSubProject() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("derived-sub-project/project.qbs")); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("derived-sub-project/project.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -569,9 +629,7 @@ void TestLanguage::disabledSubProject() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("disabled-subproject.qbs")); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("disabled-subproject.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 0); @@ -600,16 +658,14 @@ void TestLanguage::dottedNames() { QFETCH(bool, expectSuccess); try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("dotted-names/dotted-names.qbs")); QFETCH(bool, useProduct); QFETCH(bool, useModule); const QVariantMap overridden{ std::make_pair("projects.theProject.includeDottedProduct", useProduct), std::make_pair("projects.theProject.includeDottedModule", useModule) }; - params.setOverriddenValues(overridden); - TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(overridden); + resolveProject("dotted-names/dotted-names.qbs"); QVERIFY(expectSuccess); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); @@ -626,13 +682,44 @@ void TestLanguage::dottedNames() } } +void TestLanguage::duplicateMultiplexValues_data() +{ + QTest::addColumn<bool>("dummy"); + QTest::newRow("duplicate-multiplex-value") << true; + QTest::newRow("duplicate-multiplex-value2") << true; +} + +void TestLanguage::duplicateMultiplexValues() +{ + bool exceptionCaught = false; + try { + resolveProject(qPrintable(QString::fromLocal8Bit(QTest::currentDataTag()) + + QLatin1String(".qbs"))); + QVERIFY(project); + const std::vector<ResolvedProductPtr> products = project->allProducts(); + QCOMPARE(products.size(), 2); + bool x86 = false; + bool arm = false; + for (const ResolvedProductPtr &p : products) { + if (p->moduleProperties->moduleProperty("qbs", "architecture").toString() == "x86") + x86 = true; + else if (p->moduleProperties->moduleProperty("qbs", "architecture").toString() == "arm") + arm = true; + } + QVERIFY(x86); + QVERIFY(arm); + } catch (const ErrorInfo &e) { + exceptionCaught = true; + qDebug() << e.toString(); + } + QVERIFY(!exceptionCaught); +} + void TestLanguage::emptyJsFile() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("empty-js-file.qbs")); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("empty-js-file.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -647,14 +734,12 @@ void TestLanguage::enumerateProjectProperties() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("enum-project-props.qbs")); - auto project = loader->loadProject(params); + resolveProject("enum-project-props.qbs"); QVERIFY(!!project); auto products = productsFromProject(project); QCOMPARE(products.size(), 1); auto product = products.values().front(); - auto files = product->groups.front()->allFiles(); + auto files = product->groups.front()->files; QCOMPARE(product->groups.size(), size_t(1)); QCOMPARE(files.size(), size_t(1)); auto fileName = FileInfo::fileName(files.front()->absoluteFilePath); @@ -672,7 +757,7 @@ void TestLanguage::evalErrorInNonPresentModule_data() QTest::addColumn<QString>("errorMessage"); QTest::newRow("module required") - << true << "broken.qbs:4:5 Element at index 0 of list property 'broken' " + << true << "broken.qbs:2:5 Element at index 0 of list property 'broken' " "does not have string type"; QTest::newRow("module not required") << false << QString(); } @@ -682,19 +767,16 @@ void TestLanguage::evalErrorInNonPresentModule() QFETCH(bool, moduleRequired); QFETCH(QString, errorMessage); try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("eval-error-in-non-present-module.qbs")); QVariantMap overridden{std::make_pair("products.p.moduleRequired", moduleRequired)}; - params.setOverriddenValues(overridden); - TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(overridden); + resolveProject("eval-error-in-non-present-module.qbs"); QVERIFY(errorMessage.isEmpty()); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); const ResolvedProductPtr product = products.value("p"); QVERIFY(!!product); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { QVERIFY(!errorMessage.isEmpty()); QVERIFY2(e.toString().contains(errorMessage), qPrintable(e.toString())); } @@ -704,14 +786,12 @@ void TestLanguage::defaultValue() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("defaultvalue/egon.qbs")); QFETCH(QString, prop1Value); QVariantMap overridden; if (!prop1Value.isEmpty()) overridden.insert("modules.lower.prop1", prop1Value); - params.setOverriddenValues(overridden); - TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(overridden); + resolveProject("defaultvalue/egon.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 2); @@ -725,8 +805,7 @@ void TestLanguage::defaultValue() propertyValue = product->moduleProperties->property(propertyName); QFETCH(QVariant, expectedListPropValue); QCOMPARE(propertyValue.toStringList(), expectedListPropValue.toStringList()); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -754,17 +833,14 @@ void TestLanguage::environmentVariable() try { // Create new environment: const QString varName = QStringLiteral("PRODUCT_NAME"); - const QString productName = QLatin1String("MyApp") + QString::number(qrand()); + const QString productName = QLatin1String("MyApp") + QString::number(m_rand.generate()); QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert(varName, productName); QProcessEnvironment origEnv = defaultParameters.environment(); // store orig environment defaultParameters.setEnvironment(env); - defaultParameters.setProjectFilePath(testProject("environmentvariable.qbs")); - project = loader->loadProject(defaultParameters); - - defaultParameters.setEnvironment(origEnv); // reset environment + resolveProject("environmentvariable.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); @@ -781,9 +857,7 @@ void TestLanguage::errorInDisabledProduct() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("error-in-disabled-product.qbs")); - auto project = loader->loadProject(params); + resolveProject("error-in-disabled-product.qbs"); QVERIFY(!!project); auto products = productsFromProject(project); QCOMPARE(products.size(), 5); @@ -807,11 +881,11 @@ void TestLanguage::erroneousFiles_data() QTest::newRow("importloop1") << "Loop detected when importing"; QTest::newRow("nonexistentouter") - << "Can't find variable: outer"; + << "'outer' is not defined"; QTest::newRow("invalid_file") << "does not exist"; QTest::newRow("invalid-parameter-rhs") - << "ReferenceError: Can't find variable: access"; + << "'access' is not defined"; QTest::newRow("invalid-parameter-type") << "Value assigned to property 'stringParameter' does not have type 'string'."; QTest::newRow("invalid_property_type") @@ -828,6 +902,8 @@ void TestLanguage::erroneousFiles_data() << "Cyclic dependencies detected."; QTest::newRow("dependency_cycle3") << "Cyclic dependencies detected."; + QTest::newRow("dependency_cycle3a") + << "Cyclic dependencies detected."; QTest::newRow("dependency_cycle4") << "Cyclic dependencies detected."; QTest::newRow("references_cycle") @@ -876,30 +952,24 @@ void TestLanguage::erroneousFiles_data() QTest::newRow("wrongQbsVersionFormat") << "The value '.*' of Project.minimumQbsVersion is not a valid version string."; QTest::newRow("properties-item-with-invalid-condition") - << "properties-item-with-invalid-condition.qbs:4:19.*TypeError: Result of expression " - "'cpp.nonexistingproperty'"; + << "properties-item-with-invalid-condition.qbs:4:19.*" + "cannot read property 'includes' of undefined"; QTest::newRow("misused-inherited-property") << "Binding to non-item property"; QTest::newRow("undeclared_property_in_Properties_item") << "Item 'blubb' is not declared"; - QTest::newRow("same-module-prefix1") << "The name of module 'prefix1' is equal to the first " - "component of the name of module 'prefix1.suffix'"; - QTest::newRow("same-module-prefix2") << "The name of module 'prefix2' is equal to the first " - "component of the name of module 'prefix2.suffix'"; QTest::newRow("conflicting-properties-in-export-items") << "Export item in inherited item redeclares property 'theProp' with different type."; QTest::newRow("invalid-property-option") << "PropertyOptions item refers to non-existing property 's0meProp'"; QTest::newRow("missing-colon") - << "Invalid item 'cpp.dynamicLibraries'. Did you mean to set a module property?"; + << "Invalid item 'dummy.cxxFlags'. Did you mean to set a module property?"; QTest::newRow("syntax-error-in-probe") - << "syntax-error-in-probe.qbs:4:20.*ReferenceError"; + << "syntax-error-in-probe.qbs:4:20.*'fngkgsdjfgklkf' is not defined"; QTest::newRow("wrong-toplevel-item") << "wrong-toplevel-item.qbs:1:1.*The top-level item must be of type 'Project' or " "'Product', but it is of type 'Artifact'."; QTest::newRow("conflicting-module-instances") << "There is more than one equally prioritized candidate for module " "'conflicting-instances'."; - QTest::newRow("module-depends-on-product") - << "module-with-product-dependency.qbs:2:5.*Modules cannot depend on products."; QTest::newRow("overwrite-inherited-readonly-property") << "overwrite-inherited-readonly-property.qbs" ":2:21.*Cannot set read-only property 'readOnlyString'."; @@ -916,25 +986,38 @@ void TestLanguage::erroneousFiles_data() << "module-with-invalid-original.qbs:2:24.*The special value 'original' cannot be used " "on the right-hand side of a property declaration."; QTest::newRow("original-in-export-item") - << "original-in-export-item.qbs:7:32.*The special value 'original' cannot be used " + << "original-in-export-item.qbs:5:32.*The special value 'original' cannot be used " "on the right-hand side of a property declaration."; QTest::newRow("original-in-export-item2") - << "original-in-export-item2.qbs:6:9.*Item 'x.y' is not declared. Did you forget " + << "original-in-export-item2.qbs:4:9.*Item 'x.y' is not declared. Did you forget " "to add a Depends item"; QTest::newRow("original-in-export-item3") << "original-in-export-item3.qbs:6:9.*Item 'x.y' is not declared. Did you forget " "to add a Depends item"; QTest::newRow("mismatching-multiplex-dependency") - << "mismatching-multiplex-dependency.qbs:7:5.*Dependency from product " - "'b \\{\"architecture\":\"mips\"\\}' to product 'a \\{\"architecture\":\"mips\"\\}'" - " not fulfilled."; - QTest::newRow("duplicate-multiplex-value") - << "duplicate-multiplex-value.qbs:3:1.*Duplicate entry 'x86' in qbs.architectures."; - QTest::newRow("duplicate-multiplex-value2") - << "duplicate-multiplex-value2.qbs:3:1.*Duplicate entry 'architecture' in " - "Product.multiplexByQbsProperties."; + << "mismatching-multiplex-dependency.qbs:9:9.*Dependency from product " + "'b \\{\"architecture\":\"mips\"\\}' to product 'a'" + " not fulfilled. There are no eligible multiplex candidates."; + QTest::newRow("ambiguous-multiplex-dependency") + << "ambiguous-multiplex-dependency.qbs:10:9.*Dependency from product 'b " + "\\{\"architecture\":\"x86\"\\}' to product 'a' is ambiguous. Eligible multiplex " + "candidates: a \\{\"architecture\":\"x86\",\"buildVariant\":\"debug\"\\}, " + "a \\{\"architecture\":\"x86\",\"buildVariant\":\"release\"\\}."; + QTest::newRow("dependency-profile-mismatch") + << "dependency-profile-mismatch.qbs:10:5.*Product 'main' depends on 'dep', " + "which does not exist for the requested profile 'profile47'."; + QTest::newRow("dependency-profile-mismatch-2") + << "dependency-profile-mismatch-2.qbs:15:9 Dependency from product 'main' to " + "product 'dep' not fulfilled. There are no eligible multiplex candidates."; QTest::newRow("invalid-references") << "invalid-references.qbs:2:17.*Cannot open '.*nosuchproject.qbs'"; + QTest::newRow("missing-js-file") + << "missing-js-file-module.qbs.*Cannot open '.*javascriptfile.js'"; + QTest::newRow("frozen-object") << "'key' is read-only"; + QTest::newRow("frozen-object-list") << "object is not extensible"; + QTest::newRow("module-property-binding-in-project") + << "Module properties cannot be set in Project items"; + QTest::newRow("module-with-id") << "Module items cannot have an id property"; } void TestLanguage::erroneousFiles() @@ -942,10 +1025,10 @@ void TestLanguage::erroneousFiles() QFETCH(QString, errorMessage); QString fileName = QString::fromLocal8Bit(QTest::currentDataTag()) + QLatin1String(".qbs"); try { - defaultParameters.setProjectFilePath(testProject("/erroneous/") + fileName); - loader->loadProject(defaultParameters); + resolveProject(qPrintable("/erroneous/" + fileName)); } catch (const ErrorInfo &e) { - if (!e.toString().contains(QRegExp(errorMessage))) { + const QRegularExpression reg(errorMessage, QRegularExpression::DotMatchesEverythingOption); + if (!e.toString().contains(reg)) { qDebug() << "Message: " << e.toString(); qDebug() << "Expected: " << errorMessage; QFAIL("Unexpected error message."); @@ -961,8 +1044,7 @@ void TestLanguage::exports() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("exports.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("exports.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 22); @@ -1007,6 +1089,7 @@ void TestLanguage::exports() product = products.value("B"); QVERIFY(!!product); QVERIFY(product->dependencies.empty()); + QCOMPARE(product->exportedModule.productDependencies, std::vector<QString>{"C"}); product = products.value("C"); QVERIFY(!!product); QVERIFY(product->dependencies.empty()); @@ -1051,7 +1134,7 @@ void TestLanguage::exports() propertyName = QStringList() << "dummy" << "defines"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toStringList(), - QStringList() << "LIBA" << "LIBB" << "LIBC" << "LIBD"); + QStringList() << "LIBD" << "LIBC" << "LIBA" << "LIBB"); propertyName = QStringList() << "dummy" << "productName"; propertyValue = product->moduleProperties->property(propertyName); QCOMPARE(propertyValue.toString(), QString("libE")); @@ -1059,7 +1142,7 @@ void TestLanguage::exports() product = products.value("depender"); QVERIFY(!!product); QCOMPARE(product->modules.size(), size_t(2)); - for (const ResolvedModuleConstPtr &m : product->modules) { + for (const ResolvedModulePtr &m : product->modules) { QVERIFY2(m->name == QString("qbs") || m->name == QString("dependency"), qPrintable(m->name)); } @@ -1070,13 +1153,12 @@ void TestLanguage::exports() product = products.value("broken_cycle3"); QVERIFY(!!product); QCOMPARE(product->modules.size(), size_t(3)); - for (const ResolvedModuleConstPtr &m : product->modules) { + for (const ResolvedModulePtr &m : product->modules) { QVERIFY2(m->name == QString("qbs") || m->name == QString("broken_cycle1") || m->name == QString("broken_cycle2"), qPrintable(m->name)); } - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1087,8 +1169,7 @@ void TestLanguage::fileContextProperties() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("filecontextproperties.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("filecontextproperties.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); @@ -1134,14 +1215,12 @@ void TestLanguage::fileInProductAndModule() QFETCH(bool, addFileToProduct); QFETCH(bool, successExpected); try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("file-in-product-and-module.qbs")); - params.setOverriddenValues(QVariantMap{ + defaultParameters.setOverriddenValues(QVariantMap{ std::make_pair("modules.module_with_file.file1IsTarget", file1IsTarget), std::make_pair("modules.module_with_file.file2IsTarget", file2IsTarget), std::make_pair("products.p.addFileToProduct", addFileToProduct), }); - project = loader->loadProject(params); + resolveProject("file-in-product-and-module.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -1156,16 +1235,19 @@ void TestLanguage::getNativeSetting() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("getNativeSetting.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("getNativeSetting.qbs"); QString expectedTargetName; - if (HostOsInfo::isMacosHost()) - expectedTargetName = QStringLiteral("Mac OS X"); - else if (HostOsInfo::isWindowsHost()) + if (HostOsInfo::isMacosHost()) { + if (HostOsInfo::hostOsVersion() >= qbs::Version(11)) + expectedTargetName = QStringLiteral("macOS"); + else + expectedTargetName = QStringLiteral("Mac OS X"); + } else if (HostOsInfo::isWindowsHost()) { expectedTargetName = QStringLiteral("Windows"); - else + } else { expectedTargetName = QStringLiteral("Unix"); + } QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products; @@ -1228,8 +1310,7 @@ void TestLanguage::groupName() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("groupname.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("groupname.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 2); @@ -1256,8 +1337,7 @@ void TestLanguage::groupName() group = product->groups.at(2); QVERIFY(!!group); QCOMPARE(group->name, QString("Group 2")); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1267,8 +1347,7 @@ void TestLanguage::groupName() void TestLanguage::homeDirectory() { try { - defaultParameters.setProjectFilePath(testProject("homeDirectory.qbs")); - ResolvedProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("homeDirectory.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -1293,8 +1372,7 @@ void TestLanguage::homeDirectory() FileInfo::resolvePath(product->sourceDirectory, QStringLiteral("a/~/bb"))); QCOMPARE(product->productProperties.value("user").toString(), FileInfo::resolvePath(product->sourceDirectory, QStringLiteral("~foo/bar"))); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { qDebug() << e.toString(); } } @@ -1373,8 +1451,7 @@ void TestLanguage::idUsage() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("idusage.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("idusage.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 5); @@ -1398,8 +1475,7 @@ void TestLanguage::idUsage() QVERIFY(!!product5); QCOMPARE(product5->moduleProperties->moduleProperty("deepdummy.deep.moat", "zort") .toString(), QString("zort in dummy")); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1410,10 +1486,8 @@ void TestLanguage::idUniqueness() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("id-uniqueness.qbs")); - loader->loadProject(defaultParameters); - } - catch (const ErrorInfo &e) { + resolveProject("id-uniqueness.qbs"); + } catch (const ErrorInfo &e) { exceptionCaught = true; const QList<ErrorItem> items = e.items(); QCOMPARE(items.size(), 3); @@ -1428,15 +1502,13 @@ void TestLanguage::importCollection() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("import-collection/project.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("import-collection/project.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); const ResolvedProductConstPtr product = products.value("da product"); QCOMPARE(product->productProperties.value("targetName").toString(), QLatin1String("C1f1C1f2C2f1C2f2")); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1455,19 +1527,15 @@ void TestLanguage::inheritedPropertiesItems() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; QFETCH(QString, buildVariant); QFETCH(QString, productName); - params.setProjectFilePath - (testProject("inherited-properties-items/inherited-properties-items.qbs")); - params.setOverriddenValues(QVariantMap{std::make_pair("qbs.buildVariant", buildVariant)}); - TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(QVariantMap{std::make_pair("qbs.buildVariant", buildVariant)}); + resolveProject("inherited-properties-items/inherited-properties-items.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); QVERIFY(!!products.value(productName)); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1478,13 +1546,11 @@ void TestLanguage::invalidBindingInDisabledItem() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("invalidBindingInDisabledItem.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("invalidBindingInDisabledItem.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 2); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1498,13 +1564,10 @@ void TestLanguage::invalidOverrides() const bool successExpected = expectedErrorMessage.isEmpty(); bool exceptionCaught = false; try { - qbs::SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("invalid-overrides.qbs")); - params.setOverriddenValues(QVariantMap{std::make_pair(key, true)}); - const TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(QVariantMap{std::make_pair(key, true)}); + resolveProject("invalid-overrides.qbs"); QVERIFY(!!project); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; if (successExpected) qDebug() << e.toString(); @@ -1548,31 +1611,32 @@ void TestLanguage::invalidOverrides_data() << "products.MyOtherProduct.cpp.useRPaths" << QString(); } -class JSSourceValueCreator +void TestLanguage::invalidPropOnNonRequiredModule_data() { - FileContextPtr m_fileContext; - QList<QString *> m_strings; -public: - JSSourceValueCreator(const FileContextPtr &fileContext) - : m_fileContext(fileContext) - { - } + QTest::addColumn<bool>("useExistingModule"); + QTest::addColumn<bool>("errorExpected"); - ~JSSourceValueCreator() - { - qDeleteAll(m_strings); - } + QTest::newRow("existing module") << true << true; + QTest::newRow("non-existing module") << false << false; +} - JSSourceValuePtr create(const QString &sourceCode) - { - JSSourceValuePtr value = JSSourceValue::create(); - value->setFile(m_fileContext); - const auto str = new QString(sourceCode); - m_strings.push_back(str); - value->setSourceCode(QStringRef(str)); - return value; +void TestLanguage::invalidPropOnNonRequiredModule() +{ + QFETCH(bool, useExistingModule); + QFETCH(bool, errorExpected); + + try { + defaultParameters.setOverriddenValues( + {std::make_pair("project.useExistingModule", useExistingModule)}); + resolveProject("invalid-prop-on-non-required-module"); + QVERIFY(!errorExpected); + } catch (const ErrorInfo &e) { + const QString errorString = e.toString(); + QVERIFY2(errorExpected, qPrintable(errorString)); + QVERIFY2(errorString.contains("Property 'nosuchprop' is not declared"), + qPrintable(errorString)); } -}; +} void TestLanguage::itemPrototype() { @@ -1588,13 +1652,14 @@ void TestLanguage::itemPrototype() item->setProperty("y", sourceValueCreator.create("x + 1")); item->setProperty("z", sourceValueCreator.create("2")); - Evaluator evaluator(m_engine); - QCOMPARE(evaluator.property(proto, "x").toVariant().toInt(), 1); - QCOMPARE(evaluator.property(proto, "y").toVariant().toInt(), 1); - QVERIFY(!evaluator.property(proto, "z").isValid()); - QCOMPARE(evaluator.property(item, "x").toVariant().toInt(), 1); - QCOMPARE(evaluator.property(item, "y").toVariant().toInt(), 2); - QCOMPARE(evaluator.property(item, "z").toVariant().toInt(), 2); + Evaluator evaluator(m_engine.get()); + JSContext * const ctx = m_engine->context(); + QCOMPARE(getJsVariant(ctx, evaluator.property(proto, "x")).toInt(), 1); + QCOMPARE(getJsVariant(ctx, evaluator.property(proto, "y")).toInt(), 1); + QVERIFY(JS_IsUndefined(evaluator.property(proto, "z"))); + QCOMPARE(getJsVariant(ctx, evaluator.property(item, "x")).toInt(), 1); + QCOMPARE(getJsVariant(ctx, evaluator.property(item, "y")).toInt(), 2); + QCOMPARE(getJsVariant(ctx, evaluator.property(item, "z")).toInt(), 2); } void TestLanguage::itemScope() @@ -1612,11 +1677,12 @@ void TestLanguage::itemScope() item->setScope(scope2); item->setProperty("z", sourceValueCreator.create("x + y")); - Evaluator evaluator(m_engine); - QCOMPARE(evaluator.property(scope1, "x").toVariant().toInt(), 1); - QCOMPARE(evaluator.property(scope2, "y").toVariant().toInt(), 2); - QVERIFY(!evaluator.property(scope2, "x").isValid()); - QCOMPARE(evaluator.property(item, "z").toVariant().toInt(), 3); + Evaluator evaluator(m_engine.get()); + JSContext * const ctx = m_engine->context(); + QCOMPARE(getJsVariant(ctx, evaluator.property(scope1, "x")).toInt(), 1); + QCOMPARE(getJsVariant(ctx, evaluator.property(scope2, "y")).toInt(), 2); + QVERIFY(JS_IsUndefined(evaluator.property(scope2, "x"))); + QCOMPARE(getJsVariant(ctx, evaluator.property(item, "z")).toInt(), 3); } void TestLanguage::jsExtensions() @@ -1626,10 +1692,10 @@ void TestLanguage::jsExtensions() QTextStream ts(&file); QString code = ts.readAll(); QVERIFY(!code.isEmpty()); - QScriptValue evaluated = m_engine->evaluate(code, file.fileName(), 1); - if (m_engine->hasErrorOrException(evaluated)) { - qDebug() << m_engine->uncaughtExceptionBacktrace(); - QFAIL(qPrintable(m_engine->lastErrorString(evaluated))); + m_engine->evaluate(JsValueOwner::Caller, code, file.fileName(), 1); + if (JsException ex = m_engine->checkAndClearException({})) { + qDebug() << ex.stackTrace(); + QFAIL(qPrintable(ex.message())); } } @@ -1648,35 +1714,45 @@ void TestLanguage::jsImportUsedInMultipleScopes() bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("jsimportsinmultiplescopes.qbs")); - params.setOverriddenValues({std::make_pair(QStringLiteral("qbs.buildVariant"), - buildVariant)}); - params.expandBuildConfiguration(); - TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues({std::make_pair(QStringLiteral("qbs.buildVariant"), + buildVariant)}); + resolveProject("jsimportsinmultiplescopes.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); ResolvedProductPtr product = products.values().front(); QVERIFY(!!product); QCOMPARE(product->name, expectedProductName); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QVERIFY(!exceptionCaught); } +void TestLanguage::localProfileAsTopLevelProfile() +{ + bool exceptionCaught = false; + try { + defaultParameters.setTopLevelProfile("test-profile"); + resolveProject("local-profile-as-top-level-profile.qbs"); + QVERIFY(!!project); + QCOMPARE(int(project->products.size()), 1); + const PropertyMapConstPtr &props = project->products.front()->moduleProperties; + QCOMPARE(props->qbsPropertyValue("architecture"), "arm"); + QCOMPARE(props->qbsPropertyValue("targetPlatform"), "macos"); + } catch (const ErrorInfo &e) { + exceptionCaught = true; + qDebug() << e.toString(); + } + QCOMPARE(exceptionCaught, false); +} + void TestLanguage::moduleMergingVariantValues() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath - (testProject("module-merging-variant-values/module-merging-variant-values.qbs")); - params.expandBuildConfiguration(); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("module-merging-variant-values/module-merging-variant-values.qbs"); QVERIFY(!!project); QCOMPARE(int(project->products.size()), 2); } catch (const ErrorInfo &e) { @@ -1686,6 +1762,185 @@ void TestLanguage::moduleMergingVariantValues() QCOMPARE(exceptionCaught, false); } +void TestLanguage::moduleNameCollisions_data() +{ + QTest::addColumn<QString>("projectFile"); + QTest::addColumn<bool>("collisionExpected"); + + QTest::newRow("simple collision (one order)") << "simple-collision1.qbs" << true; + QTest::newRow("simple collision (other order)") << "simple-collision2.qbs" << true; + QTest::newRow("collision with more components") << "complex-collision.qbs" << true; + QTest::newRow("no collision (same length)") << "no-collision1.qbs" << false; + QTest::newRow("no collision (different length)") << "no-collision2.qbs" << false; +} + +void TestLanguage::moduleNameCollisions() +{ + QFETCH(QString, projectFile); + QFETCH(bool, collisionExpected); + + try { + const QString compositeProjectFilePath = QString("module-name-collisions/") + projectFile; + QVERIFY(resolveProject(qPrintable(compositeProjectFilePath))); + QVERIFY(!collisionExpected); + } catch (const ErrorInfo &e) { + const QString errorString = e.toString(); + QVERIFY2(collisionExpected, qPrintable(errorString)); + QVERIFY2(errorString.contains("not allowed"), qPrintable(errorString)); + } +} + +void TestLanguage::moduleParameters_data() +{ + QTest::addColumn<QVariantMap>("inputProperties"); + QTest::addColumn<QVariantMap>("expectedModuleParameters"); + QTest::addColumn<bool>("errorExpected"); + + QTest::newRow("no overrides") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "false"), + std::make_pair("project.overrideFromExport", "false"), + std::make_pair("project.overrideFromProduct", "false")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromParameters")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromParameters")})})} + << false; + QTest::newRow("override from product") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "false"), + std::make_pair("project.overrideFromExport", "false"), + std::make_pair("project.overrideFromProduct", "true")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})})} + << false; + QTest::newRow("override from export") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "false"), + std::make_pair("project.overrideFromExport", "true"), + std::make_pair("project.overrideFromProduct", "false")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromExportDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromParameters")})})} + << false; + QTest::newRow("override from export and product") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "false"), + std::make_pair("project.overrideFromExport", "true"), + std::make_pair("project.overrideFromProduct", "true")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})})} + << false; + QTest::newRow("override from module") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "true"), + std::make_pair("project.overrideFromExport", "false"), + std::make_pair("project.overrideFromProduct", "false")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromModuleDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromParameters")})})} + << false; + QTest::newRow("override from module and product") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "true"), + std::make_pair("project.overrideFromExport", "false"), + std::make_pair("project.overrideFromProduct", "true")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})})} + << false; + QTest::newRow("override from module and export") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "true"), + std::make_pair("project.overrideFromExport", "true"), + std::make_pair("project.overrideFromProduct", "false")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromExportDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromParameters")})})} + << true; + QTest::newRow("override from module, export and product") + << QVariantMap{ + std::make_pair("project.overrideFromModule", "true"), + std::make_pair("project.overrideFromExport", "true"), + std::make_pair("project.overrideFromProduct", "true")} + << QVariantMap{ + std::make_pair("higher", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})}), + std::make_pair("dep", + QVariantMap{std::make_pair("lower", + QVariantMap{std::make_pair("param", "fromProductDepends")})})} + << false; +} + +void TestLanguage::moduleParameters() +{ + QFETCH(QVariantMap, inputProperties); + QFETCH(QVariantMap, expectedModuleParameters); + QFETCH(bool, errorExpected); + + try { + defaultParameters.setOverriddenValues(inputProperties); + resolveProject("module-parameters/module-parameters.qbs"); + QVERIFY(!errorExpected); + QVERIFY(project); + QCOMPARE(int(project->products.size()), 2); + const ResolvedProductPtr mainProduct = productsFromProject(project).value("main"); + QVERIFY(mainProduct); + QCOMPARE(int(mainProduct->moduleParameters.size()), 2); + for (auto it = expectedModuleParameters.cbegin(); it != expectedModuleParameters.cend(); + ++it) { + const auto findInProduct = [&](const QString &moduleName) { + for (auto it = mainProduct->moduleParameters.cbegin(); + it != mainProduct->moduleParameters.cend(); ++it) { + if (it.key()->name == moduleName) + return it.value(); + } + return QVariantMap(); + }; + const QVariantMap actual = findInProduct(it.key()); + const QVariantMap expected = it.value().toMap(); + const bool same = qVariantMapsEqual(actual, expected); + if (!same) { + qDebug().noquote() << "---" << expected; + qDebug().noquote() << "+++" << actual; + } + QVERIFY(same); + } + } catch (const ErrorInfo &e) { + QVERIFY2(errorExpected, qPrintable(e.toString())); + } +} + void TestLanguage::modulePrioritizationBySearchPath_data() { QTest::addColumn<QStringList>("searchPaths"); @@ -1701,12 +1956,10 @@ void TestLanguage::modulePrioritizationBySearchPath() bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("module-prioritization-by-search-path/project.qbs")); - params.setOverriddenValues({std::make_pair(QStringLiteral("project.qbsSearchPaths"), - searchPaths)}); - params.expandBuildConfiguration(); - TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues( + {std::make_pair(QStringLiteral("project.qbsSearchPaths"), + searchPaths)}); + resolveProject("module-prioritization-by-search-path/project.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -1715,8 +1968,7 @@ void TestLanguage::modulePrioritizationBySearchPath() const QString actualVariant = product->moduleProperties->moduleProperty ("conflicting-instances", "moduleVariant").toString(); QCOMPARE(actualVariant, expectedVariant); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -1730,10 +1982,10 @@ void TestLanguage::moduleProperties_data() QTest::newRow("init") << QString() << QVariant(); QTest::newRow("merge_lists") << "defines" - << QVariant(QStringList() << "THE_PRODUCT" << "QT_CORE" << "QT_GUI" << "QT_NETWORK"); + << QVariant(QStringList() << "THE_PRODUCT" << "QT_NETWORK" << "QT_GUI" << "QT_CORE"); QTest::newRow("merge_lists_and_values") << "defines" - << QVariant(QStringList() << "THE_PRODUCT" << "QT_CORE" << "QT_GUI" << "QT_NETWORK"); + << QVariant(QStringList() << "THE_PRODUCT" << "QT_NETWORK" << "QT_GUI" << "QT_CORE"); QTest::newRow("merge_lists_with_duplicates") << "cxxFlags" << QVariant(QStringList() << "-foo" << "BAR" << "-foo" << "BAZ"); @@ -1782,7 +2034,7 @@ void TestLanguage::modulePropertiesInGroups() defaultParameters.setProjectFilePath(testProject("modulepropertiesingroups.qbs")); bool exceptionCaught = false; try { - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject(); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value("grouptest"); @@ -1793,7 +2045,7 @@ void TestLanguage::modulePropertiesInGroups() GroupConstPtr g2; GroupConstPtr g21; GroupConstPtr g211; - for (const GroupConstPtr &g : product->groups) { + for (const GroupPtr &g : product->groups) { if (g->name == "g1") g1= g; else if (g->name == "g2") @@ -1910,7 +2162,7 @@ void TestLanguage::modulePropertiesInGroups() QCOMPARE(g2Gmod1List1, QStringList() << "gmod1_list1_proto" << "g2"); const auto &g2Gmod1List2 = moduleProperty(g2Props, "gmod.gmod1", "gmod1_list2") .toStringList(); - QCOMPARE(g2Gmod1List2, QStringList() << "grouptest" << "g2" << "gmod1_list2_proto"); + QCOMPARE(g2Gmod1List2, QStringList() << "grouptest" << "gmod1_string_proto" << "gmod1_list2_proto"); const int g2P0 = moduleProperty(g2Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g2P0, 6); const int g2DepProp = moduleProperty(g2Props, "gmod.gmod1", "depProp").toInt(); @@ -1928,7 +2180,7 @@ void TestLanguage::modulePropertiesInGroups() QCOMPARE(g21Gmod1List1, QStringList() << "gmod1_list1_proto" << "g2"); const auto &g21Gmod1List2 = moduleProperty(g21Props, "gmod.gmod1", "gmod1_list2") .toStringList(); - QEXPECT_FAIL(0, "no re-eval when no module props set", Continue); + QEXPECT_FAIL(nullptr, "no re-eval when no module props set", Continue); QCOMPARE(g21Gmod1List2, QStringList() << "grouptest" << "g2.1" << "gmod1_list2_proto"); const int g21P0 = moduleProperty(g21Props, "gmod.gmod1", "p0").toInt(); QCOMPARE(g21P0, 6); @@ -1938,7 +2190,7 @@ void TestLanguage::modulePropertiesInGroups() QCOMPARE(g21Gmod2String, QString("g2")); const auto &g21Gmod2List = moduleProperty(g21Props, "gmod2", "gmod2_list") .toStringList(); - QEXPECT_FAIL(0, "no re-eval when no module props set", Continue); + QEXPECT_FAIL(nullptr, "no re-eval when no module props set", Continue); QCOMPARE(g21Gmod2List, QStringList() << "g2" << "commonName_in_gmod1" << "g2.1_gmod4_g2.1_gmod3" << "g2.1_gmod3" << "gmod2_list_proto"); @@ -1955,11 +2207,11 @@ void TestLanguage::modulePropertiesInGroups() QCOMPARE(g211DepProp, 2); const auto &g211Gmod2String = moduleProperty(g211Props, "gmod2", "gmod2_string").toString(); - QEXPECT_FAIL(0, "re-eval not triggered", Continue); + QEXPECT_FAIL(nullptr, "re-eval not triggered", Continue); QCOMPARE(g211Gmod2String, QString("g2.1.1")); const auto &g211Gmod2List = moduleProperty(g211Props, "gmod2", "gmod2_list") .toStringList(); - QEXPECT_FAIL(0, "re-eval not triggered", Continue); + QEXPECT_FAIL(nullptr, "re-eval not triggered", Continue); QCOMPARE(g211Gmod2List, QStringList() << "g2.1.1" << "commonName_in_gmod1" << "g2.1.1_gmod4_g2.1.1_gmod3" << "g2.1.1_gmod3" << "gmod2_list_proto"); @@ -1967,7 +2219,7 @@ void TestLanguage::modulePropertiesInGroups() QVERIFY(!!product); g1.reset(); g11.reset(); - for (const GroupConstPtr &g : product->groups) { + for (const GroupPtr &g : product->groups) { if (g->name == "g1") g1= g; else if (g->name == "g1.1") @@ -1994,17 +2246,14 @@ void TestLanguage::modulePropertyOverridesPerProduct() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setOverriddenValues({ + defaultParameters.setOverriddenValues({ std::make_pair("modules.dummy.rpaths", QStringList({"/usr/lib"})), std::make_pair("modules.dummy.someString", "m"), std::make_pair("products.b.dummy.someString", "b"), std::make_pair("products.c.dummy.someString", "c"), std::make_pair("products.c.dummy.rpaths", QStringList({"/home", "/tmp"})) }); - params.setProjectFilePath( - testProject("module-property-overrides-per-product.qbs")); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("module-property-overrides-per-product.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 3); @@ -2037,8 +2286,7 @@ void TestLanguage::modulePropertyOverridesPerProduct() QCOMPARE(listPropertyValue(a), productPropertyValue(a)); QCOMPARE(listPropertyValue(b), productPropertyValue(b)); QCOMPARE(listPropertyValue(c), productPropertyValue(c)); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2050,7 +2298,7 @@ void TestLanguage::moduleScope() bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("modulescope.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject(); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -2070,13 +2318,30 @@ void TestLanguage::moduleScope() QCOMPARE(intModuleValue("f"), 2); // overridden QCOMPARE(intModuleValue("g"), 156); // overridden, dependent on product properties QCOMPARE(intModuleValue("h"), 158); // overridden, base dependent on product properties - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); +} +void TestLanguage::moduleWithProductDependency() +{ + bool exceptionCaught = false; + try { + defaultParameters.setProjectFilePath(testProject("module-depends-on-product.qbs")); + resolveProject(); + QVERIFY(project); + QHash<QString, ResolvedProductPtr> products = productsFromProject(project); + QCOMPARE(products.size(), 2); + ResolvedProductPtr product = products.value("p1"); + QVERIFY(product); + QCOMPARE(int(product->dependencies.size()), 1); + } catch (const ErrorInfo &e) { + exceptionCaught = true; + qDebug() << e.toString(); + } + QCOMPARE(exceptionCaught, false); } void TestLanguage::modules_data() @@ -2135,9 +2400,7 @@ void TestLanguage::multiplexedExports() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("multiplexed-exports.qbs")); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("multiplexed-exports.qbs"); QVERIFY(!!project); const auto products = project->allProducts(); QCOMPARE(products.size(), size_t(4)); @@ -2171,11 +2434,9 @@ void TestLanguage::multiplexingByProfile() { QFETCH(QString, projectFileName); QFETCH(bool, successExpected); - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testDataDir() + "/multiplexing-by-profile/" + projectFileName); try { - params.setDryRun(true); - const TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setDryRun(true); + resolveProject(qPrintable("/multiplexing-by-profile/" + projectFileName)); QVERIFY(successExpected); QVERIFY(!!project); } catch (const ErrorInfo &e) { @@ -2199,11 +2460,9 @@ void TestLanguage::nonApplicableModulePropertyInProfile() QFETCH(QString, toolchain); QFETCH(bool, successExpected); try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("non-applicable-module-property-in-profile.qbs")); - params.setOverriddenValues(QVariantMap{std::make_pair("project.targetOS", targetOS), + defaultParameters.setOverriddenValues({std::make_pair("project.targetOS", targetOS), std::make_pair("project.toolchain", toolchain)}); - const TopLevelProjectPtr project = loader->loadProject(params); + resolveProject("non-applicable-module-property-in-profile.qbs"); QVERIFY(!!project); QVERIFY(successExpected); } catch (const ErrorInfo &e) { @@ -2233,8 +2492,6 @@ void TestLanguage::nonRequiredProducts() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("non-required-products.qbs")); QFETCH(bool, subProjectEnabled); QFETCH(bool, dependeeEnabled); QVariantMap overriddenValues; @@ -2242,8 +2499,8 @@ void TestLanguage::nonRequiredProducts() overriddenValues.insert("projects.subproject.condition", false); else if (!dependeeEnabled) overriddenValues.insert("products.dependee.condition", false); - params.setOverriddenValues(overriddenValues); - const TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(overriddenValues); + resolveProject("non-required-products.qbs"); QVERIFY(!!project); const auto products = productsFromProject(project); QCOMPARE(products.size(), 4 + !!subProjectEnabled); @@ -2262,8 +2519,7 @@ void TestLanguage::nonRequiredProducts() QVERIFY2(product, name); QVERIFY2(!product->enabled, name); } - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2284,7 +2540,7 @@ void TestLanguage::outerInGroup() bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("outerInGroup.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject(); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -2305,8 +2561,7 @@ void TestLanguage::outerInGroup() artifact = group->files.front(); installDir = artifact->properties->qbsPropertyValue("installDir"); QCOMPARE(installDir.toString(), QString("/somewhere/else")); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2319,16 +2574,14 @@ void TestLanguage::overriddenPropertiesAndPrototypes() try { QFETCH(QString, osName); QFETCH(QString, backendName); - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("overridden-properties-and-prototypes.qbs")); - params.setOverriddenValues({std::make_pair("modules.qbs.targetPlatform", osName)}); - TopLevelProjectConstPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues({std::make_pair("modules.qbs.targetPlatform", + osName)}); + resolveProject("overridden-properties-and-prototypes.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); QCOMPARE(project->products.front()->moduleProperties->moduleProperty( "multiple_backends", "prop").toString(), backendName); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2347,11 +2600,9 @@ void TestLanguage::overriddenVariantProperty() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; const QVariantMap objectValue{std::make_pair("x", 1), std::make_pair("y", 2)}; - params.setOverriddenValues({std::make_pair("products.p.myObject", objectValue)}); - params.setProjectFilePath(testProject("overridden-variant-property.qbs")); - TopLevelProjectConstPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues({std::make_pair("products.p.myObject", objectValue)}); + resolveProject("overridden-variant-property.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); QCOMPARE(project->products.front()->productProperties.value("myObject").toMap(), @@ -2368,9 +2619,8 @@ void TestLanguage::parameterTypes() bool exceptionCaught = false; try { defaultParameters.setProjectFilePath(testProject("parameter-types.qbs")); - loader->loadProject(defaultParameters); - } - catch (const ErrorInfo &e) { + resolveProject(); + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2381,8 +2631,7 @@ void TestLanguage::pathProperties() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("pathproperties.qbs")); - project = loader->loadProject(defaultParameters); + resolveProject("pathproperties.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); @@ -2408,6 +2657,35 @@ void TestLanguage::pathProperties() QCOMPARE(exceptionCaught, false); } +void TestLanguage::probesAndMultiplexing() +{ + bool exceptionCaught = false; + try { + resolveProject("probes-and-multiplexing.qbs"); + QVERIFY(project); + QCOMPARE(int(project->products.size()), 3); + QStringList architectures{"x86", "x86_64", "arm"}; + for (const ResolvedProductPtr &product : project->products) { + const QString arch = product->moduleProperties->moduleProperty("qbs", "architecture") + .toString(); + QVERIFY2(architectures.removeOne(arch), qPrintable(arch)); + QCOMPARE(product->productProperties.value("archFromProbe").toString(), arch); + bool foundGroup = false; + for (const GroupPtr &group : product->groups) { + if (group->name == "theGroup") { + foundGroup = true; + QCOMPARE(group->properties->moduleProperty("qbs", "sysroot"), "/" + arch); + } + } + QVERIFY(foundGroup); + } + } catch (const ErrorInfo &e) { + exceptionCaught = true; + qDebug() << e.toString(); + } + QCOMPARE(exceptionCaught, false); +} + void TestLanguage::profileValuesAndOverriddenValues() { bool exceptionCaught = false; @@ -2418,14 +2696,11 @@ void TestLanguage::profileValuesAndOverriddenValues() profile.setValue("dummy.cFlags", "IN_PROFILE"); profile.setValue("dummy.cxxFlags", "IN_PROFILE"); profile.setValue("qbs.architecture", "x86"); - SetupProjectParameters parameters = defaultParameters; - parameters.setTopLevelProfile(profile.name()); + defaultParameters.setTopLevelProfile(profile.name()); QVariantMap overriddenValues; overriddenValues.insert("modules.dummy.cFlags", "OVERRIDDEN"); - parameters.setOverriddenValues(overriddenValues); - parameters.setProjectFilePath(testProject("profilevaluesandoverriddenvalues.qbs")); - parameters.expandBuildConfiguration(); - project = loader->loadProject(parameters); + defaultParameters.setOverriddenValues(overriddenValues); + resolveProject("profilevaluesandoverriddenvalues.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); ResolvedProductPtr product = products.value("product1"); @@ -2455,7 +2730,7 @@ void TestLanguage::projectFileLookup() try { SetupProjectParameters params; params.setProjectFilePath(projectFileInput); - Loader::setupProjectFilePath(params); + params.finalizeProjectFilePath(); QVERIFY(!failureExpected); QCOMPARE(params.projectFilePath(), projectFileOutput); } catch (const ErrorInfo &) { @@ -2469,7 +2744,7 @@ void TestLanguage::projectFileLookup_data() QTest::addColumn<QString>("projectFileOutput"); QTest::addColumn<bool>("failureExpected"); - const QString baseDir = QLatin1String(SRCDIR) + "/testdata"; + const QString baseDir = testDataDir(); const QString multiProjectsDir = baseDir + "/dirwithmultipleprojects"; const QString noProjectsDir = baseDir + "/dirwithnoprojects"; const QString oneProjectDir = baseDir + "/dirwithoneproject"; @@ -2486,8 +2761,7 @@ void TestLanguage::productConditions() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("productconditions.qbs")); - TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("productconditions.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 6); @@ -2515,8 +2789,7 @@ void TestLanguage::productConditions() product = products.value("product_probe_condition_true"); QVERIFY(!!product); QVERIFY(product->enabled); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2527,8 +2800,7 @@ void TestLanguage::productDirectories() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("productdirectories.qbs")); - ResolvedProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("productdirectories.qbs"); QVERIFY(!!project); QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 1); @@ -2539,8 +2811,7 @@ void TestLanguage::productDirectories() QCOMPARE(config.value(QStringLiteral("buildDirectory")).toString(), product->buildDirectory()); QCOMPARE(config.value(QStringLiteral("sourceDirectory")).toString(), testDataDir()); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { exceptionCaught = true; qDebug() << e.toString(); } @@ -2686,8 +2957,7 @@ void TestLanguage::propertiesBlockInGroup() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("properties-block-in-group.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("properties-block-in-group.qbs"); QVERIFY(!!project); QCOMPARE(project->allProducts().size(), size_t(1)); const ResolvedProductConstPtr product = project->allProducts().front(); @@ -2711,13 +2981,11 @@ void TestLanguage::propertiesItemInModule() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath( - testProject("properties-item-in-module.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("properties-item-in-module.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 2); - for (const ResolvedProductConstPtr &p : products) { + for (const ResolvedProductPtr &p : products) { QCOMPARE(p->moduleProperties->moduleProperty("dummy", "productName").toString(), p->name); } @@ -2732,16 +3000,14 @@ void TestLanguage::propertyAssignmentInExportedGroup() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath( - testProject("property-assignment-in-exported-group.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("property-assignment-in-exported-group.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 2); - for (const ResolvedProductConstPtr &p : products) { + for (const ResolvedProductPtr &p : products) { QCOMPARE(p->moduleProperties->moduleProperty("dummy", "someString").toString(), QString()); - for (const GroupConstPtr &g : p->groups) { + for (const GroupPtr &g : p->groups) { const QString propValue = g->properties->moduleProperty("dummy", "someString").toString(); if (g->name == "exported_group") @@ -2761,8 +3027,7 @@ void TestLanguage::qbs1275() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath(testProject("qbs1275.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("qbs1275.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.count(), 5); @@ -2777,10 +3042,9 @@ void TestLanguage::qbsPropertiesInProjectCondition() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath( - testProject("qbs-properties-in-project-condition.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("qbs-properties-in-project-condition.qbs"); QVERIFY(!!project); + QVERIFY(!project->enabled); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 0); } catch (const ErrorInfo &e) { @@ -2794,16 +3058,14 @@ void TestLanguage::qbsPropertyConvenienceOverride() { bool exceptionCaught = false; try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("qbs-property-convenience-override.qbs")); - params.setOverriddenValues({std::make_pair("qbs.installPrefix", "/opt")}); - TopLevelProjectConstPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues({std::make_pair("qbs.installPrefix", "/opt")}); + resolveProject("qbs-property-convenience-override.qbs"); QVERIFY(!!project); QCOMPARE(project->products.size(), size_t(1)); QCOMPARE(project->products.front()->moduleProperties->qbsPropertyValue("installPrefix") .toString(), QString("/opt")); - } - catch (const ErrorInfo &e) { + } catch (const ErrorInfo &e) { + exceptionCaught = true; qDebug() << e.toString(); } QCOMPARE(exceptionCaught, false); @@ -2814,11 +3076,9 @@ void TestLanguage::relaxedErrorMode() m_logSink->setLogLevel(LoggerMinLevel); QFETCH(bool, strictMode); try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("relaxed-error-mode/relaxed-error-mode.qbs")); - params.setProductErrorMode(strictMode ? ErrorHandlingMode::Strict - : ErrorHandlingMode::Relaxed); - const TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setProductErrorMode(strictMode ? ErrorHandlingMode::Strict + : ErrorHandlingMode::Relaxed); + resolveProject("relaxed-error-mode/relaxed-error-mode.qbs"); QVERIFY(!strictMode); const auto productMap = productsFromProject(project); const ResolvedProductConstPtr brokenProduct = productMap.value("broken"); @@ -2841,7 +3101,7 @@ void TestLanguage::relaxedErrorMode() QVERIFY(missingFile->enabled); QCOMPARE(missingFile->groups.size(), size_t(1)); QVERIFY(missingFile->groups.front()->enabled); - QCOMPARE(missingFile->groups.front()->allFiles().size(), size_t(2)); + QCOMPARE(missingFile->groups.front()->files.size(), size_t(2)); const ResolvedProductConstPtr fine = productMap.value("fine"); QVERIFY(fine->enabled); QCOMPARE(fine->allFiles().size(), size_t(1)); @@ -2863,10 +3123,7 @@ void TestLanguage::requiredAndNonRequiredDependencies() QFETCH(QString, projectFile); QFETCH(bool, exceptionExpected); try { - SetupProjectParameters params = defaultParameters; - const QString projectFilePath = "required-and-nonrequired-dependencies/" + projectFile; - params.setProjectFilePath(testProject(projectFilePath.toLocal8Bit())); - const TopLevelProjectConstPtr project = loader->loadProject(params); + resolveProject(qPrintable("required-and-nonrequired-dependencies/" + projectFile)); QVERIFY(!!project); QVERIFY(!exceptionExpected); } catch (const ErrorInfo &e) { @@ -2893,10 +3150,7 @@ void TestLanguage::requiredAndNonRequiredDependencies_data() void TestLanguage::suppressedAndNonSuppressedErrors() { try { - SetupProjectParameters params = defaultParameters; - const QString projectFilePath = "suppressed-and-non-suppressed-errors.qbs"; - params.setProjectFilePath(testProject(projectFilePath.toLocal8Bit())); - const TopLevelProjectConstPtr project = loader->loadProject(params); + resolveProject("suppressed-and-non-suppressed-errors.qbs"); QFAIL("failure expected"); } catch (const ErrorInfo &e) { QVERIFY2(e.toString().contains("easter bunny"), qPrintable(e.toString())); @@ -2908,12 +3162,10 @@ void TestLanguage::throwingProbe() { QFETCH(bool, enableProbe); try { - SetupProjectParameters params = defaultParameters; - params.setProjectFilePath(testProject("throwing-probe.qbs")); QVariantMap properties; properties.insert(QStringLiteral("products.theProduct.enableProbe"), enableProbe); - params.setOverriddenValues(properties); - const TopLevelProjectPtr project = loader->loadProject(params); + defaultParameters.setOverriddenValues(properties); + resolveProject("throwing-probe.qbs"); QVERIFY(!!project); QVERIFY(!enableProbe); } catch (const ErrorInfo &e) { @@ -2955,9 +3207,7 @@ void TestLanguage::recursiveProductDependencies() { bool exceptionCaught = false; try { - defaultParameters.setProjectFilePath( - testProject("recursive-dependencies/recursive-dependencies.qbs")); - const TopLevelProjectPtr project = loader->loadProject(defaultParameters); + resolveProject("recursive-dependencies/recursive-dependencies.qbs"); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); QCOMPARE(products.size(), 4); @@ -3014,6 +3264,19 @@ void TestLanguage::fileTags() QCOMPARE(fileTags, expectedFileTags); } +void TestLanguage::useInternalProfile() +{ + const QString profile(QStringLiteral("theprofile")); + defaultParameters.setTopLevelProfile(profile); + resolveProject("use-internal-profile.qbs"); + QVERIFY(!!project); + QCOMPARE(project->profile(), profile); + QCOMPARE(project->products.size(), size_t(1)); + const ResolvedProductConstPtr product = project->products[0]; + QCOMPARE(product->profile(), profile); + QCOMPARE(product->moduleProperties->moduleProperty("dummy", "defines").toString(), profile); +} + void TestLanguage::wildcards_data() { QTest::addColumn<bool>("useGroup"); @@ -3182,8 +3445,8 @@ void TestLanguage::wildcards() QFile projectFile(projectFilePath); QVERIFY(projectFile.open(QIODevice::WriteOnly)); QTextStream s(&projectFile); - s << "import qbs.base 1.0" << endl << endl - << "Application {" << endl + using Qt::endl; + s << "Application {" << endl << " name: \"MyProduct\"" << endl; if (useGroup) { s << " Group {" << endl @@ -3201,7 +3464,7 @@ void TestLanguage::wildcards() } // create files - for (QString filePath : qAsConst(filesToCreate)) { + for (QString filePath : std::as_const(filesToCreate)) { filePath.prepend(m_wildcardsTestDirPath + '/'); QFileInfo fi(filePath); if (!QDir(fi.path()).exists()) @@ -3215,7 +3478,7 @@ void TestLanguage::wildcards() ResolvedProductPtr product; try { defaultParameters.setProjectFilePath(projectFilePath); - project = loader->loadProject(defaultParameters); + resolveProject(); QVERIFY(!!project); const QHash<QString, ResolvedProductPtr> products = productsFromProject(project); product = products.value("MyProduct"); @@ -3234,10 +3497,10 @@ void TestLanguage::wildcards() group = product->groups.front(); } QVERIFY(!!group); - QCOMPARE(group->files.size(), size_t(0)); + QCOMPARE(group->files.size(), expected.size()); // we assume all files are wildcards QVERIFY(!!group->wildcards); QStringList actualFilePaths; - for (const SourceArtifactConstPtr &artifact : group->wildcards->files) { + for (const SourceArtifactPtr &artifact : group->files) { QString str = artifact->absoluteFilePath; int idx = str.indexOf(m_wildcardsTestDirPath); if (idx != -1) @@ -3261,4 +3524,3 @@ int main(int argc, char *argv[]) TestLanguage tl(ConsoleLogger::instance().logSink(), s.get()); return QTest::qExec(&tl, argc, argv); } - diff --git a/tests/auto/language/tst_language.h b/tests/auto/language/tst_language.h index 3fe6d8f2a..870b7d1f8 100644 --- a/tests/auto/language/tst_language.h +++ b/tests/auto/language/tst_language.h @@ -41,10 +41,12 @@ #define TST_LANGUAGE_H #include <language/forward_decls.h> -#include <language/loader.h> +#include <language/scriptengine.h> #include <logging/ilogsink.h> +#include <logging/logger.h> #include <tools/setupprojectparameters.h> +#include <QtCore/qrandom.h> #include <QtCore/qtemporarydir.h> #include <QtTest/qtest.h> @@ -55,27 +57,9 @@ public: TestLanguage(qbs::ILogSink *logSink, qbs::Settings *settings); ~TestLanguage(); -private: - qbs::ILogSink *m_logSink; - qbs::Settings * const m_settings; - qbs::Internal::Logger m_logger; - qbs::Internal::ScriptEngine *m_engine; - qbs::Internal::Loader *loader; - qbs::Internal::TopLevelProjectPtr project; - qbs::SetupProjectParameters defaultParameters; - const QString m_wildcardsTestDirPath; - - QHash<QString, qbs::Internal::ResolvedProductPtr> productsFromProject( - qbs::Internal::ResolvedProjectPtr project); - qbs::Internal::ResolvedModuleConstPtr findModuleByName( - qbs::Internal::ResolvedProductPtr product, const QString &name); - QVariant productPropertyValue(qbs::Internal::ResolvedProductPtr product, QString propertyName); - void handleInitCleanupDataTags(const char *projectFileName, bool *handled); - private slots: void init(); void initTestCase(); - void cleanupTestCase(); void additionalProductTypes(); void baseProperty(); @@ -87,6 +71,7 @@ private slots: void chainedProbes(); void canonicalArchitecture(); void conditionalDepends(); + void convertStringList(); void delayedError(); void delayedError_data(); void dependencyOnAllProfiles(); @@ -94,6 +79,8 @@ private slots: void disabledSubProject(); void dottedNames_data(); void dottedNames(); + void duplicateMultiplexValues_data(); + void duplicateMultiplexValues(); void emptyJsFile(); void enumerateProjectProperties(); void evalErrorInNonPresentModule_data(); @@ -123,12 +110,19 @@ private slots: void invalidBindingInDisabledItem(); void invalidOverrides(); void invalidOverrides_data(); + void invalidPropOnNonRequiredModule_data(); + void invalidPropOnNonRequiredModule(); void itemPrototype(); void itemScope(); void jsExtensions(); void jsImportUsedInMultipleScopes_data(); void jsImportUsedInMultipleScopes(); + void localProfileAsTopLevelProfile(); void moduleMergingVariantValues(); + void moduleNameCollisions_data(); + void moduleNameCollisions(); + void moduleParameters_data(); + void moduleParameters(); void modulePrioritizationBySearchPath_data(); void modulePrioritizationBySearchPath(); void moduleProperties_data(); @@ -136,6 +130,7 @@ private slots: void modulePropertiesInGroups(); void modulePropertyOverridesPerProduct(); void moduleScope(); + void moduleWithProductDependency(); void modules_data(); void modules(); void multiplexedExports(); @@ -151,6 +146,7 @@ private slots: void overriddenVariantProperty(); void parameterTypes(); void pathProperties(); + void probesAndMultiplexing(); void productConditions(); void productDirectories(); void profileValuesAndOverriddenValues(); @@ -176,12 +172,31 @@ private slots: void qualifiedId(); void recursiveProductDependencies(); void rfc1034Identifier(); + void throwThings_data(); + void throwThings(); + void useInternalProfile(); void versionCompare(); void wildcards_data(); void wildcards(); private: + QHash<QString, qbs::Internal::ResolvedProductPtr> productsFromProject( + qbs::Internal::ResolvedProjectPtr project); + qbs::Internal::ResolvedModuleConstPtr findModuleByName( + qbs::Internal::ResolvedProductPtr product, const QString &name); + QVariant productPropertyValue(qbs::Internal::ResolvedProductPtr product, QString propertyName); + void handleInitCleanupDataTags(const char *projectFileName, bool *handled); + qbs::Internal::TopLevelProjectPtr resolveProject(const char *relProjectFilePath = nullptr); + + qbs::ILogSink * const m_logSink; + qbs::Settings * const m_settings; + qbs::Internal::Logger m_logger; + std::unique_ptr<qbs::Internal::ScriptEngine> m_engine; + qbs::Internal::TopLevelProjectPtr project; + qbs::SetupProjectParameters defaultParameters; + const QString m_wildcardsTestDirPath; QTemporaryDir m_tempDir; + QRandomGenerator m_rand; }; #endif // TST_LANGUAGE_H |