Unverified Commit ffe44eaa authored by Silvano Cerza's avatar Silvano Cerza Committed by GitHub

Add back support for sketches with .pde extension and deprecate it (#1157)

* Compile command now works with sketches containing .pde files

* Upload command now works with sketches and builds from .pde files

* Archive command now works with sketches containing .pde files

* [skip changelog] Add test to verify debug command works with pde sketches

* Fix lib examples not showing sketches with .pde files

* [skip changelog] Remove duplicated code and enhance tests
parent d1163cbe
...@@ -18,9 +18,13 @@ package globals ...@@ -18,9 +18,13 @@ package globals
var ( var (
empty struct{} empty struct{}
// MainFileValidExtension is the extension that must be used for files in new sketches
MainFileValidExtension string = ".ino"
// MainFileValidExtensions lists valid extensions for a sketch file // MainFileValidExtensions lists valid extensions for a sketch file
MainFileValidExtensions = map[string]struct{}{ MainFileValidExtensions = map[string]struct{}{
".ino": empty, MainFileValidExtension: empty,
// .pde extension is deprecated and must not be used for new sketches
".pde": empty, ".pde": empty,
} }
......
...@@ -19,6 +19,7 @@ import ( ...@@ -19,6 +19,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/arduino/arduino-cli/arduino/sketches"
"github.com/arduino/go-paths-helper" "github.com/arduino/go-paths-helper"
properties "github.com/arduino/go-properties-orderedmap" properties "github.com/arduino/go-properties-orderedmap"
"github.com/pkg/errors" "github.com/pkg/errors"
...@@ -172,7 +173,8 @@ func addExamplesToPathList(examplesPath *paths.Path, list *paths.PathList) error ...@@ -172,7 +173,8 @@ func addExamplesToPathList(examplesPath *paths.Path, list *paths.PathList) error
return err return err
} }
for _, file := range files { for _, file := range files {
if isExample(file) { _, err := sketches.NewSketchFromPath(file)
if err == nil {
list.Add(file) list.Add(file)
} else if file.IsDir() { } else if file.IsDir() {
if err := addExamplesToPathList(file, list); err != nil { if err := addExamplesToPathList(file, list); err != nil {
...@@ -182,9 +184,3 @@ func addExamplesToPathList(examplesPath *paths.Path, list *paths.PathList) error ...@@ -182,9 +184,3 @@ func addExamplesToPathList(examplesPath *paths.Path, list *paths.PathList) error
} }
return nil return nil
} }
// isExample returns true if examplePath contains an example
func isExample(examplePath *paths.Path) bool {
mainIno := examplePath.Join(examplePath.Base() + ".ino")
return mainIno.Exist() && mainIno.IsNotDir()
}
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"github.com/arduino/arduino-cli/arduino/builder" "github.com/arduino/arduino-cli/arduino/builder"
"github.com/arduino/arduino-cli/arduino/globals"
"github.com/arduino/go-paths-helper" "github.com/arduino/go-paths-helper"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
...@@ -27,6 +28,7 @@ import ( ...@@ -27,6 +28,7 @@ import (
// Sketch is a sketch for Arduino // Sketch is a sketch for Arduino
type Sketch struct { type Sketch struct {
Name string Name string
MainFileExtension string
FullPath *paths.Path FullPath *paths.Path
Metadata *Metadata Metadata *Metadata
} }
...@@ -52,12 +54,30 @@ func NewSketchFromPath(path *paths.Path) (*Sketch, error) { ...@@ -52,12 +54,30 @@ func NewSketchFromPath(path *paths.Path) (*Sketch, error) {
if !path.IsDir() { if !path.IsDir() {
path = path.Parent() path = path.Parent()
} }
sketchFile := path.Join(path.Base() + ".ino")
if !sketchFile.Exist() { var mainSketchFile *paths.Path
return nil, errors.Errorf("no valid sketch found in %s: missing %s", path, sketchFile.Base()) for ext := range globals.MainFileValidExtensions {
candidateSketchMainFile := path.Join(path.Base() + ext)
if candidateSketchMainFile.Exist() {
if mainSketchFile == nil {
mainSketchFile = candidateSketchMainFile
} else {
return nil, errors.Errorf("multiple main sketch files found (%v, %v)",
mainSketchFile,
candidateSketchMainFile,
)
}
}
} }
if mainSketchFile == nil {
sketchFile := path.Join(path.Base() + globals.MainFileValidExtension)
return nil, errors.Errorf("no valid sketch found in %s: missing %s", path, sketchFile)
}
sketch := &Sketch{ sketch := &Sketch{
FullPath: path, FullPath: path,
MainFileExtension: mainSketchFile.Ext(),
Name: path.Base(), Name: path.Base(),
Metadata: &Metadata{}, Metadata: &Metadata{},
} }
...@@ -108,3 +128,20 @@ func (s *Sketch) BuildPath() (*paths.Path, error) { ...@@ -108,3 +128,20 @@ func (s *Sketch) BuildPath() (*paths.Path, error) {
} }
return builder.GenBuildPath(s.FullPath), nil return builder.GenBuildPath(s.FullPath), nil
} }
// CheckForPdeFiles returns all files ending with .pde extension
// in dir, this is mainly used to warn the user that these files
// must be changed to .ino extension.
// When .pde files won't be supported anymore this function must be removed.
func CheckForPdeFiles(sketch *paths.Path) []*paths.Path {
if sketch.IsNotDir() {
sketch = sketch.Parent()
}
files, err := sketch.ReadDirRecursive()
if err != nil {
return []*paths.Path{}
}
files.FilterSuffix(".pde")
return files
}
...@@ -53,9 +53,59 @@ func TestSketchBuildPath(t *testing.T) { ...@@ -53,9 +53,59 @@ func TestSketchBuildPath(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Contains(t, buildPath.String(), "arduino-sketch-") require.Contains(t, buildPath.String(), "arduino-sketch-")
// Verifies sketch path is returned if sketch has .pde extension
sketchPath = paths.New("testdata", "SketchPde")
sketch, err = NewSketchFromPath(sketchPath)
require.NoError(t, err)
require.NotNil(t, sketch)
buildPath, err = sketch.BuildPath()
require.NoError(t, err)
require.Contains(t, buildPath.String(), "arduino-sketch-")
// Verifies error is returned if there are multiple main files
sketchPath = paths.New("testdata", "SketchMultipleMainFiles")
sketch, err = NewSketchFromPath(sketchPath)
require.Nil(t, sketch)
require.Error(t, err, "multiple main sketch files found")
// Verifies error is returned if sketch path is not set // Verifies error is returned if sketch path is not set
sketch = &Sketch{} sketch = &Sketch{}
buildPath, err = sketch.BuildPath() buildPath, err = sketch.BuildPath()
require.Nil(t, buildPath) require.Nil(t, buildPath)
require.Error(t, err, "sketch path is empty") require.Error(t, err, "sketch path is empty")
} }
func TestCheckForPdeFiles(t *testing.T) {
sketchPath := paths.New("testdata", "Sketch1")
files := CheckForPdeFiles(sketchPath)
require.Empty(t, files)
sketchPath = paths.New("testdata", "SketchPde")
files = CheckForPdeFiles(sketchPath)
require.Len(t, files, 1)
require.Equal(t, sketchPath.Join("SketchPde.pde"), files[0])
sketchPath = paths.New("testdata", "SketchMultipleMainFiles")
files = CheckForPdeFiles(sketchPath)
require.Len(t, files, 1)
require.Equal(t, sketchPath.Join("SketchMultipleMainFiles.pde"), files[0])
sketchPath = paths.New("testdata", "Sketch1", "Sketch1.ino")
files = CheckForPdeFiles(sketchPath)
require.Empty(t, files)
sketchPath = paths.New("testdata", "SketchPde", "SketchPde.pde")
files = CheckForPdeFiles(sketchPath)
require.Len(t, files, 1)
require.Equal(t, sketchPath.Parent().Join("SketchPde.pde"), files[0])
sketchPath = paths.New("testdata", "SketchMultipleMainFiles", "SketchMultipleMainFiles.ino")
files = CheckForPdeFiles(sketchPath)
require.Len(t, files, 1)
require.Equal(t, sketchPath.Parent().Join("SketchMultipleMainFiles.pde"), files[0])
sketchPath = paths.New("testdata", "SketchMultipleMainFiles", "SketchMultipleMainFiles.pde")
files = CheckForPdeFiles(sketchPath)
require.Len(t, files, 1)
require.Equal(t, sketchPath.Parent().Join("SketchMultipleMainFiles.pde"), files[0])
}
...@@ -21,6 +21,7 @@ import ( ...@@ -21,6 +21,7 @@ import (
"encoding/json" "encoding/json"
"os" "os"
"github.com/arduino/arduino-cli/arduino/sketches"
"github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/feedback"
"github.com/arduino/arduino-cli/cli/output" "github.com/arduino/arduino-cli/cli/output"
"github.com/arduino/arduino-cli/configuration" "github.com/arduino/arduino-cli/configuration"
...@@ -127,6 +128,15 @@ func run(cmd *cobra.Command, args []string) { ...@@ -127,6 +128,15 @@ func run(cmd *cobra.Command, args []string) {
} }
sketchPath := initSketchPath(path) sketchPath := initSketchPath(path)
// .pde files are still supported but deprecated, this warning urges the user to rename them
if files := sketches.CheckForPdeFiles(sketchPath); len(files) > 0 {
feedback.Error("Sketches with .pde extension are deprecated, please rename the following files to .ino:")
for _, f := range files {
feedback.Error(f)
}
}
// We must read this from settings since the value is set when the binding is accessed from viper, // We must read this from settings since the value is set when the binding is accessed from viper,
// accessing it from cobra would only read it if the flag is explicitly set by the user and ignore // accessing it from cobra would only read it if the flag is explicitly set by the user and ignore
// the config file and the env vars. // the config file and the env vars.
......
...@@ -19,10 +19,12 @@ import ( ...@@ -19,10 +19,12 @@ import (
"context" "context"
"os" "os"
"github.com/arduino/arduino-cli/arduino/sketches"
"github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/errorcodes"
"github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/feedback"
"github.com/arduino/arduino-cli/commands/sketch" "github.com/arduino/arduino-cli/commands/sketch"
rpc "github.com/arduino/arduino-cli/rpc/commands" rpc "github.com/arduino/arduino-cli/rpc/commands"
"github.com/arduino/go-paths-helper"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
...@@ -53,11 +55,19 @@ func initArchiveCommand() *cobra.Command { ...@@ -53,11 +55,19 @@ func initArchiveCommand() *cobra.Command {
func runArchiveCommand(cmd *cobra.Command, args []string) { func runArchiveCommand(cmd *cobra.Command, args []string) {
logrus.Info("Executing `arduino sketch archive`") logrus.Info("Executing `arduino sketch archive`")
sketchPath := "" sketchPath := "."
if len(args) >= 1 { if len(args) >= 1 {
sketchPath = args[0] sketchPath = args[0]
} }
// .pde files are still supported but deprecated, this warning urges the user to rename them
if files := sketches.CheckForPdeFiles(paths.New(sketchPath)); len(files) > 0 {
feedback.Error("Sketches with .pde extension are deprecated, please rename the following files to .ino:")
for _, f := range files {
feedback.Error(f)
}
}
archivePath := "" archivePath := ""
if len(args) == 2 { if len(args) == 2 {
archivePath = args[1] archivePath = args[1]
......
...@@ -19,6 +19,7 @@ import ( ...@@ -19,6 +19,7 @@ import (
"context" "context"
"os" "os"
"github.com/arduino/arduino-cli/arduino/sketches"
"github.com/arduino/arduino-cli/cli/errorcodes" "github.com/arduino/arduino-cli/cli/errorcodes"
"github.com/arduino/arduino-cli/cli/feedback" "github.com/arduino/arduino-cli/cli/feedback"
"github.com/arduino/arduino-cli/cli/instance" "github.com/arduino/arduino-cli/cli/instance"
...@@ -83,6 +84,14 @@ func run(command *cobra.Command, args []string) { ...@@ -83,6 +84,14 @@ func run(command *cobra.Command, args []string) {
} }
sketchPath := initSketchPath(path) sketchPath := initSketchPath(path)
// .pde files are still supported but deprecated, this warning urges the user to rename them
if files := sketches.CheckForPdeFiles(sketchPath); len(files) > 0 {
feedback.Error("Sketches with .pde extension are deprecated, please rename the following files to .ino:")
for _, f := range files {
feedback.Error(f)
}
}
if _, err := upload.Upload(context.Background(), &rpc.UploadReq{ if _, err := upload.Upload(context.Background(), &rpc.UploadReq{
Instance: instance, Instance: instance,
Fqbn: fqbn, Fqbn: fqbn,
......
...@@ -23,6 +23,7 @@ import ( ...@@ -23,6 +23,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/arduino/arduino-cli/arduino/sketches"
rpc "github.com/arduino/arduino-cli/rpc/commands" rpc "github.com/arduino/arduino-cli/rpc/commands"
paths "github.com/arduino/go-paths-helper" paths "github.com/arduino/go-paths-helper"
) )
...@@ -37,27 +38,17 @@ func ArchiveSketch(ctx context.Context, req *rpc.ArchiveSketchReq) (*rpc.Archive ...@@ -37,27 +38,17 @@ func ArchiveSketch(ctx context.Context, req *rpc.ArchiveSketchReq) (*rpc.Archive
sketchPath = paths.New(".") sketchPath = paths.New(".")
} }
sketchPath, err := sketchPath.Clean().Abs() sketch, err := sketches.NewSketchFromPath(sketchPath)
if err != nil { if err != nil {
return nil, fmt.Errorf("Error getting absolute sketch path %v", err) return nil, err
} }
// Get the sketch name and make sketchPath point to the ino file sketchPath = sketch.FullPath
if sketchPath.IsDir() { sketchName = sketch.Name
sketchName = sketchPath.Base()
sketchPath = sketchPath.Join(sketchName + ".ino")
} else if sketchPath.Ext() == ".ino" {
sketchName = strings.TrimSuffix(sketchPath.Base(), ".ino")
}
// Checks if it's really a sketch
if sketchPath.NotExist() {
return nil, fmt.Errorf("specified path is not a sketch: %v", sketchPath.String())
}
archivePath := paths.New(req.ArchivePath) archivePath := paths.New(req.ArchivePath)
if archivePath == nil { if archivePath == nil {
archivePath = sketchPath.Parent().Parent() archivePath = sketchPath.Parent()
} }
archivePath, err = archivePath.Clean().Abs() archivePath, err = archivePath.Clean().Abs()
...@@ -76,7 +67,7 @@ func ArchiveSketch(ctx context.Context, req *rpc.ArchiveSketchReq) (*rpc.Archive ...@@ -76,7 +67,7 @@ func ArchiveSketch(ctx context.Context, req *rpc.ArchiveSketchReq) (*rpc.Archive
return nil, fmt.Errorf("archive already exists") return nil, fmt.Errorf("archive already exists")
} }
filesToZip, err := sketchPath.Parent().ReadDirRecursive() filesToZip, err := sketchPath.ReadDirRecursive()
if err != nil { if err != nil {
return nil, fmt.Errorf("Error retrieving sketch files: %v", err) return nil, fmt.Errorf("Error retrieving sketch files: %v", err)
} }
...@@ -94,7 +85,7 @@ func ArchiveSketch(ctx context.Context, req *rpc.ArchiveSketchReq) (*rpc.Archive ...@@ -94,7 +85,7 @@ func ArchiveSketch(ctx context.Context, req *rpc.ArchiveSketchReq) (*rpc.Archive
for _, f := range filesToZip { for _, f := range filesToZip {
if !req.IncludeBuildDir { if !req.IncludeBuildDir {
filePath, err := sketchPath.Parent().Parent().RelTo(f) filePath, err := sketchPath.Parent().RelTo(f)
if err != nil { if err != nil {
return nil, fmt.Errorf("Error calculating relative file path: %v", err) return nil, fmt.Errorf("Error calculating relative file path: %v", err)
} }
...@@ -107,7 +98,7 @@ func ArchiveSketch(ctx context.Context, req *rpc.ArchiveSketchReq) (*rpc.Archive ...@@ -107,7 +98,7 @@ func ArchiveSketch(ctx context.Context, req *rpc.ArchiveSketchReq) (*rpc.Archive
// We get the parent path since we want the archive to unpack as a folder. // We get the parent path since we want the archive to unpack as a folder.
// If we don't do this the archive would contain all the sketch files as top level. // If we don't do this the archive would contain all the sketch files as top level.
err = addFileToSketchArchive(zipWriter, f, sketchPath.Parent().Parent()) err = addFileToSketchArchive(zipWriter, f, sketchPath.Parent())
if err != nil { if err != nil {
return nil, fmt.Errorf("Error adding file to archive: %v", err) return nil, fmt.Errorf("Error adding file to archive: %v", err)
} }
......
...@@ -26,6 +26,7 @@ import ( ...@@ -26,6 +26,7 @@ import (
bldr "github.com/arduino/arduino-cli/arduino/builder" bldr "github.com/arduino/arduino-cli/arduino/builder"
"github.com/arduino/arduino-cli/arduino/cores" "github.com/arduino/arduino-cli/arduino/cores"
"github.com/arduino/arduino-cli/arduino/cores/packagemanager" "github.com/arduino/arduino-cli/arduino/cores/packagemanager"
"github.com/arduino/arduino-cli/arduino/globals"
"github.com/arduino/arduino-cli/arduino/serialutils" "github.com/arduino/arduino-cli/arduino/serialutils"
"github.com/arduino/arduino-cli/arduino/sketches" "github.com/arduino/arduino-cli/arduino/sketches"
"github.com/arduino/arduino-cli/commands" "github.com/arduino/arduino-cli/commands"
...@@ -452,7 +453,7 @@ func determineBuildPathAndSketchName(importFile, importDir string, sketch *sketc ...@@ -452,7 +453,7 @@ func determineBuildPathAndSketchName(importFile, importDir string, sketch *sketc
// Case 4: only sketch specified. In this case we use the generated build path // Case 4: only sketch specified. In this case we use the generated build path
// and the given sketch name. // and the given sketch name.
return bldr.GenBuildPath(sketch.FullPath), sketch.Name + ".ino", nil return bldr.GenBuildPath(sketch.FullPath), sketch.Name + sketch.MainFileExtension, nil
} }
func detectSketchNameFromBuildPath(buildPath *paths.Path) (string, error) { func detectSketchNameFromBuildPath(buildPath *paths.Path) (string, error) {
...@@ -462,13 +463,15 @@ func detectSketchNameFromBuildPath(buildPath *paths.Path) (string, error) { ...@@ -462,13 +463,15 @@ func detectSketchNameFromBuildPath(buildPath *paths.Path) (string, error) {
} }
if absBuildPath, err := buildPath.Abs(); err == nil { if absBuildPath, err := buildPath.Abs(); err == nil {
candidateName := absBuildPath.Base() + ".ino" for ext := range globals.MainFileValidExtensions {
candidateName := absBuildPath.Base() + ext
f := files.Clone() f := files.Clone()
f.FilterPrefix(candidateName + ".") f.FilterPrefix(candidateName + ".")
if f.Len() > 0 { if f.Len() > 0 {
return candidateName, nil return candidateName, nil
} }
} }
}
candidateName := "" candidateName := ""
var candidateFile *paths.Path var candidateFile *paths.Path
...@@ -479,7 +482,7 @@ func detectSketchNameFromBuildPath(buildPath *paths.Path) (string, error) { ...@@ -479,7 +482,7 @@ func detectSketchNameFromBuildPath(buildPath *paths.Path) (string, error) {
// Sometimes we may have particular files like: // Sometimes we may have particular files like:
// Blink.ino.with_bootloader.bin // Blink.ino.with_bootloader.bin
if filepath.Ext(name) != ".ino" { if _, ok := globals.MainFileValidExtensions[filepath.Ext(name)]; !ok {
// just ignore those files // just ignore those files
continue continue
} }
......
...@@ -18,7 +18,10 @@ Support for sketch folder names starting with a number was added in Arduino IDE ...@@ -18,7 +18,10 @@ Support for sketch folder names starting with a number was added in Arduino IDE
### Primary sketch file ### Primary sketch file
Every sketch must contain a .ino or .pde file with a file name matching the sketch root folder name. Every sketch must contain a `.ino` file with a file name matching the sketch root folder name.
`.pde` is also supported but **deprecated** and will be removed in the future, using the `.ino` extension is strongly
recommended.
### Additional code files ### Additional code files
...@@ -28,7 +31,7 @@ The following extensions are supported: ...@@ -28,7 +31,7 @@ The following extensions are supported:
- .ino - [Arduino language](https://www.arduino.cc/reference/en/) files. - .ino - [Arduino language](https://www.arduino.cc/reference/en/) files.
- .pde - Alternate extension for Arduino language files. This file extension is also used by Processing sketches. .ino - .pde - Alternate extension for Arduino language files. This file extension is also used by Processing sketches. .ino
is recommended to avoid confusion. is recommended to avoid confusion. **`.pde` extension is deprecated and will be removed in the future.**
- .cpp - C++ files. - .cpp - C++ files.
- .c - C Files. - .c - C Files.
- .S - Assembly language files. - .S - Assembly language files.
......
...@@ -16,6 +16,7 @@ import os ...@@ -16,6 +16,7 @@ import os
import platform import platform
import tempfile import tempfile
import hashlib import hashlib
import shutil
from pathlib import Path from pathlib import Path
import simplejson as json import simplejson as json
...@@ -629,3 +630,68 @@ def test_compile_with_fully_precompiled_library(run_command, data_dir): ...@@ -629,3 +630,68 @@ def test_compile_with_fully_precompiled_library(run_command, data_dir):
result = run_command(f"compile -b {fqbn} {sketch_folder} -v") result = run_command(f"compile -b {fqbn} {sketch_folder} -v")
assert result.ok assert result.ok
assert "Skipping dependencies detection for precompiled library Arduino_TensorFlowLite" in result.stdout assert "Skipping dependencies detection for precompiled library Arduino_TensorFlowLite" in result.stdout
def test_compile_sketch_with_pde_extension(run_command, data_dir):
# Init the environment explicitly
assert run_command("update")
# Install core to compile
assert run_command("core install arduino:avr@1.8.3")
sketch_name = "CompilePdeSketch"
sketch_path = Path(data_dir, sketch_name)
fqbn = "arduino:avr:uno"
# Create a test sketch
assert run_command(f"sketch new {sketch_path}")
# Renames sketch file to pde
sketch_file = Path(sketch_path, f"{sketch_name}.ino").rename(sketch_path / f"{sketch_name}.pde")
# Build sketch from folder
res = run_command(f"compile --clean -b {fqbn} {sketch_path}")
assert res.ok
assert "Sketches with .pde extension are deprecated, please rename the following files to .ino:" in res.stderr
assert str(sketch_file) in res.stderr
# Build sketch from file
res = run_command(f"compile --clean -b {fqbn} {sketch_file}")
assert res.ok
assert "Sketches with .pde extension are deprecated, please rename the following files to .ino" in res.stderr
assert str(sketch_file) in res.stderr
def test_compile_sketch_with_multiple_main_files(run_command, data_dir):
# Init the environment explicitly
assert run_command("update")
# Install core to compile
assert run_command("core install arduino:avr@1.8.3")
sketch_name = "CompileSketchMultipleMainFiles"
sketch_path = Path(data_dir, sketch_name)
fqbn = "arduino:avr:uno"
# Create a test sketch
assert run_command(f"sketch new {sketch_path}")
# Copy .ino sketch file to .pde
sketch_ino_file = Path(sketch_path, f"{sketch_name}.ino")
sketch_pde_file = Path(sketch_path / f"{sketch_name}.pde")
shutil.copyfile(sketch_ino_file, sketch_pde_file)
# Build sketch from folder
res = run_command(f"compile --clean -b {fqbn} {sketch_path}")
assert res.failed
assert "Error during build: opening sketch: multiple main sketch files found" in res.stderr
# Build sketch from .ino file
res = run_command(f"compile --clean -b {fqbn} {sketch_ino_file}")
assert res.failed
assert "Error during build: opening sketch: multiple main sketch files found" in res.stderr
# Build sketch from .pde file
res = run_command(f"compile --clean -b {fqbn} {sketch_pde_file}")
assert res.failed
assert "Error during build: opening sketch: multiple main sketch files found" in res.stderr
...@@ -37,3 +37,27 @@ def test_debugger_starts(run_command, data_dir): ...@@ -37,3 +37,27 @@ def test_debugger_starts(run_command, data_dir):
programmer = "atmel_ice" programmer = "atmel_ice"
# Starts debugger # Starts debugger
assert run_command(f"debug -b {fqbn} -P {programmer} {sketch_path} --info") assert run_command(f"debug -b {fqbn} -P {programmer} {sketch_path} --info")
def test_debugger_with_pde_sketch_starts(run_command, data_dir):
assert run_command("update")
# Install core
assert run_command("core install arduino:samd")
# Create sketch for testing
sketch_name = "DebuggerPdeSketchStartTest"
sketch_path = Path(data_dir, sketch_name)
fqbn = "arduino:samd:mkr1000"
assert run_command(f"sketch new {sketch_path}")
# Renames sketch file to pde
Path(sketch_path, f"{sketch_name}.ino").rename(sketch_path / f"{sketch_name}.pde")
# Build sketch
assert run_command(f"compile -b {fqbn} {sketch_path}")
programmer = "atmel_ice"
# Starts debugger
assert run_command(f"debug -b {fqbn} -P {programmer} {sketch_path} --info")
...@@ -635,3 +635,36 @@ def test_install_with_zip_path_multiple_libraries(run_command, downloads_dir, da ...@@ -635,3 +635,36 @@ def test_install_with_zip_path_multiple_libraries(run_command, downloads_dir, da
# Verifies library are installed # Verifies library are installed
assert wifi_install_dir.exists() assert wifi_install_dir.exists()
assert ble_install_dir.exists() assert ble_install_dir.exists()
def test_lib_examples(run_command, data_dir):
assert run_command("update")
assert run_command("lib install Arduino_JSON@0.1.0")
res = run_command("lib examples Arduino_JSON --format json")
assert res.ok
data = json.loads(res.stdout)
assert len(data) == 1
examples = data[0]["examples"]
assert str(Path(data_dir, "libraries", "Arduino_JSON", "examples", "JSONArray")) in examples
assert str(Path(data_dir, "libraries", "Arduino_JSON", "examples", "JSONKitchenSink")) in examples
assert str(Path(data_dir, "libraries", "Arduino_JSON", "examples", "JSONObject")) in examples
def test_lib_examples_with_pde_file(run_command, data_dir):
assert run_command("update")
assert run_command("lib install Encoder@1.4.1")
res = run_command("lib examples Encoder --format json")
assert res.ok
data = json.loads(res.stdout)
assert len(data) == 1
examples = data[0]["examples"]
assert str(Path(data_dir, "libraries", "Encoder", "examples", "Basic")) in examples
assert str(Path(data_dir, "libraries", "Encoder", "examples", "NoInterrupts")) in examples
assert str(Path(data_dir, "libraries", "Encoder", "examples", "SpeedTest")) in examples
assert str(Path(data_dir, "libraries", "Encoder", "examples", "TwoKnobs")) in examples
...@@ -818,3 +818,31 @@ def test_sketch_archive_absolute_sketch_path_with_absolute_zip_path_and_name_wit ...@@ -818,3 +818,31 @@ def test_sketch_archive_absolute_sketch_path_with_absolute_zip_path_and_name_wit
verify_zip_contains_sketch_including_build_dir(archive_files) verify_zip_contains_sketch_including_build_dir(archive_files)
archive.close() archive.close()
def test_sketch_archive_with_pde_main_file(run_command, copy_sketch, working_dir):
sketch_name = "sketch_pde_main_file"
sketch_dir = copy_sketch(sketch_name)
sketch_file = Path(sketch_dir, f"{sketch_name}.pde")
res = run_command("sketch archive", sketch_dir)
assert res.ok
assert "Sketches with .pde extension are deprecated, please rename the following files to .ino" in res.stderr
assert str(sketch_file.relative_to(sketch_dir)) in res.stderr
archive = zipfile.ZipFile(f"{working_dir}/{sketch_name}.zip")
archive_files = archive.namelist()
assert f"{sketch_name}/{sketch_name}.pde" in archive_files
archive.close()
def test_sketch_archive_with_multiple_main_files(run_command, copy_sketch, working_dir):
sketch_name = "sketch_multiple_main_files"
sketch_dir = copy_sketch(sketch_name)
sketch_file = Path(sketch_dir, f"{sketch_name}.pde")
res = run_command("sketch archive", sketch_dir)
assert res.failed
assert "Sketches with .pde extension are deprecated, please rename the following files to .ino" in res.stderr
assert str(sketch_file.relative_to(sketch_dir)) in res.stderr
assert "Error archiving: multiple main sketch files found" in res.stderr
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
# software without disclosing the source code of your own applications. To purchase # software without disclosing the source code of your own applications. To purchase
# a commercial license, send an email to license@arduino.cc. # a commercial license, send an email to license@arduino.cc.
import os import os
import shutil
import json
from pathlib import Path from pathlib import Path
import pytest import pytest
...@@ -195,3 +197,143 @@ def test_compile_and_upload_combo_with_custom_build_path(run_command, data_dir, ...@@ -195,3 +197,143 @@ def test_compile_and_upload_combo_with_custom_build_path(run_command, data_dir,
assert f"Compile {sketch_name} for {board.fqbn} successful" in traces assert f"Compile {sketch_name} for {board.fqbn} successful" in traces
assert f"Upload {sketch_path} on {board.fqbn} started" in traces assert f"Upload {sketch_path} on {board.fqbn} started" in traces
assert "Upload successful" in traces assert "Upload successful" in traces
def test_compile_and_upload_combo_sketch_with_pde_extension(run_command, data_dir, detected_boards, wait_for_board):
assert run_command("update")
sketch_name = "CompileAndUploadPdeSketch"
sketch_path = Path(data_dir, sketch_name)
# Create a test sketch
assert run_command(f"sketch new {sketch_path}")
# Renames sketch file to pde
sketch_file = Path(sketch_path, f"{sketch_name}.ino").rename(sketch_path / f"{sketch_name}.pde")
for board in detected_boards:
# Install core
core = ":".join(board.fqbn.split(":")[:2])
assert run_command(f"core install {core}")
# Build sketch and upload from folder
wait_for_board()
res = run_command(f"compile --clean -b {board.fqbn} -u -p {board.address} {sketch_path}")
assert res.ok
assert "Sketches with .pde extension are deprecated, please rename the following files to .ino" in res.stderr
assert str(sketch_file) in res.stderr
# Build sketch and upload from file
wait_for_board()
res = run_command(f"compile --clean -b {board.fqbn} -u -p {board.address} {sketch_file}")
assert res.ok
assert "Sketches with .pde extension are deprecated, please rename the following files to .ino" in res.stderr
assert str(sketch_file) in res.stderr
def test_upload_sketch_with_pde_extension(run_command, data_dir, detected_boards, wait_for_board):
assert run_command("update")
sketch_name = "UploadPdeSketch"
sketch_path = Path(data_dir, sketch_name)
# Create a test sketch
assert run_command(f"sketch new {sketch_path}")
# Renames sketch file to pde
sketch_file = Path(sketch_path, f"{sketch_name}.ino").rename(sketch_path / f"{sketch_name}.pde")
for board in detected_boards:
# Install core
core = ":".join(board.fqbn.split(":")[:2])
assert run_command(f"core install {core}")
# Compile sketch first
res = run_command(f"compile --clean -b {board.fqbn} {sketch_path} --format json")
assert res.ok
data = json.loads(res.stdout)
build_dir = Path(data["builder_result"]["build_path"])
# Upload from sketch folder
wait_for_board()
assert run_command(f"upload -b {board.fqbn} -p {board.address} {sketch_path}")
# Upload from sketch file
wait_for_board()
assert run_command(f"upload -b {board.fqbn} -p {board.address} {sketch_file}")
wait_for_board()
res = run_command(f"upload -b {board.fqbn} -p {board.address} --input-dir {build_dir}")
assert (
"Sketches with .pde extension are deprecated, please rename the following files to .ino:" not in res.stderr
)
# Upload from binary file
wait_for_board()
# We don't need a specific file when using the --input-file flag to upload since
# it's just used to calculate the directory, so it's enough to get a random file
# that's inside that directory
binary_file = next(build_dir.glob(f"{sketch_name}.pde.*"))
res = run_command(f"upload -b {board.fqbn} -p {board.address} --input-file {binary_file}")
assert (
"Sketches with .pde extension are deprecated, please rename the following files to .ino:" not in res.stderr
)
def test_upload_with_input_dir_containing_multiple_binaries(run_command, data_dir, detected_boards, wait_for_board):
# This tests verifies the behaviour outlined in this issue:
# https://github.com/arduino/arduino-cli/issues/765#issuecomment-699678646
assert run_command("update")
# Create a two different sketches
sketch_one_name = "UploadMultipleBinariesSketchOne"
sketch_one_path = Path(data_dir, sketch_one_name)
assert run_command(f"sketch new {sketch_one_path}")
sketch_two_name = "UploadMultipleBinariesSketchTwo"
sketch_two_path = Path(data_dir, sketch_two_name)
assert run_command(f"sketch new {sketch_two_path}")
for board in detected_boards:
# Install core
core = ":".join(board.fqbn.split(":")[:2])
assert run_command(f"core install {core}")
# Compile both sketches and copy binaries in the same directory same build directory
res = run_command(f"compile --clean -b {board.fqbn} {sketch_one_path} --format json")
assert res.ok
data = json.loads(res.stdout)
build_dir_one = Path(data["builder_result"]["build_path"])
res = run_command(f"compile --clean -b {board.fqbn} {sketch_two_path} --format json")
assert res.ok
data = json.loads(res.stdout)
build_dir_two = Path(data["builder_result"]["build_path"])
# Copy binaries to same folder
binaries_dir = Path(data_dir, "build", "BuiltBinaries")
shutil.copytree(build_dir_one, binaries_dir, dirs_exist_ok=True)
shutil.copytree(build_dir_two, binaries_dir, dirs_exist_ok=True)
wait_for_board()
# Verifies upload fails because multiple binaries are found
res = run_command(f"upload -b {board.fqbn} -p {board.address} --input-dir {binaries_dir}")
assert res.failed
assert (
"Error during Upload: "
+ "retrieving build artifacts: "
+ "autodetect build artifact: "
+ "multiple build artifacts found:"
in res.stderr
)
# Copy binaries to folder with same name of a sketch
binaries_dir = Path(data_dir, "build", "UploadMultipleBinariesSketchOne")
shutil.copytree(build_dir_one, binaries_dir, dirs_exist_ok=True)
shutil.copytree(build_dir_two, binaries_dir, dirs_exist_ok=True)
wait_for_board()
# Verifies upload is successful using the binaries with the same name of the containing folder
res = run_command(f"upload -b {board.fqbn} -p {board.address} --input-dir {binaries_dir}")
assert (
"Sketches with .pde extension are deprecated, please rename the following files to .ino:" not in res.stderr
)
void setup() { }
void loop() { }
\ No newline at end of file
void setup() { }
void loop() { }
\ No newline at end of file
void setup() { }
void loop() { }
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment