forked from qt-creator/qt-creator
McuSupport: Support globbing in default paths
With this change default paths containing globbing characters will be expanded to an available path. example: "sdk-*" will be replaced with "sdk-1.2.3" if the latter is available. To test the wildcards and make sure it works with QtCreator macros a fake_kit was added containing fake packages. Task-number: QTCREATORBUG-26900 Change-Id: I31440d24e42a6170fc5f1905f884bb3be43c57bc Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -30,18 +30,37 @@ using namespace Utils;
|
|||||||
|
|
||||||
namespace McuSupport::Internal {
|
namespace McuSupport::Internal {
|
||||||
|
|
||||||
|
static const Utils::FilePath expandWildcards(const Utils::FilePath& path)
|
||||||
|
{
|
||||||
|
if (!path.fileName().contains("*") && !path.fileName().contains("?"))
|
||||||
|
return path;
|
||||||
|
|
||||||
|
const FilePath p = path.parentDir();
|
||||||
|
|
||||||
|
auto entries = p.dirEntries(
|
||||||
|
Utils::FileFilter({path.fileName()}, QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot));
|
||||||
|
|
||||||
|
if (entries.isEmpty())
|
||||||
|
return path;
|
||||||
|
|
||||||
|
// Return the last match (can correspond to the latest version)
|
||||||
|
sort(entries, [](const FilePath &a, const FilePath &b) { return a.fileName() < b.fileName(); });
|
||||||
|
|
||||||
|
return entries.last();
|
||||||
|
}
|
||||||
|
|
||||||
Macros *McuSdkRepository::globalMacros()
|
Macros *McuSdkRepository::globalMacros()
|
||||||
{
|
{
|
||||||
static Macros macros;
|
static Macros macros;
|
||||||
return ¯os;
|
return ¯os;
|
||||||
}
|
}
|
||||||
|
|
||||||
void McuSdkRepository::expandVariables()
|
void McuSdkRepository::expandVariablesAndWildcards()
|
||||||
{
|
{
|
||||||
for (const auto &target : std::as_const(mcuTargets)) {
|
for (const auto &target : std::as_const(mcuTargets)) {
|
||||||
auto macroExpander = getMacroExpander(*target);
|
auto macroExpander = getMacroExpander(*target);
|
||||||
for (const auto &package : target->packages()) {
|
for (const auto &package : target->packages()) {
|
||||||
package->setPath(macroExpander->expand(package->path()));
|
package->setPath(expandWildcards(macroExpander->expand(package->path())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public:
|
|||||||
Targets mcuTargets;
|
Targets mcuTargets;
|
||||||
Packages packages;
|
Packages packages;
|
||||||
|
|
||||||
void expandVariables();
|
void expandVariablesAndWildcards();
|
||||||
MacroExpanderPtr getMacroExpander(const McuTarget &target);
|
MacroExpanderPtr getMacroExpander(const McuTarget &target);
|
||||||
|
|
||||||
static Macros *globalMacros();
|
static Macros *globalMacros();
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ void McuSupportOptionsWidget::apply()
|
|||||||
bool pathsChanged = false;
|
bool pathsChanged = false;
|
||||||
|
|
||||||
m_settingsHandler->setAutomaticKitCreation(m_options.automaticKitCreationEnabled());
|
m_settingsHandler->setAutomaticKitCreation(m_options.automaticKitCreationEnabled());
|
||||||
m_options.sdkRepository.expandVariables();
|
m_options.sdkRepository.expandVariablesAndWildcards();
|
||||||
|
|
||||||
QMessageBox warningPopup(QMessageBox::Icon::Warning,
|
QMessageBox warningPopup(QMessageBox::Icon::Warning,
|
||||||
Tr::tr("Warning"),
|
Tr::tr("Warning"),
|
||||||
|
|||||||
@@ -593,7 +593,7 @@ McuSdkRepository targetsFromDescriptions(const QList<McuTargetDescription> &desc
|
|||||||
}
|
}
|
||||||
|
|
||||||
McuSdkRepository repo{mcuTargets, mcuPackages};
|
McuSdkRepository repo{mcuTargets, mcuPackages};
|
||||||
repo.expandVariables();
|
repo.expandVariablesAndWildcards();
|
||||||
|
|
||||||
return repo;
|
return repo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
#include "mcutargetdescription.h"
|
#include "mcutargetdescription.h"
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/macroexpander.h>
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QVersionNumber>
|
#include <QVersionNumber>
|
||||||
|
|||||||
@@ -15,8 +15,9 @@
|
|||||||
#include "ghs_tviic2d6m_baremetal_json.h"
|
#include "ghs_tviic2d6m_baremetal_json.h"
|
||||||
#include "iar_mimxrt1064_evk_freertos_json.h"
|
#include "iar_mimxrt1064_evk_freertos_json.h"
|
||||||
#include "iar_stm32f469i_discovery_baremetal_json.h"
|
#include "iar_stm32f469i_discovery_baremetal_json.h"
|
||||||
#include "msvc_desktop_json.h"
|
|
||||||
#include "mingw_desktop_json.h"
|
#include "mingw_desktop_json.h"
|
||||||
|
#include "msvc_desktop_json.h"
|
||||||
|
#include "wildcards_test_kit_json.h"
|
||||||
|
|
||||||
#include "mcuhelpers.h"
|
#include "mcuhelpers.h"
|
||||||
#include "mcukitmanager.h"
|
#include "mcukitmanager.h"
|
||||||
@@ -27,6 +28,7 @@
|
|||||||
#include "mcusupportsdk.h"
|
#include "mcusupportsdk.h"
|
||||||
#include "mcusupportversiondetection.h"
|
#include "mcusupportversiondetection.h"
|
||||||
#include "mcutargetdescription.h"
|
#include "mcutargetdescription.h"
|
||||||
|
#include "mcutargetfactory.h"
|
||||||
#include "mcutargetfactorylegacy.h"
|
#include "mcutargetfactorylegacy.h"
|
||||||
|
|
||||||
#include <baremetal/baremetalconstants.h>
|
#include <baremetal/baremetalconstants.h>
|
||||||
@@ -44,13 +46,15 @@
|
|||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/filepath.h>
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QtTest>
|
#include <QtTest>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <tuple>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace McuSupport::Internal::Test {
|
namespace McuSupport::Internal::Test {
|
||||||
@@ -172,6 +176,11 @@ const QString jlinkDetectionPath{HostOsInfo::isWindowsHost()
|
|||||||
const QString unsupportedToolchainFilePath = QString{qtForMcuSdkPath}
|
const QString unsupportedToolchainFilePath = QString{qtForMcuSdkPath}
|
||||||
+ "/lib/cmake/Qul/toolchain/unsupported.cmake";
|
+ "/lib/cmake/Qul/toolchain/unsupported.cmake";
|
||||||
|
|
||||||
|
// Build/Testing/QtMCUs
|
||||||
|
const auto testing_output_dir = (FilePath::fromString(QCoreApplication::applicationDirPath()).parentDir()
|
||||||
|
/ "Testing/QtMCUs")
|
||||||
|
.canonicalPath();
|
||||||
|
|
||||||
const QStringList jsonFiles{QString::fromUtf8(armgcc_mimxrt1050_evk_freertos_json),
|
const QStringList jsonFiles{QString::fromUtf8(armgcc_mimxrt1050_evk_freertos_json),
|
||||||
QString::fromUtf8(iar_mimxrt1064_evk_freertos_json)};
|
QString::fromUtf8(iar_mimxrt1064_evk_freertos_json)};
|
||||||
|
|
||||||
@@ -201,7 +210,7 @@ const Id cxxLanguageId{ProjectExplorer::Constants::CXX_LANGUAGE_ID};
|
|||||||
|
|
||||||
//Expand variables in a tested {targets, packages} pair
|
//Expand variables in a tested {targets, packages} pair
|
||||||
auto expandTargetsAndPackages = [](Targets &targets, Packages &packages) {
|
auto expandTargetsAndPackages = [](Targets &targets, Packages &packages) {
|
||||||
McuSdkRepository{targets, packages}.expandVariables();
|
McuSdkRepository{targets, packages}.expandVariablesAndWildcards();
|
||||||
};
|
};
|
||||||
|
|
||||||
void verifyIarToolchain(const McuToolChainPackagePtr &iarToolchainPackage)
|
void verifyIarToolchain(const McuToolChainPackagePtr &iarToolchainPackage)
|
||||||
@@ -358,6 +367,30 @@ void verifyPackage(const McuPackagePtr &package,
|
|||||||
QCOMPARE(package->versions(), versions);
|
QCOMPARE(package->versions(), versions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create fake files and folders for testing under the "testing_output_dir" folder
|
||||||
|
bool createFakePath(const FilePath& path, const bool is_file = false)
|
||||||
|
{
|
||||||
|
if (path.exists())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
//create an empty file or folder
|
||||||
|
if (is_file) {
|
||||||
|
if (!path.parentDir().createDir()) {
|
||||||
|
qWarning() << "Could not create the parent dir for testing file " << path;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!path.writeFileContents("placeholder text")) {
|
||||||
|
qWarning() << "Could not write to testing file " << path;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!path.createDir()) {
|
||||||
|
qWarning() << "Could not create testing dir " << path;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
McuSupportTest::McuSupportTest()
|
McuSupportTest::McuSupportTest()
|
||||||
: targetFactory{settingsMockPtr}
|
: targetFactory{settingsMockPtr}
|
||||||
, compilerDescription{armGccLabel, armGccEnvVar, TOOLCHAIN_DIR_CMAKE_VARIABLE, armGccLabel, armGccDirectorySetting, {}, {}, {}, {}, false}
|
, compilerDescription{armGccLabel, armGccEnvVar, TOOLCHAIN_DIR_CMAKE_VARIABLE, armGccLabel, armGccDirectorySetting, {}, {}, {}, {}, false}
|
||||||
@@ -415,6 +448,15 @@ McuSupportTest::McuSupportTest()
|
|||||||
testing::FLAGS_gmock_verbose = "error";
|
testing::FLAGS_gmock_verbose = "error";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load the test file
|
||||||
|
std::pair<Targets, Packages> McuSupportTest::createTestingKitTargetsAndPackages(QByteArray test_file)
|
||||||
|
{
|
||||||
|
McuTargetFactory factory(settingsMockPtr);
|
||||||
|
auto [targets, packages] = factory.createTargets(parseDescriptionJson(test_file), sdkPackagePtr);
|
||||||
|
expandTargetsAndPackages(targets, packages);
|
||||||
|
return {targets, packages};
|
||||||
|
}
|
||||||
|
|
||||||
void McuSupportTest::initTestCase()
|
void McuSupportTest::initTestCase()
|
||||||
{
|
{
|
||||||
EXPECT_CALL(*freeRtosPackage, environmentVariableName())
|
EXPECT_CALL(*freeRtosPackage, environmentVariableName())
|
||||||
@@ -455,6 +497,9 @@ void McuSupportTest::initTestCase()
|
|||||||
|
|
||||||
void McuSupportTest::init()
|
void McuSupportTest::init()
|
||||||
{
|
{
|
||||||
|
McuSdkRepository::globalMacros()
|
||||||
|
->insert("MCU_TESTING_FOLDER",
|
||||||
|
[dir = testing_output_dir.absoluteFilePath().toString()] { return dir; });
|
||||||
qDebug() << __func__;
|
qDebug() << __func__;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1650,6 +1695,36 @@ void McuSupportTest::test_addToSystemPathFlag()
|
|||||||
QCOMPARE(freeRtosPackage.shouldAddToSystemPath, false);
|
QCOMPARE(freeRtosPackage.shouldAddToSystemPath, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void McuSupportTest::test_processWildcards_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("package_label");
|
||||||
|
QTest::addColumn<QString>("path");
|
||||||
|
QTest::addColumn<bool>("isFile");
|
||||||
|
|
||||||
|
QTest::newRow("\"*\" at the end") << "FAKE_WILDCARD_TEST_1"
|
||||||
|
<< "folder-123" << false;
|
||||||
|
QTest::newRow("\"*\" in the middle") << "FAKE_WILDCARD_TEST_2"
|
||||||
|
<< "file-123.exe" << true;
|
||||||
|
QTest::newRow("\"*\" at the start") << "FAKE_WILDCARD_TEST_3"
|
||||||
|
<< "123-file.exe" << true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void McuSupportTest::test_processWildcards()
|
||||||
|
{
|
||||||
|
QFETCH(QString, package_label);
|
||||||
|
QFETCH(QString, path);
|
||||||
|
QFETCH(bool, isFile);
|
||||||
|
|
||||||
|
QVERIFY(createFakePath(testing_output_dir / "wildcards" / path, isFile));
|
||||||
|
|
||||||
|
auto [targets, packages] = createTestingKitTargetsAndPackages(wildcards_test_kit);
|
||||||
|
auto testWildcardsPackage = findOrDefault(packages, [&](const McuPackagePtr &pkg) {
|
||||||
|
return (pkg->label() == package_label);
|
||||||
|
});
|
||||||
|
QVERIFY(testWildcardsPackage != nullptr);
|
||||||
|
QCOMPARE(testWildcardsPackage->path().toString(), FilePath(testing_output_dir / "wildcards" / path).toString());
|
||||||
|
}
|
||||||
|
|
||||||
void McuSupportTest::test_nonemptyVersionDetector()
|
void McuSupportTest::test_nonemptyVersionDetector()
|
||||||
{
|
{
|
||||||
PackageDescription pkgDesc;
|
PackageDescription pkgDesc;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class McuSupportTest : public QObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
McuSupportTest();
|
McuSupportTest();
|
||||||
|
std::pair<Targets, Packages> createTestingKitTargetsAndPackages(QByteArray test_file);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
@@ -102,6 +103,8 @@ private slots:
|
|||||||
|
|
||||||
void test_differentValueForEachOperationSystem();
|
void test_differentValueForEachOperationSystem();
|
||||||
void test_addToSystemPathFlag();
|
void test_addToSystemPathFlag();
|
||||||
|
void test_processWildcards_data();
|
||||||
|
void test_processWildcards();
|
||||||
|
|
||||||
void test_nonemptyVersionDetector();
|
void test_nonemptyVersionDetector();
|
||||||
void test_emptyVersionDetector();
|
void test_emptyVersionDetector();
|
||||||
|
|||||||
74
src/plugins/mcusupport/test/wildcards_test_kit_json.h
Normal file
74
src/plugins/mcusupport/test/wildcards_test_kit_json.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// Copyright (C) 2022 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
// This file is intended for testing McuSupport logic by adding fake packages
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
constexpr auto wildcards_test_kit = R"(
|
||||||
|
{
|
||||||
|
"qulVersion": "2.3.0",
|
||||||
|
"compatVersion": "1",
|
||||||
|
"platform": {
|
||||||
|
"id": "fake-platform",
|
||||||
|
"vendor": "fake-vendor",
|
||||||
|
"colorDepths": [32],
|
||||||
|
"cmakeEntries": [
|
||||||
|
{
|
||||||
|
"label": "FAKE_WILDCARD_TEST_1",
|
||||||
|
"description": "Assert '*' is replaced by possible values",
|
||||||
|
"defaultValue": "%{MCU_TESTING_FOLDER}/wildcards/folder-*",
|
||||||
|
"envVar": "",
|
||||||
|
"type": "path"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "FAKE_WILDCARD_TEST_2",
|
||||||
|
"description": "Assert '*' is replaced by possible values",
|
||||||
|
"defaultValue": "%{MCU_TESTING_FOLDER}/wildcards/file-*.exe",
|
||||||
|
"envVar": "",
|
||||||
|
"type": "path"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "FAKE_WILDCARD_TEST_3",
|
||||||
|
"description": "Assert '*' is replaced by possible values",
|
||||||
|
"defaultValue": "%{MCU_TESTING_FOLDER}/wildcards/*-file.exe",
|
||||||
|
"envVar": "",
|
||||||
|
"type": "path"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"toolchain": {
|
||||||
|
"id": "fake-compiler",
|
||||||
|
"versions": [
|
||||||
|
"0.0.1"
|
||||||
|
],
|
||||||
|
"compiler": {
|
||||||
|
"cmakeVar": "QUL_TARGET_TOOLCHAIN_DIR",
|
||||||
|
"setting": "",
|
||||||
|
"label": "fake compiler",
|
||||||
|
"type": "path",
|
||||||
|
"optional": false
|
||||||
|
},
|
||||||
|
"file": {
|
||||||
|
"cmakeVar": "CMAKE_TOOLCHAIN_FILE",
|
||||||
|
"type": "file",
|
||||||
|
"defaultValue": "",
|
||||||
|
"visible": false,
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"boardSdk": {
|
||||||
|
"envVar": "",
|
||||||
|
"setting": "",
|
||||||
|
"versions": [
|
||||||
|
"0.0.1"
|
||||||
|
],
|
||||||
|
"label": "",
|
||||||
|
"cmakeVar": "QUL_BOARD_SDK_DIR",
|
||||||
|
"type": "path",
|
||||||
|
"defaultValue": "",
|
||||||
|
"versionDetection": {},
|
||||||
|
"optional": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
Reference in New Issue
Block a user