diff --git a/etc/schemas/arduino-platform-txt-definitions-schema.json b/etc/schemas/arduino-platform-txt-definitions-schema.json index 7938c5a0..3641bec5 100644 --- a/etc/schemas/arduino-platform-txt-definitions-schema.json +++ b/etc/schemas/arduino-platform-txt-definitions-schema.json @@ -877,7 +877,7 @@ "type": "string" }, { - "pattern": "^.+:.+$" + "$ref": "#/definitions/patternObjects/resourceReference" } ] } @@ -910,6 +910,194 @@ } } }, + "pluggableMonitorPattern": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPattern/base/object" + }, + { + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPatternProtocol/permissive/object" + } + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPattern/base/object" + }, + { + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPatternProtocol/specification/object" + } + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPattern/base/object" + }, + { + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPatternProtocol/strict/object" + } + } + ] + } + } + }, + "pluggableMonitorPatternProtocol": { + "base": { + "object": { + "allOf": [ + { + "type": "string" + }, + { + "minLength": 1 + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPatternProtocol/base/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPatternProtocol/base/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPatternProtocol/base/object" + } + ] + } + } + }, + "pluggableMonitorRequired": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequired/base/object" + }, + { + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequiredProtocol/permissive/object" + } + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequired/base/object" + }, + { + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequiredProtocol/specification/object" + } + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequired/base/object" + }, + { + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequiredProtocol/strict/object" + } + } + ] + } + } + }, + "pluggableMonitorRequiredProtocol": { + "base": { + "object": { + "allOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/patternObjects/resourceReference" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequiredProtocol/base/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequiredProtocol/base/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequiredProtocol/base/object" + } + ] + } + } + }, "tools": { "base": { "object": { @@ -1571,6 +1759,11 @@ } } }, + "patternObjects": { + "resourceReference": { + "pattern": "^.+:.+$" + } + }, "requiredObjects": { "root": { "base": { diff --git a/etc/schemas/arduino-platform-txt-permissive-schema.json b/etc/schemas/arduino-platform-txt-permissive-schema.json index d7c376da..e26f8821 100644 --- a/etc/schemas/arduino-platform-txt-permissive-schema.json +++ b/etc/schemas/arduino-platform-txt-permissive-schema.json @@ -57,6 +57,12 @@ "pluggable_discovery": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableDiscovery/permissive/object" }, + "pluggable_monitor.pattern": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableMonitorPattern/permissive/object" + }, + "pluggable_monitor.required": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableMonitorRequired/permissive/object" + }, "tools": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/tools/permissive/object" } diff --git a/etc/schemas/arduino-platform-txt-schema.json b/etc/schemas/arduino-platform-txt-schema.json index f63f9ad6..09328e56 100644 --- a/etc/schemas/arduino-platform-txt-schema.json +++ b/etc/schemas/arduino-platform-txt-schema.json @@ -57,6 +57,12 @@ "pluggable_discovery": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableDiscovery/specification/object" }, + "pluggable_monitor.pattern": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableMonitorPattern/specification/object" + }, + "pluggable_monitor.required": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableMonitorRequired/specification/object" + }, "tools": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/tools/specification/object" } diff --git a/etc/schemas/arduino-platform-txt-strict-schema.json b/etc/schemas/arduino-platform-txt-strict-schema.json index 59028505..445eca92 100644 --- a/etc/schemas/arduino-platform-txt-strict-schema.json +++ b/etc/schemas/arduino-platform-txt-strict-schema.json @@ -57,6 +57,12 @@ "pluggable_discovery": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableDiscovery/strict/object" }, + "pluggable_monitor.pattern": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableMonitorPattern/strict/object" + }, + "pluggable_monitor.required": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableMonitorRequired/strict/object" + }, "tools": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/tools/strict/object" } diff --git a/internal/project/platform/platformtxt/platformtxt.go b/internal/project/platform/platformtxt/platformtxt.go index 705bcf8b..2e93abce 100644 --- a/internal/project/platform/platformtxt/platformtxt.go +++ b/internal/project/platform/platformtxt/platformtxt.go @@ -59,8 +59,8 @@ func Validate(platformTxt *properties.Map) map[compliancelevel.Type]schema.Valid validation package. Even though platform.txt has a multi-level nested data structure, the format has the odd characteristic of allowing a key to be both an object and a string simultaneously, which is not compatible with Golang maps or JSON. So the - data structure used is a selective map, using a flat map except for the tools and pluggable_discovery keys, which - can contain any number of arbitrary subproperties which must be linted. + data structure used is a selective map, using a flat map except for the tools, pluggable_discovery, and + pluggable_monitor keys, which can contain any number of arbitrary subproperties which must be linted. */ platformTxtInterface := make(map[string]interface{}) keys := platformTxt.Keys() @@ -72,6 +72,10 @@ func Validate(platformTxt *properties.Map) map[compliancelevel.Type]schema.Valid // It is a pluggable_discovery.DISCOVERY_ID property. platformTxtInterface["pluggable_discovery"] = general.PropertiesToMap(platformTxt.SubTree("pluggable_discovery"), 2) } + } else if strings.HasPrefix(key, "pluggable_monitor.pattern.") { + platformTxtInterface["pluggable_monitor.pattern"] = general.PropertiesToMap(platformTxt.SubTree("pluggable_monitor.pattern"), 1) + } else if strings.HasPrefix(key, "pluggable_monitor.required.") { + platformTxtInterface["pluggable_monitor.required"] = general.PropertiesToMap(platformTxt.SubTree("pluggable_monitor.required"), 1) } else if strings.HasPrefix(key, "tools.") { platformTxtInterface["tools"] = general.PropertiesToMap(platformTxt.SubTree("tools"), 4) } else { diff --git a/internal/project/platform/platformtxt/platformtxt_test.go b/internal/project/platform/platformtxt/platformtxt_test.go index 5a76680d..bfe7b300 100644 --- a/internal/project/platform/platformtxt/platformtxt_test.go +++ b/internal/project/platform/platformtxt/platformtxt_test.go @@ -39,36 +39,38 @@ func init() { testDataPath = workingDirectory.Join("testdata") validPlatformTxtMap = map[string]string{ - "name": "Arduino AVR Boards", - "version": "1.8.3", - "compiler.warning_flags.none": "asdf", - "compiler.warning_flags.default": "asdf", - "compiler.warning_flags.more": "asdf", - "compiler.warning_flags.all": "asdf", - "compiler.c.extra_flags": "", - "compiler.c.elf.extra_flags": "", - "compiler.S.extra_flags": "", - "compiler.cpp.extra_flags": "", - "compiler.ar.extra_flags": "", - "compiler.objcopy.eep.extra_flags": "", - "compiler.elf2hex.extra_flags": "", - "recipe.c.o.pattern": "asdf {compiler.c.extra_flags}", - "recipe.cpp.o.pattern": "asdf {compiler.cpp.extra_flags}", - "recipe.S.o.pattern": "asdf {compiler.S.extra_flags}", - "recipe.ar.pattern": "asdf {compiler.ar.extra_flags}", - "recipe.c.combine.pattern": "asdf {compiler.c.elf.extra_flags}", - "recipe.objcopy.eep.pattern": "asdf", - "recipe.objcopy.hex.pattern": "asdf", - "recipe.output.tmp_file": "asdf", - "recipe.output.save_file": "asdf", - "recipe.size.pattern": "asdf", - "recipe.size.regex": "asdf", - "recipe.size.regex.data": "asdf", - "pluggable_discovery.required.0": "builtin:serial-discovery", - "pluggable_discovery.required.1": "builtin:mdns-discovery", - "tools.avrdude.upload.params.verbose": "-v", - "tools.avrdude.upload.params.quiet": "-q -q", - "tools.avrdude.upload.pattern": "asdf", + "name": "Arduino AVR Boards", + "version": "1.8.3", + "compiler.warning_flags.none": "asdf", + "compiler.warning_flags.default": "asdf", + "compiler.warning_flags.more": "asdf", + "compiler.warning_flags.all": "asdf", + "compiler.c.extra_flags": "", + "compiler.c.elf.extra_flags": "", + "compiler.S.extra_flags": "", + "compiler.cpp.extra_flags": "", + "compiler.ar.extra_flags": "", + "compiler.objcopy.eep.extra_flags": "", + "compiler.elf2hex.extra_flags": "", + "recipe.c.o.pattern": "asdf {compiler.c.extra_flags}", + "recipe.cpp.o.pattern": "asdf {compiler.cpp.extra_flags}", + "recipe.S.o.pattern": "asdf {compiler.S.extra_flags}", + "recipe.ar.pattern": "asdf {compiler.ar.extra_flags}", + "recipe.c.combine.pattern": "asdf {compiler.c.elf.extra_flags}", + "recipe.objcopy.eep.pattern": "asdf", + "recipe.objcopy.hex.pattern": "asdf", + "recipe.output.tmp_file": "asdf", + "recipe.output.save_file": "asdf", + "recipe.size.pattern": "asdf", + "recipe.size.regex": "asdf", + "recipe.size.regex.data": "asdf", + "pluggable_discovery.required.0": "builtin:serial-discovery", + "pluggable_discovery.required.1": "builtin:mdns-discovery", + "pluggable_monitor.required.carrier-pigeon": "coop:coo", + "pluggable_monitor.required.network": "foo:network-monitor", + "tools.avrdude.upload.params.verbose": "-v", + "tools.avrdude.upload.params.quiet": "-q -q", + "tools.avrdude.upload.pattern": "asdf", } } diff --git a/internal/project/platform/platformtxt/platformtxtschema_test.go b/internal/project/platform/platformtxt/platformtxtschema_test.go index ab17751a..72144a2f 100644 --- a/internal/project/platform/platformtxt/platformtxtschema_test.go +++ b/internal/project/platform/platformtxt/platformtxtschema_test.go @@ -124,6 +124,10 @@ func TestMinLength(t *testing.T) { {"recipe.preproc.macros", "recipe\\.preproc\\.macros", 1, compliancelevel.Permissive}, {"recipe.preproc.macros", "recipe\\.preproc\\.macros", 1, compliancelevel.Specification}, {"recipe.preproc.macros", "recipe\\.preproc\\.macros", 1, compliancelevel.Strict}, + + {"pluggable_monitor.pattern.foo", "pluggable_monitor\\.pattern/foo", 1, compliancelevel.Permissive}, + {"pluggable_monitor.pattern.foo", "pluggable_monitor\\.pattern/foo", 1, compliancelevel.Specification}, + {"pluggable_monitor.pattern.foo", "pluggable_monitor\\.pattern/foo", 1, compliancelevel.Strict}, } // Test schema validation results with value length < minimum. @@ -453,6 +457,13 @@ func TestPattern(t *testing.T) { {"pluggable_discovery.required.1", "pluggable_discovery/required", "foo", compliancelevel.Permissive, assert.True}, {"pluggable_discovery.required.1", "pluggable_discovery/required", "foo", compliancelevel.Specification, assert.True}, {"pluggable_discovery.required.1", "pluggable_discovery/required", "foo", compliancelevel.Strict, assert.True}, + + {"pluggable_monitor.required.foo", "pluggable_monitor\\.required/foo", "bar:baz", compliancelevel.Permissive, assert.False}, + {"pluggable_monitor.required.foo", "pluggable_monitor\\.required/foo", "bar:baz", compliancelevel.Specification, assert.False}, + {"pluggable_monitor.required.foo", "pluggable_monitor\\.required/foo", "bar:baz", compliancelevel.Strict, assert.False}, + {"pluggable_monitor.required.foo", "pluggable_monitor\\.required/foo", "bar", compliancelevel.Permissive, assert.True}, + {"pluggable_monitor.required.foo", "pluggable_monitor\\.required/foo", "bar", compliancelevel.Specification, assert.True}, + {"pluggable_monitor.required.foo", "pluggable_monitor\\.required/foo", "bar", compliancelevel.Strict, assert.True}, } for _, testTable := range testTables { diff --git a/internal/project/platform/platformtxt/testdata/valid/platform.txt b/internal/project/platform/platformtxt/testdata/valid/platform.txt index ddbab5ea..376e5a3c 100644 --- a/internal/project/platform/platformtxt/testdata/valid/platform.txt +++ b/internal/project/platform/platformtxt/testdata/valid/platform.txt @@ -25,6 +25,8 @@ recipe.size.regex=asdf recipe.size.regex.data=asdf pluggable_discovery.required.0=builtin:serial-discovery pluggable_discovery.required.1=builtin:mdns-discovery +pluggable_monitor.required.carrier-pigeon=coop:coo +pluggable_monitor.required.network=foo:network-monitor tools.avrdude.upload.params.verbose=-v tools.avrdude.upload.params.quiet=-q -q tools.avrdude.upload.pattern=asdf diff --git a/internal/rule/ruleconfiguration/ruleconfiguration.go b/internal/rule/ruleconfiguration/ruleconfiguration.go index e162284e..6900e711 100644 --- a/internal/rule/ruleconfiguration/ruleconfiguration.go +++ b/internal/rule/ruleconfiguration/ruleconfiguration.go @@ -2864,6 +2864,40 @@ var configurations = []Type{ ErrorModes: []rulemode.Type{rulemode.Default}, RuleFunction: rulefunction.PlatformTxtPluggableDiscoveryDiscoveryIDPatternMissing, }, + { + ProjectType: projecttype.Platform, + SuperprojectType: projecttype.All, + Category: "configuration files", + Subcategory: "platform.txt", + ID: "PF094", + Brief: "pluggable_monitor.pattern.PROTOCOL_ID < min length", + Description: "The `pluggable_monitor.pattern.PROTOCOL_ID` property in the platform's `platform.txt` configuration file is shorter than the minimum length.", + MessageTemplate: "pluggable_monitor.pattern.PROTOCOL_ID value for protocol(s) {{.}} is less than the minimum length.", + Reference: "https://arduino.github.io/arduino-cli/latest/platform-specification/#pluggable-monitor", + DisableModes: nil, + EnableModes: []rulemode.Type{rulemode.Default}, + InfoModes: nil, + WarningModes: nil, + ErrorModes: []rulemode.Type{rulemode.Default}, + RuleFunction: rulefunction.PlatformTxtPluggableMonitorPatternProtocolIDLTMinLength, + }, + { + ProjectType: projecttype.Platform, + SuperprojectType: projecttype.All, + Category: "configuration files", + Subcategory: "platform.txt", + ID: "PF095", + Brief: "invalid pluggable_monitor.required.PROTOCOL_ID format", + Description: "The tool dependency reference for a pluggable monitor in the platform's `platform.txt` configuration file has an invalid format.", + MessageTemplate: "Value for tool dependency reference of pluggable monitor protocol(s) {{.}} is invalid.", + Reference: "https://arduino.github.io/arduino-cli/latest/platform-specification/#pluggable-monitor", + DisableModes: nil, + EnableModes: []rulemode.Type{rulemode.Default}, + InfoModes: nil, + WarningModes: nil, + ErrorModes: []rulemode.Type{rulemode.Default}, + RuleFunction: rulefunction.PlatformTxtPluggableMonitorRequiredProtocolIDInvalid, + }, { ProjectType: projecttype.Platform, SuperprojectType: projecttype.All, diff --git a/internal/rule/rulefunction/platform.go b/internal/rule/rulefunction/platform.go index fd22ae12..bc5f093c 100644 --- a/internal/rule/rulefunction/platform.go +++ b/internal/rule/rulefunction/platform.go @@ -1736,6 +1736,62 @@ func PlatformTxtPluggableDiscoveryDiscoveryIDPatternMissing() (result ruleresult return ruleresult.Pass, "" } +// PlatformTxtPluggableMonitorPatternProtocolIDLTMinLength checks if the platform.txt pluggable_monitor.pattern.PROTOCOL_ID property value is less than the minimum length. +func PlatformTxtPluggableMonitorPatternProtocolIDLTMinLength() (result ruleresult.Type, output string) { + if !projectdata.PlatformTxtExists() { + return ruleresult.Skip, "Platform has no platform.txt" + } + + if projectdata.PlatformTxtLoadError() != nil { + return ruleresult.NotRun, "Couldn't load platform.txt" + } + + if projectdata.PlatformTxt().SubTree("pluggable_monitor.pattern").Size() == 0 { + return ruleresult.Skip, "Property not present" + } + + nonCompliant := []string{} + for _, protocol := range projectdata.PlatformTxt().SubTree("pluggable_monitor.pattern").Keys() { + if schema.PropertyLessThanMinLength("pluggable_monitor\\.pattern/"+protocol, projectdata.PlatformTxtSchemaValidationResult()[compliancelevel.Specification]) { + nonCompliant = append(nonCompliant, protocol) + } + } + + if len(nonCompliant) > 0 { + return ruleresult.Fail, strings.Join(nonCompliant, ", ") + } + + return ruleresult.Pass, "" +} + +// PlatformTxtPluggableMonitorRequiredProtocolIDInvalid checks if any of the pluggable monitor tool references have invalid format. +func PlatformTxtPluggableMonitorRequiredProtocolIDInvalid() (result ruleresult.Type, output string) { + if !projectdata.PlatformTxtExists() { + return ruleresult.Skip, "Platform has no platform.txt" + } + + if projectdata.PlatformTxtLoadError() != nil { + return ruleresult.NotRun, "Couldn't load platform.txt" + } + + if projectdata.PlatformTxt().SubTree("pluggable_monitor.required").Size() == 0 { + return ruleresult.Skip, "Property not present" + } + + nonCompliant := []string{} + for _, protocol := range projectdata.PlatformTxt().SubTree("pluggable_monitor.required").Keys() { + if schema.PropertyPatternMismatch("pluggable_monitor\\.required/"+protocol, projectdata.PlatformTxtSchemaValidationResult()[compliancelevel.Specification]) { + nonCompliant = append(nonCompliant, protocol) + } + } + + if len(nonCompliant) > 0 { + return ruleresult.Fail, strings.Join(nonCompliant, ", ") + } + + return ruleresult.Pass, "" +} + // PlatformTxtUploadFieldFieldNameGTMaxLength checks if any platform.txt tools.UPLOAD_RECIPE_ID.upload.field.FIELD_NAME property value is greater than the maximum length. func PlatformTxtUploadFieldFieldNameGTMaxLength() (result ruleresult.Type, output string) { if !projectdata.PlatformTxtExists() { diff --git a/internal/rule/rulefunction/platform_test.go b/internal/rule/rulefunction/platform_test.go index 6a5eed07..a62c3669 100644 --- a/internal/rule/rulefunction/platform_test.go +++ b/internal/rule/rulefunction/platform_test.go @@ -993,6 +993,30 @@ func TestPlatformTxtPluggableDiscoveryDiscoveryIDPatternMissing(t *testing.T) { checkPlatformRuleFunction(PlatformTxtPluggableDiscoveryDiscoveryIDPatternMissing, testTables, t) } +func TestPlatformTxtPluggableMonitorPatternProtocolIDLTMinLength(t *testing.T) { + testTables := []platformRuleFunctionTestTable{ + {"Missing", "missing-platform.txt", ruleresult.Skip, ""}, + {"Invalid", "invalid-platform.txt", ruleresult.NotRun, ""}, + {"Property absent", "no-pluggable-monitors-platform.txt", ruleresult.Skip, ""}, + {"Property LT min", "pluggable-monitor-pattern-protocol-id-LT-platform.txt", ruleresult.Fail, "^network, ble$"}, + {"Valid", "valid-with-manual-installation-pluggable-monitors-platform.txt", ruleresult.Pass, ""}, + } + + checkPlatformRuleFunction(PlatformTxtPluggableMonitorPatternProtocolIDLTMinLength, testTables, t) +} + +func TestPlatformTxtPluggableMonitorRequiredProtocolIDInvalid(t *testing.T) { + testTables := []platformRuleFunctionTestTable{ + {"Missing", "missing-platform.txt", ruleresult.Skip, ""}, + {"Invalid", "invalid-platform.txt", ruleresult.NotRun, ""}, + {"Property absent", "no-pluggable-monitors-platform.txt", ruleresult.Skip, ""}, + {"Property invalid", "invalid-pluggable-monitor-required-platform.txt", ruleresult.Fail, "^network, ble$"}, + {"Valid", "valid-platform.txt", ruleresult.Pass, ""}, + } + + checkPlatformRuleFunction(PlatformTxtPluggableMonitorRequiredProtocolIDInvalid, testTables, t) +} + func TestPlatformTxtUploadFieldFieldNameGTMaxLength(t *testing.T) { testTables := []platformRuleFunctionTestTable{ {"Missing", "missing-platform.txt", ruleresult.Skip, ""}, diff --git a/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-monitor-required-platform.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-monitor-required-platform.txt/boards.txt new file mode 100644 index 00000000..1866d3c4 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-monitor-required-platform.txt/boards.txt @@ -0,0 +1,23 @@ +buno.name=Buno +buno.build.board=BUNO +buno.build.core=arduino +buno.build.variant=standard +buno.upload.tool=avrdude +buno.upload.maximum_size=32256 +buno.upload.maximum_data_size=2048 + +uno.name=Arduino Uno +uno.build.board=UNO +uno.build.core=arduino +uno.build.variant=standard +uno.upload.tool=avrdude +uno.upload.maximum_size=32256 +uno.upload.maximum_data_size=2048 + +funo.name=Funo +funo.build.board=FUNO +funo.build.core=arduino +funo.build.variant=standard +funo.upload.tool=avrdude +funo.upload.maximum_size=32256 +funo.upload.maximum_data_size=2048 diff --git a/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-monitor-required-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-monitor-required-platform.txt/platform.txt new file mode 100644 index 00000000..cd619fda --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-monitor-required-platform.txt/platform.txt @@ -0,0 +1,60 @@ +name=Arduino AVR Boards +version=1.8.3 +compiler.warning_flags.none=asdf +compiler.warning_flags.default=asdf +compiler.warning_flags.more=asdf +compiler.warning_flags.all=asdf +compiler.optimization_flags.debug= +compiler.optimization_flags.release= +compiler.c.extra_flags= +compiler.c.elf.extra_flags= +compiler.S.extra_flags= +compiler.cpp.extra_flags= +compiler.ar.extra_flags= +compiler.objcopy.eep.extra_flags= +compiler.elf2hex.extra_flags= +recipe.c.o.pattern=asdf {compiler.c.extra_flags} +recipe.cpp.o.pattern=asdf {compiler.cpp.extra_flags} +recipe.S.o.pattern=asdf {compiler.S.extra_flags} +recipe.ar.pattern=asdf {compiler.ar.extra_flags} +recipe.c.combine.pattern=asdf {compiler.c.elf.extra_flags} +recipe.preproc.macros=asdf {compiler.cpp.extra_flags} +recipe.objcopy.eep.pattern=asdf +recipe.objcopy.hex.pattern=asdf +recipe.output.tmp_file=asdf +recipe.output.save_file=asdf +recipe.size.pattern=asdf +recipe.size.regex=asdf +recipe.size.regex.data=asdf +pluggable_discovery.required.0=builtin:serial-discovery +pluggable_discovery.required.1=builtin:mdns-discovery +pluggable_monitor.required.carrier-pigeon=coop:coo +pluggable_monitor.required.network=bar +pluggable_monitor.required.ble= +tools.avrdude.upload.field.foo_field_name=Some field label +tools.avrdude.upload.field.foo_field_name.secret=true +tools.avrdude.upload.params.verbose=-v +tools.avrdude.upload.params.quiet=-q -q +tools.avrdude.upload.pattern=asdf +tools.bossac.upload.field.bar_field_name=Some other field label +tools.bossac.upload.params.verbose=-v +tools.bossac.upload.params.quiet=-q -q +tools.bossac.upload.pattern=asdf +tools.avrdude.program.params.verbose=-v +tools.avrdude.program.params.quiet=-q -q +tools.avrdude.program.pattern=asdf +tools.bossac.program.params.verbose=-v +tools.bossac.program.params.quiet=-q -q +tools.bossac.program.pattern=asdf +tools.avrdude.erase.params.verbose=-v +tools.avrdude.erase.params.quiet=-q -q +tools.avrdude.erase.pattern=asdf +tools.bossac.erase.params.verbose=-v +tools.bossac.erase.params.quiet=-q -q +tools.bossac.erase.pattern=asdf +tools.avrdude.bootloader.params.verbose=-v +tools.avrdude.bootloader.params.quiet=-q -q +tools.avrdude.bootloader.pattern=asdf +tools.bossac.bootloader.params.verbose=-v +tools.bossac.bootloader.params.quiet=-q -q +tools.bossac.bootloader.pattern=asdf diff --git a/internal/rule/rulefunction/testdata/platforms/no-pluggable-monitors-platform.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/no-pluggable-monitors-platform.txt/boards.txt new file mode 100644 index 00000000..1866d3c4 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/no-pluggable-monitors-platform.txt/boards.txt @@ -0,0 +1,23 @@ +buno.name=Buno +buno.build.board=BUNO +buno.build.core=arduino +buno.build.variant=standard +buno.upload.tool=avrdude +buno.upload.maximum_size=32256 +buno.upload.maximum_data_size=2048 + +uno.name=Arduino Uno +uno.build.board=UNO +uno.build.core=arduino +uno.build.variant=standard +uno.upload.tool=avrdude +uno.upload.maximum_size=32256 +uno.upload.maximum_data_size=2048 + +funo.name=Funo +funo.build.board=FUNO +funo.build.core=arduino +funo.build.variant=standard +funo.upload.tool=avrdude +funo.upload.maximum_size=32256 +funo.upload.maximum_data_size=2048 diff --git a/internal/rule/rulefunction/testdata/platforms/no-pluggable-monitors-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/no-pluggable-monitors-platform.txt/platform.txt new file mode 100644 index 00000000..dec708ad --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/no-pluggable-monitors-platform.txt/platform.txt @@ -0,0 +1,52 @@ +name=Arduino AVR Boards +version=1.8.3 +compiler.warning_flags.none=asdf +compiler.warning_flags.default=asdf +compiler.warning_flags.more=asdf +compiler.warning_flags.all=asdf +compiler.optimization_flags.debug= +compiler.optimization_flags.release= +compiler.c.extra_flags= +compiler.c.elf.extra_flags= +compiler.S.extra_flags= +compiler.cpp.extra_flags= +compiler.ar.extra_flags= +compiler.objcopy.eep.extra_flags= +compiler.elf2hex.extra_flags= +recipe.c.o.pattern=asdf {compiler.c.extra_flags} +recipe.cpp.o.pattern=asdf {compiler.cpp.extra_flags} +recipe.S.o.pattern=asdf {compiler.S.extra_flags} +recipe.ar.pattern=asdf {compiler.ar.extra_flags} +recipe.c.combine.pattern=asdf {compiler.c.elf.extra_flags} +recipe.preproc.macros=asdf {compiler.cpp.extra_flags} +recipe.objcopy.eep.pattern=asdf +recipe.objcopy.hex.pattern=asdf +recipe.output.tmp_file=asdf +recipe.output.save_file=asdf +recipe.size.pattern=asdf +recipe.size.regex=asdf +recipe.size.regex.data=asdf +tools.avrdude.upload.params.verbose=-v +tools.avrdude.upload.params.quiet=-q -q +tools.avrdude.upload.pattern=asdf +tools.bossac.upload.params.verbose=-v +tools.bossac.upload.params.quiet=-q -q +tools.bossac.upload.pattern=asdf +tools.avrdude.program.params.verbose=-v +tools.avrdude.program.params.quiet=-q -q +tools.avrdude.program.pattern=asdf +tools.bossac.program.params.verbose=-v +tools.bossac.program.params.quiet=-q -q +tools.bossac.program.pattern=asdf +tools.avrdude.erase.params.verbose=-v +tools.avrdude.erase.params.quiet=-q -q +tools.avrdude.erase.pattern=asdf +tools.bossac.erase.params.verbose=-v +tools.bossac.erase.params.quiet=-q -q +tools.bossac.erase.pattern=asdf +tools.avrdude.bootloader.params.verbose=-v +tools.avrdude.bootloader.params.quiet=-q -q +tools.avrdude.bootloader.pattern=asdf +tools.bossac.bootloader.params.verbose=-v +tools.bossac.bootloader.params.quiet=-q -q +tools.bossac.bootloader.pattern=asdf diff --git a/internal/rule/rulefunction/testdata/platforms/pluggable-monitor-pattern-protocol-id-LT-platform.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/pluggable-monitor-pattern-protocol-id-LT-platform.txt/boards.txt new file mode 100644 index 00000000..1866d3c4 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/pluggable-monitor-pattern-protocol-id-LT-platform.txt/boards.txt @@ -0,0 +1,23 @@ +buno.name=Buno +buno.build.board=BUNO +buno.build.core=arduino +buno.build.variant=standard +buno.upload.tool=avrdude +buno.upload.maximum_size=32256 +buno.upload.maximum_data_size=2048 + +uno.name=Arduino Uno +uno.build.board=UNO +uno.build.core=arduino +uno.build.variant=standard +uno.upload.tool=avrdude +uno.upload.maximum_size=32256 +uno.upload.maximum_data_size=2048 + +funo.name=Funo +funo.build.board=FUNO +funo.build.core=arduino +funo.build.variant=standard +funo.upload.tool=avrdude +funo.upload.maximum_size=32256 +funo.upload.maximum_data_size=2048 diff --git a/internal/rule/rulefunction/testdata/platforms/pluggable-monitor-pattern-protocol-id-LT-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/pluggable-monitor-pattern-protocol-id-LT-platform.txt/platform.txt new file mode 100644 index 00000000..5a702292 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/pluggable-monitor-pattern-protocol-id-LT-platform.txt/platform.txt @@ -0,0 +1,56 @@ +name=Arduino AVR Boards +version=1.8.3 +compiler.warning_flags.none=asdf +compiler.warning_flags.default=asdf +compiler.warning_flags.more=asdf +compiler.warning_flags.all=asdf +compiler.optimization_flags.debug= +compiler.optimization_flags.release= +compiler.c.extra_flags= +compiler.c.elf.extra_flags= +compiler.S.extra_flags= +compiler.cpp.extra_flags= +compiler.ar.extra_flags= +compiler.objcopy.eep.extra_flags= +compiler.elf2hex.extra_flags= +recipe.c.o.pattern=asdf {compiler.c.extra_flags} +recipe.cpp.o.pattern=asdf {compiler.cpp.extra_flags} +recipe.S.o.pattern=asdf {compiler.S.extra_flags} +recipe.ar.pattern=asdf {compiler.ar.extra_flags} +recipe.c.combine.pattern=asdf {compiler.c.elf.extra_flags} +recipe.preproc.macros=asdf {compiler.cpp.extra_flags} +recipe.objcopy.eep.pattern=asdf +recipe.objcopy.hex.pattern=asdf +recipe.output.tmp_file=asdf +recipe.output.save_file=asdf +recipe.size.pattern=asdf +recipe.size.regex=asdf +recipe.size.regex.data=asdf +pluggable_discovery.foo_discovery.pattern=asdf +pluggable_monitor.pattern.carrier-pigeon=coo +pluggable_monitor.pattern.network= +pluggable_monitor.pattern.ble= +tools.avrdude.upload.params.verbose=-v +tools.avrdude.upload.params.quiet=-q -q +tools.avrdude.upload.pattern=asdf +tools.bossac.upload.params.verbose=-v +tools.bossac.upload.params.quiet=-q -q +tools.bossac.upload.pattern=asdf +tools.avrdude.program.params.verbose=-v +tools.avrdude.program.params.quiet=-q -q +tools.avrdude.program.pattern=asdf +tools.bossac.program.params.verbose=-v +tools.bossac.program.params.quiet=-q -q +tools.bossac.program.pattern=asdf +tools.avrdude.erase.params.verbose=-v +tools.avrdude.erase.params.quiet=-q -q +tools.avrdude.erase.pattern=asdf +tools.bossac.erase.params.verbose=-v +tools.bossac.erase.params.quiet=-q -q +tools.bossac.erase.pattern=asdf +tools.avrdude.bootloader.params.verbose=-v +tools.avrdude.bootloader.params.quiet=-q -q +tools.avrdude.bootloader.pattern=asdf +tools.bossac.bootloader.params.verbose=-v +tools.bossac.bootloader.params.quiet=-q -q +tools.bossac.bootloader.pattern=asdf diff --git a/internal/rule/rulefunction/testdata/platforms/valid-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/valid-platform.txt/platform.txt index ff72f156..69631f3c 100644 --- a/internal/rule/rulefunction/testdata/platforms/valid-platform.txt/platform.txt +++ b/internal/rule/rulefunction/testdata/platforms/valid-platform.txt/platform.txt @@ -28,6 +28,9 @@ recipe.size.regex=asdf recipe.size.regex.data=asdf pluggable_discovery.required.0=builtin:serial-discovery pluggable_discovery.required.1=builtin:mdns-discovery +pluggable_monitor.pattern.carrier-pigeon=coop:coo +pluggable_monitor.required.network=foo:bar +pluggable_monitor.required.ble=baz:qux tools.avrdude.upload.field.foo_field_name=Some field label tools.avrdude.upload.field.foo_field_name.secret=true tools.avrdude.upload.params.verbose=-v diff --git a/internal/rule/rulefunction/testdata/platforms/valid-with-manual-installation-pluggable-monitors-platform.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/valid-with-manual-installation-pluggable-monitors-platform.txt/boards.txt new file mode 100644 index 00000000..1866d3c4 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/valid-with-manual-installation-pluggable-monitors-platform.txt/boards.txt @@ -0,0 +1,23 @@ +buno.name=Buno +buno.build.board=BUNO +buno.build.core=arduino +buno.build.variant=standard +buno.upload.tool=avrdude +buno.upload.maximum_size=32256 +buno.upload.maximum_data_size=2048 + +uno.name=Arduino Uno +uno.build.board=UNO +uno.build.core=arduino +uno.build.variant=standard +uno.upload.tool=avrdude +uno.upload.maximum_size=32256 +uno.upload.maximum_data_size=2048 + +funo.name=Funo +funo.build.board=FUNO +funo.build.core=arduino +funo.build.variant=standard +funo.upload.tool=avrdude +funo.upload.maximum_size=32256 +funo.upload.maximum_data_size=2048 diff --git a/internal/rule/rulefunction/testdata/platforms/valid-with-manual-installation-pluggable-monitors-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/valid-with-manual-installation-pluggable-monitors-platform.txt/platform.txt new file mode 100644 index 00000000..bdd9ef4e --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/valid-with-manual-installation-pluggable-monitors-platform.txt/platform.txt @@ -0,0 +1,56 @@ +name=Arduino AVR Boards +version=1.8.3 +compiler.warning_flags.none=asdf +compiler.warning_flags.default=asdf +compiler.warning_flags.more=asdf +compiler.warning_flags.all=asdf +compiler.optimization_flags.debug= +compiler.optimization_flags.release= +compiler.c.extra_flags= +compiler.c.elf.extra_flags= +compiler.S.extra_flags= +compiler.cpp.extra_flags= +compiler.ar.extra_flags= +compiler.objcopy.eep.extra_flags= +compiler.elf2hex.extra_flags= +recipe.c.o.pattern=asdf {compiler.c.extra_flags} +recipe.cpp.o.pattern=asdf {compiler.cpp.extra_flags} +recipe.S.o.pattern=asdf {compiler.S.extra_flags} +recipe.ar.pattern=asdf {compiler.ar.extra_flags} +recipe.c.combine.pattern=asdf {compiler.c.elf.extra_flags} +recipe.preproc.macros=asdf {compiler.cpp.extra_flags} +recipe.objcopy.eep.pattern=asdf +recipe.objcopy.hex.pattern=asdf +recipe.output.tmp_file=asdf +recipe.output.save_file=asdf +recipe.size.pattern=asdf +recipe.size.regex=asdf +recipe.size.regex.data=asdf +pluggable_discovery.foo_discovery.pattern=asdf +pluggable_monitor.pattern.carrier-pigeon=coo +pluggable_monitor.pattern.network=foo +pluggable_monitor.pattern.ble=bar +tools.avrdude.upload.params.verbose=-v +tools.avrdude.upload.params.quiet=-q -q +tools.avrdude.upload.pattern=asdf +tools.bossac.upload.params.verbose=-v +tools.bossac.upload.params.quiet=-q -q +tools.bossac.upload.pattern=asdf +tools.avrdude.program.params.verbose=-v +tools.avrdude.program.params.quiet=-q -q +tools.avrdude.program.pattern=asdf +tools.bossac.program.params.verbose=-v +tools.bossac.program.params.quiet=-q -q +tools.bossac.program.pattern=asdf +tools.avrdude.erase.params.verbose=-v +tools.avrdude.erase.params.quiet=-q -q +tools.avrdude.erase.pattern=asdf +tools.bossac.erase.params.verbose=-v +tools.bossac.erase.params.quiet=-q -q +tools.bossac.erase.pattern=asdf +tools.avrdude.bootloader.params.verbose=-v +tools.avrdude.bootloader.params.quiet=-q -q +tools.avrdude.bootloader.pattern=asdf +tools.bossac.bootloader.params.verbose=-v +tools.bossac.bootloader.params.quiet=-q -q +tools.bossac.bootloader.pattern=asdf diff --git a/internal/rule/schema/schemadata/bindata.go b/internal/rule/schema/schemadata/bindata.go index 2307c8d9..51bbf517 100644 --- a/internal/rule/schema/schemadata/bindata.go +++ b/internal/rule/schema/schemadata/bindata.go @@ -5044,7 +5044,7 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "type": "string" }, { - "pattern": "^.+:.+$" + "$ref": "#/definitions/patternObjects/resourceReference" } ] } @@ -5077,6 +5077,194 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ } } }, + "pluggableMonitorPattern": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPattern/base/object" + }, + { + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPatternProtocol/permissive/object" + } + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPattern/base/object" + }, + { + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPatternProtocol/specification/object" + } + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPattern/base/object" + }, + { + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPatternProtocol/strict/object" + } + } + ] + } + } + }, + "pluggableMonitorPatternProtocol": { + "base": { + "object": { + "allOf": [ + { + "type": "string" + }, + { + "minLength": 1 + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPatternProtocol/base/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPatternProtocol/base/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorPatternProtocol/base/object" + } + ] + } + } + }, + "pluggableMonitorRequired": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequired/base/object" + }, + { + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequiredProtocol/permissive/object" + } + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequired/base/object" + }, + { + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequiredProtocol/specification/object" + } + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequired/base/object" + }, + { + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequiredProtocol/strict/object" + } + } + ] + } + } + }, + "pluggableMonitorRequiredProtocol": { + "base": { + "object": { + "allOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/patternObjects/resourceReference" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequiredProtocol/base/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequiredProtocol/base/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableMonitorRequiredProtocol/base/object" + } + ] + } + } + }, "tools": { "base": { "object": { @@ -5738,6 +5926,11 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ } } }, + "patternObjects": { + "resourceReference": { + "pattern": "^.+:.+$" + } + }, "requiredObjects": { "root": { "base": { @@ -6034,6 +6227,12 @@ var _arduinoPlatformTxtPermissiveSchemaJson = []byte(`{ "pluggable_discovery": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableDiscovery/permissive/object" }, + "pluggable_monitor.pattern": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableMonitorPattern/permissive/object" + }, + "pluggable_monitor.required": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableMonitorRequired/permissive/object" + }, "tools": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/tools/permissive/object" } @@ -6123,6 +6322,12 @@ var _arduinoPlatformTxtSchemaJson = []byte(`{ "pluggable_discovery": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableDiscovery/specification/object" }, + "pluggable_monitor.pattern": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableMonitorPattern/specification/object" + }, + "pluggable_monitor.required": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableMonitorRequired/specification/object" + }, "tools": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/tools/specification/object" } @@ -6212,6 +6417,12 @@ var _arduinoPlatformTxtStrictSchemaJson = []byte(`{ "pluggable_discovery": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableDiscovery/strict/object" }, + "pluggable_monitor.pattern": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableMonitorPattern/strict/object" + }, + "pluggable_monitor.required": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableMonitorRequired/strict/object" + }, "tools": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/tools/strict/object" }