Skip to content

Commit 8232687

Browse files
committed
Added integration test
1 parent ac6ec6d commit 8232687

File tree

4 files changed

+219
-0
lines changed

4 files changed

+219
-0
lines changed

Diff for: internal/integrationtest/arduino-cli.go

+52
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,42 @@ func (cli *ArduinoCLI) InstallMockedSerialMonitor(t *testing.T) {
286286
}
287287
}
288288

289+
// InstallMockedAvrdude will replace the already installed avrdude with a mocked one.
290+
func (cli *ArduinoCLI) InstallMockedAvrdude(t *testing.T) {
291+
fmt.Println(color.BlueString("<<< Install mocked avrdude"))
292+
293+
// Build mocked serial-discovery
294+
mockDir := FindRepositoryRootPath(t).Join("internal", "mock_avrdude")
295+
gobuild, err := paths.NewProcess(nil, "go", "build")
296+
require.NoError(t, err)
297+
gobuild.SetDirFromPath(mockDir)
298+
require.NoError(t, gobuild.Run(), "Building mocked avrdude")
299+
ext := ""
300+
if runtime.GOOS == "windows" {
301+
ext = ".exe"
302+
}
303+
mockBin := mockDir.Join("mock_avrdude" + ext)
304+
require.True(t, mockBin.Exist())
305+
fmt.Println(color.HiBlackString(" Build of mocked avrdude succeeded."))
306+
307+
// Install it replacing the current avrdudes
308+
dataDir := cli.DataDir()
309+
require.NotNil(t, dataDir, "data dir missing")
310+
311+
avrdudes, err := dataDir.Join("packages", "arduino", "tools", "avrdude").ReadDirRecursiveFiltered(
312+
nil, paths.AndFilter(
313+
paths.FilterNames("avrdude"+ext),
314+
paths.FilterOutDirectories(),
315+
),
316+
)
317+
require.NoError(t, err, "scanning data dir for avrdude(s)")
318+
require.NotEmpty(t, avrdudes, "no avrdude(s) found in data dir")
319+
for _, avrdude := range avrdudes {
320+
require.NoError(t, mockBin.CopyTo(avrdude), "installing mocked avrdude to %s", avrdude)
321+
fmt.Println(color.HiBlackString(" Mocked avrdude installed in " + avrdude.String()))
322+
}
323+
}
324+
289325
// RunWithCustomEnv executes the given arduino-cli command with the given custom env and returns the output.
290326
func (cli *ArduinoCLI) RunWithCustomEnv(env map[string]string, args ...string) ([]byte, []byte, error) {
291327
var stdoutBuf, stderrBuf bytes.Buffer
@@ -642,3 +678,19 @@ func (inst *ArduinoCLIInstance) Monitor(ctx context.Context, port *commands.Port
642678
})
643679
return monitorClient, err
644680
}
681+
682+
// Upload calls the "Upload" gRPC method.
683+
func (inst *ArduinoCLIInstance) Upload(ctx context.Context, fqbn, sketchPath, port, protocol string) (commands.ArduinoCoreService_UploadClient, error) {
684+
uploadCl, err := inst.cli.daemonClient.Upload(ctx, &commands.UploadRequest{
685+
Instance: inst.instance,
686+
Fqbn: fqbn,
687+
SketchPath: sketchPath,
688+
Verbose: true,
689+
Port: &commands.Port{
690+
Address: port,
691+
Protocol: protocol,
692+
},
693+
})
694+
logCallf(">>> Upload(%v %v port/protocol=%s/%s)\n", fqbn, sketchPath, port, protocol)
695+
return uploadCl, err
696+
}

Diff for: internal/integrationtest/daemon/upload_test.go

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2024 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-cli.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to [email protected].
15+
16+
package daemon_test
17+
18+
import (
19+
"context"
20+
"errors"
21+
"fmt"
22+
"io"
23+
"os"
24+
"strings"
25+
"testing"
26+
"time"
27+
28+
"github.com/arduino/arduino-cli/internal/integrationtest"
29+
"github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
30+
"github.com/arduino/go-paths-helper"
31+
"github.com/stretchr/testify/require"
32+
)
33+
34+
func TestUploadCancelation(t *testing.T) {
35+
env, cli := integrationtest.CreateEnvForDaemon(t)
36+
defer env.CleanUp()
37+
38+
grpcInst := cli.Create()
39+
require.NoError(t, grpcInst.Init("", "", func(ir *commands.InitResponse) {
40+
fmt.Printf("INIT> %v\n", ir.GetMessage())
41+
}))
42+
43+
plInst, err := grpcInst.PlatformInstall(context.Background(), "arduino", "avr", "1.8.6", true)
44+
require.NoError(t, err)
45+
for {
46+
msg, err := plInst.Recv()
47+
if errors.Is(err, io.EOF) {
48+
break
49+
}
50+
require.NoError(t, err)
51+
fmt.Printf("INSTALL> %v\n", msg)
52+
}
53+
54+
// Mock avrdude
55+
cli.InstallMockedAvrdude(t)
56+
57+
// Re-init instance to update changes
58+
require.NoError(t, grpcInst.Init("", "", func(ir *commands.InitResponse) {
59+
fmt.Printf("INIT> %v\n", ir.GetMessage())
60+
}))
61+
62+
// Build sketch for upload
63+
sk := paths.New("testdata", "bare_minimum")
64+
compile, err := grpcInst.Compile(context.Background(), "arduino:avr:uno", sk.String(), "")
65+
require.NoError(t, err)
66+
for {
67+
msg, err := compile.Recv()
68+
if errors.Is(err, io.EOF) {
69+
break
70+
}
71+
if err != nil {
72+
fmt.Println("COMPILE ERROR>", err)
73+
require.FailNow(t, "Expected successful compile", "compilation failed")
74+
break
75+
}
76+
if msg.GetOutStream() != nil {
77+
fmt.Printf("COMPILE OUT> %v\n", string(msg.GetOutStream()))
78+
}
79+
if msg.GetErrStream() != nil {
80+
fmt.Printf("COMPILE ERR> %v\n", string(msg.GetErrStream()))
81+
}
82+
}
83+
84+
// Try upload and interrupt the call after 1 sec
85+
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
86+
upload, err := grpcInst.Upload(ctx, "arduino:avr:uno", sk.String(), "/dev/ttyACM0", "serial")
87+
require.NoError(t, err)
88+
checkFile := ""
89+
for {
90+
msg, err := upload.Recv()
91+
if errors.Is(err, io.EOF) {
92+
require.FailNow(t, "Expected interrupted upload", "upload succeeded")
93+
break
94+
}
95+
if err != nil {
96+
fmt.Println("UPLOAD ERROR>", err)
97+
break
98+
}
99+
if out := string(msg.GetOutStream()); out != "" {
100+
fmt.Printf("UPLOAD OUT> %v\n", out)
101+
if strings.HasPrefix(out, "CHECKFILE: ") {
102+
checkFile = strings.TrimSpace(out[11:])
103+
}
104+
}
105+
if msg.GetErrStream() != nil {
106+
fmt.Printf("UPLOAD ERR> %v\n", string(msg.GetErrStream()))
107+
}
108+
}
109+
cancel()
110+
111+
// Wait 5 seconds.
112+
// If the mocked avrdude is not killed it will create a checkfile and it will remove it after 5 seconds.
113+
time.Sleep(5 * time.Second)
114+
115+
// Test if the checkfile is still there (if the file is there it means that mocked avrdude
116+
// has been correctly killed).
117+
require.NotEmpty(t, checkFile)
118+
require.FileExists(t, checkFile)
119+
require.NoError(t, os.Remove(checkFile))
120+
}

Diff for: internal/mock_avrdude/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mock_avrdude

Diff for: internal/mock_avrdude/main.go

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// This file is part arduino-cli.
3+
//
4+
// Copyright 2023 ARDUINO SA (http://www.arduino.cc/)
5+
//
6+
// This software is released under the GNU General Public License version 3,
7+
// which covers the main part of arduino-cli.
8+
// The terms of this license can be found at:
9+
// https://www.gnu.org/licenses/gpl-3.0.en.html
10+
//
11+
// You can be released from the requirements of the above licenses by purchasing
12+
// a commercial license. Buying such a license is mandatory if you want to modify or
13+
// otherwise use the software for commercial activities involving the Arduino
14+
// software without disclosing the source code of your own applications. To purchase
15+
// a commercial license, send an email to [email protected].
16+
//
17+
18+
package main
19+
20+
import (
21+
"fmt"
22+
"os"
23+
"time"
24+
25+
"github.com/arduino/go-paths-helper"
26+
)
27+
28+
func main() {
29+
tmp, err := paths.MkTempFile(nil, "test")
30+
if err != nil {
31+
fmt.Println(err)
32+
os.Exit(1)
33+
}
34+
tmp.Close()
35+
tmpPath := paths.New(tmp.Name())
36+
37+
fmt.Println("CHECKFILE:", tmpPath)
38+
39+
// Just sit here for 5 seconds
40+
time.Sleep(5 * time.Second)
41+
42+
// Remove the check file at the end
43+
tmpPath.Remove()
44+
45+
fmt.Println("COMPLETED")
46+
}

0 commit comments

Comments
 (0)