Skip to content

Commit 9003eb8

Browse files
Massimiliano Pippimasci
authored andcommitted
add upload tests, remove mocked ones
1 parent de29adb commit 9003eb8

File tree

2 files changed

+46
-255
lines changed

2 files changed

+46
-255
lines changed

cli/cli_test.go

Lines changed: 0 additions & 255 deletions
Original file line numberDiff line numberDiff line change
@@ -19,108 +19,15 @@
1919
package cli
2020

2121
import (
22-
"encoding/json"
23-
"flag"
2422
"fmt"
2523
"io/ioutil"
2624
"os"
2725
"path/filepath"
28-
"runtime"
2926
"testing"
3027

31-
"github.com/spf13/viper"
32-
33-
"github.com/arduino/arduino-cli/cli/errorcodes"
34-
"github.com/arduino/arduino-cli/cli/feedback"
35-
36-
"bou.ke/monkey"
3728
"github.com/stretchr/testify/require"
38-
semver "go.bug.st/relaxed-semver"
39-
)
40-
41-
var (
42-
// Redirecting stdOut so we can analyze output line by
43-
// line and check with what we want.
44-
stdOut = os.Stdout
45-
stdErr = os.Stderr
46-
47-
currDownloadDir string
48-
currDataDir string
49-
currUserDir string
5029
)
5130

52-
type outputRedirect struct {
53-
tempFile *os.File
54-
}
55-
56-
func (grabber *outputRedirect) Open() {
57-
tempFile, err := ioutil.TempFile(os.TempDir(), "test")
58-
if err != nil {
59-
panic("Opening temp output file")
60-
}
61-
os.Stdout = tempFile
62-
os.Stderr = tempFile
63-
grabber.tempFile = tempFile
64-
}
65-
66-
func (grabber *outputRedirect) GetOutput() []byte {
67-
_, err := grabber.tempFile.Seek(0, 0)
68-
if err != nil {
69-
panic("Rewinding temp output file")
70-
}
71-
72-
output, err := ioutil.ReadAll(grabber.tempFile)
73-
if err != nil {
74-
panic("Reading temp output file")
75-
}
76-
77-
return output
78-
}
79-
80-
func (grabber *outputRedirect) Close() {
81-
grabber.tempFile.Close()
82-
err := os.Remove(grabber.tempFile.Name())
83-
if err != nil {
84-
panic("Removing temp output file")
85-
}
86-
os.Stdout = stdOut
87-
os.Stderr = stdErr
88-
}
89-
90-
func TestMain(m *testing.M) {
91-
// all these tests perform actual operations, don't run in short mode
92-
flag.Parse()
93-
if testing.Short() {
94-
fmt.Println("skip integration tests")
95-
os.Exit(0)
96-
}
97-
98-
// SetUp
99-
currDataDir = tmpDirOrDie()
100-
os.MkdirAll(filepath.Join(currDataDir, "packages"), 0755)
101-
os.Setenv("ARDUINO_DIRECTORIES_DATA", currDataDir)
102-
currDownloadDir = tmpDirOrDie()
103-
os.Setenv("ARDUINO_DIRECTORIES_DOWNLOADS", currDownloadDir)
104-
currUserDir = filepath.Join("testdata", "custom_hardware")
105-
// use ARDUINO_SKETCHBOOK_DIR instead of ARDUINO_DIRECTORIES_USER to
106-
// ensure the backward compat code is working
107-
os.Setenv("ARDUINO_SKETCHBOOK_DIR", currUserDir)
108-
109-
// Run
110-
res := m.Run()
111-
112-
// TearDown
113-
os.RemoveAll(currDataDir)
114-
os.Unsetenv("ARDUINO_DIRECTORIES_DATA")
115-
currDataDir = ""
116-
os.RemoveAll(currDownloadDir)
117-
os.Unsetenv("ARDUINO_DIRECTORIES_DOWNLOADS")
118-
currDownloadDir = ""
119-
os.Unsetenv("ARDUINO_SKETCHBOOK_DIR")
120-
121-
os.Exit(res)
122-
}
123-
12431
func tmpDirOrDie() string {
12532
dir, err := ioutil.TempDir(os.TempDir(), "cli_test")
12633
if err != nil {
@@ -129,168 +36,6 @@ func tmpDirOrDie() string {
12936
return dir
13037
}
13138

132-
// executeWithArgs executes the Cobra Command with the given arguments
133-
// and intercepts any errors (even `os.Exit()` ones), returning the exit code
134-
func executeWithArgs(args ...string) (int, []byte) {
135-
var output []byte
136-
var exitCode int
137-
fmt.Printf("RUNNING: %s\n", args)
138-
viper.Reset()
139-
140-
// This closure is here because we won't that the defer are executed after the end of the "executeWithArgs" method
141-
func() {
142-
redirect := &outputRedirect{}
143-
redirect.Open()
144-
// re-init feedback so it'll write to our grabber
145-
feedback.SetDefaultFeedback(feedback.New(os.Stdout, os.Stdout, feedback.Text))
146-
defer func() {
147-
output = redirect.GetOutput()
148-
redirect.Close()
149-
fmt.Print(string(output))
150-
fmt.Println()
151-
}()
152-
153-
// Mock the os.Exit function, so that we can use the
154-
// error result for the test and prevent the test from exiting
155-
fakeExitFired := false
156-
fakeExit := func(code int) {
157-
exitCode = code
158-
fakeExitFired = true
159-
160-
// use panic to exit and jump to deferred recover
161-
panic(fmt.Errorf("os.Exit(%d)", code))
162-
}
163-
patch := monkey.Patch(os.Exit, fakeExit)
164-
defer patch.Unpatch()
165-
defer func() {
166-
if fakeExitFired {
167-
recover()
168-
}
169-
}()
170-
171-
// Execute the CLI command, start fresh every time
172-
ArduinoCli.ResetCommands()
173-
ArduinoCli.ResetFlags()
174-
createCliCommandTree(ArduinoCli)
175-
ArduinoCli.SetArgs(args)
176-
if err := ArduinoCli.Execute(); err != nil {
177-
exitCode = errorcodes.ErrGeneric
178-
}
179-
}()
180-
181-
return exitCode, output
182-
}
183-
184-
func detectLatestAVRCore(t *testing.T) string {
185-
jsonFile := filepath.Join(currDataDir, "package_index.json")
186-
type index struct {
187-
Packages []struct {
188-
Name string
189-
Platforms []struct {
190-
Architecture string
191-
Version string
192-
}
193-
}
194-
}
195-
var jsonIndex index
196-
jsonData, err := ioutil.ReadFile(jsonFile)
197-
require.NoError(t, err, "reading package_index.json")
198-
err = json.Unmarshal(jsonData, &jsonIndex)
199-
require.NoError(t, err, "parsing package_index.json")
200-
latest := semver.MustParse("0.0.1")
201-
for _, p := range jsonIndex.Packages {
202-
if p.Name == "arduino" {
203-
for _, pl := range p.Platforms {
204-
ver, err := semver.Parse(pl.Version)
205-
require.NoError(t, err, "version parsing")
206-
if pl.Architecture == "avr" && ver.GreaterThan(latest) {
207-
latest = ver
208-
}
209-
}
210-
break
211-
}
212-
}
213-
require.NotEmpty(t, latest, "latest avr core version")
214-
return latest.String()
215-
}
216-
217-
// END -- Utility functions
218-
219-
func TestUploadIntegration(t *testing.T) {
220-
if runtime.GOOS == "windows" {
221-
t.Skip("This test runs only on Linux")
222-
}
223-
224-
exitCode, _ := executeWithArgs("core", "update-index")
225-
require.Zero(t, exitCode)
226-
227-
exitCode, _ = executeWithArgs("core", "install", "arduino:avr")
228-
require.Zero(t, exitCode)
229-
230-
// -i flag
231-
exitCode, d := executeWithArgs("upload", "-i", filepath.Join(currUserDir, "test.hex"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0")
232-
require.Zero(t, exitCode)
233-
require.Contains(t, string(d), "QUIET")
234-
require.Contains(t, string(d), "NOVERIFY")
235-
require.Contains(t, string(d), "testdata/custom_hardware/test.hex")
236-
237-
// -i flag with implicit extension
238-
exitCode, d = executeWithArgs("upload", "-i", filepath.Join(currUserDir, "test"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0")
239-
require.Zero(t, exitCode)
240-
require.Contains(t, string(d), "QUIET")
241-
require.Contains(t, string(d), "NOVERIFY")
242-
require.Contains(t, string(d), "testdata/custom_hardware/test.hex")
243-
244-
// -i with absolute path
245-
fullPath, err := filepath.Abs(filepath.Join(currUserDir, "test.hex"))
246-
require.NoError(t, err)
247-
exitCode, d = executeWithArgs("upload", "-i", fullPath, "-b", "test:avr:testboard", "-p", "/dev/ttyACM0")
248-
require.Zero(t, exitCode)
249-
require.Contains(t, string(d), "QUIET")
250-
require.Contains(t, string(d), "NOVERIFY")
251-
require.Contains(t, string(d), "testdata/custom_hardware/test.hex")
252-
253-
// -v verbose
254-
exitCode, d = executeWithArgs("upload", "-v", "-t", "-i", filepath.Join(currUserDir, "test.hex"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0")
255-
require.Zero(t, exitCode)
256-
require.Contains(t, string(d), "VERBOSE")
257-
require.Contains(t, string(d), "VERIFY")
258-
require.Contains(t, string(d), "testdata/custom_hardware/test.hex")
259-
260-
// -t verify
261-
exitCode, d = executeWithArgs("upload", "-i", filepath.Join(currUserDir, "test.hex"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0")
262-
require.Zero(t, exitCode)
263-
require.Contains(t, string(d), "QUIET")
264-
require.Contains(t, string(d), "NOVERIFY")
265-
require.Contains(t, string(d), "testdata/custom_hardware/test.hex")
266-
267-
// -v -t verbose verify
268-
exitCode, d = executeWithArgs("upload", "-v", "-t", "-i", filepath.Join(currUserDir, "test.hex"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0")
269-
require.Zero(t, exitCode)
270-
require.Contains(t, string(d), "VERBOSE")
271-
require.Contains(t, string(d), "VERIFY")
272-
require.Contains(t, string(d), "testdata/custom_hardware/test.hex")
273-
274-
// non-existent file
275-
exitCode, _ = executeWithArgs("upload", "-i", filepath.Join(currUserDir, "test123.hex"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0")
276-
require.NotZero(t, exitCode)
277-
278-
// sketch
279-
exitCode, d = executeWithArgs("upload", filepath.Join(currUserDir, "TestSketch"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0")
280-
require.Zero(t, exitCode)
281-
require.Contains(t, string(d), "QUIET")
282-
require.Contains(t, string(d), "NOVERIFY")
283-
require.Contains(t, string(d), "testdata/custom_hardware/TestSketch/TestSketch.test.avr.testboard.hex")
284-
285-
// sketch without build
286-
exitCode, _ = executeWithArgs("upload", filepath.Join(currUserDir, "TestSketch2"), "-b", "test:avr:testboard", "-p", "/dev/ttyACM0")
287-
require.NotZero(t, exitCode)
288-
289-
// platform without 'recipe.output.tmp_file' property
290-
exitCode, _ = executeWithArgs("upload", "-i", filepath.Join(currUserDir, "test.hex"), "-b", "test2:avr:testboard", "-p", "/dev/ttyACM0")
291-
require.NotZero(t, exitCode)
292-
}
293-
29439
func TestSearchConfigTreeNotFound(t *testing.T) {
29540
tmp := tmpDirOrDie()
29641
require.Empty(t, searchConfigTree(tmp))

test/test_upload.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# This file is part of arduino-cli.
2+
#
3+
# Copyright 2020 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 modify or
12+
# otherwise use the software for commercial activities involving the Arduino
13+
# software without disclosing the source code of your own applications. To purchase
14+
# a commercial license, send an email to [email protected].
15+
import os
16+
17+
import pytest
18+
19+
from .common import running_on_ci
20+
21+
# Skip this module when running in CI environments
22+
pytestmark = pytest.mark.skipif(running_on_ci(), reason="VMs have no serial ports")
23+
24+
25+
def test_upload(run_command, data_dir, detected_boards):
26+
# Init the environment explicitly
27+
assert run_command("core update-index")
28+
29+
for board in detected_boards:
30+
# Download core
31+
assert run_command("core install {}".format(board.core))
32+
# Create a sketch
33+
sketch_path = os.path.join(data_dir, "foo")
34+
assert run_command("sketch new {}".format(sketch_path))
35+
# Build sketch
36+
assert run_command(
37+
"compile -b {fqbn} {sketch_path}".format(
38+
fqbn=board.fqbn, sketch_path=sketch_path
39+
)
40+
)
41+
# Upload
42+
assert run_command(
43+
"upload -b {fqbn} -p {port} {sketch_path}".format(
44+
sketch_path=sketch_path, fqbn=board.fqbn, port=board.address
45+
)
46+
)

0 commit comments

Comments
 (0)