Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3ccdb9d

Browse files
authored
Fixed compile error when sketch has a broken symlink (#2497)
* Removed unneeded pointer * Improved error message * Update go-paths library * Added integration tests * Reduced timeout for symlink-loop tests * Fixed unit tests Previously the unit tests were creating the wrong env to test: internal/arduino/libraries/testdata/TestLib ├── examples │ ├── UpGoer1 -> testdata/TestLib │ └── UpGoer2 -> testdata/TestLib ├── library.properties └── src └── TestLib.h The two UpGoer1 and UpGoer2 are broken links. The correct tree is the following: internal/arduino/libraries/testdata/TestLib ├── examples │ ├── UpGoer1 -> .. │ └── UpGoer2 -> .. ├── library.properties └── src └── TestLib.h that actually triggers the symlink loop we are testing. * Fixed integration test * Removed apparently useless check for "readable" files
1 parent 8115da1 commit 3ccdb9d

File tree

14 files changed

+104
-26
lines changed

14 files changed

+104
-26
lines changed

‎.licenses/go/github.com/arduino/go-paths-helper.dep.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: github.com/arduino/go-paths-helper
3-
version: v1.11.0
3+
version: v1.12.0
44
type: go
55
summary:
66
homepage: https://pkg.go.dev/github.com/arduino/go-paths-helper

‎go.mod‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ replace github.com/mailru/easyjson => github.com/cmaglie/easyjson v0.8.1
77

88
require (
99
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371
10-
github.com/arduino/go-paths-helper v1.11.0
10+
github.com/arduino/go-paths-helper v1.12.0
1111
github.com/arduino/go-properties-orderedmap v1.8.0
1212
github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b
1313
github.com/arduino/go-win32-utils v1.0.0

‎go.sum‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ
1111
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
1212
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
1313
github.com/arduino/go-paths-helper v1.0.1/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
14-
github.com/arduino/go-paths-helper v1.11.0 h1:hkpGb9AtCTByTj2FKutuHWb3klDf4kAKL10hW+fN+oE=
15-
github.com/arduino/go-paths-helper v1.11.0/go.mod h1:jcpW4wr0u69GlXhTYydsdsqAjLaYK5n7oWHfKqOG6LM=
14+
github.com/arduino/go-paths-helper v1.12.0 h1:xizOQtI9iHdl19qXd1EmWg5i9W//2bOCOYwlNv8F61E=
15+
github.com/arduino/go-paths-helper v1.12.0/go.mod h1:jcpW4wr0u69GlXhTYydsdsqAjLaYK5n7oWHfKqOG6LM=
1616
github.com/arduino/go-properties-orderedmap v1.8.0 h1:wEfa6hHdpezrVOh787OmClsf/Kd8qB+zE3P2Xbrn0CQ=
1717
github.com/arduino/go-properties-orderedmap v1.8.0/go.mod h1:DKjD2VXY/NZmlingh4lSFMEYCVubfeArCsGPGDwb2yk=
1818
github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b h1:9hDi4F2st6dbLC3y4i02zFT5quS4X6iioWifGlVwfy4=

‎internal/arduino/libraries/libraries_test.go‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,16 @@ func TestLibrariesLoader(t *testing.T) {
9595
func TestSymlinkLoop(t *testing.T) {
9696
// Set up directory structure of test library.
9797
testLib := paths.New("testdata", "TestLib")
98-
examplesPath := testLib.Join("examples")
98+
examplesPath, err := testLib.Join("examples").Abs()
99+
require.NoError(t, err)
99100
require.NoError(t, examplesPath.Mkdir())
100101
defer examplesPath.RemoveAll()
101102

102103
// It's probably most friendly for contributors using Windows to create the symlinks needed for the test on demand.
103-
err := os.Symlink(examplesPath.Join("..").String(), examplesPath.Join("UpGoer1").String())
104+
err = os.Symlink(examplesPath.String(), examplesPath.Join("UpGoer1").String())
104105
require.NoError(t, err, "This test must be run as administrator on Windows to have symlink creation privilege.")
105106
// It's necessary to have multiple symlinks to a parent directory to create the loop.
106-
err = os.Symlink(examplesPath.Join("..").String(), examplesPath.Join("UpGoer2").String())
107+
err = os.Symlink(examplesPath.String(), examplesPath.Join("UpGoer2").String())
107108
require.NoError(t, err)
108109

109110
// The failure condition is Load() never returning, testing for which requires setting up a timeout.
@@ -123,15 +124,16 @@ func TestSymlinkLoop(t *testing.T) {
123124
func TestLegacySymlinkLoop(t *testing.T) {
124125
// Set up directory structure of test library.
125126
testLib := paths.New("testdata", "LegacyLib")
126-
examplesPath := testLib.Join("examples")
127+
examplesPath, err := testLib.Join("examples").Abs()
128+
require.NoError(t, err)
127129
require.NoError(t, examplesPath.Mkdir())
128130
defer examplesPath.RemoveAll()
129131

130132
// It's probably most friendly for contributors using Windows to create the symlinks needed for the test on demand.
131-
err := os.Symlink(examplesPath.Join("..").String(), examplesPath.Join("UpGoer1").String())
133+
err = os.Symlink(examplesPath.String(), examplesPath.Join("UpGoer1").String())
132134
require.NoError(t, err, "This test must be run as administrator on Windows to have symlink creation privilege.")
133135
// It's necessary to have multiple symlinks to a parent directory to create the loop.
134-
err = os.Symlink(examplesPath.Join("..").String(), examplesPath.Join("UpGoer2").String())
136+
err = os.Symlink(examplesPath.String(), examplesPath.Join("UpGoer2").String())
135137
require.NoError(t, err)
136138

137139
// The failure condition is Load() never returning, testing for which requires setting up a timeout.

‎internal/arduino/sketch/sketch.go‎

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,11 @@ func New(path *paths.Path) (*Sketch, error) {
111111

112112
sketchFolderFiles, err := sketch.supportedFiles()
113113
if err != nil {
114-
return nil, err
114+
return nil, fmt.Errorf("%s: %w", tr("reading sketch files"), err)
115115
}
116116

117117
// Collect files
118-
for _, p := range *sketchFolderFiles {
119-
// Skip files that can't be opened
120-
f, err := p.Open()
121-
if err != nil {
122-
continue
123-
}
124-
f.Close()
125-
118+
for _, p := range sketchFolderFiles {
126119
ext := p.Ext()
127120
if globals.MainFileValidExtensions[ext] {
128121
if p.EqualsTo(mainFile) {
@@ -160,7 +153,7 @@ func New(path *paths.Path) (*Sketch, error) {
160153

161154
// supportedFiles reads all files recursively contained in Sketch and
162155
// filter out unneded or unsupported ones and returns them
163-
func (s *Sketch) supportedFiles() (*paths.PathList, error) {
156+
func (s *Sketch) supportedFiles() (paths.PathList, error) {
164157
filterValidExtensions := func(p *paths.Path) bool {
165158
return globals.MainFileValidExtensions[p.Ext()] || globals.AdditionalFileValidExtensions[p.Ext()]
166159
}
@@ -180,7 +173,7 @@ func (s *Sketch) supportedFiles() (*paths.PathList, error) {
180173
if err != nil {
181174
return nil, err
182175
}
183-
return &files, nil
176+
return files, nil
184177
}
185178

186179
// GetProfile returns the requested profile or an error if not found

‎internal/arduino/sketch/sketch_test.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ func TestNewSketchWithSymlinkLoop(t *testing.T) {
341341
return false
342342
}
343343
},
344-
20*time.Second,
344+
5*time.Second,
345345
10*time.Millisecond,
346346
"Infinite symlink loop while loading sketch",
347347
)
@@ -380,7 +380,7 @@ func TestSketchWithMultipleSymlinkLoops(t *testing.T) {
380380
return false
381381
}
382382
},
383-
20*time.Second,
383+
5*time.Second,
384384
10*time.Millisecond,
385385
"Infinite symlink loop while loading sketch",
386386
)

‎internal/integrationtest/compile_1/compile_test.go‎

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,16 +220,36 @@ func compileWithSketchWithSymlinkSelfloop(t *testing.T, env *integrationtest.Env
220220
require.NoError(t, err)
221221
require.Contains(t, string(stdout), "Sketch created in: "+sketchPath.String())
222222

223-
// create a symlink that loops on himself
223+
// Create a symlink that loops on himself
224+
//
225+
// /tmp/cli2843369229/Arduino/CompileIntegrationTestSymlinkSelfLoop
226+
// ├── CompileIntegrationTestSymlinkSelfLoop.ino
227+
// └── loop -> /tmp/cli2843369229/Arduino/CompileIntegrationTestSymlinkSelfLoop/loop
228+
//
229+
// in this case the link is "broken", and it will be ignored by the compiler
224230
loopFilePath := sketchPath.Join("loop")
225231
err = os.Symlink(loopFilePath.String(), loopFilePath.String())
226232
require.NoError(t, err)
227233

228-
// Build sketch for arduino:avr:uno
234+
_, _, err = cli.Run("compile", "-b", fqbn, sketchPath.String())
235+
require.NoError(t, err)
236+
237+
// Add a symlink that loops on himself named as a .ino file
238+
//
239+
// /tmp/cli2843369229/Arduino/CompileIntegrationTestSymlinkSelfLoop
240+
// ├── CompileIntegrationTestSymlinkSelfLoop.ino
241+
// ├── loop -> /tmp/cli2843369229/Arduino/CompileIntegrationTestSymlinkSelfLoop/loop
242+
// └── loop.ino -> /tmp/cli2843369229/Arduino/CompileIntegrationTestSymlinkSelfLoop/loop.ino
243+
//
244+
// in this case the new link is "broken" as before, but being part of the sketch will trigger an error.
245+
loopInoFilePath := sketchPath.Join("loop.ino")
246+
err = os.Symlink(loopFilePath.String(), loopInoFilePath.String())
247+
require.NoError(t, err)
248+
229249
_, stderr, err := cli.Run("compile", "-b", fqbn, sketchPath.String())
230250
// The assertion is a bit relaxed in this case because win behaves differently from macOs and linux
231251
// returning a different error detailed message
232-
require.Contains(t, string(stderr), "Can't open sketch:")
252+
require.Contains(t, string(stderr), "Error during build:")
233253
require.Error(t, err)
234254
}
235255
{
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2023 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 license@arduino.cc.
15+
16+
package compile_test
17+
18+
import (
19+
"testing"
20+
21+
"github.com/arduino/arduino-cli/internal/integrationtest"
22+
"github.com/arduino/go-paths-helper"
23+
"github.com/stretchr/testify/require"
24+
)
25+
26+
func TestCompileWithBrokenSymLinks(t *testing.T) {
27+
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
28+
t.Cleanup(env.CleanUp)
29+
30+
// Install Arduino AVR Boards
31+
_, _, err := cli.Run("core", "install", "arduino:avr@1.8.6")
32+
require.NoError(t, err)
33+
34+
t.Run("NonSketchFileBroken", func(t *testing.T) {
35+
sketch, err := paths.New("testdata", "ValidSketchWithBrokenSymlink").Abs()
36+
require.NoError(t, err)
37+
_, _, err = cli.Run("compile", "-b", "arduino:avr:uno", sketch.String())
38+
require.NoError(t, err)
39+
})
40+
41+
t.Run("SketchFileBroken", func(t *testing.T) {
42+
sketch, err := paths.New("testdata", "ValidSketchWithBrokenSketchFileSymlink").Abs()
43+
require.NoError(t, err)
44+
_, _, err = cli.Run("compile", "-b", "arduino:avr:uno", sketch.String())
45+
require.Error(t, err)
46+
})
47+
48+
t.Run("NonInoSketchFileBroken", func(t *testing.T) {
49+
sketch, err := paths.New("testdata", "ValidSketchWithNonInoBrokenSketchFileSymlink").Abs()
50+
require.NoError(t, err)
51+
_, _, err = cli.Run("compile", "-b", "arduino:avr:uno", sketch.String())
52+
require.Error(t, err)
53+
})
54+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
void setup() {}
2+
void loop() {}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
broken

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /