From e98b7d31b118047fd80c39937685e751900e3aaf Mon Sep 17 00:00:00 2001 From: per1234 Date: Sun, 30 May 2021 06:20:25 -0700 Subject: [PATCH] Add rule for 3rd party library.properties maintainer using "Arduino" 3rd party libraries are not maintained by Arduino. Even when 3rd party libraries are based on official libraries, it is best practice for the library.properties `maintainer` field to be updated to reflect the true maintainer of the project. There is already rule LP027 to promote accuracy in documenting maintainership by prohibiting maintainer values that start with "Arduino". However, this might not cover all inaccurate maintainer declarations. For this reason, a new rule (LP057) is added here to prohibit maintainer values in 3rd party libraries from containing the term "Arduino" anywhere (case insensitive). Violations of this rule only result in an error when in "strict" compliance mode. --- ...-library-properties-definitions-schema.json | 15 +++++++++------ .../librarypropertiesschemas_test.go | 3 +++ .../ruleconfiguration/ruleconfiguration.go | 16 ++++++++++++++++ internal/rule/rulefunction/library.go | 18 ++++++++++++++++++ internal/rule/rulefunction/library_test.go | 11 +++++++++++ .../library.properties | 10 ++++++++++ .../src/MaintainerContainsArduino.h | 0 internal/rule/schema/schemadata/bindata.go | 15 +++++++++------ 8 files changed, 76 insertions(+), 12 deletions(-) create mode 100644 internal/rule/rulefunction/testdata/libraries/MaintainerContainsArduino/library.properties create mode 100644 internal/rule/rulefunction/testdata/libraries/MaintainerContainsArduino/src/MaintainerContainsArduino.h diff --git a/etc/schemas/arduino-library-properties-definitions-schema.json b/etc/schemas/arduino-library-properties-definitions-schema.json index 90e4d294..5a38ff6b 100644 --- a/etc/schemas/arduino-library-properties-definitions-schema.json +++ b/etc/schemas/arduino-library-properties-definitions-schema.json @@ -10,6 +10,11 @@ "not": { "pattern": "^[aA][rR][dD][uU][iI][nN][oO].*$" } + }, + "notContainsArduino": { + "not": { + "pattern": "^.+[aA][rR][dD][uU][iI][nN][oO].*$" + } } } }, @@ -77,11 +82,6 @@ "pattern": "^.* .*$" } }, - "notContainsArduino": { - "not": { - "pattern": "^.+[aA][rR][dD][uU][iI][nN][oO].*$" - } - }, "notContainsSuperfluousTerms": { "not": { "pattern": "^.*[lL][iI][bB][rR][aA][rR][yY].*$" @@ -101,7 +101,7 @@ "$ref": "#/definitions/propertiesObjects/name/strict/definitions/patternObjects/notContainsSpaces" }, { - "$ref": "#/definitions/propertiesObjects/name/strict/definitions/patternObjects/notContainsArduino" + "$ref": "#/definitions/general/patternObjects/notContainsArduino" }, { "$ref": "#/definitions/propertiesObjects/name/strict/definitions/patternObjects/notContainsSuperfluousTerms" @@ -238,6 +238,9 @@ "allOf": [ { "$ref": "#/definitions/propertiesObjects/maintainer/specification/object" + }, + { + "$ref": "#/definitions/general/patternObjects/notContainsArduino" } ] } diff --git a/internal/project/library/libraryproperties/librarypropertiesschemas_test.go b/internal/project/library/libraryproperties/librarypropertiesschemas_test.go index f17270ca..4fde2c83 100644 --- a/internal/project/library/libraryproperties/librarypropertiesschemas_test.go +++ b/internal/project/library/libraryproperties/librarypropertiesschemas_test.go @@ -291,8 +291,11 @@ func TestPropertiesVersionPattern(t *testing.T) { func TestPropertiesMaintainerPattern(t *testing.T) { testTables := []propertyValueTestTable{ {"Starts with arduino", "arduinofoo", compliancelevel.Permissive, assert.False}, + {"Contains arduino", "fooarduinobar", compliancelevel.Permissive, assert.False}, {"Starts with arduino", "arduinofoo", compliancelevel.Specification, assert.True}, + {"Contains arduino", "fooarduinobar", compliancelevel.Specification, assert.False}, {"Starts with arduino", "arduinofoo", compliancelevel.Strict, assert.True}, + {"Contains arduino", "fooarduinobar", compliancelevel.Strict, assert.True}, } checkPropertyPatternMismatch("maintainer", testTables, t) diff --git a/internal/rule/ruleconfiguration/ruleconfiguration.go b/internal/rule/ruleconfiguration/ruleconfiguration.go index e0fc1c3d..208aa9f9 100644 --- a/internal/rule/ruleconfiguration/ruleconfiguration.go +++ b/internal/rule/ruleconfiguration/ruleconfiguration.go @@ -681,6 +681,22 @@ var configurations = []Type{ ErrorModes: []rulemode.Type{rulemode.Strict}, RuleFunction: rulefunction.LibraryPropertiesMaintainerFieldStartsWithArduino, }, + { + ProjectType: projecttype.Library, + SuperprojectType: projecttype.All, + Category: "library.properties", + Subcategory: "maintainer field", + ID: "LP057", + Brief: `maintainer contains "Arduino"`, + Description: "Case insensitive.", + MessageTemplate: `library.properties maintainer value {{.}} contains "Arduino". 3rd party libraries are not maintained by Arduino.`, + DisableModes: []rulemode.Type{rulemode.Official}, + EnableModes: []rulemode.Type{rulemode.Default}, + InfoModes: nil, + WarningModes: []rulemode.Type{rulemode.Default}, + ErrorModes: []rulemode.Type{rulemode.Strict}, + RuleFunction: rulefunction.LibraryPropertiesMaintainerFieldContainsArduino, + }, { ProjectType: projecttype.Library, SuperprojectType: projecttype.All, diff --git a/internal/rule/rulefunction/library.go b/internal/rule/rulefunction/library.go index 0417301f..b0cbf248 100644 --- a/internal/rule/rulefunction/library.go +++ b/internal/rule/rulefunction/library.go @@ -744,6 +744,24 @@ func LibraryPropertiesMaintainerFieldStartsWithArduino() (result ruleresult.Type return ruleresult.Pass, "" } +// LibraryPropertiesMaintainerFieldContainsArduino checks if the library.properties "maintainer" value contains "Arduino". +func LibraryPropertiesMaintainerFieldContainsArduino() (result ruleresult.Type, output string) { + if projectdata.LibraryPropertiesLoadError() != nil { + return ruleresult.NotRun, "Couldn't load library.properties" + } + + maintainer, ok := projectdata.LibraryProperties().GetOk("maintainer") + if !ok { + return ruleresult.NotRun, "Field not present" + } + + if schema.ValidationErrorMatch("^#/maintainer$", "/patternObjects/notContainsArduino", "", "", projectdata.LibraryPropertiesSchemaValidationResult()[compliancelevel.Strict]) { + return ruleresult.Fail, maintainer + } + + return ruleresult.Pass, "" +} + // LibraryPropertiesEmailFieldAsMaintainerAlias checks whether the library.properties "email" field is being used as an alias for the "maintainer" field. func LibraryPropertiesEmailFieldAsMaintainerAlias() (result ruleresult.Type, output string) { if projectdata.LibraryPropertiesLoadError() != nil { diff --git a/internal/rule/rulefunction/library_test.go b/internal/rule/rulefunction/library_test.go index b1f30462..c6df14e2 100644 --- a/internal/rule/rulefunction/library_test.go +++ b/internal/rule/rulefunction/library_test.go @@ -568,6 +568,17 @@ func TestLibraryPropertiesMaintainerFieldStartsWithArduino(t *testing.T) { checkLibraryRuleFunction(LibraryPropertiesMaintainerFieldStartsWithArduino, testTables, t) } +func TestLibraryPropertiesMaintainerFieldContainsArduino(t *testing.T) { + testTables := []libraryRuleFunctionTestTable{ + {"Invalid", "InvalidLibraryProperties", ruleresult.NotRun, ""}, + {"Legacy", "Legacy", ruleresult.NotRun, ""}, + {"Maintainer field contains Arduino", "MaintainerContainsArduino", ruleresult.Fail, ""}, + {"Valid", "Recursive", ruleresult.Pass, ""}, + } + + checkLibraryRuleFunction(LibraryPropertiesMaintainerFieldContainsArduino, testTables, t) +} + func TestLibraryPropertiesEmailFieldAsMaintainerAlias(t *testing.T) { testTables := []libraryRuleFunctionTestTable{ {"Unable to load", "InvalidLibraryProperties", ruleresult.NotRun, ""}, diff --git a/internal/rule/rulefunction/testdata/libraries/MaintainerContainsArduino/library.properties b/internal/rule/rulefunction/testdata/libraries/MaintainerContainsArduino/library.properties new file mode 100644 index 00000000..1415c48a --- /dev/null +++ b/internal/rule/rulefunction/testdata/libraries/MaintainerContainsArduino/library.properties @@ -0,0 +1,10 @@ +name=MaintainerContainsArduino +version=1.0.0 +author=Cristian Maglie , Pippo Pluto +maintainer=Cristian "Arduino Wizard" Maglie +sentence=A library that makes coding a web server a breeze. +paragraph=Supports HTTP1.1 and you can do GET and POST. +category=Communication +url=http://example.com/ +architectures=avr +includes=Recursive.h diff --git a/internal/rule/rulefunction/testdata/libraries/MaintainerContainsArduino/src/MaintainerContainsArduino.h b/internal/rule/rulefunction/testdata/libraries/MaintainerContainsArduino/src/MaintainerContainsArduino.h new file mode 100644 index 00000000..e69de29b diff --git a/internal/rule/schema/schemadata/bindata.go b/internal/rule/schema/schemadata/bindata.go index 76c99be6..fae8d4cd 100644 --- a/internal/rule/schema/schemadata/bindata.go +++ b/internal/rule/schema/schemadata/bindata.go @@ -1429,6 +1429,11 @@ var _arduinoLibraryPropertiesDefinitionsSchemaJson = []byte(`{ "not": { "pattern": "^[aA][rR][dD][uU][iI][nN][oO].*$" } + }, + "notContainsArduino": { + "not": { + "pattern": "^.+[aA][rR][dD][uU][iI][nN][oO].*$" + } } } }, @@ -1496,11 +1501,6 @@ var _arduinoLibraryPropertiesDefinitionsSchemaJson = []byte(`{ "pattern": "^.* .*$" } }, - "notContainsArduino": { - "not": { - "pattern": "^.+[aA][rR][dD][uU][iI][nN][oO].*$" - } - }, "notContainsSuperfluousTerms": { "not": { "pattern": "^.*[lL][iI][bB][rR][aA][rR][yY].*$" @@ -1520,7 +1520,7 @@ var _arduinoLibraryPropertiesDefinitionsSchemaJson = []byte(`{ "$ref": "#/definitions/propertiesObjects/name/strict/definitions/patternObjects/notContainsSpaces" }, { - "$ref": "#/definitions/propertiesObjects/name/strict/definitions/patternObjects/notContainsArduino" + "$ref": "#/definitions/general/patternObjects/notContainsArduino" }, { "$ref": "#/definitions/propertiesObjects/name/strict/definitions/patternObjects/notContainsSuperfluousTerms" @@ -1657,6 +1657,9 @@ var _arduinoLibraryPropertiesDefinitionsSchemaJson = []byte(`{ "allOf": [ { "$ref": "#/definitions/propertiesObjects/maintainer/specification/object" + }, + { + "$ref": "#/definitions/general/patternObjects/notContainsArduino" } ] }