Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 54c5590

Browse files
committedOct 25, 2021
Different approach
1 parent 8aa92a1 commit 54c5590

6 files changed

+1312
-1280
lines changed
 
Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,11 @@
1-
import itertools
21
from pathlib import Path
32
import json
4-
import re
5-
6-
7-
def get_test_functions(tests_path):
8-
test_functions_regex = re.compile(r"^def (test_[a-zA-Z_]*)\(")
9-
test_functions = []
10-
for test_file in tests_path.glob("test_*.py"):
11-
12-
for line in test_file.read_text().splitlines():
13-
if match := test_functions_regex.match(line):
14-
test_functions.append(f"{test_file}::{match.group(1)}")
15-
return test_functions
163

174

185
if __name__ == "__main__":
196
import sys
207

218
tests_path = sys.argv[1]
22-
test_functions = get_test_functions(Path(tests_path))
23-
24-
# We split the test functions in 80 different lists because the maximum jobs
25-
# that can be run on Github Workflows generated by the matrix syntax is 256.
26-
# Since we run all tests on Linux, Windows and Mac OS the number of this list
27-
# must be multiplied by 3. 80 * 3 == 240 so we're in the green.
28-
TESTS_SPLIT = 80
29-
cycle = itertools.cycle(range(TESTS_SPLIT))
30-
groups = [[] for _ in range(TESTS_SPLIT)]
31-
for f in test_functions:
32-
index = next(cycle)
33-
groups[index].append(f)
349

35-
print(json.dumps([" ".join(g) for g in groups]))
10+
test_files = [str(f) for f in Path(tests_path).glob("test_*.py")]
11+
print(json.dumps(test_files))

‎test/test_compile.py

Lines changed: 0 additions & 1254 deletions
This file was deleted.

‎test/test_compile_part_1.py

Lines changed: 403 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,403 @@
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 license@arduino.cc.
15+
16+
import os
17+
import platform
18+
import tempfile
19+
import hashlib
20+
from pathlib import Path
21+
import simplejson as json
22+
23+
import pytest
24+
25+
from .common import running_on_ci
26+
27+
28+
def test_compile_without_fqbn(run_command):
29+
# Init the environment explicitly
30+
run_command(["core", "update-index"])
31+
32+
# Install Arduino AVR Boards
33+
run_command(["core", "install", "arduino:avr@1.8.3"])
34+
35+
# Build sketch without FQBN
36+
result = run_command(["compile"])
37+
assert result.failed
38+
39+
40+
def test_compile_with_simple_sketch(run_command, data_dir, working_dir):
41+
# Init the environment explicitly
42+
run_command(["core", "update-index"])
43+
44+
# Download latest AVR
45+
run_command(["core", "install", "arduino:avr"])
46+
47+
sketch_name = "CompileIntegrationTest"
48+
sketch_path = Path(data_dir, sketch_name)
49+
fqbn = "arduino:avr:uno"
50+
51+
# Create a test sketch
52+
result = run_command(["sketch", "new", sketch_path])
53+
assert result.ok
54+
assert f"Sketch created in: {sketch_path}" in result.stdout
55+
56+
# Build sketch for arduino:avr:uno
57+
result = run_command(["compile", "-b", fqbn, sketch_path])
58+
assert result.ok
59+
60+
# Build sketch for arduino:avr:uno with json output
61+
result = run_command(["compile", "-b", fqbn, sketch_path, "--format", "json"])
62+
assert result.ok
63+
# check is a valid json and contains requested data
64+
compile_output = json.loads(result.stdout)
65+
assert compile_output["compiler_out"] != ""
66+
assert compile_output["compiler_err"] == ""
67+
68+
# Verifies expected binaries have been built
69+
sketch_path_md5 = hashlib.md5(bytes(sketch_path)).hexdigest().upper()
70+
build_dir = Path(tempfile.gettempdir(), f"arduino-sketch-{sketch_path_md5}")
71+
assert (build_dir / f"{sketch_name}.ino.eep").exists()
72+
assert (build_dir / f"{sketch_name}.ino.elf").exists()
73+
assert (build_dir / f"{sketch_name}.ino.hex").exists()
74+
assert (build_dir / f"{sketch_name}.ino.with_bootloader.bin").exists()
75+
assert (build_dir / f"{sketch_name}.ino.with_bootloader.hex").exists()
76+
77+
# Verifies binaries are not exported by default to Sketch folder
78+
sketch_build_dir = Path(sketch_path, "build", fqbn.replace(":", "."))
79+
assert not (sketch_build_dir / f"{sketch_name}.ino.eep").exists()
80+
assert not (sketch_build_dir / f"{sketch_name}.ino.elf").exists()
81+
assert not (sketch_build_dir / f"{sketch_name}.ino.hex").exists()
82+
assert not (sketch_build_dir / f"{sketch_name}.ino.with_bootloader.bin").exists()
83+
assert not (sketch_build_dir / f"{sketch_name}.ino.with_bootloader.hex").exists()
84+
85+
86+
@pytest.mark.skipif(
87+
running_on_ci() and platform.system() == "Windows",
88+
reason="Test disabled on Github Actions Win VM until tmpdir inconsistent behavior bug is fixed",
89+
)
90+
def test_output_flag_default_path(run_command, data_dir, working_dir):
91+
# Init the environment explicitly
92+
run_command(["core", "update-index"])
93+
94+
# Install Arduino AVR Boards
95+
run_command(["core", "install", "arduino:avr@1.8.3"])
96+
97+
# Create a test sketch
98+
sketch_path = os.path.join(data_dir, "test_output_flag_default_path")
99+
fqbn = "arduino:avr:uno"
100+
result = run_command(["sketch", "new", sketch_path])
101+
assert result.ok
102+
103+
# Test the --output-dir flag defaulting to current working dir
104+
result = run_command(["compile", "-b", fqbn, sketch_path, "--output-dir", "test"])
105+
assert result.ok
106+
target = os.path.join(working_dir, "test")
107+
assert os.path.exists(target) and os.path.isdir(target)
108+
109+
110+
def test_compile_with_sketch_with_symlink_selfloop(run_command, data_dir):
111+
# Init the environment explicitly
112+
run_command(["core", "update-index"])
113+
114+
# Install Arduino AVR Boards
115+
run_command(["core", "install", "arduino:avr@1.8.3"])
116+
117+
sketch_name = "CompileIntegrationTestSymlinkSelfLoop"
118+
sketch_path = os.path.join(data_dir, sketch_name)
119+
fqbn = "arduino:avr:uno"
120+
121+
# Create a test sketch
122+
result = run_command(["sketch", "new", sketch_path])
123+
assert result.ok
124+
assert "Sketch created in: {}".format(sketch_path) in result.stdout
125+
126+
# create a symlink that loops on himself
127+
loop_file_path = os.path.join(sketch_path, "loop")
128+
os.symlink(loop_file_path, loop_file_path)
129+
130+
# Build sketch for arduino:avr:uno
131+
result = run_command(["compile", "-b", fqbn, sketch_path])
132+
# The assertion is a bit relaxed in this case because win behaves differently from macOs and linux
133+
# returning a different error detailed message
134+
assert "Error during build: Can't open sketch:" in result.stderr
135+
assert not result.ok
136+
137+
sketch_name = "CompileIntegrationTestSymlinkDirLoop"
138+
sketch_path = os.path.join(data_dir, sketch_name)
139+
fqbn = "arduino:avr:uno"
140+
141+
# Create a test sketch
142+
result = run_command(["sketch", "new", sketch_path])
143+
assert result.ok
144+
assert "Sketch created in: {}".format(sketch_path) in result.stdout
145+
146+
# create a symlink that loops on the upper level
147+
loop_dir_path = os.path.join(sketch_path, "loop_dir")
148+
os.mkdir(loop_dir_path)
149+
loop_dir_symlink_path = os.path.join(loop_dir_path, "loop_dir_symlink")
150+
os.symlink(loop_dir_path, loop_dir_symlink_path)
151+
152+
# Build sketch for arduino:avr:uno
153+
result = run_command(["compile", "-b", fqbn, sketch_path])
154+
# The assertion is a bit relaxed in this case because win behaves differently from macOs and linux
155+
# returning a different error detailed message
156+
assert "Error during build: Can't open sketch:" in result.stderr
157+
assert not result.ok
158+
159+
160+
def test_compile_blacklisted_sketchname(run_command, data_dir):
161+
"""
162+
Compile should ignore folders named `RCS`, `.git` and the likes, but
163+
it should be ok for a sketch to be named like RCS.ino
164+
"""
165+
# Init the environment explicitly
166+
run_command(["core", "update-index"])
167+
168+
# Install Arduino AVR Boards
169+
run_command(["core", "install", "arduino:avr@1.8.3"])
170+
171+
sketch_name = "RCS"
172+
sketch_path = os.path.join(data_dir, sketch_name)
173+
fqbn = "arduino:avr:uno"
174+
175+
# Create a test sketch
176+
result = run_command(["sketch", "new", sketch_path])
177+
assert result.ok
178+
assert "Sketch created in: {}".format(sketch_path) in result.stdout
179+
180+
# Build sketch for arduino:avr:uno
181+
result = run_command(["compile", "-b", fqbn, sketch_path])
182+
assert result.ok
183+
184+
185+
def test_compile_without_precompiled_libraries(run_command, data_dir):
186+
# Init the environment explicitly
187+
url = "https://adafruit.github.io/arduino-board-index/package_adafruit_index.json"
188+
assert run_command(["core", "update-index", f"--additional-urls={url}"])
189+
assert run_command(["core", "install", "arduino:mbed@1.3.1", f"--additional-urls={url}"])
190+
191+
# Precompiled version of Arduino_TensorflowLite
192+
assert run_command(["lib", "install", "Arduino_LSM9DS1"])
193+
assert run_command(["lib", "install", "Arduino_TensorflowLite@2.1.1-ALPHA-precompiled"])
194+
195+
sketch_path = Path(data_dir, "libraries", "Arduino_TensorFlowLite", "examples", "hello_world")
196+
assert run_command(["compile", "-b", "arduino:mbed:nano33ble", sketch_path])
197+
198+
assert run_command(["core", "install", "arduino:samd@1.8.7", f"--additional-urls={url}"])
199+
assert run_command(["core", "install", "adafruit:samd@1.6.4", f"--additional-urls={url}"])
200+
# should work on adafruit too after https://github.com/arduino/arduino-cli/pull/1134
201+
assert run_command(["compile", "-b", "adafruit:samd:adafruit_feather_m4", sketch_path])
202+
203+
# Non-precompiled version of Arduino_TensorflowLite
204+
assert run_command(["lib", "install", "Arduino_TensorflowLite@2.1.0-ALPHA"])
205+
assert run_command(["compile", "-b", "arduino:mbed:nano33ble", sketch_path])
206+
assert run_command(["compile", "-b", "adafruit:samd:adafruit_feather_m4", sketch_path])
207+
208+
# Bosch sensor library
209+
assert run_command(["lib", "install", "BSEC Software Library@1.5.1474"])
210+
sketch_path = Path(data_dir, "libraries", "BSEC_Software_Library", "examples", "basic")
211+
assert run_command(["compile", "-b", "arduino:samd:mkr1000", sketch_path])
212+
assert run_command(["compile", "-b", "arduino:mbed:nano33ble", sketch_path])
213+
214+
# USBBlaster library
215+
assert run_command(["lib", "install", "USBBlaster@1.0.0"])
216+
sketch_path = Path(data_dir, "libraries", "USBBlaster", "examples", "USB_Blaster")
217+
assert run_command(["compile", "-b", "arduino:samd:mkrvidor4000", sketch_path])
218+
219+
220+
def test_compile_with_build_properties_flag(run_command, data_dir, copy_sketch):
221+
# Init the environment explicitly
222+
assert run_command(["core", "update-index"])
223+
224+
# Install Arduino AVR Boards
225+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
226+
227+
sketch_path = copy_sketch("sketch_with_single_string_define")
228+
fqbn = "arduino:avr:uno"
229+
230+
# Compile using a build property with quotes
231+
res = run_command(
232+
[
233+
"compile",
234+
"-b",
235+
fqbn,
236+
'--build-properties="build.extra_flags=\\"-DMY_DEFINE=\\"hello world\\"\\""',
237+
sketch_path,
238+
"--verbose",
239+
"--clean",
240+
]
241+
)
242+
assert res.failed
243+
assert "Flag --build-properties has been deprecated, please use --build-property instead." not in res.stderr
244+
245+
# Try again with quotes
246+
res = run_command(
247+
[
248+
"compile",
249+
"-b",
250+
fqbn,
251+
'--build-properties="build.extra_flags=-DMY_DEFINE=\\"hello\\""',
252+
sketch_path,
253+
"--verbose",
254+
"--clean",
255+
]
256+
)
257+
assert res.failed
258+
assert "Flag --build-properties has been deprecated, please use --build-property instead." not in res.stderr
259+
260+
# Try without quotes
261+
sketch_path = copy_sketch("sketch_with_single_int_define")
262+
res = run_command(
263+
[
264+
"compile",
265+
"-b",
266+
fqbn,
267+
'--build-properties="build.extra_flags=-DMY_DEFINE=1"',
268+
sketch_path,
269+
"--verbose",
270+
"--clean",
271+
]
272+
)
273+
assert res.ok
274+
assert "Flag --build-properties has been deprecated, please use --build-property instead." in res.stderr
275+
assert "-DMY_DEFINE=1" in res.stdout
276+
277+
sketch_path = copy_sketch("sketch_with_multiple_int_defines")
278+
res = run_command(
279+
[
280+
"compile",
281+
"-b",
282+
fqbn,
283+
'--build-properties="build.extra_flags=-DFIRST_PIN=1,compiler.cpp.extra_flags=-DSECOND_PIN=2"',
284+
sketch_path,
285+
"--verbose",
286+
"--clean",
287+
]
288+
)
289+
assert res.ok
290+
assert "Flag --build-properties has been deprecated, please use --build-property instead." in res.stderr
291+
assert "-DFIRST_PIN=1" in res.stdout
292+
assert "-DSECOND_PIN=2" in res.stdout
293+
294+
295+
def test_compile_with_build_property_containing_quotes(run_command, data_dir, copy_sketch):
296+
# Init the environment explicitly
297+
assert run_command(["core", "update-index"])
298+
299+
# Install Arduino AVR Boards
300+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
301+
302+
sketch_path = copy_sketch("sketch_with_single_string_define")
303+
fqbn = "arduino:avr:uno"
304+
305+
# Compile using a build property with quotes
306+
res = run_command(
307+
[
308+
"compile",
309+
"-b",
310+
fqbn,
311+
'--build-property=build.extra_flags=\\"-DMY_DEFINE=\\"hello world\\"\\"',
312+
sketch_path,
313+
"--verbose",
314+
]
315+
)
316+
assert res.ok
317+
assert '-DMY_DEFINE=\\"hello world\\"' in res.stdout
318+
319+
320+
def test_compile_with_multiple_build_property_flags(run_command, data_dir, copy_sketch, working_dir):
321+
# Init the environment explicitly
322+
assert run_command(["core", "update-index"])
323+
324+
# Install Arduino AVR Boards
325+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
326+
327+
sketch_path = copy_sketch("sketch_with_multiple_defines")
328+
fqbn = "arduino:avr:uno"
329+
330+
# Compile using multiple build properties separated by a space
331+
res = run_command(
332+
[
333+
"compile",
334+
"-b",
335+
fqbn,
336+
'--build-property=compiler.cpp.extra_flags=\\"-DPIN=2 -DSSID=\\"This is a String\\"\\"',
337+
sketch_path,
338+
"--verbose",
339+
"--clean",
340+
]
341+
)
342+
assert res.failed
343+
344+
# Compile using multiple build properties separated by a space and properly quoted
345+
res = run_command(
346+
[
347+
"compile",
348+
"-b",
349+
fqbn,
350+
'--build-property=compiler.cpp.extra_flags=-DPIN=2 \\"-DSSID=\\"This is a String\\"\\"',
351+
sketch_path,
352+
"--verbose",
353+
"--clean",
354+
]
355+
)
356+
assert res.ok
357+
assert '-DPIN=2 "-DSSID=\\"This is a String\\""' in res.stdout
358+
359+
# Tries compilation using multiple build properties separated by a comma
360+
res = run_command(
361+
[
362+
"compile",
363+
"-b",
364+
fqbn,
365+
'--build-property=compiler.cpp.extra_flags=\\"-DPIN=2,-DSSID=\\"This is a String\\"\\"',
366+
sketch_path,
367+
"--verbose",
368+
"--clean",
369+
]
370+
)
371+
assert res.failed
372+
373+
res = run_command(
374+
[
375+
"compile",
376+
"-b",
377+
fqbn,
378+
'--build-property=compiler.cpp.extra_flags=\\"-DPIN=2\\"',
379+
'--build-property=compiler.cpp.extra_flags=\\"-DSSID=\\"This is a String\\"\\"',
380+
sketch_path,
381+
"--verbose",
382+
"--clean",
383+
]
384+
)
385+
assert res.failed
386+
assert "-DPIN=2" not in res.stdout
387+
assert '-DSSID=\\"This is a String\\"' in res.stdout
388+
389+
res = run_command(
390+
[
391+
"compile",
392+
"-b",
393+
fqbn,
394+
'--build-property=compiler.cpp.extra_flags=\\"-DPIN=2\\"',
395+
'--build-property=build.extra_flags=\\"-DSSID=\\"hello world\\"\\"',
396+
sketch_path,
397+
"--verbose",
398+
"--clean",
399+
]
400+
)
401+
assert res.ok
402+
assert "-DPIN=2" in res.stdout
403+
assert '-DSSID=\\"hello world\\"' in res.stdout

‎test/test_compile_part_2.py

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
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 license@arduino.cc.
15+
16+
import tempfile
17+
import hashlib
18+
from pathlib import Path
19+
import simplejson as json
20+
21+
22+
def test_compile_with_output_dir_flag(run_command, data_dir):
23+
# Init the environment explicitly
24+
run_command(["core", "update-index"])
25+
26+
# Download latest AVR
27+
run_command(["core", "install", "arduino:avr"])
28+
29+
sketch_name = "CompileWithOutputDir"
30+
sketch_path = Path(data_dir, sketch_name)
31+
fqbn = "arduino:avr:uno"
32+
33+
# Create a test sketch
34+
result = run_command(["sketch", "new", sketch_path])
35+
assert result.ok
36+
assert f"Sketch created in: {sketch_path}" in result.stdout
37+
38+
# Test the --output-dir flag with absolute path
39+
output_dir = Path(data_dir, "test_dir", "output_dir")
40+
result = run_command(["compile", "-b", fqbn, sketch_path, "--output-dir", output_dir])
41+
assert result.ok
42+
43+
# Verifies expected binaries have been built
44+
sketch_path_md5 = hashlib.md5(bytes(sketch_path)).hexdigest().upper()
45+
build_dir = Path(tempfile.gettempdir(), f"arduino-sketch-{sketch_path_md5}")
46+
assert (build_dir / f"{sketch_name}.ino.eep").exists()
47+
assert (build_dir / f"{sketch_name}.ino.elf").exists()
48+
assert (build_dir / f"{sketch_name}.ino.hex").exists()
49+
assert (build_dir / f"{sketch_name}.ino.with_bootloader.bin").exists()
50+
assert (build_dir / f"{sketch_name}.ino.with_bootloader.hex").exists()
51+
52+
# Verifies binaries are exported when --output-dir flag is specified
53+
assert output_dir.exists()
54+
assert output_dir.is_dir()
55+
assert (output_dir / f"{sketch_name}.ino.eep").exists()
56+
assert (output_dir / f"{sketch_name}.ino.elf").exists()
57+
assert (output_dir / f"{sketch_name}.ino.hex").exists()
58+
assert (output_dir / f"{sketch_name}.ino.with_bootloader.bin").exists()
59+
assert (output_dir / f"{sketch_name}.ino.with_bootloader.hex").exists()
60+
61+
62+
def test_compile_with_export_binaries_flag(run_command, data_dir):
63+
# Init the environment explicitly
64+
run_command(["core", "update-index"])
65+
66+
# Download latest AVR
67+
run_command(["core", "install", "arduino:avr"])
68+
69+
sketch_name = "CompileWithExportBinariesFlag"
70+
sketch_path = Path(data_dir, sketch_name)
71+
fqbn = "arduino:avr:uno"
72+
73+
# Create a test sketch
74+
assert run_command(["sketch", "new", sketch_path])
75+
76+
# Test the --output-dir flag with absolute path
77+
result = run_command(["compile", "-b", fqbn, sketch_path, "--export-binaries"])
78+
assert result.ok
79+
assert Path(sketch_path, "build").exists()
80+
assert Path(sketch_path, "build").is_dir()
81+
82+
# Verifies binaries are exported when --export-binaries flag is set
83+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.eep").exists()
84+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.elf").exists()
85+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.hex").exists()
86+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.with_bootloader.bin").exists()
87+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.with_bootloader.hex").exists()
88+
89+
90+
def test_compile_with_custom_build_path(run_command, data_dir):
91+
# Init the environment explicitly
92+
run_command(["core", "update-index"])
93+
94+
# Download latest AVR
95+
run_command(["core", "install", "arduino:avr"])
96+
97+
sketch_name = "CompileWithBuildPath"
98+
sketch_path = Path(data_dir, sketch_name)
99+
fqbn = "arduino:avr:uno"
100+
101+
# Create a test sketch
102+
result = run_command(["sketch", "new", sketch_path])
103+
assert result.ok
104+
assert f"Sketch created in: {sketch_path}" in result.stdout
105+
106+
# Test the --build-path flag with absolute path
107+
build_path = Path(data_dir, "test_dir", "build_dir")
108+
result = run_command(["compile", "-b", fqbn, sketch_path, "--build-path", build_path])
109+
print(result.stderr)
110+
assert result.ok
111+
112+
# Verifies expected binaries have been built to build_path
113+
assert build_path.exists()
114+
assert build_path.is_dir()
115+
assert (build_path / f"{sketch_name}.ino.eep").exists()
116+
assert (build_path / f"{sketch_name}.ino.elf").exists()
117+
assert (build_path / f"{sketch_name}.ino.hex").exists()
118+
assert (build_path / f"{sketch_name}.ino.with_bootloader.bin").exists()
119+
assert (build_path / f"{sketch_name}.ino.with_bootloader.hex").exists()
120+
121+
# Verifies there are no binaries in temp directory
122+
sketch_path_md5 = hashlib.md5(bytes(sketch_path)).hexdigest().upper()
123+
build_dir = Path(tempfile.gettempdir(), f"arduino-sketch-{sketch_path_md5}")
124+
assert not (build_dir / f"{sketch_name}.ino.eep").exists()
125+
assert not (build_dir / f"{sketch_name}.ino.elf").exists()
126+
assert not (build_dir / f"{sketch_name}.ino.hex").exists()
127+
assert not (build_dir / f"{sketch_name}.ino.with_bootloader.bin").exists()
128+
assert not (build_dir / f"{sketch_name}.ino.with_bootloader.hex").exists()
129+
130+
131+
def test_compile_with_export_binaries_env_var(run_command, data_dir, downloads_dir):
132+
# Init the environment explicitly
133+
run_command(["core", "update-index"])
134+
135+
# Download latest AVR
136+
run_command(["core", "install", "arduino:avr"])
137+
138+
sketch_name = "CompileWithExportBinariesEnvVar"
139+
sketch_path = Path(data_dir, sketch_name)
140+
fqbn = "arduino:avr:uno"
141+
142+
# Create a test sketch
143+
assert run_command(["sketch", "new", sketch_path])
144+
145+
env = {
146+
"ARDUINO_DATA_DIR": data_dir,
147+
"ARDUINO_DOWNLOADS_DIR": downloads_dir,
148+
"ARDUINO_SKETCHBOOK_DIR": data_dir,
149+
"ARDUINO_SKETCH_ALWAYS_EXPORT_BINARIES": "true",
150+
}
151+
# Test compilation with export binaries env var set
152+
result = run_command(["compile", "-b", fqbn, sketch_path], custom_env=env)
153+
assert result.ok
154+
assert Path(sketch_path, "build").exists()
155+
assert Path(sketch_path, "build").is_dir()
156+
157+
# Verifies binaries are exported when export binaries env var is set
158+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.eep").exists()
159+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.elf").exists()
160+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.hex").exists()
161+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.with_bootloader.bin").exists()
162+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.with_bootloader.hex").exists()
163+
164+
165+
def test_compile_with_export_binaries_config(run_command, data_dir, downloads_dir):
166+
# Init the environment explicitly
167+
run_command(["core", "update-index"])
168+
169+
# Download latest AVR
170+
run_command(["core", "install", "arduino:avr"])
171+
172+
sketch_name = "CompileWithExportBinariesConfig"
173+
sketch_path = Path(data_dir, sketch_name)
174+
fqbn = "arduino:avr:uno"
175+
176+
# Create a test sketch
177+
assert run_command(["sketch", "new", sketch_path])
178+
179+
# Create settings with export binaries set to true
180+
env = {
181+
"ARDUINO_DATA_DIR": data_dir,
182+
"ARDUINO_DOWNLOADS_DIR": downloads_dir,
183+
"ARDUINO_SKETCHBOOK_DIR": data_dir,
184+
"ARDUINO_SKETCH_ALWAYS_EXPORT_BINARIES": "true",
185+
}
186+
assert run_command(["config", "init", "--dest-dir", "."], custom_env=env)
187+
188+
# Test compilation with export binaries env var set
189+
result = run_command(["compile", "-b", fqbn, sketch_path])
190+
assert result.ok
191+
assert Path(sketch_path, "build").exists()
192+
assert Path(sketch_path, "build").is_dir()
193+
194+
# Verifies binaries are exported when export binaries env var is set
195+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.eep").exists()
196+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.elf").exists()
197+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.hex").exists()
198+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.with_bootloader.bin").exists()
199+
assert (sketch_path / "build" / fqbn.replace(":", ".") / f"{sketch_name}.ino.with_bootloader.hex").exists()
200+
201+
202+
def test_compile_with_invalid_url(run_command, data_dir):
203+
# Init the environment explicitly
204+
run_command(["core", "update-index"])
205+
206+
# Download latest AVR
207+
run_command(["core", "install", "arduino:avr"])
208+
209+
sketch_name = "CompileWithInvalidURL"
210+
sketch_path = Path(data_dir, sketch_name)
211+
fqbn = "arduino:avr:uno"
212+
213+
# Create a test sketch
214+
assert run_command(["sketch", "new", sketch_path])
215+
216+
# Create settings with custom invalid URL
217+
assert run_command(
218+
["config", "init", "--dest-dir", ".", "--additional-urls", "https://example.com/package_example_index.json"]
219+
)
220+
221+
# Verifies compilation fails cause of missing local index file
222+
res = run_command(["compile", "-b", fqbn, sketch_path])
223+
assert res.ok
224+
lines = [l.strip() for l in res.stderr.splitlines()]
225+
assert "Error initializing instance: Loading index file: loading json index file" in lines[0]
226+
expected_index_file = Path(data_dir, "package_example_index.json")
227+
assert f"loading json index file {expected_index_file}: " + f"open {expected_index_file}:" in lines[-1]
228+
229+
230+
def test_compile_with_custom_libraries(run_command, copy_sketch):
231+
# Creates config with additional URL to install necessary core
232+
url = "http://arduino.esp8266.com/stable/package_esp8266com_index.json"
233+
assert run_command(["config", "init", "--dest-dir", ".", "--additional-urls", url])
234+
235+
# Init the environment explicitly
236+
assert run_command(["update"])
237+
238+
# Install core to compile
239+
assert run_command(["core", "install", "esp8266:esp8266"])
240+
241+
sketch_path = copy_sketch("sketch_with_multiple_custom_libraries")
242+
fqbn = "esp8266:esp8266:nodemcu:xtal=80,vt=heap,eesz=4M1M,wipe=none,baud=115200"
243+
244+
first_lib = Path(sketch_path, "libraries1")
245+
second_lib = Path(sketch_path, "libraries2")
246+
# This compile command has been taken from this issue:
247+
# https://github.com/arduino/arduino-cli/issues/973
248+
assert run_command(["compile", "--libraries", first_lib, "--libraries", second_lib, "-b", fqbn, sketch_path])
249+
250+
251+
def test_compile_with_archives_and_long_paths(run_command):
252+
# Creates config with additional URL to install necessary core
253+
url = "http://arduino.esp8266.com/stable/package_esp8266com_index.json"
254+
assert run_command(["config", "init", "--dest-dir", ".", "--additional-urls", url])
255+
256+
# Init the environment explicitly
257+
assert run_command(["update"])
258+
259+
# Install core to compile
260+
assert run_command(["core", "install", "esp8266:esp8266@2.7.4"])
261+
262+
# Install test library
263+
assert run_command(["lib", "install", "ArduinoIoTCloud"])
264+
265+
result = run_command(["lib", "examples", "ArduinoIoTCloud", "--format", "json"])
266+
assert result.ok
267+
lib_output = json.loads(result.stdout)
268+
sketch_path = Path(lib_output[0]["library"]["install_dir"], "examples", "ArduinoIoTCloud-Advanced")
269+
270+
assert run_command(["compile", "-b", "esp8266:esp8266:huzzah", sketch_path])
271+
272+
273+
def test_compile_with_precompiled_library(run_command, data_dir):
274+
assert run_command(["update"])
275+
276+
assert run_command(["core", "install", "arduino:samd@1.8.11"])
277+
fqbn = "arduino:samd:mkrzero"
278+
279+
# Install precompiled library
280+
# For more information see:
281+
# https://arduino.github.io/arduino-cli/latest/library-specification/#precompiled-binaries
282+
assert run_command(["lib", "install", "BSEC Software Library@1.5.1474"])
283+
sketch_folder = Path(data_dir, "libraries", "BSEC_Software_Library", "examples", "basic")
284+
285+
# Compile and verify dependencies detection for fully precompiled library is not skipped
286+
result = run_command(["compile", "-b", fqbn, sketch_folder, "-v"])
287+
assert result.ok
288+
assert "Skipping dependencies detection for precompiled library BSEC Software Library" not in result.stdout

‎test/test_compile_part_3.py

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
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 license@arduino.cc.
15+
16+
import shutil
17+
from git import Repo
18+
from pathlib import Path
19+
20+
21+
def test_compile_with_fully_precompiled_library(run_command, data_dir):
22+
assert run_command(["update"])
23+
24+
assert run_command(["core", "install", "arduino:mbed@1.3.1"])
25+
fqbn = "arduino:mbed:nano33ble"
26+
27+
# Install fully precompiled library
28+
# For more information see:
29+
# https://arduino.github.io/arduino-cli/latest/library-specification/#precompiled-binaries
30+
assert run_command(["lib", "install", "Arduino_TensorFlowLite@2.1.1-ALPHA-precompiled"])
31+
sketch_folder = Path(data_dir, "libraries", "Arduino_TensorFlowLite", "examples", "hello_world")
32+
33+
# Install example dependency
34+
# assert run_command("lib install Arduino_LSM9DS1")
35+
36+
# Compile and verify dependencies detection for fully precompiled library is skipped
37+
result = run_command(["compile", "-b", fqbn, sketch_folder, "-v"])
38+
assert result.ok
39+
assert "Skipping dependencies detection for precompiled library Arduino_TensorFlowLite" in result.stdout
40+
41+
42+
def test_compile_sketch_with_pde_extension(run_command, data_dir):
43+
# Init the environment explicitly
44+
assert run_command(["update"])
45+
46+
# Install core to compile
47+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
48+
49+
sketch_name = "CompilePdeSketch"
50+
sketch_path = Path(data_dir, sketch_name)
51+
fqbn = "arduino:avr:uno"
52+
53+
# Create a test sketch
54+
assert run_command(["sketch", "new", sketch_path])
55+
56+
# Renames sketch file to pde
57+
sketch_file = Path(sketch_path, f"{sketch_name}.ino").rename(sketch_path / f"{sketch_name}.pde")
58+
59+
# Build sketch from folder
60+
res = run_command(["compile", "--clean", "-b", fqbn, sketch_path])
61+
assert res.ok
62+
assert "Sketches with .pde extension are deprecated, please rename the following files to .ino:" in res.stderr
63+
assert str(sketch_file) in res.stderr
64+
65+
# Build sketch from file
66+
res = run_command(["compile", "--clean", "-b", fqbn, sketch_file])
67+
assert res.ok
68+
assert "Sketches with .pde extension are deprecated, please rename the following files to .ino" in res.stderr
69+
assert str(sketch_file) in res.stderr
70+
71+
72+
def test_compile_sketch_with_multiple_main_files(run_command, data_dir):
73+
# Init the environment explicitly
74+
assert run_command(["update"])
75+
76+
# Install core to compile
77+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
78+
79+
sketch_name = "CompileSketchMultipleMainFiles"
80+
sketch_path = Path(data_dir, sketch_name)
81+
fqbn = "arduino:avr:uno"
82+
83+
# Create a test sketch
84+
assert run_command(["sketch", "new", sketch_path])
85+
86+
# Copy .ino sketch file to .pde
87+
sketch_ino_file = Path(sketch_path, f"{sketch_name}.ino")
88+
sketch_pde_file = Path(sketch_path / f"{sketch_name}.pde")
89+
shutil.copyfile(sketch_ino_file, sketch_pde_file)
90+
91+
# Build sketch from folder
92+
res = run_command(["compile", "--clean", "-b", fqbn, sketch_path])
93+
assert res.failed
94+
assert "Error during build: Can't open sketch: multiple main sketch files found" in res.stderr
95+
96+
# Build sketch from .ino file
97+
res = run_command(["compile", "--clean", "-b", fqbn, sketch_ino_file])
98+
assert res.failed
99+
assert "Error during build: Can't open sketch: multiple main sketch files found" in res.stderr
100+
101+
# Build sketch from .pde file
102+
res = run_command(["compile", "--clean", "-b", fqbn, sketch_pde_file])
103+
assert res.failed
104+
assert "Error during build: Can't open sketch: multiple main sketch files found" in res.stderr
105+
106+
107+
def test_compile_sketch_case_mismatch_fails(run_command, data_dir):
108+
# Init the environment explicitly
109+
assert run_command(["update"])
110+
111+
# Install core to compile
112+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
113+
114+
sketch_name = "CompileSketchCaseMismatch"
115+
sketch_path = Path(data_dir, sketch_name)
116+
fqbn = "arduino:avr:uno"
117+
118+
assert run_command(["sketch", "new", sketch_path])
119+
120+
# Rename main .ino file so casing is different from sketch name
121+
sketch_main_file = Path(sketch_path, f"{sketch_name}.ino").rename(sketch_path / f"{sketch_name.lower()}.ino")
122+
123+
# Verifies compilation fails when:
124+
# * Compiling with sketch path
125+
res = run_command(["compile", "--clean", "-b", fqbn, sketch_path])
126+
assert res.failed
127+
assert "Error during build: Can't open sketch: no valid sketch found" in res.stderr
128+
# * Compiling with sketch main file
129+
res = run_command(["compile", "--clean", "-b", fqbn, sketch_main_file])
130+
assert res.failed
131+
assert "Error during build: Can't open sketch: no valid sketch found" in res.stderr
132+
# * Compiling in sketch path
133+
res = run_command(["compile", "--clean", "-b", fqbn], custom_working_dir=sketch_path)
134+
assert res.failed
135+
assert "Error during build: Can't open sketch: no valid sketch found" in res.stderr
136+
137+
138+
def test_compile_with_only_compilation_database_flag(run_command, data_dir):
139+
assert run_command(["update"])
140+
141+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
142+
143+
sketch_name = "CompileSketchOnlyCompilationDatabaseFlag"
144+
sketch_path = Path(data_dir, sketch_name)
145+
fqbn = "arduino:avr:uno"
146+
147+
assert run_command(["sketch", "new", sketch_path])
148+
149+
# Verifies no binaries exist
150+
build_path = Path(sketch_path, "build")
151+
assert not build_path.exists()
152+
153+
# Compile with both --export-binaries and --only-compilation-database flags
154+
assert run_command(
155+
["compile", "--export-binaries", "--only-compilation-database", "--clean", "-b", fqbn, sketch_path]
156+
)
157+
158+
# Verifies no binaries are exported
159+
assert not build_path.exists()
160+
161+
# Verifies no binaries exist
162+
build_path = Path(data_dir, "export-dir")
163+
assert not build_path.exists()
164+
165+
# Compile by setting the --output-dir flag and --only-compilation-database flags
166+
assert run_command(
167+
["compile", "--output-dir", build_path, "--only-compilation-database", "--clean", "-b", fqbn, sketch_path]
168+
)
169+
170+
# Verifies no binaries are exported
171+
assert not build_path.exists()
172+
173+
174+
def test_compile_using_platform_local_txt(run_command, data_dir):
175+
assert run_command(["update"])
176+
177+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
178+
179+
sketch_name = "CompileSketchUsingPlatformLocalTxt"
180+
sketch_path = Path(data_dir, sketch_name)
181+
fqbn = "arduino:avr:uno"
182+
183+
assert run_command(["sketch", "new", sketch_path])
184+
185+
# Verifies compilation works without issues
186+
assert run_command(["compile", "--clean", "-b", fqbn, sketch_path])
187+
188+
# Overrides default platform compiler with an unexisting one
189+
platform_local_txt = Path(data_dir, "packages", "arduino", "hardware", "avr", "1.8.3", "platform.local.txt")
190+
platform_local_txt.write_text("compiler.c.cmd=my-compiler-that-does-not-exist")
191+
192+
# Verifies compilation now fails because compiler is not found
193+
res = run_command(["compile", "--clean", "-b", fqbn, sketch_path])
194+
assert res.failed
195+
assert "my-compiler-that-does-not-exist" in res.stderr
196+
197+
198+
def test_compile_using_boards_local_txt(run_command, data_dir):
199+
assert run_command(["update"])
200+
201+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
202+
203+
sketch_name = "CompileSketchUsingBoardsLocalTxt"
204+
sketch_path = Path(data_dir, sketch_name)
205+
# Use a made up board
206+
fqbn = "arduino:avr:nessuno"
207+
208+
assert run_command(["sketch", "new", sketch_path])
209+
210+
# Verifies compilation fails because board doesn't exist
211+
res = run_command(["compile", "--clean", "-b", fqbn, sketch_path])
212+
assert res.failed
213+
assert "Error during build: Error resolving FQBN: board arduino:avr:nessuno not found" in res.stderr
214+
215+
# Use custom boards.local.txt with made arduino:avr:nessuno board
216+
boards_local_txt = Path(data_dir, "packages", "arduino", "hardware", "avr", "1.8.3", "boards.local.txt")
217+
shutil.copyfile(Path(__file__).parent / "testdata" / "boards.local.txt", boards_local_txt)
218+
219+
assert run_command(["compile", "--clean", "-b", fqbn, sketch_path])
220+
221+
222+
def test_compile_manually_installed_platform(run_command, data_dir):
223+
assert run_command(["update"])
224+
225+
sketch_name = "CompileSketchManuallyInstalledPlatformUsingPlatformLocalTxt"
226+
sketch_path = Path(data_dir, sketch_name)
227+
fqbn = "arduino-beta-development:avr:uno"
228+
assert run_command(["sketch", "new", sketch_path])
229+
230+
# Manually installs a core in sketchbooks hardware folder
231+
git_url = "https://github.com/arduino/ArduinoCore-avr.git"
232+
repo_dir = Path(data_dir, "hardware", "arduino-beta-development", "avr")
233+
assert Repo.clone_from(git_url, repo_dir, multi_options=["-b 1.8.3"])
234+
235+
# Installs also the same core via CLI so all the necessary tools are installed
236+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
237+
238+
# Verifies compilation works without issues
239+
assert run_command(["compile", "--clean", "-b", fqbn, sketch_path])
240+
241+
242+
def test_compile_manually_installed_platform_using_platform_local_txt(run_command, data_dir):
243+
assert run_command(["update"])
244+
245+
sketch_name = "CompileSketchManuallyInstalledPlatformUsingPlatformLocalTxt"
246+
sketch_path = Path(data_dir, sketch_name)
247+
fqbn = "arduino-beta-development:avr:uno"
248+
assert run_command(["sketch", "new", sketch_path])
249+
250+
# Manually installs a core in sketchbooks hardware folder
251+
git_url = "https://github.com/arduino/ArduinoCore-avr.git"
252+
repo_dir = Path(data_dir, "hardware", "arduino-beta-development", "avr")
253+
assert Repo.clone_from(git_url, repo_dir, multi_options=["-b 1.8.3"])
254+
255+
# Installs also the same core via CLI so all the necessary tools are installed
256+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
257+
258+
# Verifies compilation works without issues
259+
assert run_command(["compile", "--clean", "-b", fqbn, sketch_path])
260+
261+
# Overrides default platform compiler with an unexisting one
262+
platform_local_txt = Path(repo_dir, "platform.local.txt")
263+
platform_local_txt.write_text("compiler.c.cmd=my-compiler-that-does-not-exist")
264+
265+
# Verifies compilation now fails because compiler is not found
266+
res = run_command(["compile", "--clean", "-b", fqbn, sketch_path])
267+
assert res.failed
268+
assert "my-compiler-that-does-not-exist" in res.stderr

‎test/test_compile_part_4.py

Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
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 license@arduino.cc.
15+
16+
import tempfile
17+
import hashlib
18+
import shutil
19+
from git import Repo
20+
from pathlib import Path
21+
22+
23+
def test_compile_manually_installed_platform_using_boards_local_txt(run_command, data_dir):
24+
assert run_command(["update"])
25+
26+
sketch_name = "CompileSketchManuallyInstalledPlatformUsingBoardsLocalTxt"
27+
sketch_path = Path(data_dir, sketch_name)
28+
fqbn = "arduino-beta-development:avr:nessuno"
29+
assert run_command(["sketch", "new", sketch_path])
30+
31+
# Manually installs a core in sketchbooks hardware folder
32+
git_url = "https://github.com/arduino/ArduinoCore-avr.git"
33+
repo_dir = Path(data_dir, "hardware", "arduino-beta-development", "avr")
34+
assert Repo.clone_from(git_url, repo_dir, multi_options=["-b 1.8.3"])
35+
36+
# Installs also the same core via CLI so all the necessary tools are installed
37+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
38+
39+
# Verifies compilation fails because board doesn't exist
40+
res = run_command(["compile", "--clean", "-b", fqbn, sketch_path])
41+
assert res.failed
42+
assert (
43+
"Error during build: Error resolving FQBN: board arduino-beta-development:avr:nessuno not found" in res.stderr
44+
)
45+
46+
# Use custom boards.local.txt with made arduino:avr:nessuno board
47+
boards_local_txt = Path(repo_dir, "boards.local.txt")
48+
shutil.copyfile(Path(__file__).parent / "testdata" / "boards.local.txt", boards_local_txt)
49+
50+
assert run_command(["compile", "--clean", "-b", fqbn, sketch_path])
51+
52+
53+
def test_compile_with_library(run_command, data_dir):
54+
assert run_command(["update"])
55+
56+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
57+
58+
sketch_name = "CompileSketchWithWiFi101Dependency"
59+
sketch_path = Path(data_dir, sketch_name)
60+
fqbn = "arduino:avr:uno"
61+
# Create new sketch and add library include
62+
assert run_command(["sketch", "new", sketch_path])
63+
sketch_file = sketch_path / f"{sketch_name}.ino"
64+
lines = []
65+
with open(sketch_file, "r") as f:
66+
lines = f.readlines()
67+
lines = ["#include <WiFi101.h>\n"] + lines
68+
with open(sketch_file, "w") as f:
69+
f.writelines(lines)
70+
71+
# Manually installs a library
72+
git_url = "https://github.com/arduino-libraries/WiFi101.git"
73+
lib_path = Path(data_dir, "my-libraries", "WiFi101")
74+
assert Repo.clone_from(git_url, lib_path, multi_options=["-b 0.16.1"])
75+
76+
res = run_command(["compile", "-b", fqbn, sketch_path, "--library", lib_path, "-v"])
77+
assert res.ok
78+
assert "WiFi101" in res.stdout
79+
80+
81+
def test_compile_with_library_priority(run_command, data_dir):
82+
assert run_command(["update"])
83+
84+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
85+
86+
sketch_name = "CompileSketchWithLibraryPriority"
87+
sketch_path = Path(data_dir, sketch_name)
88+
fqbn = "arduino:avr:uno"
89+
90+
# Manually installs a library
91+
git_url = "https://github.com/arduino-libraries/WiFi101.git"
92+
manually_install_lib_path = Path(data_dir, "my-libraries", "WiFi101")
93+
assert Repo.clone_from(git_url, manually_install_lib_path, multi_options=["-b 0.16.1"])
94+
95+
# Install the same library we installed manually
96+
assert run_command(["lib", "install", "WiFi101"])
97+
98+
# Create new sketch and add library include
99+
assert run_command(["sketch", "new", sketch_path])
100+
sketch_file = sketch_path / f"{sketch_name}.ino"
101+
lines = []
102+
with open(sketch_file, "r") as f:
103+
lines = f.readlines()
104+
lines = ["#include <WiFi101.h>"] + lines
105+
with open(sketch_file, "w") as f:
106+
f.writelines(lines)
107+
108+
res = run_command(["compile", "-b", fqbn, sketch_path, "--library", manually_install_lib_path, "-v"])
109+
assert res.ok
110+
cli_installed_lib_path = Path(data_dir, "libraries", "WiFi101")
111+
expected_output = [
112+
'Multiple libraries were found for "WiFi101.h"',
113+
f" Used: {manually_install_lib_path}",
114+
f" Not used: {cli_installed_lib_path}",
115+
]
116+
assert "\n".join(expected_output) in res.stdout
117+
118+
119+
def test_recompile_with_different_library(run_command, data_dir):
120+
assert run_command(["update"])
121+
122+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
123+
124+
sketch_name = "RecompileCompileSketchWithDifferentLibrary"
125+
sketch_path = Path(data_dir, sketch_name)
126+
fqbn = "arduino:avr:uno"
127+
128+
# Install library
129+
assert run_command(["lib", "install", "WiFi101"])
130+
131+
# Manually installs the same library already installed
132+
git_url = "https://github.com/arduino-libraries/WiFi101.git"
133+
manually_install_lib_path = Path(data_dir, "my-libraries", "WiFi101")
134+
assert Repo.clone_from(git_url, manually_install_lib_path, multi_options=["-b 0.16.1"])
135+
136+
# Create new sketch and add library include
137+
assert run_command(["sketch", "new", sketch_path])
138+
sketch_file = sketch_path / f"{sketch_name}.ino"
139+
lines = []
140+
with open(sketch_file, "r") as f:
141+
lines = f.readlines()
142+
lines = ["#include <WiFi101.h>"] + lines
143+
with open(sketch_file, "w") as f:
144+
f.writelines(lines)
145+
146+
sketch_path_md5 = hashlib.md5(bytes(sketch_path)).hexdigest().upper()
147+
build_dir = Path(tempfile.gettempdir(), f"arduino-sketch-{sketch_path_md5}")
148+
149+
# Compile sketch using library not managed by CLI
150+
res = run_command(["compile", "-b", fqbn, "--library", manually_install_lib_path, sketch_path, "-v"])
151+
assert res.ok
152+
obj_path = build_dir / "libraries" / "WiFi101" / "WiFi.cpp.o"
153+
assert f"Using previously compiled file: {obj_path}" not in res.stdout
154+
155+
# Compile again using library installed from CLI
156+
res = run_command(["compile", "-b", fqbn, sketch_path, "-v"])
157+
assert res.ok
158+
obj_path = build_dir / "libraries" / "WiFi101" / "WiFi.cpp.o"
159+
assert f"Using previously compiled file: {obj_path}" not in res.stdout
160+
161+
162+
def test_compile_with_conflicting_libraries_include(run_command, data_dir, copy_sketch):
163+
assert run_command(["update"])
164+
165+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
166+
167+
# Install conflicting libraries
168+
git_url = "https://github.com/pstolarz/OneWireNg.git"
169+
one_wire_ng_lib_path = Path(data_dir, "libraries", "onewireng_0_8_1")
170+
assert Repo.clone_from(git_url, one_wire_ng_lib_path, multi_options=["-b 0.8.1"])
171+
172+
git_url = "https://github.com/PaulStoffregen/OneWire.git"
173+
one_wire_lib_path = Path(data_dir, "libraries", "onewire_2_3_5")
174+
assert Repo.clone_from(git_url, one_wire_lib_path, multi_options=["-b v2.3.5"])
175+
176+
sketch_path = copy_sketch("sketch_with_conflicting_libraries_include")
177+
fqbn = "arduino:avr:uno"
178+
179+
res = run_command(["compile", "-b", fqbn, sketch_path, "--verbose"])
180+
assert res.ok
181+
expected_output = [
182+
'Multiple libraries were found for "OneWire.h"',
183+
f" Used: {one_wire_lib_path}",
184+
f" Not used: {one_wire_ng_lib_path}",
185+
]
186+
assert "\n".join(expected_output) in res.stdout
187+
188+
189+
def test_compile_with_invalid_build_options_json(run_command, data_dir):
190+
assert run_command(["update"])
191+
192+
assert run_command(["core", "install", "arduino:avr@1.8.3"])
193+
194+
sketch_name = "CompileInvalidBuildOptionsJson"
195+
sketch_path = Path(data_dir, sketch_name)
196+
fqbn = "arduino:avr:uno"
197+
198+
# Create a test sketch
199+
assert run_command(["sketch", "new", sketch_path])
200+
201+
# Get the build directory
202+
sketch_path_md5 = hashlib.md5(bytes(sketch_path)).hexdigest().upper()
203+
build_dir = Path(tempfile.gettempdir(), f"arduino-sketch-{sketch_path_md5}")
204+
205+
assert run_command(["compile", "-b", fqbn, sketch_path, "--verbose"])
206+
207+
# Breaks the build.options.json file
208+
build_options_json = build_dir / "build.options.json"
209+
with open(build_options_json, "w") as f:
210+
f.write("invalid json")
211+
212+
assert run_command(["compile", "-b", fqbn, sketch_path, "--verbose"])
213+
214+
215+
def test_compile_with_esp32_bundled_libraries(run_command, data_dir, copy_sketch):
216+
# Some esp cores have have bundled libraries that are optimize for that architecture,
217+
# it might happen that if the user has a library with the same name installed conflicts
218+
# can ensue and the wrong library is used for compilation, thus it fails.
219+
# This happens because for "historical" reasons these platform have their "name" key
220+
# in the "library.properties" flag suffixed with "(esp32)" or similar even though that
221+
# doesn't respect the libraries specification.
222+
# https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format
223+
#
224+
# The reason those libraries have these suffixes is to avoid an annoying bug in the Java IDE
225+
# that would have caused the libraries that are both bundled with the core and the Java IDE to be
226+
# always marked as updatable. For more info see: https://github.com/arduino/Arduino/issues/4189
227+
assert run_command(["update"])
228+
229+
# Update index with esp32 core and install it
230+
url = "https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json"
231+
core_version = "1.0.6"
232+
assert run_command(["core", "update-index", f"--additional-urls={url}"])
233+
assert run_command(["core", "install", f"esp32:esp32@{core_version}", f"--additional-urls={url}"])
234+
235+
# Install a library with the same name as one bundled with the core
236+
assert run_command(["lib", "install", "SD"])
237+
238+
sketch_path = copy_sketch("sketch_with_sd_library")
239+
fqbn = "esp32:esp32:esp32"
240+
241+
res = run_command(["compile", "-b", fqbn, sketch_path, "--verbose"])
242+
assert res.failed
243+
244+
core_bundled_lib_path = Path(data_dir, "packages", "esp32", "hardware", "esp32", core_version, "libraries", "SD")
245+
cli_installed_lib_path = Path(data_dir, "libraries", "SD")
246+
expected_output = [
247+
'Multiple libraries were found for "SD.h"',
248+
f" Used: {core_bundled_lib_path}",
249+
f" Not used: {cli_installed_lib_path}",
250+
]
251+
assert "\n".join(expected_output) not in res.stdout
252+
253+
254+
def test_compile_with_esp8266_bundled_libraries(run_command, data_dir, copy_sketch):
255+
# Some esp cores have have bundled libraries that are optimize for that architecture,
256+
# it might happen that if the user has a library with the same name installed conflicts
257+
# can ensue and the wrong library is used for compilation, thus it fails.
258+
# This happens because for "historical" reasons these platform have their "name" key
259+
# in the "library.properties" flag suffixed with "(esp32)" or similar even though that
260+
# doesn't respect the libraries specification.
261+
# https://arduino.github.io/arduino-cli/latest/library-specification/#libraryproperties-file-format
262+
#
263+
# The reason those libraries have these suffixes is to avoid an annoying bug in the Java IDE
264+
# that would have caused the libraries that are both bundled with the core and the Java IDE to be
265+
# always marked as updatable. For more info see: https://github.com/arduino/Arduino/issues/4189
266+
assert run_command(["update"])
267+
268+
# Update index with esp8266 core and install it
269+
url = "http://arduino.esp8266.com/stable/package_esp8266com_index.json"
270+
core_version = "2.7.4"
271+
assert run_command(["core", "update-index", f"--additional-urls={url}"])
272+
assert run_command(["core", "install", f"esp8266:esp8266@{core_version}", f"--additional-urls={url}"])
273+
274+
# Install a library with the same name as one bundled with the core
275+
assert run_command(["lib", "install", "SD"])
276+
277+
sketch_path = copy_sketch("sketch_with_sd_library")
278+
fqbn = "esp8266:esp8266:generic"
279+
280+
res = run_command(["compile", "-b", fqbn, sketch_path, "--verbose"])
281+
assert res.failed
282+
283+
core_bundled_lib_path = Path(
284+
data_dir, "packages", "esp8266", "hardware", "esp8266", core_version, "libraries", "SD"
285+
)
286+
cli_installed_lib_path = Path(data_dir, "libraries", "SD")
287+
expected_output = [
288+
'Multiple libraries were found for "SD.h"',
289+
f" Used: {core_bundled_lib_path}",
290+
f" Not used: {cli_installed_lib_path}",
291+
]
292+
assert "\n".join(expected_output) not in res.stdout
293+
294+
295+
def test_compile_sketch_with_tpp_file_include(run_command, copy_sketch):
296+
assert run_command(["update"])
297+
298+
# Download latest AVR
299+
run_command(["core", "install", "arduino:avr"])
300+
301+
sketch_name = "sketch_with_tpp_file_include"
302+
sketch_path = copy_sketch(sketch_name)
303+
fqbn = "arduino:avr:uno"
304+
305+
assert run_command(["compile", "-b", fqbn, sketch_path, "--verbose"])
306+
307+
308+
def test_compile_sketch_with_ipp_file_include(run_command, copy_sketch):
309+
assert run_command(["update"])
310+
311+
# Download latest AVR
312+
run_command(["core", "install", "arduino:avr"])
313+
314+
sketch_name = "sketch_with_ipp_file_include"
315+
sketch_path = copy_sketch(sketch_name)
316+
fqbn = "arduino:avr:uno"
317+
318+
assert run_command(["compile", "-b", fqbn, sketch_path, "--verbose"])
319+
320+
321+
def test_compile_with_relative_build_path(run_command, data_dir, copy_sketch):
322+
assert run_command(["update"])
323+
324+
run_command(["core", "install", "arduino:avr@1.8.3"])
325+
326+
sketch_name = "sketch_simple"
327+
sketch_path = copy_sketch(sketch_name)
328+
fqbn = "arduino:avr:uno"
329+
330+
build_path = Path("..", "build_path")
331+
working_dir = Path(data_dir, "working_dir")
332+
working_dir.mkdir()
333+
assert run_command(
334+
["compile", "-b", fqbn, "--build-path", build_path, sketch_path, "-v"],
335+
custom_working_dir=working_dir,
336+
)
337+
338+
absolute_build_path = Path(data_dir, "build_path")
339+
built_files = [f.name for f in absolute_build_path.glob("*")]
340+
assert f"{sketch_name}.ino.eep" in built_files
341+
assert f"{sketch_name}.ino.elf" in built_files
342+
assert f"{sketch_name}.ino.hex" in built_files
343+
assert f"{sketch_name}.ino.with_bootloader.bin" in built_files
344+
assert f"{sketch_name}.ino.with_bootloader.hex" in built_files
345+
assert "build.options.json" in built_files
346+
assert "compile_commands.json" in built_files
347+
assert "core" in built_files
348+
assert "includes.cache" in built_files
349+
assert "libraries" in built_files
350+
assert "preproc" in built_files
351+
assert "sketch" in built_files

0 commit comments

Comments
 (0)
Please sign in to comment.