Skip to content

Commit db3526b

Browse files
authored
Merge pull request #78 from arduino/per1234/stray-sketches
Add check for stray sketches in library
2 parents 0b0292d + 0c72384 commit db3526b

File tree

10 files changed

+119
-0
lines changed

10 files changed

+119
-0
lines changed

Diff for: check/checkconfigurations/checkconfigurations.go

+15
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,21 @@ var configurations = []Type{
926926
ErrorModes: nil,
927927
CheckFunction: checkfunctions.LibraryHasExe,
928928
},
929+
{
930+
ProjectType: projecttype.Library,
931+
Category: "structure",
932+
Subcategory: "",
933+
ID: "",
934+
Brief: "stray sketch",
935+
Description: "",
936+
MessageTemplate: "Sketch(es) found outside examples and extras folders: {{.}}. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-examples",
937+
DisableModes: nil,
938+
EnableModes: []checkmode.Type{checkmode.All},
939+
InfoModes: nil,
940+
WarningModes: []checkmode.Type{checkmode.Permissive},
941+
ErrorModes: []checkmode.Type{checkmode.Default},
942+
CheckFunction: checkfunctions.LibraryHasStraySketches,
943+
},
929944
{
930945
ProjectType: projecttype.Library,
931946
Category: "structure",

Diff for: check/checkfunctions/library.go

+40
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/arduino/arduino-check/check/checkresult"
3030
"github.com/arduino/arduino-check/configuration"
3131
"github.com/arduino/arduino-check/project/library"
32+
"github.com/arduino/arduino-check/project/sketch"
3233
"github.com/arduino/arduino-cli/arduino/libraries"
3334
"github.com/arduino/arduino-cli/arduino/utils"
3435
"github.com/arduino/go-properties-orderedmap"
@@ -990,6 +991,45 @@ func LibraryHasExe() (result checkresult.Type, output string) {
990991
return checkresult.Pass, ""
991992
}
992993

994+
// LibraryHasStraySketches checks for sketches outside the `examples` and `extras` folders.
995+
func LibraryHasStraySketches() (result checkresult.Type, output string) {
996+
straySketchPaths := []string{}
997+
if sketch.ContainsMainSketchFile(checkdata.ProjectPath()) { // Check library root.
998+
straySketchPaths = append(straySketchPaths, checkdata.ProjectPath().String())
999+
}
1000+
1001+
// Check subfolders.
1002+
projectPathListing, err := checkdata.ProjectPath().ReadDir()
1003+
if err != nil {
1004+
panic(err)
1005+
}
1006+
projectPathListing.FilterDirs()
1007+
1008+
for _, topLevelSubfolder := range projectPathListing {
1009+
if topLevelSubfolder.Base() == "examples" || topLevelSubfolder.Base() == "extras" {
1010+
continue // Skip valid sketch locations.
1011+
}
1012+
1013+
topLevelSubfolderRecursiveListing, err := topLevelSubfolder.ReadDirRecursive()
1014+
if err != nil {
1015+
panic(err)
1016+
}
1017+
topLevelSubfolderRecursiveListing.FilterDirs()
1018+
1019+
for _, subfolder := range topLevelSubfolderRecursiveListing {
1020+
if sketch.ContainsMainSketchFile(subfolder) {
1021+
straySketchPaths = append(straySketchPaths, subfolder.String())
1022+
}
1023+
}
1024+
}
1025+
1026+
if len(straySketchPaths) > 0 {
1027+
return checkresult.Fail, strings.Join(straySketchPaths, ", ")
1028+
}
1029+
1030+
return checkresult.Pass, ""
1031+
}
1032+
9931033
// ProhibitedCharactersInLibraryFolderName checks for prohibited characters in the library folder name.
9941034
func ProhibitedCharactersInLibraryFolderName() (result checkresult.Type, output string) {
9951035
if !validProjectPathBaseName(checkdata.ProjectPath().Base()) {

Diff for: check/checkfunctions/library_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,18 @@ func TestLibraryHasExe(t *testing.T) {
292292

293293
checkLibraryCheckFunction(LibraryHasExe, testTables, t)
294294
}
295+
296+
func TestLibraryHasStraySketches(t *testing.T) {
297+
testTables := []libraryCheckFunctionTestTable{
298+
{"Sketch in root", "SketchInRoot", checkresult.Fail, ""},
299+
{"Sketch in subfolder", "MisspelledExamplesFolder", checkresult.Fail, ""},
300+
{"Sketch in legit location", "ExamplesFolder", checkresult.Pass, ""},
301+
{"No sketches", "Recursive", checkresult.Pass, ""},
302+
}
303+
304+
checkLibraryCheckFunction(LibraryHasStraySketches, testTables, t)
305+
}
306+
295307
func TestProhibitedCharactersInLibraryFolderName(t *testing.T) {
296308
testTables := []libraryCheckFunctionTestTable{
297309
{"Has prohibited characters", "Prohibited CharactersInFolderName", checkresult.Fail, ""},
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,9 @@
1+
name=SketchInRoot
2+
version=1.0.0
3+
author=Cristian Maglie <[email protected]>, Pippo Pluto <[email protected]>
4+
maintainer=Cristian Maglie <[email protected]>
5+
sentence=A library that makes coding a web server a breeze.
6+
paragraph=Supports HTTP1.1 and you can do GET and POST.
7+
category=Communication
8+
url=http://example.com/
9+
architectures=avr

Diff for: check/checkfunctions/testdata/libraries/SketchInRoot/src/SketchInRoot.h

Whitespace-only changes.

Diff for: project/sketch/sketch.go

+26
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ See: https://arduino.github.io/arduino-cli/latest/sketch-specification/
2020
package sketch
2121

2222
import (
23+
"fmt"
24+
2325
"github.com/arduino/arduino-cli/arduino/globals"
2426
"github.com/arduino/go-paths-helper"
2527
)
@@ -31,6 +33,30 @@ func HasMainFileValidExtension(filePath *paths.Path) bool {
3133
return hasMainFileValidExtension
3234
}
3335

36+
// ContainsMainSketchFile checks whether the provided path contains a file with valid main sketch file extension.
37+
func ContainsMainSketchFile(searchPath *paths.Path) bool {
38+
if searchPath.NotExist() {
39+
panic(fmt.Sprintf("Error: provided path %s does not exist.", searchPath))
40+
}
41+
if searchPath.IsNotDir() {
42+
panic(fmt.Sprintf("Error: provided path %s is not a directory.", searchPath))
43+
}
44+
45+
directoryListing, err := searchPath.ReadDir()
46+
if err != nil {
47+
panic(err)
48+
}
49+
50+
directoryListing.FilterOutDirs()
51+
for _, potentialHeaderFile := range directoryListing {
52+
if HasMainFileValidExtension(potentialHeaderFile) {
53+
return true
54+
}
55+
}
56+
57+
return false
58+
}
59+
3460
// HasSupportedExtension returns whether the file at the given path has any of the file extensions supported for source/header files of a sketch.
3561
func HasSupportedExtension(filePath *paths.Path) bool {
3662
_, hasAdditionalFileValidExtensions := globals.AdditionalFileValidExtensions[filePath.Ext()]

Diff for: project/sketch/sketch_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,30 @@
1616
package sketch
1717

1818
import (
19+
"os"
1920
"testing"
2021

2122
"github.com/arduino/go-paths-helper"
2223
"github.com/stretchr/testify/assert"
2324
)
2425

26+
var testDataPath *paths.Path
27+
28+
func init() {
29+
workingDirectory, _ := os.Getwd()
30+
testDataPath = paths.New(workingDirectory, "testdata")
31+
}
32+
2533
func TestHasMainFileValidExtension(t *testing.T) {
2634
assert.True(t, HasMainFileValidExtension(paths.New("/foo/bar.ino")))
2735
assert.False(t, HasMainFileValidExtension(paths.New("/foo/bar.h")))
2836
}
2937

38+
func TestContainsMainSketchFile(t *testing.T) {
39+
assert.True(t, ContainsMainSketchFile(testDataPath.Join("Valid")))
40+
assert.False(t, ContainsMainSketchFile(testDataPath.Join("ContainsNoMainSketchFile")))
41+
}
42+
3043
func TestHasSupportedExtension(t *testing.T) {
3144
assert.True(t, HasSupportedExtension(paths.New("/foo/bar.ino")))
3245
assert.True(t, HasSupportedExtension(paths.New("/foo/bar.h")))

Diff for: project/sketch/testdata/ContainsNoMainSketchFile/foo.bar

Whitespace-only changes.

Diff for: project/sketch/testdata/Valid/Valid.ino

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
void setup() {}
2+
void loop() {}

0 commit comments

Comments
 (0)