Skip to content

Commit 0b0292d

Browse files
authored
Merge pull request #77 from arduino/per1234/src-incorrect-case-check
Add checks for incorrect src subfolder name case
2 parents c65d0cc + 0bcb1ff commit 0b0292d

File tree

17 files changed

+193
-10
lines changed

17 files changed

+193
-10
lines changed

Diff for: check/checkconfigurations/checkconfigurations.go

+30
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,21 @@ var configurations = []Type{
971971
ErrorModes: []checkmode.Type{checkmode.Default},
972972
CheckFunction: checkfunctions.LibraryFolderNameGTMaxLength,
973973
},
974+
{
975+
ProjectType: projecttype.Library,
976+
Category: "structure",
977+
Subcategory: "",
978+
ID: "",
979+
Brief: "incorrect src folder case",
980+
Description: "",
981+
MessageTemplate: "Incorrect src folder case. This will cause the library to not be recognized on case-sensitive operating systems. See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-root-folder",
982+
DisableModes: nil,
983+
EnableModes: []checkmode.Type{checkmode.Default},
984+
InfoModes: nil,
985+
WarningModes: nil,
986+
ErrorModes: []checkmode.Type{checkmode.Default},
987+
CheckFunction: checkfunctions.IncorrectLibrarySrcFolderNameCase,
988+
},
974989
{
975990
ProjectType: projecttype.Library,
976991
Category: "structure",
@@ -1046,6 +1061,21 @@ var configurations = []Type{
10461061
ErrorModes: []checkmode.Type{checkmode.Default},
10471062
CheckFunction: checkfunctions.RecursiveLibraryWithUtilityFolder,
10481063
},
1064+
{
1065+
ProjectType: projecttype.Sketch,
1066+
Category: "structure",
1067+
Subcategory: "",
1068+
ID: "",
1069+
Brief: "incorrect src folder case",
1070+
Description: "",
1071+
MessageTemplate: "Incorrect src folder case. This will cause the source files under it to not be compiled on case-sensitive operating systems. See: https://arduino.github.io/arduino-cli/latest/sketch-specification/#src-subfolder",
1072+
DisableModes: nil,
1073+
EnableModes: []checkmode.Type{checkmode.Default},
1074+
InfoModes: nil,
1075+
WarningModes: []checkmode.Type{checkmode.Default},
1076+
ErrorModes: []checkmode.Type{checkmode.Strict},
1077+
CheckFunction: checkfunctions.IncorrectSketchSrcFolderNameCase,
1078+
},
10491079
{
10501080
ProjectType: projecttype.Sketch,
10511081
Category: "structure",

Diff for: check/checkfunctions/library.go

+24-10
Original file line numberDiff line numberDiff line change
@@ -904,16 +904,8 @@ func LibraryPropertiesMisspelledOptionalField() (result checkresult.Type, output
904904

905905
// LibraryInvalid checks whether the provided path is a valid library.
906906
func LibraryInvalid() (result checkresult.Type, output string) {
907-
directoryListing, err := checkdata.LoadedLibrary().SourceDir.ReadDir()
908-
if err != nil {
909-
panic(err)
910-
}
911-
912-
directoryListing.FilterOutDirs()
913-
for _, potentialHeaderFile := range directoryListing {
914-
if library.HasHeaderFileValidExtension(potentialHeaderFile) {
915-
return checkresult.Pass, ""
916-
}
907+
if library.ContainsHeaderFile(checkdata.LoadedLibrary().SourceDir) {
908+
return checkresult.Pass, ""
917909
}
918910

919911
return checkresult.Fail, ""
@@ -1016,6 +1008,28 @@ func LibraryFolderNameGTMaxLength() (result checkresult.Type, output string) {
10161008
return checkresult.Pass, ""
10171009
}
10181010

1011+
// IncorrectLibrarySrcFolderNameCase checks for incorrect case of src subfolder name in recursive format libraries.
1012+
func IncorrectLibrarySrcFolderNameCase() (result checkresult.Type, output string) {
1013+
if library.ContainsMetadataFile(checkdata.ProjectPath()) && library.ContainsHeaderFile(checkdata.ProjectPath()) {
1014+
// Flat layout, so no special treatment of src subfolder.
1015+
return checkresult.NotRun, ""
1016+
}
1017+
1018+
// The library is intended to have the recursive layout.
1019+
directoryListing, err := checkdata.ProjectPath().ReadDir()
1020+
if err != nil {
1021+
panic(err)
1022+
}
1023+
directoryListing.FilterDirs()
1024+
1025+
path, found := containsIncorrectPathBaseCase(directoryListing, "src")
1026+
if found {
1027+
return checkresult.Fail, path.String()
1028+
}
1029+
1030+
return checkresult.Pass, ""
1031+
}
1032+
10191033
// MisspelledExamplesFolderName checks for incorrectly spelled `examples` folder name.
10201034
func MisspelledExamplesFolderName() (result checkresult.Type, output string) {
10211035
directoryListing, err := checkdata.ProjectPath().ReadDir()

Diff for: check/checkfunctions/library_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,16 @@ func TestLibraryFolderNameGTMaxLength(t *testing.T) {
310310
checkLibraryCheckFunction(LibraryFolderNameGTMaxLength, testTables, t)
311311
}
312312

313+
func TestIncorrectLibrarySrcFolderNameCase(t *testing.T) {
314+
testTables := []libraryCheckFunctionTestTable{
315+
{"Flat, not precompiled", "Flat", checkresult.NotRun, ""},
316+
{"Incorrect case", "IncorrectSrcFolderNameCase", checkresult.Fail, ""},
317+
{"Correct case", "Recursive", checkresult.Pass, ""},
318+
}
319+
320+
checkLibraryCheckFunction(IncorrectLibrarySrcFolderNameCase, testTables, t)
321+
}
322+
313323
func TestMisspelledExamplesFolderName(t *testing.T) {
314324
testTables := []libraryCheckFunctionTestTable{
315325
{"Correctly spelled", "ExamplesFolder", checkresult.Pass, ""},

Diff for: check/checkfunctions/sketch.go

+16
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,22 @@ import (
2525
"github.com/arduino/arduino-check/project/sketch"
2626
)
2727

28+
// IncorrectSketchSrcFolderNameCase checks for incorrect case of src subfolder name in recursive format libraries.
29+
func IncorrectSketchSrcFolderNameCase() (result checkresult.Type, output string) {
30+
directoryListing, err := checkdata.ProjectPath().ReadDir()
31+
if err != nil {
32+
panic(err)
33+
}
34+
directoryListing.FilterDirs()
35+
36+
path, found := containsIncorrectPathBaseCase(directoryListing, "src")
37+
if found {
38+
return checkresult.Fail, path.String()
39+
}
40+
41+
return checkresult.Pass, ""
42+
}
43+
2844
// ProhibitedCharactersInSketchFileName checks for prohibited characters in the sketch file names.
2945
func ProhibitedCharactersInSketchFileName() (result checkresult.Type, output string) {
3046
directoryListing, _ := checkdata.ProjectPath().ReadDir()

Diff for: check/checkfunctions/sketch_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ func checkSketchCheckFunction(checkFunction Type, testTables []sketchCheckFuncti
6060
}
6161
}
6262

63+
func TestIncorrectSketchSrcFolderNameCase(t *testing.T) {
64+
testTables := []sketchCheckFunctionTestTable{
65+
{"Incorrect case", "IncorrectSrcFolderNameCase", checkresult.Fail, ""},
66+
{"Correct case", "Valid", checkresult.Pass, ""},
67+
}
68+
69+
checkSketchCheckFunction(IncorrectSketchSrcFolderNameCase, testTables, t)
70+
}
71+
6372
func TestProhibitedCharactersInSketchFileName(t *testing.T) {
6473
testTables := []sketchCheckFunctionTestTable{
6574
{"Has prohibited characters", "ProhibitedCharactersInFileName", checkresult.Fail, "^Prohibited CharactersInFileName.h$"},

Diff for: check/checkfunctions/testdata/libraries/IncorrectSrcFolderNameCase/SRC/IncorrectSrcFolderNameCase.h

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=IncorrectSrcFolderNameCase
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
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
void setup() {}
2+
void loop() {}

Diff for: check/checkfunctions/testdata/sketches/IncorrectSrcFolderNameCase/SRC/src.cpp

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

Diff for: check/checkfunctions/testdata/sketches/SrcSubfolder/src/src.cpp

Whitespace-only changes.

Diff for: project/library/library.go

+50
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package library
1818

1919
import (
20+
"fmt"
21+
2022
"github.com/arduino/go-paths-helper"
2123
)
2224

@@ -35,6 +37,30 @@ func HasHeaderFileValidExtension(filePath *paths.Path) bool {
3537
return hasHeaderFileValidExtension
3638
}
3739

40+
// ContainsHeaderFile checks whether the provided path contains a file with valid header extension.
41+
func ContainsHeaderFile(searchPath *paths.Path) bool {
42+
if searchPath.NotExist() {
43+
panic(fmt.Sprintf("Error: provided path %s does not exist.", searchPath))
44+
}
45+
if searchPath.IsNotDir() {
46+
panic(fmt.Sprintf("Error: provided path %s is not a directory.", searchPath))
47+
}
48+
49+
directoryListing, err := searchPath.ReadDir()
50+
if err != nil {
51+
panic(err)
52+
}
53+
54+
directoryListing.FilterOutDirs()
55+
for _, potentialHeaderFile := range directoryListing {
56+
if HasHeaderFileValidExtension(potentialHeaderFile) {
57+
return true
58+
}
59+
}
60+
61+
return false
62+
}
63+
3864
// See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-metadata
3965
var metadataFilenames = map[string]struct{}{
4066
"library.properties": empty,
@@ -49,6 +75,30 @@ func IsMetadataFile(filePath *paths.Path) bool {
4975
return false
5076
}
5177

78+
// ContainsMetadataFile checks whether the provided path contains an Arduino library metadata file.
79+
func ContainsMetadataFile(searchPath *paths.Path) bool {
80+
if searchPath.NotExist() {
81+
panic(fmt.Sprintf("Error: provided path %s does not exist.", searchPath))
82+
}
83+
if searchPath.IsNotDir() {
84+
panic(fmt.Sprintf("Error: provided path %s is not a directory.", searchPath))
85+
}
86+
87+
directoryListing, err := searchPath.ReadDir()
88+
if err != nil {
89+
panic(err)
90+
}
91+
92+
directoryListing.FilterOutDirs()
93+
for _, potentialMetadataFile := range directoryListing {
94+
if IsMetadataFile(potentialMetadataFile) {
95+
return true
96+
}
97+
}
98+
99+
return false
100+
}
101+
52102
// See: https://arduino.github.io/arduino-cli/latest/library-specification/#library-examples
53103
var examplesFolderValidNames = map[string]struct{}{
54104
"examples": empty,

Diff for: project/library/library_test.go

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// This file is part of arduino-check.
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-check.
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 library
17+
18+
import (
19+
"os"
20+
"testing"
21+
22+
"github.com/arduino/go-paths-helper"
23+
"github.com/stretchr/testify/assert"
24+
)
25+
26+
var testDataPath *paths.Path
27+
28+
func init() {
29+
workingDirectory, _ := os.Getwd()
30+
testDataPath = paths.New(workingDirectory, "testdata")
31+
}
32+
33+
func TestContainsHeaderFile(t *testing.T) {
34+
assert.True(t, ContainsHeaderFile(testDataPath.Join("ContainsHeaderFile")))
35+
assert.False(t, ContainsHeaderFile(testDataPath.Join("ContainsNoHeaderFile")))
36+
}
37+
38+
func TestContainsMetadataFile(t *testing.T) {
39+
assert.True(t, ContainsMetadataFile(testDataPath.Join("ContainsMetadataFile")))
40+
assert.False(t, ContainsMetadataFile(testDataPath.Join("ContainsNoMetadataFile")))
41+
}

Diff for: project/library/testdata/ContainsHeaderFile/foo.h

Whitespace-only changes.

Diff for: project/library/testdata/ContainsMetadataFile/library.properties

Whitespace-only changes.

Diff for: project/library/testdata/ContainsNoHeaderFile/foo.bar

Whitespace-only changes.

Diff for: project/library/testdata/ContainsNoMetadataFile/foo.bar

Whitespace-only changes.

0 commit comments

Comments
 (0)