Unverified Commit e53d2f5c authored by MatteoPologruto's avatar MatteoPologruto Committed by GitHub

[skip-changelog] Run integration tests concurrently (#1953)

* Run integration tests concurrently

This enhancement reduces the amount of time needed to execute integration tests, since each test package no longer has to wait for the previous ones to be completed. In order to do this, a regex is used
to match each test file. It is also specified the path to the directory that contains the file.

* Merge all test files that share a package into one

Having different test files that shared the same package was inefficient, because the whole package test was run one time for each file. This enhancement avoids repeating the same tests more than once.
parent ec3e71ca
...@@ -58,13 +58,61 @@ jobs: ...@@ -58,13 +58,61 @@ jobs:
echo "result=$RESULT" >> $GITHUB_OUTPUT echo "result=$RESULT" >> $GITHUB_OUTPUT
test: tests-collector:
runs-on: ubuntu-latest
needs: run-determination needs: run-determination
if: needs.run-determination.outputs.result == 'true' if: needs.run-determination.outputs.result == 'true'
outputs:
tests-data: ${{ steps.collection.outputs.tests-data }}
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Collect tests
id: collection
run: |
echo "tests-data=$(go list ./internal/integrationtest/... | grep integrationtest/ | tr "/" " " | cut -d " " -f 6 | jq -cR '[inputs]')" >> $GITHUB_OUTPUT
test-integration:
needs: tests-collector
strategy: strategy:
fail-fast: false matrix:
operating-system:
- ubuntu-latest
- windows-latest
- macos-latest
tests: ${{ fromJSON(needs.tests-collector.outputs.tests-data) }}
runs-on: ${{ matrix.operating-system }}
steps:
# By default, actions/checkout converts the repo's LF line endings to CRLF on the Windows runner.
- name: Disable EOL conversions
run: git config --global core.autocrlf false
- name: Checkout repository
uses: actions/checkout@v3
- name: Install Go
uses: actions/setup-go@v3
with:
go-version: ${{ env.GO_VERSION }}
- name: Install Task
uses: arduino/setup-task@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
version: 3.x
- name: Run tests
shell: bash
run: |
export GO_TEST_PACKAGE="github.com/arduino/arduino-cli/internal/integrationtest/${{ matrix.tests }}"
task go:integration-test
test:
needs: run-determination
strategy:
matrix: matrix:
operating-system: operating-system:
- ubuntu-latest - ubuntu-latest
......
...@@ -105,6 +105,23 @@ tasks: ...@@ -105,6 +105,23 @@ tasks:
{{default .DEFAULT_GO_PACKAGES .GO_PACKAGES}} \ {{default .DEFAULT_GO_PACKAGES .GO_PACKAGES}} \
{{.TEST_LDFLAGS}} {{.TEST_LDFLAGS}}
go:integration-test:
desc: Run the Go-based integration tests
deps:
- task: go:build
dir: '{{default "./" .GO_MODULE_PATH}}'
cmds:
- |
go test \
-v \
-short \
{{ .GO_TEST_PACKAGE }} \
-run '{{default ".*" .GO_TEST_REGEX}}' \
{{default "-timeout 20m -coverpkg=./... -covermode=atomic" .GO_TEST_FLAGS}} \
-coverprofile=coverage_unit.txt \
{{default .DEFAULT_INTEGRATIONTEST_GO_PACKAGES .GO_PACKAGES}} \
{{.TEST_LDFLAGS}}
# Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/test-go-integration-task/Taskfile.yml # Source: https://github.com/arduino/tooling-project-assets/blob/main/workflow-templates/assets/test-go-integration-task/Taskfile.yml
go:test-integration: go:test-integration:
desc: Run integration tests desc: Run integration tests
...@@ -342,10 +359,13 @@ tasks: ...@@ -342,10 +359,13 @@ tasks:
vars: vars:
PROJECT_NAME: "arduino-cli" PROJECT_NAME: "arduino-cli"
DIST_DIR: "dist" DIST_DIR: "dist"
# all modules of this project except for "legacy/..." module # all modules of this project except for "legacy/..." module and integration test
DEFAULT_GO_PACKAGES: DEFAULT_GO_PACKAGES:
sh: | sh: |
echo $(cd {{default "./" .GO_MODULE_PATH}} && go list ./... | grep -v legacy | tr '\n' ' ' || echo '"ERROR: Unable to discover Go packages"') echo $(cd {{default "./" .GO_MODULE_PATH}} && go list ./... | grep -v internal/integrationtest | grep -v legacy | tr '\n' ' ' || echo '"ERROR: Unable to discover Go packages"')
DEFAULT_INTEGRATIONTEST_GO_PACKAGES:
sh: |
echo $(cd {{default "./" .GO_MODULE_PATH}} && go list ./... | grep internal/integrationtest | tr '\n' ' ' || echo '"ERROR: Unable to discover Go packages"')
# build vars # build vars
COMMIT: COMMIT:
sh: echo "$(git log --no-show-signature -n 1 --format=%h)" sh: echo "$(git log --no-show-signature -n 1 --format=%h)"
......
// 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 board_test
import (
"testing"
"github.com/arduino/arduino-cli/internal/integrationtest"
"github.com/stretchr/testify/require"
"go.bug.st/testifyjson/requirejson"
)
func TestCorrectBoardListOrdering(t *testing.T) {
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
defer env.CleanUp()
_, _, err := cli.Run("core", "install", "arduino:avr")
require.NoError(t, err)
jsonOut, _, err := cli.Run("board", "listall", "--format", "json")
require.NoError(t, err)
requirejson.Query(t, jsonOut, "[.boards[] | .fqbn]", `[
"arduino:avr:yun",
"arduino:avr:uno",
"arduino:avr:unomini",
"arduino:avr:diecimila",
"arduino:avr:nano",
"arduino:avr:mega",
"arduino:avr:megaADK",
"arduino:avr:leonardo",
"arduino:avr:leonardoeth",
"arduino:avr:micro",
"arduino:avr:esplora",
"arduino:avr:mini",
"arduino:avr:ethernet",
"arduino:avr:fio",
"arduino:avr:bt",
"arduino:avr:LilyPadUSB",
"arduino:avr:lilypad",
"arduino:avr:pro",
"arduino:avr:atmegang",
"arduino:avr:robotControl",
"arduino:avr:robotMotor",
"arduino:avr:gemma",
"arduino:avr:circuitplay32u4cat",
"arduino:avr:yunmini",
"arduino:avr:chiwawa",
"arduino:avr:one",
"arduino:avr:unowifi"
]`)
}
...@@ -29,6 +29,45 @@ import ( ...@@ -29,6 +29,45 @@ import (
"gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing"
) )
func TestCorrectBoardListOrdering(t *testing.T) {
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
defer env.CleanUp()
_, _, err := cli.Run("core", "install", "arduino:avr")
require.NoError(t, err)
jsonOut, _, err := cli.Run("board", "listall", "--format", "json")
require.NoError(t, err)
requirejson.Query(t, jsonOut, "[.boards[] | .fqbn]", `[
"arduino:avr:yun",
"arduino:avr:uno",
"arduino:avr:unomini",
"arduino:avr:diecimila",
"arduino:avr:nano",
"arduino:avr:mega",
"arduino:avr:megaADK",
"arduino:avr:leonardo",
"arduino:avr:leonardoeth",
"arduino:avr:micro",
"arduino:avr:esplora",
"arduino:avr:mini",
"arduino:avr:ethernet",
"arduino:avr:fio",
"arduino:avr:bt",
"arduino:avr:LilyPadUSB",
"arduino:avr:lilypad",
"arduino:avr:pro",
"arduino:avr:atmegang",
"arduino:avr:robotControl",
"arduino:avr:robotMotor",
"arduino:avr:gemma",
"arduino:avr:circuitplay32u4cat",
"arduino:avr:yunmini",
"arduino:avr:chiwawa",
"arduino:avr:one",
"arduino:avr:unowifi"
]`)
}
func TestBoardList(t *testing.T) { func TestBoardList(t *testing.T) {
if os.Getenv("CI") != "" { if os.Getenv("CI") != "" {
t.Skip("VMs have no serial ports") t.Skip("VMs have no serial ports")
......
// 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 (
"encoding/json"
"testing"
"github.com/arduino/arduino-cli/internal/integrationtest"
"github.com/arduino/go-paths-helper"
"github.com/stretchr/testify/require"
)
func TestCompileWithoutPrecompiledLibraries(t *testing.T) {
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
defer env.CleanUp()
// Init the environment explicitly
url := "https://adafruit.github.io/arduino-board-index/package_adafruit_index.json"
_, _, err := cli.Run("core", "update-index", "--additional-urls="+url)
require.NoError(t, err)
_, _, err = cli.Run("core", "install", "arduino:mbed@1.3.1", "--additional-urls="+url)
require.NoError(t, err)
// // Precompiled version of Arduino_TensorflowLite
// _, _, err = cli.Run("lib", "install", "Arduino_LSM9DS1")
// require.NoError(t, err)
// _, _, err = cli.Run("lib", "install", "Arduino_TensorflowLite@2.1.1-ALPHA-precompiled")
// require.NoError(t, err)
// sketchPath := cli.SketchbookDir().Join("libraries", "Arduino_TensorFlowLite", "examples", "hello_world")
// _, _, err = cli.Run("compile", "-b", "arduino:mbed:nano33ble", sketchPath.String())
// require.NoError(t, err)
_, _, err = cli.Run("core", "install", "arduino:samd@1.8.7", "--additional-urls="+url)
require.NoError(t, err)
// _, _, err = cli.Run("core", "install", "adafruit:samd@1.6.4", "--additional-urls="+url)
// require.NoError(t, err)
// // should work on adafruit too after https://github.com/arduino/arduino-cli/pull/1134
// _, _, err = cli.Run("compile", "-b", "adafruit:samd:adafruit_feather_m4", sketchPath.String())
// require.NoError(t, err)
// // Non-precompiled version of Arduino_TensorflowLite
// _, _, err = cli.Run("lib", "install", "Arduino_TensorflowLite@2.1.0-ALPHA")
// require.NoError(t, err)
// _, _, err = cli.Run("compile", "-b", "arduino:mbed:nano33ble", sketchPath.String())
// require.NoError(t, err)
// _, _, err = cli.Run("compile", "-b", "adafruit:samd:adafruit_feather_m4", sketchPath.String())
// require.NoError(t, err)
// Bosch sensor library
_, _, err = cli.Run("lib", "install", "BSEC Software Library@1.5.1474")
require.NoError(t, err)
sketchPath := cli.SketchbookDir().Join("libraries", "BSEC_Software_Library", "examples", "basic")
_, _, err = cli.Run("compile", "-b", "arduino:samd:mkr1000", sketchPath.String())
require.NoError(t, err)
_, _, err = cli.Run("compile", "-b", "arduino:mbed:nano33ble", sketchPath.String())
require.NoError(t, err)
// USBBlaster library
_, _, err = cli.Run("lib", "install", "USBBlaster@1.0.0")
require.NoError(t, err)
sketchPath = cli.SketchbookDir().Join("libraries", "USBBlaster", "examples", "USB_Blaster")
_, _, err = cli.Run("compile", "-b", "arduino:samd:mkrvidor4000", sketchPath.String())
require.NoError(t, err)
}
func TestCompileWithCustomLibraries(t *testing.T) {
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
defer env.CleanUp()
// Creates config with additional URL to install necessary core
url := "http://arduino.esp8266.com/stable/package_esp8266com_index.json"
_, _, err := cli.Run("config", "init", "--dest-dir", ".", "--additional-urls", url)
require.NoError(t, err)
// Init the environment explicitly
_, _, err = cli.Run("update")
require.NoError(t, err)
_, _, err = cli.Run("core", "install", "esp8266:esp8266")
require.NoError(t, err)
sketchName := "sketch_with_multiple_custom_libraries"
sketchPath := cli.CopySketch(sketchName)
fqbn := "esp8266:esp8266:nodemcu:xtal=80,vt=heap,eesz=4M1M,wipe=none,baud=115200"
firstLib := sketchPath.Join("libraries1")
secondLib := sketchPath.Join("libraries2")
_, _, err = cli.Run("compile", "--libraries", firstLib.String(), "--libraries", secondLib.String(), "-b", fqbn, sketchPath.String())
require.NoError(t, err)
}
func TestCompileWithArchivesAndLongPaths(t *testing.T) {
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
defer env.CleanUp()
// Creates config with additional URL to install necessary core
url := "http://arduino.esp8266.com/stable/package_esp8266com_index.json"
_, _, err := cli.Run("config", "init", "--dest-dir", ".", "--additional-urls", url)
require.NoError(t, err)
// Init the environment explicitly
_, _, err = cli.Run("update")
require.NoError(t, err)
// Install core to compile
_, _, err = cli.Run("core", "install", "esp8266:esp8266@2.7.4")
require.NoError(t, err)
// Install test library
_, _, err = cli.Run("lib", "install", "ArduinoIoTCloud")
require.NoError(t, err)
stdout, _, err := cli.Run("lib", "examples", "ArduinoIoTCloud", "--format", "json")
require.NoError(t, err)
var libOutput []map[string]interface{}
err = json.Unmarshal(stdout, &libOutput)
require.NoError(t, err)
sketchPath := paths.New(libOutput[0]["library"].(map[string]interface{})["install_dir"].(string))
sketchPath = sketchPath.Join("examples", "ArduinoIoTCloud-Advanced")
_, _, err = cli.Run("compile", "-b", "esp8266:esp8266:huzzah", sketchPath.String())
require.NoError(t, err)
}
func TestCompileWithPrecompileLibrary(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:samd@1.8.11")
require.NoError(t, err)
fqbn := "arduino:samd:mkrzero"
// Install precompiled library
// For more information see:
// https://arduino.github.io/arduino-cli/latest/library-specification/#precompiled-binaries
_, _, err = cli.Run("lib", "install", "BSEC Software Library@1.5.1474")
require.NoError(t, err)
sketchFolder := cli.SketchbookDir().Join("libraries", "BSEC_Software_Library", "examples", "basic")
// Compile and verify dependencies detection for fully precompiled library is not skipped
stdout, _, err := cli.Run("compile", "-b", fqbn, sketchFolder.String(), "-v")
require.NoError(t, err)
require.NotContains(t, string(stdout), "Skipping dependencies detection for precompiled library BSEC Software Library")
}
// 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 (
"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 TestCompileWithFullyPrecompiledLibrary(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:mbed@1.3.1")
require.NoError(t, err)
fqbn := "arduino:mbed:nano33ble"
// Create settings with library unsafe install set to true
envVar := cli.GetDefaultEnv()
envVar["ARDUINO_LIBRARY_ENABLE_UNSAFE_INSTALL"] = "true"
_, _, err = cli.RunWithCustomEnv(envVar, "config", "init", "--dest-dir", ".")
require.NoError(t, err)
// Install fully precompiled library
// For more information see:
// https://arduino.github.io/arduino-cli/latest/library-specification/#precompiled-binaries
wd, err := paths.Getwd()
require.NoError(t, err)
_, _, err = cli.Run("lib", "install", "--zip-path", wd.Parent().Join("testdata", "Arduino_TensorFlowLite-2.1.0-ALPHA-precompiled.zip").String())
require.NoError(t, err)
sketchFolder := cli.SketchbookDir().Join("libraries", "Arduino_TensorFlowLite-2.1.0-ALPHA-precompiled", "examples", "hello_world")
// Install example dependency
_, _, err = cli.Run("lib", "install", "Arduino_LSM9DS1")
require.NoError(t, err)
// Compile and verify dependencies detection for fully precompiled library is skipped
stdout, _, err := cli.Run("compile", "-b", fqbn, sketchFolder.String(), "-v")
require.NoError(t, err)
require.Contains(t, string(stdout), "Skipping dependencies detection for precompiled library Arduino_TensorFlowLite")
}
func TestCompileManuallyInstalledPlatform(t *testing.T) {
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
defer env.CleanUp()
_, _, err := cli.Run("update")
require.NoError(t, err)
sketchName := "CompileSketchManuallyInstalledPlatformUsingPlatformLocalTxt"
sketchPath := cli.SketchbookDir().Join(sketchName)
fqbn := "arduino-beta-development:avr:uno"
_, _, 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 works without issues
_, _, err = cli.Run("compile", "--clean", "-b", fqbn, sketchPath.String())
require.NoError(t, err)
}
func TestCompileManuallyInstalledPlatformUsingPlatformLocalTxt(t *testing.T) {
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
defer env.CleanUp()
_, _, err := cli.Run("update")
require.NoError(t, err)
sketchName := "CompileSketchManuallyInstalledPlatformUsingPlatformLocalTxt"
sketchPath := cli.SketchbookDir().Join(sketchName)
fqbn := "arduino-beta-development:avr:uno"
_, _, 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 works without issues
_, _, err = cli.Run("compile", "--clean", "-b", fqbn, sketchPath.String())
require.NoError(t, err)
// Overrides default platform compiler with an unexisting one
platformLocalTxt := repoDir.Join("platform.local.txt")
platformLocalTxt.WriteFile([]byte("compiler.c.cmd=my-compiler-that-does-not-exist"))
// Verifies compilation now fails because compiler is not found
_, stderr, err := cli.Run("compile", "--clean", "-b", fqbn, sketchPath.String())
require.Error(t, err)
require.Contains(t, string(stderr), "my-compiler-that-does-not-exist")
}
// 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 core_test
import (
"testing"
"github.com/arduino/arduino-cli/internal/integrationtest"
"github.com/arduino/go-paths-helper"
"github.com/stretchr/testify/require"
"go.bug.st/testifyjson/requirejson"
)
func TestCorrectHandlingOfPlatformVersionProperty(t *testing.T) {
// See: https://github.com/arduino/arduino-cli/issues/1823
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
defer env.CleanUp()
// Copy test platform
testPlatform := paths.New("testdata", "issue_1823", "DxCore-dev")
require.NoError(t, testPlatform.CopyDirTo(cli.SketchbookDir().Join("hardware", "DxCore-dev")))
// Trigger problematic call
out, _, err := cli.Run("core", "list", "--format", "json")
require.NoError(t, err)
requirejson.Contains(t, out, `[{"id":"DxCore-dev:megaavr","installed":"1.4.10","name":"DxCore"}]`)
}
...@@ -26,6 +26,21 @@ import ( ...@@ -26,6 +26,21 @@ import (
"go.bug.st/testifyjson/requirejson" "go.bug.st/testifyjson/requirejson"
) )
func TestCorrectHandlingOfPlatformVersionProperty(t *testing.T) {
// See: https://github.com/arduino/arduino-cli/issues/1823
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
defer env.CleanUp()
// Copy test platform
testPlatform := paths.New("testdata", "issue_1823", "DxCore-dev")
require.NoError(t, testPlatform.CopyDirTo(cli.SketchbookDir().Join("hardware", "DxCore-dev")))
// Trigger problematic call
out, _, err := cli.Run("core", "list", "--format", "json")
require.NoError(t, err)
requirejson.Contains(t, out, `[{"id":"DxCore-dev:megaavr","installed":"1.4.10","name":"DxCore"}]`)
}
func TestCoreSearch(t *testing.T) { func TestCoreSearch(t *testing.T) {
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t) env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
defer env.CleanUp() defer env.CleanUp()
......
// 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 daemon_test
import (
"context"
"fmt"
"io"
"testing"
"time"
"github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/stretchr/testify/require"
)
func TestArduinoCliDaemon(t *testing.T) {
// See: https://github.com/arduino/arduino-cli/pull/1804
t.SkipNow() // TO BE Removed once the bug is fixed
env, cli := createEnvForDaemon(t)
defer env.CleanUp()
grpcInst := cli.Create()
require.NoError(t, grpcInst.Init("", "", func(ir *commands.InitResponse) {
fmt.Printf("INIT> %v\n", ir.GetMessage())
}))
// Run a one-shot board list
boardListResp, err := grpcInst.BoardList(time.Second)
require.NoError(t, err)
fmt.Printf("Got boardlist response with %d ports\n", len(boardListResp.GetPorts()))
// Run a one-shot board list again (should not fail)
boardListResp, err = grpcInst.BoardList(time.Second)
require.NoError(t, err)
fmt.Printf("Got boardlist response with %d ports\n", len(boardListResp.GetPorts()))
testWatcher := func() {
// Run watcher
watcher, err := grpcInst.BoardListWatch()
require.NoError(t, err)
ctx, cancel := context.WithCancel(context.Background())
go func() {
defer cancel()
for {
msg, err := watcher.Recv()
if err == io.EOF {
fmt.Println("Watcher EOF")
return
}
require.Empty(t, msg.Error, "Board list watcher returned an error")
require.NoError(t, err, "BoardListWatch grpc call returned an error")
fmt.Printf("WATCH> %v\n", msg)
}
}()
time.Sleep(time.Second)
require.NoError(t, watcher.CloseSend())
select {
case <-ctx.Done():
// all right!
case <-time.After(time.Second):
require.Fail(t, "BoardListWatch didn't close")
}
}
testWatcher()
testWatcher()
}
// 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 daemon_test
import (
"context"
"fmt"
"io"
"testing"
"github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/arduino/go-paths-helper"
"github.com/stretchr/testify/require"
)
func TestDaemonCompileOptions(t *testing.T) {
// See: https://github.com/arduino/arduino-cli/issues/1614
// See: https://github.com/arduino/arduino-cli/pull/1820
env, cli := createEnvForDaemon(t)
defer env.CleanUp()
grpcInst := cli.Create()
require.NoError(t, grpcInst.Init("", "", func(ir *commands.InitResponse) {
fmt.Printf("INIT> %v\n", ir.GetMessage())
}))
plInst, err := grpcInst.PlatformInstall(context.Background(), "arduino", "avr", "1.8.5", true)
require.NoError(t, err)
for {
msg, err := plInst.Recv()
if err == io.EOF {
break
}
require.NoError(t, err)
fmt.Printf("INSTALL> %v\n", msg)
}
// Install boards.local.txt to trigger bug
platformLocalTxt := paths.New("testdata", "boards.local.txt-issue1614")
err = platformLocalTxt.CopyTo(cli.DataDir().
Join("packages", "arduino", "hardware", "avr", "1.8.5", "boards.local.txt"))
require.NoError(t, err)
// Re-init instance to update changes
require.NoError(t, grpcInst.Init("", "", func(ir *commands.InitResponse) {
fmt.Printf("INIT> %v\n", ir.GetMessage())
}))
// Build sketch (with errors)
sk := paths.New("testdata", "bare_minimum")
compile, err := grpcInst.Compile(context.Background(), "arduino:avr:uno:some_menu=bad", sk.String())
require.NoError(t, err)
for {
msg, err := compile.Recv()
if err == io.EOF {
require.FailNow(t, "Expected compilation failure", "compilation succeeded")
break
}
if err != nil {
fmt.Println("COMPILE ERROR>", err)
break
}
if msg.ErrStream != nil {
fmt.Printf("COMPILE> %v\n", string(msg.GetErrStream()))
}
}
// Build sketch (without errors)
compile, err = grpcInst.Compile(context.Background(), "arduino:avr:uno:some_menu=good", sk.String())
require.NoError(t, err)
for {
msg, err := compile.Recv()
if err == io.EOF {
break
}
require.NoError(t, err)
if msg.ErrStream != nil {
fmt.Printf("COMPILE> %v\n", string(msg.GetErrStream()))
}
}
}
func TestDaemonCompileAfterFailedLibInstall(t *testing.T) {
// See: https://github.com/arduino/arduino-cli/issues/1812
env, cli := createEnvForDaemon(t)
defer env.CleanUp()
grpcInst := cli.Create()
require.NoError(t, grpcInst.Init("", "", func(ir *commands.InitResponse) {
fmt.Printf("INIT> %v\n", ir.GetMessage())
}))
// Build sketch (with errors)
sk := paths.New("testdata", "bare_minimum")
compile, err := grpcInst.Compile(context.Background(), "", sk.String())
require.NoError(t, err)
for {
msg, err := compile.Recv()
if err == io.EOF {
require.FailNow(t, "Expected compilation failure", "compilation succeeded")
break
}
if err != nil {
fmt.Println("COMPILE ERROR>", err)
require.Contains(t, err.Error(), "Missing FQBN")
break
}
if msg.ErrStream != nil {
fmt.Printf("COMPILE> %v\n", string(msg.GetErrStream()))
}
}
}
// 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 daemon_test
import (
"context"
"fmt"
"io"
"testing"
"github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/stretchr/testify/require"
)
func TestDaemonCoreUpdateIndex(t *testing.T) {
env, cli := createEnvForDaemon(t)
defer env.CleanUp()
grpcInst := cli.Create()
require.NoError(t, grpcInst.Init("", "", func(ir *commands.InitResponse) {
fmt.Printf("INIT> %v\n", ir.GetMessage())
}))
// Set extra indexes
err := cli.SetValue(
"board_manager.additional_urls", ""+
`["http://arduino.esp8266.com/stable/package_esp8266com_index.json",`+
` "http://downloads.arduino.cc/package_inexistent_index.json"]`)
require.NoError(t, err)
analyzeUpdateIndexClient := func(cl commands.ArduinoCoreService_UpdateIndexClient) (error, map[string]*commands.DownloadProgressEnd) {
analyzer := NewDownloadProgressAnalyzer(t)
for {
msg, err := cl.Recv()
// fmt.Println("DOWNLOAD>", msg)
if err == io.EOF {
return nil, analyzer.Results
}
if err != nil {
return err, analyzer.Results
}
require.NoError(t, err)
analyzer.Process(msg.GetDownloadProgress())
}
}
{
cl, err := grpcInst.UpdateIndex(context.Background(), true)
require.NoError(t, err)
err, res := analyzeUpdateIndexClient(cl)
require.NoError(t, err)
require.Len(t, res, 1)
require.True(t, res["https://downloads.arduino.cc/packages/package_index.tar.bz2"].Success)
}
{
cl, err := grpcInst.UpdateIndex(context.Background(), false)
require.NoError(t, err)
err, res := analyzeUpdateIndexClient(cl)
require.Error(t, err)
require.Len(t, res, 3)
require.True(t, res["https://downloads.arduino.cc/packages/package_index.tar.bz2"].Success)
require.True(t, res["http://arduino.esp8266.com/stable/package_esp8266com_index.json"].Success)
require.False(t, res["http://downloads.arduino.cc/package_inexistent_index.json"].Success)
}
}
// 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 daemon_test
import (
"context"
"fmt"
"io"
"testing"
"github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/stretchr/testify/require"
)
func TestDaemonBundleLibInstall(t *testing.T) {
env, cli := createEnvForDaemon(t)
defer env.CleanUp()
grpcInst := cli.Create()
require.NoError(t, grpcInst.Init("", "", func(ir *commands.InitResponse) {
fmt.Printf("INIT> %v\n", ir.GetMessage())
}))
// Install libraries in bundled dir
{
instCl, err := grpcInst.LibraryInstall(context.Background(), "Arduino_BuiltIn", "", false, false, true)
require.NoError(t, err)
for {
msg, err := instCl.Recv()
if err == io.EOF {
break
}
require.NoError(t, err)
fmt.Printf("LIB INSTALL> %+v\n", msg)
}
}
// Check if libraries are installed as expected
{
resp, err := grpcInst.LibraryList(context.Background(), "", "", true, false)
require.NoError(t, err)
libsAndLocation := map[string]commands.LibraryLocation{}
for _, lib := range resp.GetInstalledLibraries() {
libsAndLocation[lib.Library.Name] = lib.Library.Location
}
require.Contains(t, libsAndLocation, "Ethernet")
require.Contains(t, libsAndLocation, "SD")
require.Contains(t, libsAndLocation, "Firmata")
require.Equal(t, libsAndLocation["Ethernet"], commands.LibraryLocation_LIBRARY_LOCATION_BUILTIN)
require.Equal(t, libsAndLocation["SD"], commands.LibraryLocation_LIBRARY_LOCATION_BUILTIN)
require.Equal(t, libsAndLocation["Firmata"], commands.LibraryLocation_LIBRARY_LOCATION_BUILTIN)
}
// Install a library in sketchbook to override bundled
{
instCl, err := grpcInst.LibraryInstall(context.Background(), "Ethernet", "", false, false, false)
require.NoError(t, err)
for {
msg, err := instCl.Recv()
if err == io.EOF {
break
}
require.NoError(t, err)
fmt.Printf("LIB INSTALL> %+v\n", msg)
}
}
// Check if libraries are installed as expected
installedEthernetVersion := ""
{
resp, err := grpcInst.LibraryList(context.Background(), "", "", true, false)
require.NoError(t, err)
libsAndLocation := map[string]commands.LibraryLocation{}
for _, lib := range resp.GetInstalledLibraries() {
libsAndLocation[lib.Library.Name] = lib.Library.Location
if lib.Library.Name == "Ethernet" {
installedEthernetVersion = lib.Library.Version
}
}
require.Contains(t, libsAndLocation, "Ethernet")
require.Contains(t, libsAndLocation, "SD")
require.Contains(t, libsAndLocation, "Firmata")
require.Equal(t, libsAndLocation["Ethernet"], commands.LibraryLocation_LIBRARY_LOCATION_USER)
require.Equal(t, libsAndLocation["SD"], commands.LibraryLocation_LIBRARY_LOCATION_BUILTIN)
require.Equal(t, libsAndLocation["Firmata"], commands.LibraryLocation_LIBRARY_LOCATION_BUILTIN)
}
// Remove library from sketchbook
{
uninstCl, err := grpcInst.LibraryUninstall(context.Background(), "Ethernet", installedEthernetVersion)
require.NoError(t, err)
for {
msg, err := uninstCl.Recv()
if err == io.EOF {
break
}
require.NoError(t, err)
fmt.Printf("LIB INSTALL> %+v\n", msg)
}
}
// Check if libraries are installed as expected
{
resp, err := grpcInst.LibraryList(context.Background(), "", "", true, false)
require.NoError(t, err)
libsAndLocation := map[string]commands.LibraryLocation{}
for _, lib := range resp.GetInstalledLibraries() {
libsAndLocation[lib.Library.Name] = lib.Library.Location
}
require.Contains(t, libsAndLocation, "Ethernet")
require.Contains(t, libsAndLocation, "SD")
require.Contains(t, libsAndLocation, "Firmata")
require.Equal(t, libsAndLocation["Ethernet"], commands.LibraryLocation_LIBRARY_LOCATION_BUILTIN)
require.Equal(t, libsAndLocation["SD"], commands.LibraryLocation_LIBRARY_LOCATION_BUILTIN)
require.Equal(t, libsAndLocation["Firmata"], commands.LibraryLocation_LIBRARY_LOCATION_BUILTIN)
}
// Un-Set builtin libraries dir
err := cli.SetValue("directories.builtin.libraries", `""`)
require.NoError(t, err)
// Re-init
require.NoError(t, grpcInst.Init("", "", func(ir *commands.InitResponse) {
fmt.Printf("INIT> %v\n", ir.GetMessage())
}))
// Install libraries in bundled dir (should now fail)
{
instCl, err := grpcInst.LibraryInstall(context.Background(), "Arduino_BuiltIn", "", false, false, true)
require.NoError(t, err)
for {
msg, err := instCl.Recv()
if err == io.EOF {
require.FailNow(t, "LibraryInstall is supposed to fail because builtin libraries directory is not set")
}
if err != nil {
fmt.Println("LIB INSTALL ERROR:", err)
break
}
fmt.Printf("LIB INSTALL> %+v\n", msg)
}
}
}
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