diff --git a/arduino/cores/packagemanager/loader.go b/arduino/cores/packagemanager/loader.go index ac1b82e7118..3b94fc3a76d 100644 --- a/arduino/cores/packagemanager/loader.go +++ b/arduino/cores/packagemanager/loader.go @@ -19,6 +19,7 @@ import ( "fmt" "os" "path/filepath" + "strings" "github.com/arduino/arduino-cli/arduino/cores" "github.com/arduino/arduino-cli/configuration" @@ -250,8 +251,7 @@ func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, platformPat pm.Log.Infof("Package is built-in") } if err := pm.loadPlatformRelease(release, platformPath); err != nil { - return status.Newf(codes.FailedPrecondition, "loading platform release: %s", err) - + return status.Newf(codes.FailedPrecondition, "loading platform release %s: %s", release, err) } pm.Log.WithField("platform", release).Infof("Loaded platform") @@ -279,7 +279,7 @@ func (pm *PackageManager) loadPlatform(targetPackage *cores.Package, platformPat } release := platform.GetOrCreateRelease(version) if err := pm.loadPlatformRelease(release, versionDir); err != nil { - return status.Newf(codes.FailedPrecondition, "loading platform release: %s", err) + return status.Newf(codes.FailedPrecondition, "loading platform release %s: %s", release, err) } pm.Log.WithField("platform", release).Infof("Loaded platform") } @@ -341,7 +341,7 @@ func (pm *PackageManager) loadPlatformRelease(platform *cores.PlatformRelease, p } if err := pm.loadBoards(platform); err != nil { - return err + return fmt.Errorf("loading boards: %s", err) } return nil @@ -374,14 +374,47 @@ func (pm *PackageManager) loadBoards(platform *cores.PlatformRelease) error { propertiesByBoard := boardsProperties.FirstLevelOf() - platform.Menus = propertiesByBoard["menu"] + if menus, ok := propertiesByBoard["menu"]; ok { + platform.Menus = menus + } else { + platform.Menus = properties.NewMap() + } - delete(propertiesByBoard, "menu") // TODO: check this one + // This is not a board id so we remove it to correctly + // set all other boards properties + delete(propertiesByBoard, "menu") + skippedBoards := []string{} for boardID, boardProperties := range propertiesByBoard { - boardProperties.Set("_id", boardID) // TODO: What is that for?? - board := platform.GetOrCreateBoard(boardID) + var board *cores.Board + for key := range boardProperties.AsMap() { + if !strings.HasPrefix(key, "menu.") { + continue + } + // Menu keys are formed like this: + // menu.cache.off=false + // menu.cache.on=true + // so we assume that the a second element in the slice exists + menuName := strings.Split(key, ".")[1] + if !platform.Menus.ContainsKey(menuName) { + fqbn := fmt.Sprintf("%s:%s:%s", platform.Platform.Package.Name, platform.Platform.Architecture, boardID) + skippedBoards = append(skippedBoards, fqbn) + goto next_board + } + } + // The board's ID must be available in a board's properties since it can + // be used in all configuration files for several reasons, like setting compilation + // flags depending on the board id. + // For more info: + // https://arduino.github.io/arduino-cli/dev/platform-specification/#global-predefined-properties + boardProperties.Set("_id", boardID) + board = platform.GetOrCreateBoard(boardID) board.Properties.Merge(boardProperties) + next_board: + } + + if len(skippedBoards) > 0 { + return fmt.Errorf("skipping loading of boards %s: malformed custom board options", strings.Join(skippedBoards, ", ")) } return nil diff --git a/arduino/cores/packagemanager/package_manager_test.go b/arduino/cores/packagemanager/package_manager_test.go index 0c12edb506f..ff51923c35a 100644 --- a/arduino/cores/packagemanager/package_manager_test.go +++ b/arduino/cores/packagemanager/package_manager_test.go @@ -228,8 +228,10 @@ func TestFindToolsRequiredForBoard(t *testing.T) { loadIndex("https://dl.espressif.com/dl/package_esp32_index.json") loadIndex("http://arduino.esp8266.com/stable/package_esp8266com_index.json") loadIndex("https://adafruit.github.io/arduino-board-index/package_adafruit_index.json") - errs := pm.LoadHardware() - require.Len(t, errs, 0) + // We ignore the errors returned since they might not be necessarily blocking + // but just warnings for the user, like in the case a board is not loaded + // because of malformed menus + pm.LoadHardware() esp32, err := pm.FindBoardWithFQBN("esp32:esp32:esp32") require.NoError(t, err) esptool231 := pm.FindToolDependency(&cores.ToolDependency{ diff --git a/legacy/builder/test/user_hardware/my_avr_platform/avr/boards.txt b/legacy/builder/test/user_hardware/my_avr_platform/avr/boards.txt index 35bd354871d..5b50b4dfaf1 100644 --- a/legacy/builder/test/user_hardware/my_avr_platform/avr/boards.txt +++ b/legacy/builder/test/user_hardware/my_avr_platform/avr/boards.txt @@ -1,3 +1,5 @@ +menu.cpu=Processor + custom_yun.name=Arduino Yún custom_yun.upload.via_ssh=true diff --git a/test/test_core.py b/test/test_core.py index 8b255fbe1ec..e01517589ec 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -14,6 +14,7 @@ # a commercial license, send an email to license@arduino.cc. import os import datetime +import shutil import time import platform import pytest @@ -675,3 +676,39 @@ def test_core_list_platform_without_platform_txt(run_command, data_dir): core = cores[0] assert core["id"] == "some-packager:some-arch" assert core["name"] == "some-packager-some-arch" + + +def test_core_with_wrong_custom_board_options_is_loaded(run_command, data_dir): + test_platform_name = "platform_with_wrong_custom_board_options" + platform_install_dir = Path(data_dir, "hardware", "arduino-beta-dev", test_platform_name) + platform_install_dir.mkdir(parents=True) + + # Install platform in Sketchbook hardware dir + shutil.copytree( + Path(__file__).parent / "testdata" / test_platform_name, platform_install_dir, dirs_exist_ok=True, + ) + + assert run_command("update") + + res = run_command("core list --format json") + assert res.ok + + cores = json.loads(res.stdout) + mapped = {core["id"]: core for core in cores} + assert len(mapped) == 1 + # Verifies platform is loaded except excluding board with wrong options + assert "arduino-beta-dev:platform_with_wrong_custom_board_options" in mapped + boards = {b["fqbn"]: b for b in mapped["arduino-beta-dev:platform_with_wrong_custom_board_options"]["boards"]} + assert len(boards) == 1 + # Verify board with malformed options is not loaded + assert "arduino-beta-dev:platform_with_wrong_custom_board_options:nessuno" not in boards + # Verify other board is loaded + assert "arduino-beta-dev:platform_with_wrong_custom_board_options:altra" in boards + # Verify warning is shown to user + assert ( + "Error initializing instance: " + + "loading platform release arduino-beta-dev:platform_with_wrong_custom_board_options@4.2.0: " + + "loading boards: " + + "skipping loading of boards arduino-beta-dev:platform_with_wrong_custom_board_options:nessuno: " + + "malformed custom board options" + ) in res.stderr diff --git a/test/testdata/platform_with_wrong_custom_board_options/boards.txt b/test/testdata/platform_with_wrong_custom_board_options/boards.txt new file mode 100644 index 00000000000..7eb84395f77 --- /dev/null +++ b/test/testdata/platform_with_wrong_custom_board_options/boards.txt @@ -0,0 +1,63 @@ +menu.cpu=Processor + +nessuno.name=Arduino Nessuno +nessuno.vid.0=0x2341 +nessuno.pid.0=0x0043 +nessuno.vid.1=0x2341 +nessuno.pid.1=0x0001 +nessuno.vid.2=0x2A03 +nessuno.pid.2=0x0043 +nessuno.vid.3=0x2341 +nessuno.pid.3=0x0243 +nessuno.upload.tool=avrdude +nessuno.upload.protocol=arduino +nessuno.upload.maximum_size=32256 +nessuno.upload.maximum_data_size=2048 +nessuno.upload.speed=115200 +nessuno.bootloader.tool=avrdude +nessuno.bootloader.low_fuses=0xFF +nessuno.bootloader.high_fuses=0xDE +nessuno.bootloader.extended_fuses=0xFD +nessuno.bootloader.unlock_bits=0x3F +nessuno.bootloader.lock_bits=0x0F +nessuno.bootloader.file=optiboot/optiboot_atmega328.hex +nessuno.build.mcu=atmega328p +nessuno.build.f_cpu=16000000L +nessuno.build.board=AVR_NESSUNO +nessuno.build.core=arduino +nessuno.build.variant=standard + +nessuno.menu.cache.on=Enabled +nessuno.menu.cache.on.build.cache_flags=-DENABLE_CACHE +nessuno.menu.cache.off=Disabled +nessuno.menu.cache.off.build.cache_flags= + +altra.name=Arduino Altra +altra.vid.0=0x2341 +altra.pid.0=0x0043 +altra.vid.1=0x2341 +altra.pid.1=0x0001 +altra.vid.2=0x2A03 +altra.pid.2=0x0043 +altra.vid.3=0x2341 +altra.pid.3=0x0243 +altra.upload.tool=avrdude +altra.upload.protocol=arduino +altra.upload.maximum_size=32256 +altra.upload.maximum_data_size=2048 +altra.upload.speed=115200 +altra.bootloader.tool=avrdude +altra.bootloader.low_fuses=0xFF +altra.bootloader.high_fuses=0xDE +altra.bootloader.extended_fuses=0xFD +altra.bootloader.unlock_bits=0x3F +altra.bootloader.lock_bits=0x0F +altra.bootloader.file=optiboot/optiboot_atmega328.hex +altra.build.mcu=atmega328p +altra.build.f_cpu=16000000L +altra.build.board=AVR_ALTRA +altra.build.core=arduino +altra.build.variant=standard +altra.menu.cpu.atmega328=ATmega328P +altra.menu.cpu.atmega168=ATmega168 +altra.menufoo=bar diff --git a/test/testdata/platform_with_wrong_custom_board_options/platform.txt b/test/testdata/platform_with_wrong_custom_board_options/platform.txt new file mode 100644 index 00000000000..682f130ed49 --- /dev/null +++ b/test/testdata/platform_with_wrong_custom_board_options/platform.txt @@ -0,0 +1,2 @@ +name=Arduino Test Boards +version=4.2.0 \ No newline at end of file
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: