From bd98bde48872ecb98c57db94a4a9b1e9c9dc215c Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 16 Nov 2022 14:25:55 +0100 Subject: [PATCH] Split `compile` integration tests in two parts --- .../{compile => compile_1}/compile_test.go | 425 ---------------- .../integrationtest/compile_2/compile_test.go | 454 ++++++++++++++++++ 2 files changed, 454 insertions(+), 425 deletions(-) rename internal/integrationtest/{compile => compile_1}/compile_test.go (73%) create mode 100644 internal/integrationtest/compile_2/compile_test.go diff --git a/internal/integrationtest/compile/compile_test.go b/internal/integrationtest/compile_1/compile_test.go similarity index 73% rename from internal/integrationtest/compile/compile_test.go rename to internal/integrationtest/compile_1/compile_test.go index de1e9c2e626..c1f856d071b 100644 --- a/internal/integrationtest/compile/compile_test.go +++ b/internal/integrationtest/compile_1/compile_test.go @@ -1101,428 +1101,3 @@ func compileWithFakeSecureBootCore(t *testing.T, env *integrationtest.Environmen require.Contains(t, string(stdout), "my-sign-key.pem") require.Contains(t, string(stdout), "my-encrypt-key.pem") } - -func TestCompilePart4(t *testing.T) { - env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) - defer env.CleanUp() - - _, _, err := cli.Run("update") - require.NoError(t, err) - - _, _, err = cli.Run("core", "install", "arduino:avr@1.8.3") - require.NoError(t, err) - - // Manually installs a library - gitUrl := "https://github.com/arduino-libraries/WiFi101.git" - libPath := cli.SketchbookDir().Join("my-libraries", "WiFi101") - _, err = git.PlainClone(libPath.String(), false, &git.CloneOptions{ - URL: gitUrl, - ReferenceName: plumbing.NewTagReferenceName("0.16.1"), - }) - require.NoError(t, err) - - integrationtest.CLISubtests{ - {"WithLibrary", compileWithLibrary}, - {"WithLibraryPriority", compileWithLibraryPriority}, - {"WithDifferentLibrary", recompileWithDifferentLibrary}, - }.Run(t, env, cli) -} - -func compileWithLibrary(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI) { - sketchName := "CompileSketchWithWiFi101Dependency" - sketchPath := cli.SketchbookDir().Join(sketchName) - defer sketchPath.RemoveAll() - fqbn := "arduino:avr:uno" - - libPath := cli.SketchbookDir().Join("my-libraries", "WiFi101") - - // Create new sketch and add library include - _, _, err := cli.Run("sketch", "new", sketchPath.String()) - require.NoError(t, err) - sketchFile := sketchPath.Join(sketchName + ".ino") - data, err := sketchFile.ReadFile() - require.NoError(t, err) - data = append([]byte("#include \n"), data...) - err = sketchFile.WriteFile(data) - require.NoError(t, err) - - stdout, _, err := cli.Run("compile", "-b", fqbn, sketchPath.String(), "--library", libPath.String(), "-v") - require.NoError(t, err) - require.Contains(t, string(stdout), "WiFi101") -} - -func compileWithLibraryPriority(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI) { - sketchName := "CompileSketchWithLibraryPriority" - sketchPath := cli.SketchbookDir().Join(sketchName) - defer sketchPath.RemoveAll() - fqbn := "arduino:avr:uno" - - manuallyInstalledLibPath := cli.SketchbookDir().Join("my-libraries", "WiFi101") - - // Install the same library we installed manually - _, _, err := cli.Run("lib", "install", "WiFi101") - require.NoError(t, err) - defer cli.SketchbookDir().Join("libraries").RemoveAll() - - // Create new sketch and add library include - _, _, err = cli.Run("sketch", "new", sketchPath.String()) - require.NoError(t, err) - sketchFile := sketchPath.Join(sketchName + ".ino") - lines, err := sketchFile.ReadFileAsLines() - require.NoError(t, err) - lines = append([]string{"#include \n"}, lines...) - var data []byte - for _, l := range lines { - data = append(data, []byte(l)...) - } - err = sketchFile.WriteFile(data) - require.NoError(t, err) - - stdout, _, err := cli.Run("compile", "-b", fqbn, sketchPath.String(), "--library", manuallyInstalledLibPath.String(), "-v") - require.NoError(t, err) - cliInstalledLibPath := cli.SketchbookDir().Join("libraries", "WiFi101") - expectedOutput := [3]string{ - "Multiple libraries were found for \"WiFi101.h\"", - " Used: " + manuallyInstalledLibPath.String(), - " Not used: " + cliInstalledLibPath.String(), - } - require.Contains(t, string(stdout), expectedOutput[0]+"\n"+expectedOutput[1]+"\n"+expectedOutput[2]+"\n") -} - -func recompileWithDifferentLibrary(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI) { - sketchName := "RecompileCompileSketchWithDifferentLibrary" - sketchPath := cli.SketchbookDir().Join(sketchName) - defer sketchPath.RemoveAll() - fqbn := "arduino:avr:uno" - - // Install library - _, _, err := cli.Run("lib", "install", "WiFi101") - require.NoError(t, err) - defer cli.SketchbookDir().Join("libraries").RemoveAll() - - manuallyInstalledLibPath := cli.SketchbookDir().Join("my-libraries", "WiFi101") - - // Create new sketch and add library include - _, _, err = cli.Run("sketch", "new", sketchPath.String()) - require.NoError(t, err) - sketchFile := sketchPath.Join(sketchName + ".ino") - lines, err := sketchFile.ReadFileAsLines() - require.NoError(t, err) - lines = append([]string{"#include \n"}, lines...) - var data []byte - for _, l := range lines { - data = append(data, []byte(l)...) - } - err = sketchFile.WriteFile(data) - require.NoError(t, err) - - md5 := md5.Sum(([]byte(sketchPath.String()))) - sketchPathMd5 := strings.ToUpper(hex.EncodeToString(md5[:])) - require.NotEmpty(t, sketchPathMd5) - buildDir := paths.TempDir().Join("arduino-sketch-" + sketchPathMd5) - - // Compile sketch using library not managed by CLI - stdout, _, err := cli.Run("compile", "-b", fqbn, "--library", manuallyInstalledLibPath.String(), sketchPath.String(), "-v") - require.NoError(t, err) - objPath := buildDir.Join("libraries", "WiFi101", "WiFi.cpp.o") - require.NotContains(t, string(stdout), "Using previously compiled file: "+objPath.String()) - - // Compile again using library installed from CLI - stdout, _, err = cli.Run("compile", "-b", fqbn, sketchPath.String(), "-v") - require.NoError(t, err) - require.NotContains(t, string(stdout), "Using previously compiled file: "+objPath.String()) -} - -func TestCompileManuallyInstalledPlatformUsingBoardsLocalTxt(t *testing.T) { - env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) - defer env.CleanUp() - - _, _, err := cli.Run("update") - require.NoError(t, err) - - sketchName := "CompileSketchManuallyInstalledPlatformUsingBoardsLocalTxt" - sketchPath := cli.SketchbookDir().Join(sketchName) - fqbn := "arduino-beta-development:avr:nessuno" - _, _, err = cli.Run("sketch", "new", sketchPath.String()) - require.NoError(t, err) - - // Manually installs a core in sketchbooks hardware folder - gitUrl := "https://github.com/arduino/ArduinoCore-avr.git" - repoDir := cli.SketchbookDir().Join("hardware", "arduino-beta-development", "avr") - _, err = git.PlainClone(repoDir.String(), false, &git.CloneOptions{ - URL: gitUrl, - ReferenceName: plumbing.NewTagReferenceName("1.8.3"), - }) - require.NoError(t, err) - - // Installs also the same core via CLI so all the necessary tools are installed - _, _, err = cli.Run("core", "install", "arduino:avr@1.8.3") - require.NoError(t, err) - - // Verifies compilation fails because board doesn't exist - _, stderr, err := cli.Run("compile", "--clean", "-b", fqbn, sketchPath.String()) - require.Error(t, err) - require.Contains(t, string(stderr), "Error during build: Error resolving FQBN: board arduino-beta-development:avr:nessuno not found") - - // Use custom boards.local.txt with made arduino:avr:nessuno board - boardsLocalTxt := repoDir.Join("boards.local.txt") - err = paths.New("..", "testdata", "boards.local.txt").CopyTo(boardsLocalTxt) - require.NoError(t, err) - - _, _, err = cli.Run("compile", "--clean", "-b", fqbn, sketchPath.String()) - require.NoError(t, err) -} - -func TestCompileWithConflictingLibrariesInclude(t *testing.T) { - env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) - defer env.CleanUp() - - _, _, err := cli.Run("update") - require.NoError(t, err) - - _, _, err = cli.Run("core", "install", "arduino:avr@1.8.3") - require.NoError(t, err) - - // Installs conflicting libraries - gitUrl := "https://github.com/pstolarz/OneWireNg.git" - oneWireNgLibPath := cli.SketchbookDir().Join("libraries", "onewireng_0_8_1") - _, err = git.PlainClone(oneWireNgLibPath.String(), false, &git.CloneOptions{ - URL: gitUrl, - ReferenceName: plumbing.NewTagReferenceName("0.8.1"), - }) - require.NoError(t, err) - - gitUrl = "https://github.com/PaulStoffregen/OneWire.git" - oneWireLibPath := cli.SketchbookDir().Join("libraries", "onewire_2_3_5") - _, err = git.PlainClone(oneWireLibPath.String(), false, &git.CloneOptions{ - URL: gitUrl, - ReferenceName: plumbing.NewTagReferenceName("v2.3.5"), - }) - require.NoError(t, err) - - sketchPath := cli.CopySketch("sketch_with_conflicting_libraries_include") - fqbn := "arduino:avr:uno" - - stdout, _, err := cli.Run("compile", "-b", fqbn, sketchPath.String(), "--verbose") - require.NoError(t, err) - expectedOutput := [3]string{ - "Multiple libraries were found for \"OneWire.h\"", - " Used: " + oneWireLibPath.String(), - " Not used: " + oneWireNgLibPath.String(), - } - require.Contains(t, string(stdout), expectedOutput[0]+"\n"+expectedOutput[1]+"\n"+expectedOutput[2]+"\n") -} - -func TestCompileWithEsp32BundledLibraries(t *testing.T) { - // Some esp cores have have bundled libraries that are optimize for that architecture, - // it might happen that if the user has a library with the same name installed conflicts - // can ensue and the wrong library is used for compilation, thus it fails. - // This happens because for "historical" reasons these platform have their "name" key - // in the "library.properties" flag suffixed with "(esp32)" or similar even though that - // doesn't respect the libraries specification. - // https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format - // - // The reason those libraries have these suffixes is to avoid an annoying bug in the Java IDE - // that would have caused the libraries that are both bundled with the core and the Java IDE to be - // always marked as updatable. For more info see: https://github.com/arduino/Arduino/issues/4189 - env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) - defer env.CleanUp() - - _, _, err := cli.Run("update") - require.NoError(t, err) - - // Update index with esp32 core and install it - url := "https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json" - coreVersion := "1.0.6" - _, _, err = cli.Run("core", "update-index", "--additional-urls="+url) - require.NoError(t, err) - _, _, err = cli.Run("core", "install", "esp32:esp32@"+coreVersion, "--additional-urls="+url) - require.NoError(t, err) - - // Install a library with the same name as one bundled with the core - _, _, err = cli.Run("lib", "install", "SD") - require.NoError(t, err) - - sketchPath := cli.CopySketch("sketch_with_sd_library") - fqbn := "esp32:esp32:esp32" - - stdout, _, err := cli.Run("compile", "-b", fqbn, sketchPath.String(), "--verbose") - require.Error(t, err) - - coreBundledLibPath := cli.DataDir().Join("packages", "esp32", "hardware", "esp32", coreVersion, "libraries", "SD") - cliInstalledLibPath := cli.SketchbookDir().Join("libraries", "SD") - expectedOutput := [3]string{ - "Multiple libraries were found for \"OneWire.h\"", - " Used: " + coreBundledLibPath.String(), - " Not used: " + cliInstalledLibPath.String(), - } - require.NotContains(t, string(stdout), expectedOutput[0]+"\n"+expectedOutput[1]+"\n"+expectedOutput[2]+"\n") -} - -func TestCompileWithEsp8266BundledLibraries(t *testing.T) { - // Some esp cores have have bundled libraries that are optimize for that architecture, - // it might happen that if the user has a library with the same name installed conflicts - // can ensue and the wrong library is used for compilation, thus it fails. - // This happens because for "historical" reasons these platform have their "name" key - // in the "library.properties" flag suffixed with "(esp32)" or similar even though that - // doesn't respect the libraries specification. - // https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format - // - // The reason those libraries have these suffixes is to avoid an annoying bug in the Java IDE - // that would have caused the libraries that are both bundled with the core and the Java IDE to be - // always marked as updatable. For more info see: https://github.com/arduino/Arduino/issues/4189 - env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) - defer env.CleanUp() - - _, _, err := cli.Run("update") - require.NoError(t, err) - - // Update index with esp8266 core and install it - url := "http://arduino.esp8266.com/stable/package_esp8266com_index.json" - coreVersion := "2.7.4" - _, _, err = cli.Run("core", "update-index", "--additional-urls="+url) - require.NoError(t, err) - _, _, err = cli.Run("core", "install", "esp8266:esp8266@"+coreVersion, "--additional-urls="+url) - require.NoError(t, err) - - // Install a library with the same name as one bundled with the core - _, _, err = cli.Run("lib", "install", "SD") - require.NoError(t, err) - - sketchPath := cli.CopySketch("sketch_with_sd_library") - fqbn := "esp8266:esp8266:generic" - - stdout, _, err := cli.Run("compile", "-b", fqbn, sketchPath.String(), "--verbose") - require.Error(t, err) - - coreBundledLibPath := cli.DataDir().Join("packages", "esp8266", "hardware", "esp8266", coreVersion, "libraries", "SD") - cliInstalledLibPath := cli.SketchbookDir().Join("libraries", "SD") - expectedOutput := [3]string{ - "Multiple libraries were found for \"OneWire.h\"", - " Used: " + coreBundledLibPath.String(), - " Not used: " + cliInstalledLibPath.String(), - } - require.NotContains(t, string(stdout), expectedOutput[0]+"\n"+expectedOutput[1]+"\n"+expectedOutput[2]+"\n") -} - -func TestGenerateCompileCommandsJsonResilience(t *testing.T) { - env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) - defer env.CleanUp() - - _, _, err := cli.Run("update") - require.NoError(t, err) - - // check it didn't fail with esp32@2.0.1 that has a prebuild hook that must run: - // https://github.com/arduino/arduino-cli/issues/1547 - url := "https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json" - _, _, err = cli.Run("core", "update-index", "--additional-urls="+url) - require.NoError(t, err) - _, _, err = cli.Run("core", "install", "esp32:esp32@2.0.1", "--additional-urls="+url) - require.NoError(t, err) - sketchPath := cli.CopySketch("sketch_simple") - _, _, err = cli.Run("compile", "-b", "esp32:esp32:featheresp32", "--only-compilation-database", sketchPath.String()) - require.NoError(t, err) - - // check it didn't fail on a sketch with a missing include - sketchPath = cli.CopySketch("sketch_with_missing_include") - _, _, err = cli.Run("compile", "-b", "esp32:esp32:featheresp32", "--only-compilation-database", sketchPath.String()) - require.NoError(t, err) -} - -func TestCompileSketchSketchWithTppFileInclude(t *testing.T) { - env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) - defer env.CleanUp() - - _, _, err := cli.Run("update") - require.NoError(t, err) - - // Download latest AVR - _, _, err = cli.Run("core", "install", "arduino:avr") - require.NoError(t, err) - - sketchPath := cli.CopySketch("sketch_with_tpp_file_include") - fqbn := "arduino:avr:uno" - - _, _, err = cli.Run("compile", "-b", fqbn, sketchPath.String(), "--verbose") - require.NoError(t, err) -} - -func TestCompileSketchWithIppFileInclude(t *testing.T) { - env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) - defer env.CleanUp() - - _, _, err := cli.Run("update") - require.NoError(t, err) - - // Download latest AVR - _, _, err = cli.Run("core", "install", "arduino:avr") - require.NoError(t, err) - - sketchPath := cli.CopySketch("sketch_with_ipp_file_include") - fqbn := "arduino:avr:uno" - - _, _, err = cli.Run("compile", "-b", fqbn, sketchPath.String(), "--verbose") - require.NoError(t, err) -} - -func TestCompileWithoutUploadAndFqbn(t *testing.T) { - env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) - defer env.CleanUp() - - _, _, err := cli.Run("update") - require.NoError(t, err) - - // Create a sketch - sketchPath := cli.SketchbookDir().Join("SketchSimple") - _, _, err = cli.Run("sketch", "new", sketchPath.String()) - require.NoError(t, err) - - _, stderr, err := cli.Run("compile", sketchPath.String()) - require.Error(t, err) - require.Contains(t, string(stderr), "Missing FQBN (Fully Qualified Board Name)") -} - -func TestCompileNonInstalledPlatformWithWrongPackagerAndArch(t *testing.T) { - env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) - defer env.CleanUp() - - _, _, err := cli.Run("update") - require.NoError(t, err) - - // Create a sketch - sketchPath := cli.SketchbookDir().Join("SketchSimple") - _, _, err = cli.Run("sketch", "new", sketchPath.String()) - require.NoError(t, err) - - // Compile with wrong packager - _, stderr, err := cli.Run("compile", "-b", "wrong:avr:uno", sketchPath.String()) - require.Error(t, err) - require.Contains(t, string(stderr), "Error during build: Platform 'wrong:avr' not found: platform not installed") - require.Contains(t, string(stderr), "Platform wrong:avr is not found in any known index") - - // Compile with wrong arch - _, stderr, err = cli.Run("compile", "-b", "arduino:wrong:uno", sketchPath.String()) - require.Error(t, err) - require.Contains(t, string(stderr), "Error during build: Platform 'arduino:wrong' not found: platform not installed") - require.Contains(t, string(stderr), "Platform arduino:wrong is not found in any known index") -} - -func TestCompileWithKnownPlatformNotInstalled(t *testing.T) { - env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) - defer env.CleanUp() - - _, _, err := cli.Run("update") - require.NoError(t, err) - - // Create a sketch - sketchPath := cli.SketchbookDir().Join("SketchSimple") - _, _, err = cli.Run("sketch", "new", sketchPath.String()) - require.NoError(t, err) - - // Try to compile using a platform found in the index but not installed - _, stderr, err := cli.Run("compile", "-b", "arduino:avr:uno", sketchPath.String()) - require.Error(t, err) - require.Contains(t, string(stderr), "Error during build: Platform 'arduino:avr' not found: platform not installed") - // Verifies command to fix error is shown to user - require.Contains(t, string(stderr), "Try running `arduino-cli core install arduino:avr`") -} diff --git a/internal/integrationtest/compile_2/compile_test.go b/internal/integrationtest/compile_2/compile_test.go new file mode 100644 index 00000000000..c59c18d839e --- /dev/null +++ b/internal/integrationtest/compile_2/compile_test.go @@ -0,0 +1,454 @@ +// This file is part of arduino-cli. +// +// Copyright 2022 ARDUINO SA (http://www.arduino.cc/) +// +// This software is released under the GNU General Public License version 3, +// which covers the main part of arduino-cli. +// The terms of this license can be found at: +// https://www.gnu.org/licenses/gpl-3.0.en.html +// +// You can be released from the requirements of the above licenses by purchasing +// a commercial license. Buying such a license is mandatory if you want to +// modify or otherwise use the software for commercial activities involving the +// Arduino software without disclosing the source code of your own applications. +// To purchase a commercial license, send an email to license@arduino.cc. + +package compile_test + +import ( + "crypto/md5" + "encoding/hex" + "strings" + "testing" + + "github.com/arduino/arduino-cli/internal/integrationtest" + "github.com/arduino/go-paths-helper" + "github.com/stretchr/testify/require" + "gopkg.in/src-d/go-git.v4" + "gopkg.in/src-d/go-git.v4/plumbing" +) + +func TestCompilePart4(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("update") + require.NoError(t, err) + + _, _, err = cli.Run("core", "install", "arduino:avr@1.8.3") + require.NoError(t, err) + + // Manually installs a library + gitUrl := "https://github.com/arduino-libraries/WiFi101.git" + libPath := cli.SketchbookDir().Join("my-libraries", "WiFi101") + _, err = git.PlainClone(libPath.String(), false, &git.CloneOptions{ + URL: gitUrl, + ReferenceName: plumbing.NewTagReferenceName("0.16.1"), + }) + require.NoError(t, err) + + integrationtest.CLISubtests{ + {"WithLibrary", compileWithLibrary}, + {"WithLibraryPriority", compileWithLibraryPriority}, + {"WithDifferentLibrary", recompileWithDifferentLibrary}, + }.Run(t, env, cli) +} + +func compileWithLibrary(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI) { + sketchName := "CompileSketchWithWiFi101Dependency" + sketchPath := cli.SketchbookDir().Join(sketchName) + defer sketchPath.RemoveAll() + fqbn := "arduino:avr:uno" + + libPath := cli.SketchbookDir().Join("my-libraries", "WiFi101") + + // Create new sketch and add library include + _, _, err := cli.Run("sketch", "new", sketchPath.String()) + require.NoError(t, err) + sketchFile := sketchPath.Join(sketchName + ".ino") + data, err := sketchFile.ReadFile() + require.NoError(t, err) + data = append([]byte("#include \n"), data...) + err = sketchFile.WriteFile(data) + require.NoError(t, err) + + stdout, _, err := cli.Run("compile", "-b", fqbn, sketchPath.String(), "--library", libPath.String(), "-v") + require.NoError(t, err) + require.Contains(t, string(stdout), "WiFi101") +} + +func compileWithLibraryPriority(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI) { + sketchName := "CompileSketchWithLibraryPriority" + sketchPath := cli.SketchbookDir().Join(sketchName) + defer sketchPath.RemoveAll() + fqbn := "arduino:avr:uno" + + manuallyInstalledLibPath := cli.SketchbookDir().Join("my-libraries", "WiFi101") + + // Install the same library we installed manually + _, _, err := cli.Run("lib", "install", "WiFi101") + require.NoError(t, err) + defer cli.SketchbookDir().Join("libraries").RemoveAll() + + // Create new sketch and add library include + _, _, err = cli.Run("sketch", "new", sketchPath.String()) + require.NoError(t, err) + sketchFile := sketchPath.Join(sketchName + ".ino") + lines, err := sketchFile.ReadFileAsLines() + require.NoError(t, err) + lines = append([]string{"#include \n"}, lines...) + var data []byte + for _, l := range lines { + data = append(data, []byte(l)...) + } + err = sketchFile.WriteFile(data) + require.NoError(t, err) + + stdout, _, err := cli.Run("compile", "-b", fqbn, sketchPath.String(), "--library", manuallyInstalledLibPath.String(), "-v") + require.NoError(t, err) + cliInstalledLibPath := cli.SketchbookDir().Join("libraries", "WiFi101") + expectedOutput := [3]string{ + "Multiple libraries were found for \"WiFi101.h\"", + " Used: " + manuallyInstalledLibPath.String(), + " Not used: " + cliInstalledLibPath.String(), + } + require.Contains(t, string(stdout), expectedOutput[0]+"\n"+expectedOutput[1]+"\n"+expectedOutput[2]+"\n") +} + +func recompileWithDifferentLibrary(t *testing.T, env *integrationtest.Environment, cli *integrationtest.ArduinoCLI) { + sketchName := "RecompileCompileSketchWithDifferentLibrary" + sketchPath := cli.SketchbookDir().Join(sketchName) + defer sketchPath.RemoveAll() + fqbn := "arduino:avr:uno" + + // Install library + _, _, err := cli.Run("lib", "install", "WiFi101") + require.NoError(t, err) + defer cli.SketchbookDir().Join("libraries").RemoveAll() + + manuallyInstalledLibPath := cli.SketchbookDir().Join("my-libraries", "WiFi101") + + // Create new sketch and add library include + _, _, err = cli.Run("sketch", "new", sketchPath.String()) + require.NoError(t, err) + sketchFile := sketchPath.Join(sketchName + ".ino") + lines, err := sketchFile.ReadFileAsLines() + require.NoError(t, err) + lines = append([]string{"#include \n"}, lines...) + var data []byte + for _, l := range lines { + data = append(data, []byte(l)...) + } + err = sketchFile.WriteFile(data) + require.NoError(t, err) + + md5 := md5.Sum(([]byte(sketchPath.String()))) + sketchPathMd5 := strings.ToUpper(hex.EncodeToString(md5[:])) + require.NotEmpty(t, sketchPathMd5) + buildDir := paths.TempDir().Join("arduino-sketch-" + sketchPathMd5) + + // Compile sketch using library not managed by CLI + stdout, _, err := cli.Run("compile", "-b", fqbn, "--library", manuallyInstalledLibPath.String(), sketchPath.String(), "-v") + require.NoError(t, err) + objPath := buildDir.Join("libraries", "WiFi101", "WiFi.cpp.o") + require.NotContains(t, string(stdout), "Using previously compiled file: "+objPath.String()) + + // Compile again using library installed from CLI + stdout, _, err = cli.Run("compile", "-b", fqbn, sketchPath.String(), "-v") + require.NoError(t, err) + require.NotContains(t, string(stdout), "Using previously compiled file: "+objPath.String()) +} + +func TestCompileManuallyInstalledPlatformUsingBoardsLocalTxt(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("update") + require.NoError(t, err) + + sketchName := "CompileSketchManuallyInstalledPlatformUsingBoardsLocalTxt" + sketchPath := cli.SketchbookDir().Join(sketchName) + fqbn := "arduino-beta-development:avr:nessuno" + _, _, err = cli.Run("sketch", "new", sketchPath.String()) + require.NoError(t, err) + + // Manually installs a core in sketchbooks hardware folder + gitUrl := "https://github.com/arduino/ArduinoCore-avr.git" + repoDir := cli.SketchbookDir().Join("hardware", "arduino-beta-development", "avr") + _, err = git.PlainClone(repoDir.String(), false, &git.CloneOptions{ + URL: gitUrl, + ReferenceName: plumbing.NewTagReferenceName("1.8.3"), + }) + require.NoError(t, err) + + // Installs also the same core via CLI so all the necessary tools are installed + _, _, err = cli.Run("core", "install", "arduino:avr@1.8.3") + require.NoError(t, err) + + // Verifies compilation fails because board doesn't exist + _, stderr, err := cli.Run("compile", "--clean", "-b", fqbn, sketchPath.String()) + require.Error(t, err) + require.Contains(t, string(stderr), "Error during build: Error resolving FQBN: board arduino-beta-development:avr:nessuno not found") + + // Use custom boards.local.txt with made arduino:avr:nessuno board + boardsLocalTxt := repoDir.Join("boards.local.txt") + err = paths.New("..", "testdata", "boards.local.txt").CopyTo(boardsLocalTxt) + require.NoError(t, err) + + _, _, err = cli.Run("compile", "--clean", "-b", fqbn, sketchPath.String()) + require.NoError(t, err) +} + +func TestCompileWithConflictingLibrariesInclude(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("update") + require.NoError(t, err) + + _, _, err = cli.Run("core", "install", "arduino:avr@1.8.3") + require.NoError(t, err) + + // Installs conflicting libraries + gitUrl := "https://github.com/pstolarz/OneWireNg.git" + oneWireNgLibPath := cli.SketchbookDir().Join("libraries", "onewireng_0_8_1") + _, err = git.PlainClone(oneWireNgLibPath.String(), false, &git.CloneOptions{ + URL: gitUrl, + ReferenceName: plumbing.NewTagReferenceName("0.8.1"), + }) + require.NoError(t, err) + + gitUrl = "https://github.com/PaulStoffregen/OneWire.git" + oneWireLibPath := cli.SketchbookDir().Join("libraries", "onewire_2_3_5") + _, err = git.PlainClone(oneWireLibPath.String(), false, &git.CloneOptions{ + URL: gitUrl, + ReferenceName: plumbing.NewTagReferenceName("v2.3.5"), + }) + require.NoError(t, err) + + sketchPath := cli.CopySketch("sketch_with_conflicting_libraries_include") + fqbn := "arduino:avr:uno" + + stdout, _, err := cli.Run("compile", "-b", fqbn, sketchPath.String(), "--verbose") + require.NoError(t, err) + expectedOutput := [3]string{ + "Multiple libraries were found for \"OneWire.h\"", + " Used: " + oneWireLibPath.String(), + " Not used: " + oneWireNgLibPath.String(), + } + require.Contains(t, string(stdout), expectedOutput[0]+"\n"+expectedOutput[1]+"\n"+expectedOutput[2]+"\n") +} + +func TestCompileWithEsp32BundledLibraries(t *testing.T) { + // Some esp cores have have bundled libraries that are optimize for that architecture, + // it might happen that if the user has a library with the same name installed conflicts + // can ensue and the wrong library is used for compilation, thus it fails. + // This happens because for "historical" reasons these platform have their "name" key + // in the "library.properties" flag suffixed with "(esp32)" or similar even though that + // doesn't respect the libraries specification. + // https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format + // + // The reason those libraries have these suffixes is to avoid an annoying bug in the Java IDE + // that would have caused the libraries that are both bundled with the core and the Java IDE to be + // always marked as updatable. For more info see: https://github.com/arduino/Arduino/issues/4189 + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("update") + require.NoError(t, err) + + // Update index with esp32 core and install it + url := "https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json" + coreVersion := "1.0.6" + _, _, err = cli.Run("core", "update-index", "--additional-urls="+url) + require.NoError(t, err) + _, _, err = cli.Run("core", "install", "esp32:esp32@"+coreVersion, "--additional-urls="+url) + require.NoError(t, err) + + // Install a library with the same name as one bundled with the core + _, _, err = cli.Run("lib", "install", "SD") + require.NoError(t, err) + + sketchPath := cli.CopySketch("sketch_with_sd_library") + fqbn := "esp32:esp32:esp32" + + stdout, _, err := cli.Run("compile", "-b", fqbn, sketchPath.String(), "--verbose") + require.Error(t, err) + + coreBundledLibPath := cli.DataDir().Join("packages", "esp32", "hardware", "esp32", coreVersion, "libraries", "SD") + cliInstalledLibPath := cli.SketchbookDir().Join("libraries", "SD") + expectedOutput := [3]string{ + "Multiple libraries were found for \"OneWire.h\"", + " Used: " + coreBundledLibPath.String(), + " Not used: " + cliInstalledLibPath.String(), + } + require.NotContains(t, string(stdout), expectedOutput[0]+"\n"+expectedOutput[1]+"\n"+expectedOutput[2]+"\n") +} + +func TestCompileWithEsp8266BundledLibraries(t *testing.T) { + // Some esp cores have have bundled libraries that are optimize for that architecture, + // it might happen that if the user has a library with the same name installed conflicts + // can ensue and the wrong library is used for compilation, thus it fails. + // This happens because for "historical" reasons these platform have their "name" key + // in the "library.properties" flag suffixed with "(esp32)" or similar even though that + // doesn't respect the libraries specification. + // https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format + // + // The reason those libraries have these suffixes is to avoid an annoying bug in the Java IDE + // that would have caused the libraries that are both bundled with the core and the Java IDE to be + // always marked as updatable. For more info see: https://github.com/arduino/Arduino/issues/4189 + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("update") + require.NoError(t, err) + + // Update index with esp8266 core and install it + url := "http://arduino.esp8266.com/stable/package_esp8266com_index.json" + coreVersion := "2.7.4" + _, _, err = cli.Run("core", "update-index", "--additional-urls="+url) + require.NoError(t, err) + _, _, err = cli.Run("core", "install", "esp8266:esp8266@"+coreVersion, "--additional-urls="+url) + require.NoError(t, err) + + // Install a library with the same name as one bundled with the core + _, _, err = cli.Run("lib", "install", "SD") + require.NoError(t, err) + + sketchPath := cli.CopySketch("sketch_with_sd_library") + fqbn := "esp8266:esp8266:generic" + + stdout, _, err := cli.Run("compile", "-b", fqbn, sketchPath.String(), "--verbose") + require.Error(t, err) + + coreBundledLibPath := cli.DataDir().Join("packages", "esp8266", "hardware", "esp8266", coreVersion, "libraries", "SD") + cliInstalledLibPath := cli.SketchbookDir().Join("libraries", "SD") + expectedOutput := [3]string{ + "Multiple libraries were found for \"OneWire.h\"", + " Used: " + coreBundledLibPath.String(), + " Not used: " + cliInstalledLibPath.String(), + } + require.NotContains(t, string(stdout), expectedOutput[0]+"\n"+expectedOutput[1]+"\n"+expectedOutput[2]+"\n") +} + +func TestGenerateCompileCommandsJsonResilience(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("update") + require.NoError(t, err) + + // check it didn't fail with esp32@2.0.1 that has a prebuild hook that must run: + // https://github.com/arduino/arduino-cli/issues/1547 + url := "https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json" + _, _, err = cli.Run("core", "update-index", "--additional-urls="+url) + require.NoError(t, err) + _, _, err = cli.Run("core", "install", "esp32:esp32@2.0.1", "--additional-urls="+url) + require.NoError(t, err) + sketchPath := cli.CopySketch("sketch_simple") + _, _, err = cli.Run("compile", "-b", "esp32:esp32:featheresp32", "--only-compilation-database", sketchPath.String()) + require.NoError(t, err) + + // check it didn't fail on a sketch with a missing include + sketchPath = cli.CopySketch("sketch_with_missing_include") + _, _, err = cli.Run("compile", "-b", "esp32:esp32:featheresp32", "--only-compilation-database", sketchPath.String()) + require.NoError(t, err) +} + +func TestCompileSketchSketchWithTppFileInclude(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("update") + require.NoError(t, err) + + // Download latest AVR + _, _, err = cli.Run("core", "install", "arduino:avr") + require.NoError(t, err) + + sketchPath := cli.CopySketch("sketch_with_tpp_file_include") + fqbn := "arduino:avr:uno" + + _, _, err = cli.Run("compile", "-b", fqbn, sketchPath.String(), "--verbose") + require.NoError(t, err) +} + +func TestCompileSketchWithIppFileInclude(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("update") + require.NoError(t, err) + + // Download latest AVR + _, _, err = cli.Run("core", "install", "arduino:avr") + require.NoError(t, err) + + sketchPath := cli.CopySketch("sketch_with_ipp_file_include") + fqbn := "arduino:avr:uno" + + _, _, err = cli.Run("compile", "-b", fqbn, sketchPath.String(), "--verbose") + require.NoError(t, err) +} + +func TestCompileWithoutUploadAndFqbn(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("update") + require.NoError(t, err) + + // Create a sketch + sketchPath := cli.SketchbookDir().Join("SketchSimple") + _, _, err = cli.Run("sketch", "new", sketchPath.String()) + require.NoError(t, err) + + _, stderr, err := cli.Run("compile", sketchPath.String()) + require.Error(t, err) + require.Contains(t, string(stderr), "Missing FQBN (Fully Qualified Board Name)") +} + +func TestCompileNonInstalledPlatformWithWrongPackagerAndArch(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("update") + require.NoError(t, err) + + // Create a sketch + sketchPath := cli.SketchbookDir().Join("SketchSimple") + _, _, err = cli.Run("sketch", "new", sketchPath.String()) + require.NoError(t, err) + + // Compile with wrong packager + _, stderr, err := cli.Run("compile", "-b", "wrong:avr:uno", sketchPath.String()) + require.Error(t, err) + require.Contains(t, string(stderr), "Error during build: Platform 'wrong:avr' not found: platform not installed") + require.Contains(t, string(stderr), "Platform wrong:avr is not found in any known index") + + // Compile with wrong arch + _, stderr, err = cli.Run("compile", "-b", "arduino:wrong:uno", sketchPath.String()) + require.Error(t, err) + require.Contains(t, string(stderr), "Error during build: Platform 'arduino:wrong' not found: platform not installed") + require.Contains(t, string(stderr), "Platform arduino:wrong is not found in any known index") +} + +func TestCompileWithKnownPlatformNotInstalled(t *testing.T) { + env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) + defer env.CleanUp() + + _, _, err := cli.Run("update") + require.NoError(t, err) + + // Create a sketch + sketchPath := cli.SketchbookDir().Join("SketchSimple") + _, _, err = cli.Run("sketch", "new", sketchPath.String()) + require.NoError(t, err) + + // Try to compile using a platform found in the index but not installed + _, stderr, err := cli.Run("compile", "-b", "arduino:avr:uno", sketchPath.String()) + require.Error(t, err) + require.Contains(t, string(stderr), "Error during build: Platform 'arduino:avr' not found: platform not installed") + // Verifies command to fix error is shown to user + require.Contains(t, string(stderr), "Try running `arduino-cli core install arduino:avr`") +}