Skip to content

Commit 1cb146d

Browse files
committed
Add test for hang on loading library with symlink loop
1 parent d458040 commit 1cb146d

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

Diff for: arduino/libraries/loader_test.go

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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
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 libraries
17+
18+
import (
19+
"os"
20+
"testing"
21+
"time"
22+
23+
paths "github.com/arduino/go-paths-helper"
24+
"github.com/stretchr/testify/assert"
25+
"github.com/stretchr/testify/require"
26+
)
27+
28+
func TestSymlinkLoop(t *testing.T) {
29+
// Set up directory structure of test library.
30+
libraryPath, err := paths.TempDir().MkTempDir("TestSymlinkLoop")
31+
defer libraryPath.RemoveAll() // Clean up after the test.
32+
require.Nil(t, err)
33+
err = libraryPath.Join("TestSymlinkLoop.h").WriteFile([]byte{})
34+
require.Nil(t, err)
35+
examplesPath := libraryPath.Join("examples")
36+
err = examplesPath.Mkdir()
37+
require.Nil(t, err)
38+
39+
// It's probably most friendly for contributors using Windows to create the symlinks needed for the test on demand.
40+
err = os.Symlink(examplesPath.Join("..").String(), examplesPath.Join("UpGoer1").String())
41+
require.Nil(t, err, "This test must be run as administrator on Windows to have symlink creation privilege.")
42+
// It's necessary to have multiple symlinks to a parent directory to create the loop.
43+
err = os.Symlink(examplesPath.Join("..").String(), examplesPath.Join("UpGoer2").String())
44+
require.Nil(t, err)
45+
46+
// The failure condition is Load() never returning, testing for which requires setting up a timeout.
47+
done := make(chan bool)
48+
go func() {
49+
_, err = Load(libraryPath, User)
50+
done <- true
51+
}()
52+
53+
assert.Eventually(
54+
t,
55+
func() bool {
56+
select {
57+
case <-done:
58+
return true
59+
default:
60+
return false
61+
}
62+
},
63+
20*time.Second,
64+
10*time.Millisecond,
65+
"Infinite symlink loop while loading library",
66+
)
67+
require.Nil(t, err)
68+
}

0 commit comments

Comments
 (0)