Skip to content

[breaking] Remove auto detection of Arduino IDE built-in libraries and tools / Allow gRPC install of built-in libraries #1817

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Sep 2, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added integration test for library install in bundled directory
  • Loading branch information
cmaglie committed Sep 1, 2022
commit bc9c8cbebf598f42ba08bb8d35004ed551ea09b6
1 change: 1 addition & 0 deletions arduino/libraries/librariesmanager/librariesmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ func NewLibraryManager(indexDir *paths.Path, downloadsDir *paths.Path) *Librarie
// LoadIndex reads a library_index.json from a file and returns
// the corresponding Index structure.
func (lm *LibrariesManager) LoadIndex() error {
logrus.WithField("index", lm.IndexFile).Info("Loading libraries index file")
index, err := librariesindex.LoadIndex(lm.IndexFile)
if err != nil {
lm.Index = librariesindex.EmptyIndex
Expand Down
74 changes: 62 additions & 12 deletions internal/integrationtest/arduino-cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package integrationtest
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"os"
Expand All @@ -28,6 +29,7 @@ import (

"github.com/arduino/arduino-cli/executils"
"github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
"github.com/arduino/arduino-cli/rpc/cc/arduino/cli/settings/v1"
"github.com/arduino/go-paths-helper"
"github.com/fatih/color"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -61,17 +63,18 @@ func CreateArduinoCLIWithEnvironment(t *testing.T) (*testsuite.Environment, *Ard

// ArduinoCLI is an Arduino CLI client.
type ArduinoCLI struct {
path *paths.Path
t *require.Assertions
proc *executils.Process
cliEnvVars []string
cliConfigPath *paths.Path
stagingDir *paths.Path
dataDir *paths.Path
sketchbookDir *paths.Path
daemonAddr string
daemonConn *grpc.ClientConn
daemonClient commands.ArduinoCoreServiceClient
path *paths.Path
t *require.Assertions
proc *executils.Process
cliEnvVars []string
cliConfigPath *paths.Path
stagingDir *paths.Path
dataDir *paths.Path
sketchbookDir *paths.Path
daemonAddr string
daemonConn *grpc.ClientConn
daemonClient commands.ArduinoCoreServiceClient
daemonSettingsClient settings.SettingsServiceClient
}

// ArduinoCLIConfig is the configuration of the ArduinoCLI client
Expand Down Expand Up @@ -196,7 +199,7 @@ func (cli *ArduinoCLI) StartDaemon(verbose bool) string {
cli.t.NoError(err)
cli.daemonConn = conn
cli.daemonClient = commands.NewArduinoCoreServiceClient(conn)

cli.daemonSettingsClient = settings.NewSettingsServiceClient(conn)
return cli.daemonAddr
}

Expand Down Expand Up @@ -226,6 +229,17 @@ func (cli *ArduinoCLI) Create() *ArduinoCLIInstance {
}
}

// SetValue calls the "SetValue" gRPC method.
func (cli *ArduinoCLI) SetValue(key, jsonData string) error {
req := &settings.SetValueRequest{
Key: key,
JsonData: jsonData,
}
logCallf(">>> SetValue(%+v)\n", req)
_, err := cli.daemonSettingsClient.SetValue(context.Background(), req)
return err
}

// Init calls the "Init" gRPC method.
func (inst *ArduinoCLIInstance) Init(profile string, sketchPath string, respCB func(*commands.InitResponse)) error {
initReq := &commands.InitRequest{
Expand Down Expand Up @@ -302,3 +316,39 @@ func (inst *ArduinoCLIInstance) Compile(ctx context.Context, fqbn, sketchPath st
logCallf(">>> Compile(%v %v)\n", fqbn, sketchPath)
return compileCl, err
}

// LibraryList calls the "LibraryList" gRPC method.
func (inst *ArduinoCLIInstance) LibraryList(ctx context.Context, name, fqbn string, all, updatable bool) (*commands.LibraryListResponse, error) {
req := &commands.LibraryListRequest{
Instance: inst.instance,
Name: name,
Fqbn: fqbn,
All: all,
Updatable: updatable,
}
logCallf(">>> LibraryList(%v) -> ", req)
resp, err := inst.cli.daemonClient.LibraryList(ctx, req)
logCallf("err=%v\n", err)
r, _ := json.MarshalIndent(resp, " ", " ")
logCallf("<<< LibraryList resp: %s\n", string(r))
return resp, err
}

// LibraryInstall calls the "LibraryInstall" gRPC method.
func (inst *ArduinoCLIInstance) LibraryInstall(ctx context.Context, name, version string, noDeps, noOverwrite, installAsBundled bool) (commands.ArduinoCoreService_LibraryInstallClient, error) {
installLocation := commands.LibraryInstallLocation_LIBRARY_INSTALL_LOCATION_USER
if installAsBundled {
installLocation = commands.LibraryInstallLocation_LIBRARY_INSTALL_LOCATION_BUILTIN
}
req := &commands.LibraryInstallRequest{
Instance: inst.instance,
Name: name,
Version: version,
NoDeps: noDeps,
NoOverwrite: noOverwrite,
InstallLocation: installLocation,
}
installCl, err := inst.cli.daemonClient.LibraryInstall(ctx, req)
logCallf(">>> LibraryInstall(%+v)\n", req)
return installCl, err
}
126 changes: 126 additions & 0 deletions internal/integrationtest/daemon/daemon_lib_install_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// 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 [email protected].

package daemon_test

import (
"context"
"encoding/json"
"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 (should 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)
}
}

// Set builtin libraries dir
builtinLibsDir := cli.DataDir().Join("libraries")
jsonBuiltinLibsDir, err := json.Marshal(builtinLibsDir)
require.NoError(t, err)
err = cli.SetValue("directories.builtin.libraries", string(jsonBuiltinLibsDir))
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
{
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
{
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_USER)
require.Equal(t, libsAndLocation["SD"], commands.LibraryLocation_LIBRARY_LOCATION_BUILTIN)
require.Equal(t, libsAndLocation["Firmata"], commands.LibraryLocation_LIBRARY_LOCATION_BUILTIN)
}
}