Skip to content

Commit 292277f

Browse files
author
Roberto Sora
authored
Add unit and integration testing for the sketch recursive load functionality (#462)
* add testcases to cover #358 (Symbolic link as sketch directory) and #424 (folder with .ino extension) * add test to check error throw on symlink loop detection * create symlink via test code to ensure cross platform creation * fixed assert to make the check cross platform * fixed all symlink check asserts to make the check cross platform * nitpicking
1 parent 44d0f4d commit 292277f

File tree

12 files changed

+121
-1
lines changed

12 files changed

+121
-1
lines changed

Diff for: arduino/builder/sketch_test.go

+42
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,48 @@ func TestLoadSketchFolder(t *testing.T) {
8282
require.Equal(t, "helper.h", filepath.Base(s.AdditionalFiles[2].Path))
8383
}
8484

85+
func TestLoadSketchFolderSymlink(t *testing.T) {
86+
// pass the path to the sketch folder
87+
symlinkSketchPath := filepath.Join("testdata", t.Name())
88+
srcSketchPath := t.Name() + "Src"
89+
os.Symlink(srcSketchPath, symlinkSketchPath)
90+
mainFilePath := filepath.Join(symlinkSketchPath, t.Name()+".ino")
91+
s, err := builder.SketchLoad(symlinkSketchPath, "")
92+
require.Nil(t, err)
93+
require.NotNil(t, s)
94+
require.Equal(t, mainFilePath, s.MainFile.Path)
95+
require.Equal(t, symlinkSketchPath, s.LocationPath)
96+
require.Len(t, s.OtherSketchFiles, 2)
97+
require.Equal(t, "old.pde", filepath.Base(s.OtherSketchFiles[0].Path))
98+
require.Equal(t, "other.ino", filepath.Base(s.OtherSketchFiles[1].Path))
99+
require.Len(t, s.AdditionalFiles, 3)
100+
require.Equal(t, "header.h", filepath.Base(s.AdditionalFiles[0].Path))
101+
require.Equal(t, "s_file.S", filepath.Base(s.AdditionalFiles[1].Path))
102+
require.Equal(t, "helper.h", filepath.Base(s.AdditionalFiles[2].Path))
103+
104+
// pass the path to the main file
105+
symlinkSketchPath = mainFilePath
106+
s, err = builder.SketchLoad(symlinkSketchPath, "")
107+
require.Nil(t, err)
108+
require.NotNil(t, s)
109+
require.Equal(t, mainFilePath, s.MainFile.Path)
110+
require.Len(t, s.OtherSketchFiles, 2)
111+
require.Equal(t, "old.pde", filepath.Base(s.OtherSketchFiles[0].Path))
112+
require.Equal(t, "other.ino", filepath.Base(s.OtherSketchFiles[1].Path))
113+
require.Len(t, s.AdditionalFiles, 3)
114+
require.Equal(t, "header.h", filepath.Base(s.AdditionalFiles[0].Path))
115+
require.Equal(t, "s_file.S", filepath.Base(s.AdditionalFiles[1].Path))
116+
require.Equal(t, "helper.h", filepath.Base(s.AdditionalFiles[2].Path))
117+
}
118+
119+
func TestLoadSketchFolderIno(t *testing.T) {
120+
// pass the path to the sketch folder
121+
sketchPath := filepath.Join("testdata", t.Name())
122+
_, err := builder.SketchLoad(sketchPath, "")
123+
require.Error(t, err)
124+
require.Contains(t, err.Error(), "sketch must not be a directory")
125+
}
126+
85127
func TestLoadSketchFolderWrongMain(t *testing.T) {
86128
sketchPath := filepath.Join("testdata", t.Name())
87129
_, err := builder.SketchLoad(sketchPath, "")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
void setup() {
2+
3+
}
4+
5+
void loop() {
6+
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
void setup()
2+
void loop) }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
void setup() {
2+
3+
}
4+
5+
void loop() {
6+
7+
}

Diff for: arduino/builder/testdata/TestLoadSketchFolderSymlinkSrc/doc.txt

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#define FOO "BAR"

Diff for: arduino/builder/testdata/TestLoadSketchFolderSymlinkSrc/old.pde

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
String hello() {
2+
return "world";
3+
}

Diff for: arduino/builder/testdata/TestLoadSketchFolderSymlinkSrc/s_file.S

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#include <testlib4.h>
2+
#error "Whattya looking at?"

Diff for: arduino/builder/testdata/TestLoadSketchFolderSymlinkSrc/src/helper.h

Whitespace-only changes.

Diff for: test/test_compile.py

+57-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def test_compile_with_simple_sketch(run_command, data_dir):
3939
result = run_command("core update-index")
4040
assert result.ok
4141

42-
# # Download latest AVR
42+
# Download latest AVR
4343
result = run_command("core install arduino:avr")
4444
assert result.ok
4545

@@ -70,6 +70,62 @@ def test_compile_with_simple_sketch(run_command, data_dir):
7070
assert is_message_sequence_in_json_log_traces(expected_trace_sequence, json_log_lines)
7171

7272

73+
def test_compile_with_sketch_with_symlink_selfloop(run_command, data_dir):
74+
# Init the environment explicitly
75+
result = run_command("core update-index")
76+
assert result.ok
77+
78+
# Download latest AVR
79+
result = run_command("core install arduino:avr")
80+
assert result.ok
81+
82+
sketch_name = "CompileIntegrationTestSymlinkSelfLoop"
83+
sketch_path = os.path.join(data_dir, sketch_name)
84+
fqbn = "arduino:avr:uno"
85+
86+
# Create a test sketch
87+
result = run_command("sketch new {}".format(sketch_path))
88+
assert result.ok
89+
assert "Sketch created in: {}".format(sketch_path) in result.stdout
90+
91+
# create a symlink that loops on himself
92+
loop_file_path = os.path.join(sketch_path, "loop")
93+
os.symlink(loop_file_path, loop_file_path)
94+
95+
# Build sketch for arduino:avr:uno
96+
result = run_command(
97+
"compile -b {fqbn} {sketch_path}".format(
98+
fqbn=fqbn, sketch_path=sketch_path))
99+
# The assertion is a bit relaxed in this case because win behaves differently from macOs and linux
100+
# returning a different error detailed message
101+
assert "Error during sketch processing" in result.stderr
102+
assert not result.ok
103+
104+
sketch_name = "CompileIntegrationTestSymlinkDirLoop"
105+
sketch_path = os.path.join(data_dir, sketch_name)
106+
fqbn = "arduino:avr:uno"
107+
108+
# Create a test sketch
109+
result = run_command("sketch new {}".format(sketch_path))
110+
assert result.ok
111+
assert "Sketch created in: {}".format(sketch_path) in result.stdout
112+
113+
# create a symlink that loops on the upper level
114+
loop_dir_path = os.path.join(sketch_path, "loop_dir")
115+
os.mkdir(loop_dir_path)
116+
loop_dir_symlink_path = os.path.join(loop_dir_path, "loop_dir_symlink")
117+
os.symlink(loop_dir_path, loop_dir_symlink_path)
118+
119+
# Build sketch for arduino:avr:uno
120+
result = run_command(
121+
"compile -b {fqbn} {sketch_path}".format(
122+
fqbn=fqbn, sketch_path=sketch_path))
123+
# The assertion is a bit relaxed also in this case because macOS behaves differently from win and linux:
124+
# the cli does not follow recursively the symlink til breaking
125+
assert "Error during sketch processing" in result.stderr
126+
assert not result.ok
127+
128+
73129
@pytest.mark.skipif(running_on_ci(), reason="VMs have no serial ports")
74130
def test_compile_and_compile_combo(run_command, data_dir):
75131
# Init the environment explicitly

0 commit comments

Comments
 (0)