diff --git a/etc/schemas/arduino-boards-txt-definitions-schema.json b/etc/schemas/arduino-boards-txt-definitions-schema.json index 0468b254..e3144e51 100644 --- a/etc/schemas/arduino-boards-txt-definitions-schema.json +++ b/etc/schemas/arduino-boards-txt-definitions-schema.json @@ -145,6 +145,13 @@ }, "serial.disableRTS": { "$ref": "#/definitions/propertiesObjects/boardIDSerialDisableRTS/permissive/object" + } + } + }, + { + "patternProperties": { + "^upload.tool(\\..+)?$": { + "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/permissive/object" }, "upload.maximum_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumSize/permissive/object" @@ -152,22 +159,15 @@ "upload.maximum_data_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumDataSize/permissive/object" }, - "upload.protocol": { + "upload(\\..+)?\\.protocol": { "$ref": "#/definitions/propertiesObjects/boardIDUploadProtocol/permissive/object" }, - "upload.tool": { - "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/permissive/object" - }, - "upload.use_1200bps_touch": { + "upload(\\..+)?\\.use_1200bps_touch": { "$ref": "#/definitions/propertiesObjects/boardIDUploadUse1200bpsTouch/permissive/object" }, - "upload.wait_for_upload_port": { + "upload(\\..+)?\\.wait_for_upload_port": { "$ref": "#/definitions/propertiesObjects/boardIDUploadWaitForUploadPort/permissive/object" - } - } - }, - { - "patternProperties": { + }, "^[vp]id\\.[0-9]+$": { "$ref": "#/definitions/propertiesObjects/boardIDXidN/permissive/object" } @@ -210,6 +210,13 @@ }, "serial.disableRTS": { "$ref": "#/definitions/propertiesObjects/boardIDSerialDisableRTS/specification/object" + } + } + }, + { + "patternProperties": { + "^upload.tool(\\..+)?$": { + "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/specification/object" }, "upload.maximum_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumSize/specification/object" @@ -217,22 +224,15 @@ "upload.maximum_data_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumDataSize/specification/object" }, - "upload.protocol": { + "upload(\\..+)?\\.protocol": { "$ref": "#/definitions/propertiesObjects/boardIDUploadProtocol/specification/object" }, - "upload.tool": { - "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/specification/object" - }, - "upload.use_1200bps_touch": { + "upload(\\..+)?\\.use_1200bps_touch": { "$ref": "#/definitions/propertiesObjects/boardIDUploadUse1200bpsTouch/specification/object" }, - "upload.wait_for_upload_port": { + "upload(\\..+)?\\.wait_for_upload_port": { "$ref": "#/definitions/propertiesObjects/boardIDUploadWaitForUploadPort/specification/object" - } - } - }, - { - "patternProperties": { + }, "^[vp]id\\.[0-9]+$": { "$ref": "#/definitions/propertiesObjects/boardIDXidN/specification/object" } @@ -275,6 +275,13 @@ }, "serial.disableRTS": { "$ref": "#/definitions/propertiesObjects/boardIDSerialDisableRTS/strict/object" + } + } + }, + { + "patternProperties": { + "^upload.tool(\\..+)?$": { + "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/strict/object" }, "upload.maximum_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumSize/strict/object" @@ -282,22 +289,15 @@ "upload.maximum_data_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumDataSize/strict/object" }, - "upload.protocol": { + "upload(\\..+)?\\.protocol": { "$ref": "#/definitions/propertiesObjects/boardIDUploadProtocol/strict/object" }, - "upload.tool": { - "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/strict/object" - }, - "upload.use_1200bps_touch": { + "upload(\\..+)?\\.use_1200bps_touch": { "$ref": "#/definitions/propertiesObjects/boardIDUploadUse1200bpsTouch/strict/object" }, - "upload.wait_for_upload_port": { + "upload(\\..+)?\\.wait_for_upload_port": { "$ref": "#/definitions/propertiesObjects/boardIDUploadWaitForUploadPort/strict/object" - } - } - }, - { - "patternProperties": { + }, "^[vp]id\\.[0-9]+$": { "$ref": "#/definitions/propertiesObjects/boardIDXidN/strict/object" } @@ -624,6 +624,13 @@ }, "serial.disableRTS": { "$ref": "#/definitions/propertiesObjects/boardIDSerialDisableRTS/permissive/object" + } + } + }, + { + "patternProperties": { + "^upload.tool(\\..+)?$": { + "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/permissive/object" }, "upload.maximum_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumSize/permissive/object" @@ -631,22 +638,15 @@ "upload.maximum_data_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumDataSize/permissive/object" }, - "upload.protocol": { + "upload(\\..+)?\\.protocol": { "$ref": "#/definitions/propertiesObjects/boardIDUploadProtocol/permissive/object" }, - "upload.tool": { - "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/permissive/object" - }, - "upload.use_1200bps_touch": { + "upload(\\..+)?\\.use_1200bps_touch": { "$ref": "#/definitions/propertiesObjects/boardIDUploadUse1200bpsTouch/permissive/object" }, - "upload.wait_for_upload_port": { + "upload(\\..+)?\\.wait_for_upload_port": { "$ref": "#/definitions/propertiesObjects/boardIDUploadWaitForUploadPort/permissive/object" - } - } - }, - { - "patternProperties": { + }, "^[vp]id\\.[0-9]+$": { "$ref": "#/definitions/propertiesObjects/boardIDXidN/permissive/object" } @@ -677,6 +677,13 @@ }, "serial.disableRTS": { "$ref": "#/definitions/propertiesObjects/boardIDSerialDisableRTS/specification/object" + } + } + }, + { + "patternProperties": { + "^upload.tool(\\..+)?$": { + "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/specification/object" }, "upload.maximum_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumSize/specification/object" @@ -684,22 +691,15 @@ "upload.maximum_data_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumDataSize/specification/object" }, - "upload.protocol": { + "upload(\\..+)?\\.protocol": { "$ref": "#/definitions/propertiesObjects/boardIDUploadProtocol/specification/object" }, - "upload.tool": { - "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/specification/object" - }, - "upload.use_1200bps_touch": { + "upload(\\..+)?\\.use_1200bps_touch": { "$ref": "#/definitions/propertiesObjects/boardIDUploadUse1200bpsTouch/specification/object" }, - "upload.wait_for_upload_port": { + "upload(\\..+)?\\.wait_for_upload_port": { "$ref": "#/definitions/propertiesObjects/boardIDUploadWaitForUploadPort/specification/object" - } - } - }, - { - "patternProperties": { + }, "^[vp]id\\.[0-9]+$": { "$ref": "#/definitions/propertiesObjects/boardIDXidN/specification/object" } @@ -730,6 +730,13 @@ }, "serial.disableRTS": { "$ref": "#/definitions/propertiesObjects/boardIDSerialDisableRTS/strict/object" + } + } + }, + { + "patternProperties": { + "^upload.tool(\\..+)?$": { + "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/strict/object" }, "upload.maximum_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumSize/strict/object" @@ -737,22 +744,15 @@ "upload.maximum_data_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumDataSize/strict/object" }, - "upload.protocol": { + "upload(\\..+)?\\.protocol": { "$ref": "#/definitions/propertiesObjects/boardIDUploadProtocol/strict/object" }, - "upload.tool": { - "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/strict/object" - }, - "upload.use_1200bps_touch": { + "upload(\\..+)?\\.use_1200bps_touch": { "$ref": "#/definitions/propertiesObjects/boardIDUploadUse1200bpsTouch/strict/object" }, - "upload.wait_for_upload_port": { + "upload(\\..+)?\\.wait_for_upload_port": { "$ref": "#/definitions/propertiesObjects/boardIDUploadWaitForUploadPort/strict/object" - } - } - }, - { - "patternProperties": { + }, "^[vp]id\\.[0-9]+$": { "$ref": "#/definitions/propertiesObjects/boardIDXidN/strict/object" } @@ -773,7 +773,7 @@ "type": "string" }, { - "$ref": "#/definitions/enumObjects/booleanString" + "$ref": "general-definitions-schema.json#/definitions/enumObjects/booleanString" } ] } @@ -814,7 +814,7 @@ "type": "string" }, { - "$ref": "#/definitions/enumObjects/booleanString" + "$ref": "general-definitions-schema.json#/definitions/enumObjects/booleanString" } ] } @@ -1016,7 +1016,7 @@ "type": "string" }, { - "$ref": "#/definitions/enumObjects/booleanString" + "$ref": "general-definitions-schema.json#/definitions/enumObjects/booleanString" } ] } @@ -1057,7 +1057,7 @@ "type": "string" }, { - "$ref": "#/definitions/enumObjects/booleanString" + "$ref": "general-definitions-schema.json#/definitions/enumObjects/booleanString" } ] } @@ -1215,11 +1215,6 @@ } } } - }, - "enumObjects": { - "booleanString": { - "enum": ["true", "false"] - } } } } diff --git a/etc/schemas/arduino-platform-txt-definitions-schema.json b/etc/schemas/arduino-platform-txt-definitions-schema.json index 2fbc4b33..57ce303e 100644 --- a/etc/schemas/arduino-platform-txt-definitions-schema.json +++ b/etc/schemas/arduino-platform-txt-definitions-schema.json @@ -700,6 +700,215 @@ } } }, + "pluggableDiscovery": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableDiscovery/base/object" + }, + { + "properties": { + "required": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequired/permissive/object" + } + }, + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryDiscoveryName/permissive/object" + } + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableDiscovery/base/object" + }, + { + "properties": { + "required": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequired/specification/object" + } + }, + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryDiscoveryName/specification/object" + } + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableDiscovery/base/object" + }, + { + "properties": { + "required": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequired/strict/object" + } + }, + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryDiscoveryName/strict/object" + } + } + ] + } + } + }, + "pluggableDiscoveryDiscoveryName": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryDiscoveryName/base/object" + }, + { + "$ref": "#/definitions/requiredObjects/pluggableDiscoveryDiscoveryName/permissive/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryDiscoveryName/base/object" + }, + { + "$ref": "#/definitions/requiredObjects/pluggableDiscoveryDiscoveryName/specification/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryDiscoveryName/base/object" + }, + { + "$ref": "#/definitions/requiredObjects/pluggableDiscoveryDiscoveryName/strict/object" + } + ] + } + } + }, + "pluggableDiscoveryRequired": { + "base": { + "object": { + "allOf": [ + { + "type": "array" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequired/base/object" + }, + { + "items": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequiredN/permissive/object" + } + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequired/base/object" + }, + { + "items": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequiredN/specification/object" + } + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequired/base/object" + }, + { + "items": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequiredN/strict/object" + } + } + ] + } + } + }, + "pluggableDiscoveryRequiredN": { + "base": { + "object": { + "allOf": [ + { + "type": "string" + }, + { + "pattern": "^.+:.+$" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequiredN/base/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequiredN/base/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequiredN/base/object" + } + ] + } + } + }, "tools": { "base": { "object": { @@ -866,6 +1075,13 @@ }, { "$ref": "#/definitions/requiredObjects/toolsToolNameUpload/permissive/object" + }, + { + "properties": { + "field": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadField/permissive/object" + } + } } ] } @@ -878,6 +1094,13 @@ }, { "$ref": "#/definitions/requiredObjects/toolsToolNameUpload/specification/object" + }, + { + "properties": { + "field": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadField/specification/object" + } + } } ] } @@ -890,6 +1113,163 @@ }, { "$ref": "#/definitions/requiredObjects/toolsToolNameUpload/strict/object" + }, + { + "properties": { + "field": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadField/strict/object" + } + } + } + ] + } + } + }, + "toolsToolNameUploadField": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadField/base/object" + }, + { + "patternProperties": { + "^.+([^.].*|\\.([^s].*)?|\\.se([^c].*)?|\\.sec([^r].*)?|\\.secr([^e].*)?|\\.secre([^t].*)?|\\.secret.+)$": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldName/permissive/object" + }, + "^.+\\.secret$": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldNameSecret/permissive/object" + } + } + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadField/base/object" + }, + { + "patternProperties": { + "^.+([^.].*|\\.([^s].*)?|\\.se([^c].*)?|\\.sec([^r].*)?|\\.secr([^e].*)?|\\.secre([^t].*)?|\\.secret.+)$": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldName/specification/object" + }, + "^.+\\.secret$": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldNameSecret/specification/object" + } + } + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadField/base/object" + }, + { + "patternProperties": { + "^.+([^.].*|\\.([^s].*)?|\\.se([^c].*)?|\\.sec([^r].*)?|\\.secr([^e].*)?|\\.secre([^t].*)?|\\.secret.+)$": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldName/strict/object" + }, + "^.+\\.secret$": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldNameSecret/strict/object" + } + } + } + ] + } + } + }, + "toolsToolNameUploadFieldFieldName": { + "base": { + "object": { + "allOf": [ + { + "type": "string" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldName/base/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldName/base/object" + }, + { + "maxLength": 50 + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldName/specification/object" + } + ] + } + } + }, + "toolsToolNameUploadFieldFieldNameSecret": { + "base": { + "object": { + "allOf": [ + { + "type": "string" + }, + { + "$ref": "general-definitions-schema.json#/definitions/enumObjects/booleanString" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldNameSecret/base/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldNameSecret/base/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldNameSecret/base/object" } ] } @@ -911,6 +1291,13 @@ { "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/base/object" }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/permissive/object" + } + } + }, { "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/permissive/object" } @@ -923,6 +1310,13 @@ { "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/base/object" }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/specification/object" + } + } + }, { "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/specification/object" } @@ -935,6 +1329,13 @@ { "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/base/object" }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/strict/object" + } + } + }, { "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/strict/object" } @@ -958,6 +1359,13 @@ { "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/base/object" }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/permissive/object" + } + } + }, { "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/permissive/object" } @@ -970,6 +1378,13 @@ { "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/base/object" }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/specification/object" + } + } + }, { "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/specification/object" } @@ -982,6 +1397,13 @@ { "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/base/object" }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/strict/object" + } + } + }, { "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/strict/object" } @@ -1005,6 +1427,13 @@ { "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/base/object" }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/permissive/object" + } + } + }, { "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/permissive/object" } @@ -1017,6 +1446,13 @@ { "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/base/object" }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/specification/object" + } + } + }, { "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/specification/object" } @@ -1029,12 +1465,66 @@ { "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/base/object" }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/strict/object" + } + } + }, { "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/strict/object" } ] } } + }, + "toolsToolNameActionNameParams": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/base/object" + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionNameParams/permissive/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/base/object" + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionNameParams/specification/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/base/object" + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionNameParams/strict/object" + } + ] + } + } } }, "dependenciesObjects": { @@ -1145,12 +1635,50 @@ } } }, + "pluggableDiscoveryDiscoveryName": { + "base": { + "object": { + "allOf": [ + { + "required": ["pattern"] + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/requiredObjects/pluggableDiscoveryDiscoveryName/base/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/requiredObjects/pluggableDiscoveryDiscoveryName/base/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/requiredObjects/pluggableDiscoveryDiscoveryName/base/object" + } + ] + } + } + }, "toolsToolNameActionName": { "base": { "object": { "allOf": [ { - "required": ["params.verbose", "params.quiet", "pattern"] + "required": ["params", "pattern"] } ] } @@ -1183,6 +1711,44 @@ } } }, + "toolsToolNameActionNameParams": { + "base": { + "object": { + "allOf": [ + { + "required": ["verbose", "quiet"] + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionNameParams/base/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionNameParams/base/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionNameParams/base/object" + } + ] + } + } + }, "toolsToolNameUpload": { "base": { "object": { diff --git a/etc/schemas/arduino-platform-txt-permissive-schema.json b/etc/schemas/arduino-platform-txt-permissive-schema.json index 50e85c5d..af541a7a 100644 --- a/etc/schemas/arduino-platform-txt-permissive-schema.json +++ b/etc/schemas/arduino-platform-txt-permissive-schema.json @@ -54,6 +54,9 @@ "recipe.size.pattern": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/recipeSizePattern/permissive/object" }, + "pluggable_discovery": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableDiscovery/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 d66b9c52..fc299a13 100644 --- a/etc/schemas/arduino-platform-txt-schema.json +++ b/etc/schemas/arduino-platform-txt-schema.json @@ -54,6 +54,9 @@ "recipe.size.pattern": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/recipeSizePattern/specification/object" }, + "pluggable_discovery": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableDiscovery/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 871d1453..05f71286 100644 --- a/etc/schemas/arduino-platform-txt-strict-schema.json +++ b/etc/schemas/arduino-platform-txt-strict-schema.json @@ -54,6 +54,9 @@ "recipe.size.pattern": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/recipeSizePattern/strict/object" }, + "pluggable_discovery": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableDiscovery/strict/object" + }, "tools": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/tools/strict/object" } diff --git a/etc/schemas/general-definitions-schema.json b/etc/schemas/general-definitions-schema.json index 5ecff6d9..7e0ab5c2 100644 --- a/etc/schemas/general-definitions-schema.json +++ b/etc/schemas/general-definitions-schema.json @@ -23,6 +23,11 @@ "pattern": "^[aA][rR][dD][uU][iI][nN][oO].*$" } } + }, + "enumObjects": { + "booleanString": { + "enum": ["true", "false"] + } } } } diff --git a/internal/project/general/general.go b/internal/project/general/general.go index 6cefa62a..c2e28446 100644 --- a/internal/project/general/general.go +++ b/internal/project/general/general.go @@ -25,7 +25,7 @@ PropertiesToMap converts properties.Map data structures to map[string]interface The Arduino project configuration fields have an odd usage of the properties.Map format. Dots may sometimes indicate nested keys, but in other cases they are merely a character in the key string. There are cases where a completely programmatic recursion of the properties into a fully nested structure would result in the impossibility of some keys -having bot a string and a map type, which is not supported. For this reason, it's necessary to manually configure the +having both a string and a map type, which is not supported. For this reason, it's necessary to manually configure the recursion of key levels on a case-by-case basis. In the event a full recursion of key levels is desired, set the levels argument to a value <1. */ @@ -51,3 +51,17 @@ func PropertiesToMap(flatProperties *properties.Map, levels int) map[string]inte return propertiesInterface } + +// PropertiesToList parses a property that has a list data type and returns it in the map[string]interface{} type +// consumed by the JSON schema parser. +func PropertiesToList(flatProperties *properties.Map, key string) map[string]interface{} { + list := flatProperties.ExtractSubIndexLists(key) + // Convert the slice to the required interface type + listInterface := make([]interface{}, len(list)) + for i, v := range list { + listInterface[i] = v + } + mapInterface := make(map[string]interface{}) + mapInterface[key] = listInterface + return mapInterface +} diff --git a/internal/project/general/general_test.go b/internal/project/general/general_test.go index bb4c5ba1..58226e79 100644 --- a/internal/project/general/general_test.go +++ b/internal/project/general/general_test.go @@ -102,3 +102,23 @@ func TestPropertiesToMap(t *testing.T) { assert.True(t, reflect.DeepEqual(expectedMapOutput, PropertiesToMap(propertiesInput, 3))) assert.True(t, reflect.DeepEqual(expectedMapOutput, PropertiesToMap(propertiesInput, 0))) } + +func TestPropertiesToList(t *testing.T) { + rawProperties := []byte(` + hello=world + foo.1=asdf + foo.2=zxcv + `) + propertiesInput, err := properties.LoadFromBytes(rawProperties) + require.Nil(t, err) + + expectedMapOutput := map[string]interface{}{ + "hello": []interface{}{"world"}, + } + assert.True(t, reflect.DeepEqual(expectedMapOutput, PropertiesToList(propertiesInput, "hello"))) + + expectedMapOutput = map[string]interface{}{ + "foo": []interface{}{"asdf", "zxcv"}, + } + assert.True(t, reflect.DeepEqual(expectedMapOutput, PropertiesToList(propertiesInput, "foo"))) +} diff --git a/internal/project/platform/boardstxt/boardstxtschema_test.go b/internal/project/platform/boardstxt/boardstxtschema_test.go index c4e09df5..ac71f537 100644 --- a/internal/project/platform/boardstxt/boardstxtschema_test.go +++ b/internal/project/platform/boardstxt/boardstxtschema_test.go @@ -88,9 +88,17 @@ func TestMinLength(t *testing.T) { {"foo.upload.tool", "foo/upload\\.tool", 1, compliancelevel.Specification}, {"foo.upload.tool", "foo/upload\\.tool", 1, compliancelevel.Strict}, + {"foo.upload.tool.serial", "foo/upload\\.tool.serial", 1, compliancelevel.Permissive}, + {"foo.upload.tool.serial", "foo/upload\\.tool.serial", 1, compliancelevel.Specification}, + {"foo.upload.tool.serial", "foo/upload\\.tool.serial", 1, compliancelevel.Strict}, + {"foo.menu.bar.baz.upload.tool", "foo/menu/bar/baz/upload\\.tool", 1, compliancelevel.Permissive}, {"foo.menu.bar.baz.upload.tool", "foo/menu/bar/baz/upload\\.tool", 1, compliancelevel.Specification}, {"foo.menu.bar.baz.upload.tool", "foo/menu/bar/baz/upload\\.tool", 1, compliancelevel.Strict}, + + {"foo.menu.bar.baz.upload.tool.serial", "foo/menu/bar/baz/upload\\.tool.serial", 1, compliancelevel.Permissive}, + {"foo.menu.bar.baz.upload.tool.serial", "foo/menu/bar/baz/upload\\.tool.serial", 1, compliancelevel.Specification}, + {"foo.menu.bar.baz.upload.tool.serial", "foo/menu/bar/baz/upload\\.tool.serial", 1, compliancelevel.Strict}, } // Test schema validation results with value length < minimum. @@ -226,6 +234,16 @@ func TestEnum(t *testing.T) { {"nano.upload.use_1200bps_touch", "nano/upload\\.use_1200bps_touch", "foo", compliancelevel.Specification, assert.True}, {"nano.upload.use_1200bps_touch", "nano/upload\\.use_1200bps_touch", "foo", compliancelevel.Strict, assert.True}, + {"nano.upload.serial.use_1200bps_touch", "nano/upload\\.serial\\.use_1200bps_touch", "true", compliancelevel.Permissive, assert.False}, + {"nano.upload.serial.use_1200bps_touch", "nano/upload\\.serial\\.use_1200bps_touch", "true", compliancelevel.Specification, assert.False}, + {"nano.upload.serial.use_1200bps_touch", "nano/upload\\.serial\\.use_1200bps_touch", "true", compliancelevel.Strict, assert.False}, + {"nano.upload.serial.use_1200bps_touch", "nano/upload\\.serial\\.use_1200bps_touch", "false", compliancelevel.Permissive, assert.False}, + {"nano.upload.serial.use_1200bps_touch", "nano/upload\\.serial\\.use_1200bps_touch", "false", compliancelevel.Specification, assert.False}, + {"nano.upload.serial.use_1200bps_touch", "nano/upload\\.serial\\.use_1200bps_touch", "false", compliancelevel.Strict, assert.False}, + {"nano.upload.serial.use_1200bps_touch", "nano/upload\\.serial\\.use_1200bps_touch", "foo", compliancelevel.Permissive, assert.True}, + {"nano.upload.serial.use_1200bps_touch", "nano/upload\\.serial\\.use_1200bps_touch", "foo", compliancelevel.Specification, assert.True}, + {"nano.upload.serial.use_1200bps_touch", "nano/upload\\.serial\\.use_1200bps_touch", "foo", compliancelevel.Strict, assert.True}, + {"nano.menu.bar.baz.upload.use_1200bps_touch", "nano/menu/bar/baz/upload\\.use_1200bps_touch", "true", compliancelevel.Permissive, assert.False}, {"nano.menu.bar.baz.upload.use_1200bps_touch", "nano/menu/bar/baz/upload\\.use_1200bps_touch", "true", compliancelevel.Specification, assert.False}, {"nano.menu.bar.baz.upload.use_1200bps_touch", "nano/menu/bar/baz/upload\\.use_1200bps_touch", "true", compliancelevel.Strict, assert.False}, @@ -236,6 +254,16 @@ func TestEnum(t *testing.T) { {"nano.menu.bar.baz.upload.use_1200bps_touch", "nano/menu/bar/baz/upload\\.use_1200bps_touch", "foo", compliancelevel.Specification, assert.True}, {"nano.menu.bar.baz.upload.use_1200bps_touch", "nano/menu/bar/baz/upload\\.use_1200bps_touch", "foo", compliancelevel.Strict, assert.True}, + {"nano.menu.bar.baz.upload.serial.use_1200bps_touch", "nano/menu/bar/baz/upload\\.serial\\.use_1200bps_touch", "true", compliancelevel.Permissive, assert.False}, + {"nano.menu.bar.baz.upload.serial.use_1200bps_touch", "nano/menu/bar/baz/upload\\.serial\\.use_1200bps_touch", "true", compliancelevel.Specification, assert.False}, + {"nano.menu.bar.baz.upload.serial.use_1200bps_touch", "nano/menu/bar/baz/upload\\.serial\\.use_1200bps_touch", "true", compliancelevel.Strict, assert.False}, + {"nano.menu.bar.baz.upload.serial.use_1200bps_touch", "nano/menu/bar/baz/upload\\.serial\\.use_1200bps_touch", "false", compliancelevel.Permissive, assert.False}, + {"nano.menu.bar.baz.upload.serial.use_1200bps_touch", "nano/menu/bar/baz/upload\\.serial\\.use_1200bps_touch", "false", compliancelevel.Specification, assert.False}, + {"nano.menu.bar.baz.upload.serial.use_1200bps_touch", "nano/menu/bar/baz/upload\\.serial\\.use_1200bps_touch", "false", compliancelevel.Strict, assert.False}, + {"nano.menu.bar.baz.upload.serial.use_1200bps_touch", "nano/menu/bar/baz/upload\\.serial\\.use_1200bps_touch", "foo", compliancelevel.Permissive, assert.True}, + {"nano.menu.bar.baz.upload.serial.use_1200bps_touch", "nano/menu/bar/baz/upload\\.serial\\.use_1200bps_touch", "foo", compliancelevel.Specification, assert.True}, + {"nano.menu.bar.baz.upload.serial.use_1200bps_touch", "nano/menu/bar/baz/upload\\.serial\\.use_1200bps_touch", "foo", compliancelevel.Strict, assert.True}, + {"nano.upload.wait_for_upload_port", "nano/upload\\.wait_for_upload_port", "true", compliancelevel.Permissive, assert.False}, {"nano.upload.wait_for_upload_port", "nano/upload\\.wait_for_upload_port", "true", compliancelevel.Specification, assert.False}, {"nano.upload.wait_for_upload_port", "nano/upload\\.wait_for_upload_port", "true", compliancelevel.Strict, assert.False}, @@ -246,6 +274,16 @@ func TestEnum(t *testing.T) { {"nano.upload.wait_for_upload_port", "nano/upload\\.wait_for_upload_port", "foo", compliancelevel.Specification, assert.True}, {"nano.upload.wait_for_upload_port", "nano/upload\\.wait_for_upload_port", "foo", compliancelevel.Strict, assert.True}, + {"nano.upload.serial.wait_for_upload_port", "nano/upload\\.serial\\.wait_for_upload_port", "true", compliancelevel.Permissive, assert.False}, + {"nano.upload.serial.wait_for_upload_port", "nano/upload\\.serial\\.wait_for_upload_port", "true", compliancelevel.Specification, assert.False}, + {"nano.upload.serial.wait_for_upload_port", "nano/upload\\.serial\\.wait_for_upload_port", "true", compliancelevel.Strict, assert.False}, + {"nano.upload.serial.wait_for_upload_port", "nano/upload\\.serial\\.wait_for_upload_port", "false", compliancelevel.Permissive, assert.False}, + {"nano.upload.serial.wait_for_upload_port", "nano/upload\\.serial\\.wait_for_upload_port", "false", compliancelevel.Specification, assert.False}, + {"nano.upload.serial.wait_for_upload_port", "nano/upload\\.serial\\.wait_for_upload_port", "false", compliancelevel.Strict, assert.False}, + {"nano.upload.serial.wait_for_upload_port", "nano/upload\\.serial\\.wait_for_upload_port", "foo", compliancelevel.Permissive, assert.True}, + {"nano.upload.serial.wait_for_upload_port", "nano/upload\\.serial\\.wait_for_upload_port", "foo", compliancelevel.Specification, assert.True}, + {"nano.upload.serial.wait_for_upload_port", "nano/upload\\.serial\\.wait_for_upload_port", "foo", compliancelevel.Strict, assert.True}, + {"nano.menu.bar.baz.upload.wait_for_upload_port", "nano/menu/bar/baz/upload\\.wait_for_upload_port", "true", compliancelevel.Permissive, assert.False}, {"nano.menu.bar.baz.upload.wait_for_upload_port", "nano/menu/bar/baz/upload\\.wait_for_upload_port", "true", compliancelevel.Specification, assert.False}, {"nano.menu.bar.baz.upload.wait_for_upload_port", "nano/menu/bar/baz/upload\\.wait_for_upload_port", "true", compliancelevel.Strict, assert.False}, @@ -255,6 +293,16 @@ func TestEnum(t *testing.T) { {"nano.menu.bar.baz.upload.wait_for_upload_port", "nano/menu/bar/baz/upload\\.wait_for_upload_port", "foo", compliancelevel.Permissive, assert.True}, {"nano.menu.bar.baz.upload.wait_for_upload_port", "nano/menu/bar/baz/upload\\.wait_for_upload_port", "foo", compliancelevel.Specification, assert.True}, {"nano.menu.bar.baz.upload.wait_for_upload_port", "nano/menu/bar/baz/upload\\.wait_for_upload_port", "foo", compliancelevel.Strict, assert.True}, + + {"nano.menu.bar.baz.upload.serial.wait_for_upload_port", "nano/menu/bar/baz/upload\\.serial\\.wait_for_upload_port", "true", compliancelevel.Permissive, assert.False}, + {"nano.menu.bar.baz.upload.serial.wait_for_upload_port", "nano/menu/bar/baz/upload\\.serial\\.wait_for_upload_port", "true", compliancelevel.Specification, assert.False}, + {"nano.menu.bar.baz.upload.serial.wait_for_upload_port", "nano/menu/bar/baz/upload\\.serial\\.wait_for_upload_port", "true", compliancelevel.Strict, assert.False}, + {"nano.menu.bar.baz.upload.serial.wait_for_upload_port", "nano/menu/bar/baz/upload\\.serial\\.wait_for_upload_port", "false", compliancelevel.Permissive, assert.False}, + {"nano.menu.bar.baz.upload.serial.wait_for_upload_port", "nano/menu/bar/baz/upload\\.serial\\.wait_for_upload_port", "false", compliancelevel.Specification, assert.False}, + {"nano.menu.bar.baz.upload.serial.wait_for_upload_port", "nano/menu/bar/baz/upload\\.serial\\.wait_for_upload_port", "false", compliancelevel.Strict, assert.False}, + {"nano.menu.bar.baz.upload.serial.wait_for_upload_port", "nano/menu/bar/baz/upload\\.serial\\.wait_for_upload_port", "foo", compliancelevel.Permissive, assert.True}, + {"nano.menu.bar.baz.upload.serial.wait_for_upload_port", "nano/menu/bar/baz/upload\\.serial\\.wait_for_upload_port", "foo", compliancelevel.Specification, assert.True}, + {"nano.menu.bar.baz.upload.serial.wait_for_upload_port", "nano/menu/bar/baz/upload\\.serial\\.wait_for_upload_port", "foo", compliancelevel.Strict, assert.True}, } for _, testTable := range testTables { diff --git a/internal/project/platform/platformtxt/platformtxt.go b/internal/project/platform/platformtxt/platformtxt.go index d6d9b513..aa5f4541 100644 --- a/internal/project/platform/platformtxt/platformtxt.go +++ b/internal/project/platform/platformtxt/platformtxt.go @@ -20,6 +20,7 @@ See: https://arduino.github.io/arduino-cli/latest/platform-specification/#platfo package platformtxt import ( + "fmt" "strings" "github.com/arduino/arduino-lint/internal/project/general" @@ -57,14 +58,21 @@ 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 key, which can contain any number of - arbitrary tool name subproperties which must be linted. + 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. */ platformTxtInterface := make(map[string]interface{}) keys := platformTxt.Keys() for _, key := range keys { - if strings.HasPrefix(key, "tools.") { - platformTxtInterface["tools"] = general.PropertiesToMap(platformTxt.SubTree("tools"), 3) + if strings.HasPrefix(key, "pluggable_discovery.") { + if key == "pluggable_discovery.required" || strings.HasPrefix(key, "pluggable_discovery.required.") { + platformTxtInterface["pluggable_discovery"] = general.PropertiesToList(platformTxt.SubTree("pluggable_discovery"), "required") + } else { + // It is a pluggable_discovery.DISCOVERY_ID property. + platformTxtInterface["pluggable_discovery"] = general.PropertiesToMap(platformTxt.SubTree("pluggable_discovery"), 2) + } + } else if strings.HasPrefix(key, "tools.") { + platformTxtInterface["tools"] = general.PropertiesToMap(platformTxt.SubTree("tools"), 4) } else { platformTxtInterface[key] = platformTxt.Get(key) } @@ -77,6 +85,32 @@ func Validate(platformTxt *properties.Map) map[compliancelevel.Type]schema.Valid return validationResults } +// PluggableDiscoveryNames returns the list of pluggable discovery names from the given platform.txt properties. +func PluggableDiscoveryNames(platformTxt *properties.Map) []string { + names := platformTxt.SubTree("pluggable_discovery").FirstLevelKeys() + for i := range names { + for i < len(names) && names[i] == "required" { + names = append(names[:i], names[i+1:]...) + } + } + + return names +} + +// UserProvidedFieldNames returns the list of user provided field names platform.txt properties, mapped by tool name. +func UserProvidedFieldNames(platformTxt *properties.Map) map[string][]string { + fieldNames := make(map[string][]string) + toolsProps := platformTxt.SubTree("tools") + for _, tool := range toolsProps.FirstLevelKeys() { + fieldProps := toolsProps.SubTree(fmt.Sprintf("%s.upload.field", tool)) + for _, fieldName := range fieldProps.FirstLevelKeys() { + fieldNames[tool] = append(fieldNames[tool], fieldName) + } + } + + return fieldNames +} + // ToolNames returns the list of tool names from the given platform.txt properties. func ToolNames(platformTxt *properties.Map) []string { return platformTxt.SubTree("tools").FirstLevelKeys() diff --git a/internal/project/platform/platformtxt/platformtxt_test.go b/internal/project/platform/platformtxt/platformtxt_test.go index a55168fc..7a108ff5 100644 --- a/internal/project/platform/platformtxt/platformtxt_test.go +++ b/internal/project/platform/platformtxt/platformtxt_test.go @@ -16,6 +16,7 @@ package platformtxt import ( + "reflect" "testing" "github.com/arduino/arduino-lint/internal/rule/schema/compliancelevel" @@ -62,6 +63,8 @@ func init() { "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", @@ -90,6 +93,37 @@ func TestValidate(t *testing.T) { assert.NotNil(t, validationResult[compliancelevel.Strict].Result, "Invalid (strict)") } +func TestPluggableDiscoveryNames(t *testing.T) { + platformTxt := properties.NewFromHashmap(validPlatformTxtMap) + + assert.ElementsMatch(t, []string{}, PluggableDiscoveryNames(platformTxt), "No elements for pluggable_discovery.required properties.") + + platformTxt.Set("pluggable_discovery.foo_discovery.pattern", "asdf") + platformTxt.Set("pluggable_discovery.bar_discovery.pattern", "zxcv") + assert.ElementsMatch(t, []string{"foo_discovery", "bar_discovery"}, PluggableDiscoveryNames(platformTxt), "pluggable_discovery.DISCOVERY_ID properties add elements for each DISCOVERY_ID.") +} + +func TestUserProvidedFieldNames(t *testing.T) { + platformTxt := properties.NewFromHashmap(validPlatformTxtMap) + + assertion := make(map[string][]string) + assert.True(t, reflect.DeepEqual(assertion, UserProvidedFieldNames(platformTxt))) + + platformTxt.Set("tools.avrdude.upload.field.foo_field_name", "Some field label") + assertion = map[string][]string{ + "avrdude": {"foo_field_name"}, + } + assert.True(t, reflect.DeepEqual(assertion, UserProvidedFieldNames(platformTxt))) + + platformTxt.Set("tools.avrdude.upload.field.bar_field_name", "Some field label") + platformTxt.Set("tools.bossac.upload.field.baz_field_name", "Some field label") + assertion = map[string][]string{ + "avrdude": {"foo_field_name", "bar_field_name"}, + "bossac": {"baz_field_name"}, + } + assert.True(t, reflect.DeepEqual(assertion, UserProvidedFieldNames(platformTxt))) +} + func TestToolNames(t *testing.T) { platformTxt := properties.NewFromHashmap(validPlatformTxtMap) diff --git a/internal/project/platform/platformtxt/platformtxtschema_test.go b/internal/project/platform/platformtxt/platformtxtschema_test.go index 8c13640b..c687949c 100644 --- a/internal/project/platform/platformtxt/platformtxtschema_test.go +++ b/internal/project/platform/platformtxt/platformtxtschema_test.go @@ -57,6 +57,8 @@ var validPlatformTxtRaw = []byte(` recipe.size.regex.data=asdf tools.avrdude.upload.params.verbose=-v tools.avrdude.upload.params.quiet=-q -q + tools.avrdude.upload.field.foo_field_name=Some field label + tools.avrdude.upload.field.foo_field_name.secret=true tools.avrdude.upload.pattern=asdf tools.avrdude.program.params.verbose=-v tools.avrdude.program.params.quiet=-q -q @@ -144,118 +146,162 @@ func TestMinLength(t *testing.T) { } } -func TestRequired(t *testing.T) { +func TestMaxLength(t *testing.T) { testTables := []struct { propertyName string validationErrorPropertyName string + maxLength int complianceLevel compliancelevel.Type - assertion assert.BoolAssertionFunc }{ - {"name", "name", compliancelevel.Permissive, assert.True}, - {"name", "name", compliancelevel.Specification, assert.True}, - {"name", "name", compliancelevel.Strict, assert.True}, - - {"version", "version", compliancelevel.Permissive, assert.True}, - {"version", "version", compliancelevel.Specification, assert.True}, - {"version", "version", compliancelevel.Strict, assert.True}, - - {"compiler.warning_flags.none", "compiler\\.warning_flags\\.none", compliancelevel.Permissive, assert.False}, - {"compiler.warning_flags.none", "compiler\\.warning_flags\\.none", compliancelevel.Specification, assert.False}, - {"compiler.warning_flags.none", "compiler\\.warning_flags\\.none", compliancelevel.Strict, assert.True}, - - {"compiler.warning_flags.default", "compiler\\.warning_flags\\.default", compliancelevel.Permissive, assert.False}, - {"compiler.warning_flags.default", "compiler\\.warning_flags\\.default", compliancelevel.Specification, assert.False}, - {"compiler.warning_flags.default", "compiler\\.warning_flags\\.default", compliancelevel.Strict, assert.True}, - - {"compiler.warning_flags.more", "compiler\\.warning_flags\\.more", compliancelevel.Permissive, assert.False}, - {"compiler.warning_flags.more", "compiler\\.warning_flags\\.more", compliancelevel.Specification, assert.False}, - {"compiler.warning_flags.more", "compiler\\.warning_flags\\.more", compliancelevel.Strict, assert.True}, - - {"compiler.warning_flags.all", "compiler\\.warning_flags\\.all", compliancelevel.Permissive, assert.False}, - {"compiler.warning_flags.all", "compiler\\.warning_flags\\.all", compliancelevel.Specification, assert.False}, - {"compiler.warning_flags.all", "compiler\\.warning_flags\\.all", compliancelevel.Strict, assert.True}, - - {"recipe.c.o.pattern", "recipe\\.c\\.o\\.pattern", compliancelevel.Permissive, assert.True}, - {"recipe.c.o.pattern", "recipe\\.c\\.o\\.pattern", compliancelevel.Specification, assert.True}, - {"recipe.c.o.pattern", "recipe\\.c\\.o\\.pattern", compliancelevel.Strict, assert.True}, - - {"recipe.cpp.o.pattern", "recipe\\.cpp\\.o\\.pattern", compliancelevel.Permissive, assert.True}, - {"recipe.cpp.o.pattern", "recipe\\.cpp\\.o\\.pattern", compliancelevel.Specification, assert.True}, - {"recipe.cpp.o.pattern", "recipe\\.cpp\\.o\\.pattern", compliancelevel.Strict, assert.True}, - - {"recipe.S.o.pattern", "recipe\\.S\\.o\\.pattern", compliancelevel.Permissive, assert.True}, - {"recipe.S.o.pattern", "recipe\\.S\\.o\\.pattern", compliancelevel.Specification, assert.True}, - {"recipe.S.o.pattern", "recipe\\.S\\.o\\.pattern", compliancelevel.Strict, assert.True}, - - {"recipe.ar.pattern", "recipe\\.ar\\.pattern", compliancelevel.Permissive, assert.True}, - {"recipe.ar.pattern", "recipe\\.ar\\.pattern", compliancelevel.Specification, assert.True}, - {"recipe.ar.pattern", "recipe\\.ar\\.pattern", compliancelevel.Strict, assert.True}, - - {"recipe.c.combine.pattern", "recipe\\.c\\.combine\\.pattern", compliancelevel.Permissive, assert.True}, - {"recipe.c.combine.pattern", "recipe\\.c\\.combine\\.pattern", compliancelevel.Specification, assert.True}, - {"recipe.c.combine.pattern", "recipe\\.c\\.combine\\.pattern", compliancelevel.Strict, assert.True}, - - {"recipe.output.tmp_file", "recipe\\.output\\.tmp_file", compliancelevel.Permissive, assert.True}, - {"recipe.output.tmp_file", "recipe\\.output\\.tmp_file", compliancelevel.Specification, assert.True}, - {"recipe.output.tmp_file", "recipe\\.output\\.tmp_file", compliancelevel.Strict, assert.True}, - - {"tools.avrdude.upload.pattern", "tools/avrdude/upload/pattern", compliancelevel.Permissive, assert.True}, - {"tools.avrdude.upload.pattern", "tools/avrdude/upload/pattern", compliancelevel.Specification, assert.True}, - {"tools.avrdude.upload.pattern", "tools/avrdude/upload/pattern", compliancelevel.Strict, assert.True}, - - {"tools.avrdude.program.params.verbose", "tools/avrdude/program/params\\.verbose", compliancelevel.Permissive, assert.True}, - {"tools.avrdude.program.params.verbose", "tools/avrdude/program/params\\.verbose", compliancelevel.Specification, assert.True}, - {"tools.avrdude.program.params.verbose", "tools/avrdude/program/params\\.verbose", compliancelevel.Strict, assert.True}, - - {"tools.avrdude.program.params.quiet", "tools/avrdude/program/params\\.quiet", compliancelevel.Permissive, assert.True}, - {"tools.avrdude.program.params.quiet", "tools/avrdude/program/params\\.quiet", compliancelevel.Specification, assert.True}, - {"tools.avrdude.program.params.quiet", "tools/avrdude/program/params\\.quiet", compliancelevel.Strict, assert.True}, - - {"tools.avrdude.program.pattern", "tools/avrdude/program/pattern", compliancelevel.Permissive, assert.True}, - {"tools.avrdude.program.pattern", "tools/avrdude/program/pattern", compliancelevel.Specification, assert.True}, - {"tools.avrdude.program.pattern", "tools/avrdude/program/pattern", compliancelevel.Strict, assert.True}, - - {"tools.bossac.upload.pattern", "tools/bossac/upload/pattern", compliancelevel.Permissive, assert.True}, - {"tools.bossac.upload.pattern", "tools/bossac/upload/pattern", compliancelevel.Specification, assert.True}, - {"tools.bossac.upload.pattern", "tools/bossac/upload/pattern", compliancelevel.Strict, assert.True}, - - {"compiler.c.extra_flags", "compiler.c.extra_flags", compliancelevel.Permissive, assert.False}, - {"compiler.c.extra_flags", "compiler.c.extra_flags", compliancelevel.Specification, assert.False}, - {"compiler.c.extra_flags", "compiler.c.extra_flags", compliancelevel.Strict, assert.True}, - - {"compiler.c.elf.extra_flags", "compiler.c.elf.extra_flags", compliancelevel.Permissive, assert.False}, - {"compiler.c.elf.extra_flags", "compiler.c.elf.extra_flags", compliancelevel.Specification, assert.False}, - {"compiler.c.elf.extra_flags", "compiler.c.elf.extra_flags", compliancelevel.Strict, assert.True}, - - {"compiler.S.extra_flags", "compiler.S.extra_flags", compliancelevel.Permissive, assert.False}, - {"compiler.S.extra_flags", "compiler.S.extra_flags", compliancelevel.Specification, assert.False}, - {"compiler.S.extra_flags", "compiler.S.extra_flags", compliancelevel.Strict, assert.True}, + {"tools.avrdude.upload.field.foo_field_name", "tools/avrdude/upload/field/foo_field_name", 50, compliancelevel.Specification}, + {"tools.avrdude.upload.field.foo_field_name", "tools/avrdude/upload/field/foo_field_name", 50, compliancelevel.Strict}, + } - {"compiler.cpp.extra_flags", "compiler.cpp.extra_flags", compliancelevel.Permissive, assert.False}, - {"compiler.cpp.extra_flags", "compiler.cpp.extra_flags", compliancelevel.Specification, assert.False}, - {"compiler.cpp.extra_flags", "compiler.cpp.extra_flags", compliancelevel.Strict, assert.True}, + // Test schema validation results with value length > maximum. + for _, testTable := range testTables { + platformTxt, err := properties.LoadFromBytes(validPlatformTxtRaw) + require.Nil(t, err) + platformTxt.Set(testTable.propertyName, strings.Repeat("a", testTable.maxLength+1)) - {"compiler.ar.extra_flags", "compiler.ar.extra_flags", compliancelevel.Permissive, assert.False}, - {"compiler.ar.extra_flags", "compiler.ar.extra_flags", compliancelevel.Specification, assert.False}, - {"compiler.ar.extra_flags", "compiler.ar.extra_flags", compliancelevel.Strict, assert.True}, + t.Run(fmt.Sprintf("%s greater than maximum length of %d (%s)", testTable.propertyName, testTable.maxLength, testTable.complianceLevel), func(t *testing.T) { + assert.True(t, schema.PropertyGreaterThanMaxLength(testTable.validationErrorPropertyName, platformtxt.Validate(platformTxt)[testTable.complianceLevel])) + }) - {"recipe.size.pattern", "recipe.size.pattern", compliancelevel.Permissive, assert.False}, - {"recipe.size.pattern", "recipe.size.pattern", compliancelevel.Specification, assert.False}, - {"recipe.size.pattern", "recipe.size.pattern", compliancelevel.Strict, assert.True}, + // Test schema validation results with maximum value length. + platformTxt, err = properties.LoadFromBytes(validPlatformTxtRaw) + require.Nil(t, err) + platformTxt.Set(testTable.propertyName, strings.Repeat("a", testTable.maxLength)) - {"recipe.size.regex", "recipe.size.regex", compliancelevel.Permissive, assert.False}, - {"recipe.size.regex", "recipe.size.regex", compliancelevel.Specification, assert.False}, - {"recipe.size.regex", "recipe.size.regex", compliancelevel.Strict, assert.True}, + t.Run(fmt.Sprintf("%s at maximum length of %d (%s)", testTable.propertyName, testTable.maxLength, testTable.complianceLevel), func(t *testing.T) { + assert.False(t, schema.PropertyGreaterThanMaxLength(testTable.validationErrorPropertyName, platformtxt.Validate(platformTxt)[testTable.complianceLevel])) + }) + } +} - {"recipe.size.regex.data", "recipe.size.regex.data", compliancelevel.Permissive, assert.False}, - {"recipe.size.regex.data", "recipe.size.regex.data", compliancelevel.Specification, assert.False}, - {"recipe.size.regex.data", "recipe.size.regex.data", compliancelevel.Strict, assert.True}, +func TestRequired(t *testing.T) { + testTables := []struct { + propertyName string + replacementPropertyName string // Used for testing subkeys that are required only when the higher level key is present. + validationErrorPropertyName string + complianceLevel compliancelevel.Type + assertion assert.BoolAssertionFunc + }{ + {"name", "", "name", compliancelevel.Permissive, assert.True}, + {"name", "", "name", compliancelevel.Specification, assert.True}, + {"name", "", "name", compliancelevel.Strict, assert.True}, + + {"version", "", "version", compliancelevel.Permissive, assert.True}, + {"version", "", "version", compliancelevel.Specification, assert.True}, + {"version", "", "version", compliancelevel.Strict, assert.True}, + + {"compiler.warning_flags.none", "", "compiler\\.warning_flags\\.none", compliancelevel.Permissive, assert.False}, + {"compiler.warning_flags.none", "", "compiler\\.warning_flags\\.none", compliancelevel.Specification, assert.False}, + {"compiler.warning_flags.none", "", "compiler\\.warning_flags\\.none", compliancelevel.Strict, assert.True}, + + {"compiler.warning_flags.default", "", "compiler\\.warning_flags\\.default", compliancelevel.Permissive, assert.False}, + {"compiler.warning_flags.default", "", "compiler\\.warning_flags\\.default", compliancelevel.Specification, assert.False}, + {"compiler.warning_flags.default", "", "compiler\\.warning_flags\\.default", compliancelevel.Strict, assert.True}, + + {"compiler.warning_flags.more", "", "compiler\\.warning_flags\\.more", compliancelevel.Permissive, assert.False}, + {"compiler.warning_flags.more", "", "compiler\\.warning_flags\\.more", compliancelevel.Specification, assert.False}, + {"compiler.warning_flags.more", "", "compiler\\.warning_flags\\.more", compliancelevel.Strict, assert.True}, + + {"compiler.warning_flags.all", "", "compiler\\.warning_flags\\.all", compliancelevel.Permissive, assert.False}, + {"compiler.warning_flags.all", "", "compiler\\.warning_flags\\.all", compliancelevel.Specification, assert.False}, + {"compiler.warning_flags.all", "", "compiler\\.warning_flags\\.all", compliancelevel.Strict, assert.True}, + + {"recipe.c.o.pattern", "", "recipe\\.c\\.o\\.pattern", compliancelevel.Permissive, assert.True}, + {"recipe.c.o.pattern", "", "recipe\\.c\\.o\\.pattern", compliancelevel.Specification, assert.True}, + {"recipe.c.o.pattern", "", "recipe\\.c\\.o\\.pattern", compliancelevel.Strict, assert.True}, + + {"recipe.cpp.o.pattern", "", "recipe\\.cpp\\.o\\.pattern", compliancelevel.Permissive, assert.True}, + {"recipe.cpp.o.pattern", "", "recipe\\.cpp\\.o\\.pattern", compliancelevel.Specification, assert.True}, + {"recipe.cpp.o.pattern", "", "recipe\\.cpp\\.o\\.pattern", compliancelevel.Strict, assert.True}, + + {"recipe.S.o.pattern", "", "recipe\\.S\\.o\\.pattern", compliancelevel.Permissive, assert.True}, + {"recipe.S.o.pattern", "", "recipe\\.S\\.o\\.pattern", compliancelevel.Specification, assert.True}, + {"recipe.S.o.pattern", "", "recipe\\.S\\.o\\.pattern", compliancelevel.Strict, assert.True}, + + {"recipe.ar.pattern", "", "recipe\\.ar\\.pattern", compliancelevel.Permissive, assert.True}, + {"recipe.ar.pattern", "", "recipe\\.ar\\.pattern", compliancelevel.Specification, assert.True}, + {"recipe.ar.pattern", "", "recipe\\.ar\\.pattern", compliancelevel.Strict, assert.True}, + + {"recipe.c.combine.pattern", "", "recipe\\.c\\.combine\\.pattern", compliancelevel.Permissive, assert.True}, + {"recipe.c.combine.pattern", "", "recipe\\.c\\.combine\\.pattern", compliancelevel.Specification, assert.True}, + {"recipe.c.combine.pattern", "", "recipe\\.c\\.combine\\.pattern", compliancelevel.Strict, assert.True}, + + {"recipe.output.tmp_file", "", "recipe\\.output\\.tmp_file", compliancelevel.Permissive, assert.True}, + {"recipe.output.tmp_file", "", "recipe\\.output\\.tmp_file", compliancelevel.Specification, assert.True}, + {"recipe.output.tmp_file", "", "recipe\\.output\\.tmp_file", compliancelevel.Strict, assert.True}, + + {"tools.avrdude.upload.pattern", "", "tools/avrdude/upload/pattern", compliancelevel.Permissive, assert.True}, + {"tools.avrdude.upload.pattern", "", "tools/avrdude/upload/pattern", compliancelevel.Specification, assert.True}, + {"tools.avrdude.upload.pattern", "", "tools/avrdude/upload/pattern", compliancelevel.Strict, assert.True}, + + {"tools.avrdude.program.params.verbose", "", "tools/avrdude/program/params/verbose", compliancelevel.Permissive, assert.True}, + {"tools.avrdude.program.params.verbose", "", "tools/avrdude/program/params/verbose", compliancelevel.Specification, assert.True}, + {"tools.avrdude.program.params.verbose", "", "tools/avrdude/program/params/verbose", compliancelevel.Strict, assert.True}, + + {"tools.avrdude.program.params.quiet", "", "tools/avrdude/program/params/quiet", compliancelevel.Permissive, assert.True}, + {"tools.avrdude.program.params.quiet", "", "tools/avrdude/program/params/quiet", compliancelevel.Specification, assert.True}, + {"tools.avrdude.program.params.quiet", "", "tools/avrdude/program/params/quiet", compliancelevel.Strict, assert.True}, + + {"tools.avrdude.program.pattern", "", "tools/avrdude/program/pattern", compliancelevel.Permissive, assert.True}, + {"tools.avrdude.program.pattern", "", "tools/avrdude/program/pattern", compliancelevel.Specification, assert.True}, + {"tools.avrdude.program.pattern", "", "tools/avrdude/program/pattern", compliancelevel.Strict, assert.True}, + + {"tools.bossac.upload.pattern", "", "tools/bossac/upload/pattern", compliancelevel.Permissive, assert.True}, + {"tools.bossac.upload.pattern", "", "tools/bossac/upload/pattern", compliancelevel.Specification, assert.True}, + {"tools.bossac.upload.pattern", "", "tools/bossac/upload/pattern", compliancelevel.Strict, assert.True}, + + {"compiler.c.extra_flags", "", "compiler.c.extra_flags", compliancelevel.Permissive, assert.False}, + {"compiler.c.extra_flags", "", "compiler.c.extra_flags", compliancelevel.Specification, assert.False}, + {"compiler.c.extra_flags", "", "compiler.c.extra_flags", compliancelevel.Strict, assert.True}, + + {"compiler.c.elf.extra_flags", "", "compiler.c.elf.extra_flags", compliancelevel.Permissive, assert.False}, + {"compiler.c.elf.extra_flags", "", "compiler.c.elf.extra_flags", compliancelevel.Specification, assert.False}, + {"compiler.c.elf.extra_flags", "", "compiler.c.elf.extra_flags", compliancelevel.Strict, assert.True}, + + {"compiler.S.extra_flags", "", "compiler.S.extra_flags", compliancelevel.Permissive, assert.False}, + {"compiler.S.extra_flags", "", "compiler.S.extra_flags", compliancelevel.Specification, assert.False}, + {"compiler.S.extra_flags", "", "compiler.S.extra_flags", compliancelevel.Strict, assert.True}, + + {"compiler.cpp.extra_flags", "", "compiler.cpp.extra_flags", compliancelevel.Permissive, assert.False}, + {"compiler.cpp.extra_flags", "", "compiler.cpp.extra_flags", compliancelevel.Specification, assert.False}, + {"compiler.cpp.extra_flags", "", "compiler.cpp.extra_flags", compliancelevel.Strict, assert.True}, + + {"compiler.ar.extra_flags", "", "compiler.ar.extra_flags", compliancelevel.Permissive, assert.False}, + {"compiler.ar.extra_flags", "", "compiler.ar.extra_flags", compliancelevel.Specification, assert.False}, + {"compiler.ar.extra_flags", "", "compiler.ar.extra_flags", compliancelevel.Strict, assert.True}, + + {"pluggable_discovery.foo.pattern", "pluggable_discovery.foo.bar", "pluggable_discovery/foo/pattern", compliancelevel.Permissive, assert.True}, + {"pluggable_discovery.foo.pattern", "pluggable_discovery.foo.bar", "pluggable_discovery/foo/pattern", compliancelevel.Specification, assert.True}, + {"pluggable_discovery.foo.pattern", "pluggable_discovery.foo.bar", "pluggable_discovery/foo/pattern", compliancelevel.Strict, assert.True}, + // Property is only required when there is a pluggable_discovery.foo object + {"pluggable_discovery.foo.pattern", "", "pluggable_discovery/foo/pattern", compliancelevel.Permissive, assert.False}, + {"pluggable_discovery.foo.pattern", "", "pluggable_discovery/foo/pattern", compliancelevel.Specification, assert.False}, + {"pluggable_discovery.foo.pattern", "", "pluggable_discovery/foo/pattern", compliancelevel.Strict, assert.False}, + + {"recipe.size.pattern", "", "recipe.size.pattern", compliancelevel.Permissive, assert.False}, + {"recipe.size.pattern", "", "recipe.size.pattern", compliancelevel.Specification, assert.False}, + {"recipe.size.pattern", "", "recipe.size.pattern", compliancelevel.Strict, assert.True}, + + {"recipe.size.regex", "", "recipe.size.regex", compliancelevel.Permissive, assert.False}, + {"recipe.size.regex", "", "recipe.size.regex", compliancelevel.Specification, assert.False}, + {"recipe.size.regex", "", "recipe.size.regex", compliancelevel.Strict, assert.True}, + + {"recipe.size.regex.data", "", "recipe.size.regex.data", compliancelevel.Permissive, assert.False}, + {"recipe.size.regex.data", "", "recipe.size.regex.data", compliancelevel.Specification, assert.False}, + {"recipe.size.regex.data", "", "recipe.size.regex.data", compliancelevel.Strict, assert.True}, } for _, testTable := range testTables { platformTxt, err := properties.LoadFromBytes(validPlatformTxtRaw) require.Nil(t, err) platformTxt.Remove(testTable.propertyName) + if testTable.replacementPropertyName != "" { + platformTxt.Set(testTable.replacementPropertyName, "foo") + } validationResult := platformtxt.Validate(platformTxt) t.Run(fmt.Sprintf("%s (%s)", testTable.propertyName, testTable.complianceLevel), func(t *testing.T) { @@ -306,6 +352,16 @@ func TestEnum(t *testing.T) { {"compiler.ar.extra_flags", "compiler\\.ar\\.extra_flags", "foo", compliancelevel.Permissive, assert.False}, {"compiler.ar.extra_flags", "compiler\\.ar\\.extra_flags", "foo", compliancelevel.Specification, assert.False}, {"compiler.ar.extra_flags", "compiler\\.ar\\.extra_flags", "foo", compliancelevel.Strict, assert.True}, + + {"tools.avrdude.upload.field.foo_field_name.secret", "tools/avrdude/upload/field/foo_field_name\\.secret", "true", compliancelevel.Permissive, assert.False}, + {"tools.avrdude.upload.field.foo_field_name.secret", "tools/avrdude/upload/field/foo_field_name\\.secret", "true", compliancelevel.Specification, assert.False}, + {"tools.avrdude.upload.field.foo_field_name.secret", "tools/avrdude/upload/field/foo_field_name\\.secret", "true", compliancelevel.Strict, assert.False}, + {"tools.avrdude.upload.field.foo_field_name.secret", "tools/avrdude/upload/field/foo_field_name\\.secret", "false", compliancelevel.Permissive, assert.False}, + {"tools.avrdude.upload.field.foo_field_name.secret", "tools/avrdude/upload/field/foo_field_name\\.secret", "false", compliancelevel.Specification, assert.False}, + {"tools.avrdude.upload.field.foo_field_name.secret", "tools/avrdude/upload/field/foo_field_name\\.secret", "false", compliancelevel.Strict, assert.False}, + {"tools.avrdude.upload.field.foo_field_name.secret", "tools/avrdude/upload/field/foo_field_name\\.secret", "foo", compliancelevel.Permissive, assert.True}, + {"tools.avrdude.upload.field.foo_field_name.secret", "tools/avrdude/upload/field/foo_field_name\\.secret", "foo", compliancelevel.Specification, assert.True}, + {"tools.avrdude.upload.field.foo_field_name.secret", "tools/avrdude/upload/field/foo_field_name\\.secret", "foo", compliancelevel.Strict, assert.True}, } for _, testTable := range testTables { @@ -383,6 +439,19 @@ func TestPattern(t *testing.T) { {"recipe.preproc.macros", "recipe\\.preproc\\.macros", "foo", compliancelevel.Permissive, assert.False}, {"recipe.preproc.macros", "recipe\\.preproc\\.macros", "foo", compliancelevel.Specification, assert.False}, {"recipe.preproc.macros", "recipe\\.preproc\\.macros", "foo", compliancelevel.Strict, assert.True}, + + {"pluggable_discovery.required", "pluggable_discovery/required", "foo:bar", compliancelevel.Permissive, assert.False}, + {"pluggable_discovery.required", "pluggable_discovery/required", "foo:bar", compliancelevel.Specification, assert.False}, + {"pluggable_discovery.required", "pluggable_discovery/required", "foo:bar", compliancelevel.Strict, assert.False}, + {"pluggable_discovery.required", "pluggable_discovery/required", "foo", compliancelevel.Permissive, assert.True}, + {"pluggable_discovery.required", "pluggable_discovery/required", "foo", compliancelevel.Specification, assert.True}, + {"pluggable_discovery.required", "pluggable_discovery/required", "foo", compliancelevel.Strict, assert.True}, + {"pluggable_discovery.required.1", "pluggable_discovery/required", "foo:bar", compliancelevel.Permissive, assert.False}, + {"pluggable_discovery.required.1", "pluggable_discovery/required", "foo:bar", compliancelevel.Specification, assert.False}, + {"pluggable_discovery.required.1", "pluggable_discovery/required", "foo:bar", compliancelevel.Strict, assert.False}, + {"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}, } 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 3adfb9b6..ddbab5ea 100644 --- a/internal/project/platform/platformtxt/testdata/valid/platform.txt +++ b/internal/project/platform/platformtxt/testdata/valid/platform.txt @@ -23,6 +23,8 @@ 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 diff --git a/internal/project/projectdata/platform.go b/internal/project/projectdata/platform.go index b22b9273..aa4da58a 100644 --- a/internal/project/projectdata/platform.go +++ b/internal/project/projectdata/platform.go @@ -58,10 +58,14 @@ func InitializeForPlatform(project project.Type) { if platformTxtLoadError != nil { logrus.Tracef("Error loading platform.txt from %s: %s", project.Path, platformTxtLoadError) platformTxtSchemaValidationResult = nil + platformTxtPluggableDiscoveryNames = nil + platformTxtUserProvidedFieldNames = nil platformTxtToolNames = nil } else { platformTxtSchemaValidationResult = platformtxt.Validate(platformTxt) + platformTxtPluggableDiscoveryNames = platformtxt.PluggableDiscoveryNames(platformTxt) + platformTxtUserProvidedFieldNames = platformtxt.UserProvidedFieldNames(platformTxt) platformTxtToolNames = platformtxt.ToolNames(platformTxt) } } @@ -145,7 +149,7 @@ func ProgrammersTxtProgrammerIds() []string { var platformTxtExists bool -// PlatformTxtExists returns whether the platform contains a programmer.txt file. +// PlatformTxtExists returns whether the platform contains a platform.txt file. func PlatformTxtExists() bool { return platformTxtExists } @@ -171,6 +175,20 @@ func PlatformTxtSchemaValidationResult() map[compliancelevel.Type]schema.Validat return platformTxtSchemaValidationResult } +var platformTxtPluggableDiscoveryNames []string + +// PlatformTxtPluggableDiscoveryNames returns the list of pluggable discoveries present in the platform's platform.txt. +func PlatformTxtPluggableDiscoveryNames() []string { + return platformTxtPluggableDiscoveryNames +} + +var platformTxtUserProvidedFieldNames map[string][]string + +// PlatformTxtUserProvidedFieldNames returns the list of user provided field names present in the platform's platform.txt, mapped by board name. +func PlatformTxtUserProvidedFieldNames() map[string][]string { + return platformTxtUserProvidedFieldNames +} + var platformTxtToolNames []string // PlatformTxtToolNames returns the list of tools present in the platform's platform.txt. diff --git a/internal/project/projectdata/platform_test.go b/internal/project/projectdata/platform_test.go index 8effadeb..5f8e0ae6 100644 --- a/internal/project/projectdata/platform_test.go +++ b/internal/project/projectdata/platform_test.go @@ -16,6 +16,7 @@ package projectdata import ( + "reflect" "testing" "github.com/arduino/arduino-lint/internal/project" @@ -36,22 +37,24 @@ func init() { func TestInitializeForPlatform(t *testing.T) { testTables := []struct { - testName string - platformFolderName string - boardsTxtAssertion assert.ValueAssertionFunc - boardsTxtLoadErrorAssertion assert.ValueAssertionFunc - platformTxtExistsAssertion assert.BoolAssertionFunc - platformTxtAssertion assert.ValueAssertionFunc - platformTxtLoadErrorAssertion assert.ValueAssertionFunc - platformTxtSchemaValidationResultAssertion assert.ValueAssertionFunc - platformTxtToolNamesAssertion []string + testName string + platformFolderName string + boardsTxtAssertion assert.ValueAssertionFunc + boardsTxtLoadErrorAssertion assert.ValueAssertionFunc + platformTxtExistsAssertion assert.BoolAssertionFunc + platformTxtAssertion assert.ValueAssertionFunc + platformTxtLoadErrorAssertion assert.ValueAssertionFunc + platformTxtSchemaValidationResultAssertion assert.ValueAssertionFunc + platformTxtPluggableDiscoveryNamesAssertion []string + platformTxtUserProvidedFieldNamesAssertion map[string][]string + platformTxtToolNamesAssertion []string }{ - {"Valid boards.txt", "valid-boards.txt", assert.NotNil, assert.Nil, assert.False, assert.Nil, assert.NotNil, assert.Nil, nil}, - {"Invalid boards.txt", "invalid-boards.txt", assert.Nil, assert.NotNil, assert.False, assert.Nil, assert.NotNil, assert.Nil, nil}, - {"Missing boards.txt", "missing-boards.txt", assert.Nil, assert.NotNil, assert.False, assert.Nil, assert.NotNil, assert.Nil, nil}, - {"Valid platform.txt", "valid-platform.txt", assert.NotNil, assert.Nil, assert.True, assert.NotNil, assert.Nil, assert.NotNil, []string{"avrdude", "bossac"}}, - {"Invalid platform.txt", "invalid-platform.txt", assert.NotNil, assert.Nil, assert.True, assert.Nil, assert.NotNil, assert.Nil, nil}, - {"Missing platform.txt", "missing-platform.txt", assert.NotNil, assert.Nil, assert.False, assert.Nil, assert.NotNil, assert.Nil, nil}, + {"Valid boards.txt", "valid-boards.txt", assert.NotNil, assert.Nil, assert.False, assert.Nil, assert.NotNil, assert.Nil, nil, nil, nil}, + {"Invalid boards.txt", "invalid-boards.txt", assert.Nil, assert.NotNil, assert.False, assert.Nil, assert.NotNil, assert.Nil, nil, nil, nil}, + {"Missing boards.txt", "missing-boards.txt", assert.Nil, assert.NotNil, assert.False, assert.Nil, assert.NotNil, assert.Nil, nil, nil, nil}, + {"Valid platform.txt", "valid-platform.txt", assert.NotNil, assert.Nil, assert.True, assert.NotNil, assert.Nil, assert.NotNil, []string{"foo_discovery", "bar_discovery"}, map[string][]string{"avrdude": {"foo_field_name"}}, []string{"avrdude", "bossac"}}, + {"Invalid platform.txt", "invalid-platform.txt", assert.NotNil, assert.Nil, assert.True, assert.Nil, assert.NotNil, assert.Nil, nil, nil, nil}, + {"Missing platform.txt", "missing-platform.txt", assert.NotNil, assert.Nil, assert.False, assert.Nil, assert.NotNil, assert.Nil, nil, nil, nil}, } for _, testTable := range testTables { @@ -72,6 +75,8 @@ func TestInitializeForPlatform(t *testing.T) { testTable.platformTxtAssertion(t, PlatformTxt(), testTable.testName) testTable.platformTxtLoadErrorAssertion(t, PlatformTxtLoadError(), testTable.testName) testTable.platformTxtSchemaValidationResultAssertion(t, PlatformTxtSchemaValidationResult(), testTable.testName) + assert.Equal(t, testTable.platformTxtPluggableDiscoveryNamesAssertion, PlatformTxtPluggableDiscoveryNames(), testTable.testName) + assert.True(t, reflect.DeepEqual(testTable.platformTxtUserProvidedFieldNamesAssertion, PlatformTxtUserProvidedFieldNames()), testTable.testName) assert.Equal(t, testTable.platformTxtToolNamesAssertion, PlatformTxtToolNames(), testTable.testName) } } diff --git a/internal/project/projectdata/testdata/platforms/valid-platform.txt/platform.txt b/internal/project/projectdata/testdata/platforms/valid-platform.txt/platform.txt index 14781796..2a217d81 100644 --- a/internal/project/projectdata/testdata/platforms/valid-platform.txt/platform.txt +++ b/internal/project/projectdata/testdata/platforms/valid-platform.txt/platform.txt @@ -23,6 +23,10 @@ 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_discovery.bar_discovery.pattern=zxcv +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 diff --git a/internal/rule/ruleconfiguration/ruleconfiguration.go b/internal/rule/ruleconfiguration/ruleconfiguration.go index bed0553c..89721672 100644 --- a/internal/rule/ruleconfiguration/ruleconfiguration.go +++ b/internal/rule/ruleconfiguration/ruleconfiguration.go @@ -1781,9 +1781,9 @@ var configurations = []Type{ Category: "configuration files", Subcategory: "boards.txt", ID: "PF016", - Brief: "missing upload.tool", - Description: "A board definition in the platform's `boards.txt` configuration file is missing the `upload.tool` property.", - MessageTemplate: "Missing upload.tool property for board ID(s) {{.}}", + Brief: "missing upload.tool.", + Description: "A board definition in the platform's `boards.txt` configuration file is missing the `upload.tool.` property.", + MessageTemplate: "Missing upload.tool. property for board ID(s) {{.}}", Reference: "https://arduino.github.io/arduino-cli/latest/platform-specification/#sketch-upload-configuration", DisableModes: nil, EnableModes: []rulemode.Type{rulemode.Default}, @@ -1798,9 +1798,9 @@ var configurations = []Type{ Category: "configuration files", Subcategory: "boards.txt", ID: "PF017", - Brief: "upload.tool < min length", - Description: "The `upload.tool` property for a board definition in the platform's `boards.txt` configuration file is shorter than the minimum length.", - MessageTemplate: "upload.tool value for board ID(s) {{.}} is less than the minimum length.", + Brief: "upload.tool. < min length", + Description: "The `upload.tool.` property for a board definition in the platform's `boards.txt` configuration file is shorter than the minimum length.", + MessageTemplate: "upload.tool. value for board ID(s) {{.}} is less than the minimum length.", Reference: "https://arduino.github.io/arduino-cli/latest/platform-specification/#sketch-upload-configuration", DisableModes: nil, EnableModes: []rulemode.Type{rulemode.Default}, @@ -2829,6 +2829,74 @@ var configurations = []Type{ ErrorModes: []rulemode.Type{rulemode.Strict}, RuleFunction: rulefunction.PlatformTxtRecipeSizeRegexDataMissing, }, + { + ProjectType: projecttype.Platform, + SuperprojectType: projecttype.All, + Category: "configuration files", + Subcategory: "platform.txt", + ID: "PF090", + Brief: "invalid pluggable_discovery.required format", + Description: "The tool dependency reference for a pluggable discovery in the platform's `platform.txt` configuration file has an invalid format.", + MessageTemplate: "Value for tool dependency reference of pluggable discovery(s) {{.}} is invalid.", + Reference: "https://arduino.github.io/arduino-cli/latest/platform-specification/#pluggable-discovery", + DisableModes: nil, + EnableModes: []rulemode.Type{rulemode.Default}, + InfoModes: nil, + WarningModes: nil, + ErrorModes: []rulemode.Type{rulemode.Default}, + RuleFunction: rulefunction.PlatformTxtPluggableDiscoveryRequiredInvalid, + }, + { + ProjectType: projecttype.Platform, + SuperprojectType: projecttype.All, + Category: "configuration files", + Subcategory: "platform.txt", + ID: "PF091", + Brief: "missing pluggable_discovery.DISCOVERY_ID.pattern", + Description: "A manual installation pluggable discovery in the platform's `platform.txt` configuration file is missing the `pattern` property.", + MessageTemplate: "Missing pattern for {{.}} pluggable discovery(s).", + Reference: "https://arduino.github.io/arduino-cli/latest/platform-specification/#pluggable-discovery", + DisableModes: nil, + EnableModes: []rulemode.Type{rulemode.Default}, + InfoModes: nil, + WarningModes: nil, + ErrorModes: []rulemode.Type{rulemode.Default}, + RuleFunction: rulefunction.PlatformTxtPluggableDiscoveryDiscoveryIDPatternMissing, + }, + { + ProjectType: projecttype.Platform, + SuperprojectType: projecttype.All, + Category: "configuration files", + Subcategory: "platform.txt", + ID: "PF092", + Brief: "upload.field.FIELD_NAME > max length", + Description: "The `tools.UPLOAD_RECIPE_ID.upload.field.FIELD_NAME` property in the platform's `platform.txt` configuration file is longer than the maximum length.", + MessageTemplate: "upload.UPLOAD_RECIPE_ID.upload.field.FIELD_NAME property is longer than the maximum length for fields: {{.}}", + Reference: "https://arduino.github.io/arduino-cli/dev/platform-specification/#user-provided-fields", + DisableModes: nil, + EnableModes: []rulemode.Type{rulemode.Default}, + InfoModes: nil, + WarningModes: nil, + ErrorModes: []rulemode.Type{rulemode.Default}, + RuleFunction: rulefunction.PlatformTxtUploadFieldFieldNameGTMaxLength, + }, + { + ProjectType: projecttype.Platform, + SuperprojectType: projecttype.All, + Category: "configuration files", + Subcategory: "platform.txt", + ID: "PF093", + Brief: "upload.field.FIELD_NAME.secret invalid", + Description: "The `tools.UPLOAD_RECIPE_ID.upload.field.FIELD_NAME.secret` property in the platform's `platform.txt` configuration file has an invalid value.", + MessageTemplate: "tools.UPLOAD_RECIPE_ID.upload.field.FIELD_NAME.secret value is invalid or field(s) {{.}}", + Reference: "https://arduino.github.io/arduino-cli/dev/platform-specification/#user-provided-fields", + DisableModes: nil, + EnableModes: []rulemode.Type{rulemode.Default}, + InfoModes: nil, + WarningModes: nil, + ErrorModes: []rulemode.Type{rulemode.Default}, + RuleFunction: rulefunction.PlatformTxtUploadFieldFieldNameSecretInvalid, + }, { ProjectType: projecttype.Platform, SuperprojectType: projecttype.All, diff --git a/internal/rule/rulefunction/platform.go b/internal/rule/rulefunction/platform.go index 63aec64f..bbdee73d 100644 --- a/internal/rule/rulefunction/platform.go +++ b/internal/rule/rulefunction/platform.go @@ -16,12 +16,14 @@ package rulefunction import ( + "fmt" "strings" "github.com/arduino/arduino-lint/internal/project/projectdata" "github.com/arduino/arduino-lint/internal/rule/ruleresult" "github.com/arduino/arduino-lint/internal/rule/schema" "github.com/arduino/arduino-lint/internal/rule/schema/compliancelevel" + "github.com/arduino/go-properties-orderedmap" "github.com/sirupsen/logrus" ) @@ -103,7 +105,7 @@ func BoardsTxtBoardIDBuildBoardMissing() (result ruleresult.Type, output string) return ruleresult.Skip, "boards.txt has no boards" } - nonCompliantBoardIDs := boardIDMissingRequiredProperty(projectdata.BoardsTxtBoardIds(), "build.board") + nonCompliantBoardIDs := boardIDMissingRequiredProperty(projectdata.BoardsTxtBoardIds(), "build.board", false) if len(nonCompliantBoardIDs) > 0 { return ruleresult.Fail, strings.Join(nonCompliantBoardIDs, ", ") @@ -141,7 +143,7 @@ func BoardsTxtBoardIDBuildCoreMissing() (result ruleresult.Type, output string) return ruleresult.Skip, "boards.txt has no visible boards" } - nonCompliantBoardIDs := boardIDMissingRequiredProperty(projectdata.BoardsTxtVisibleBoardIds(), "build.core") + nonCompliantBoardIDs := boardIDMissingRequiredProperty(projectdata.BoardsTxtVisibleBoardIds(), "build.core", false) if len(nonCompliantBoardIDs) > 0 { return ruleresult.Fail, strings.Join(nonCompliantBoardIDs, ", ") @@ -284,7 +286,7 @@ func BoardsTxtBoardIDUploadToolMissing() (result ruleresult.Type, output string) return ruleresult.Skip, "boards.txt has no visible boards" } - nonCompliantBoardIDs := boardIDMissingRequiredProperty(projectdata.BoardsTxtVisibleBoardIds(), "upload.tool") + nonCompliantBoardIDs := boardIDMissingRequiredProperty(projectdata.BoardsTxtVisibleBoardIds(), "upload.tool", true) if len(nonCompliantBoardIDs) > 0 { return ruleresult.Fail, strings.Join(nonCompliantBoardIDs, ", ") @@ -303,7 +305,7 @@ func BoardsTxtBoardIDUploadToolLTMinLength() (result ruleresult.Type, output str return ruleresult.Skip, "boards.txt has no boards" } - nonCompliantBoardIDs := boardIDValueLTMinLength(projectdata.BoardsTxtBoardIds(), "upload\\.tool", compliancelevel.Specification) + nonCompliantBoardIDs := boardIDValueLTMinLength(projectdata.BoardsTxtBoardIds(), "upload\\.tool(\\..+)?", compliancelevel.Specification) if len(nonCompliantBoardIDs) > 0 { return ruleresult.Fail, strings.Join(nonCompliantBoardIDs, ", ") @@ -322,7 +324,7 @@ func BoardsTxtBoardIDUploadMaximumSizeMissing() (result ruleresult.Type, output return ruleresult.Skip, "boards.txt has no visible boards" } - nonCompliantBoardIDs := boardIDMissingRequiredProperty(projectdata.BoardsTxtVisibleBoardIds(), "upload.maximum_size") + nonCompliantBoardIDs := boardIDMissingRequiredProperty(projectdata.BoardsTxtVisibleBoardIds(), "upload.maximum_size", false) if len(nonCompliantBoardIDs) > 0 { return ruleresult.Fail, strings.Join(nonCompliantBoardIDs, ", ") @@ -341,7 +343,7 @@ func BoardsTxtBoardIDUploadMaximumSizeInvalid() (result ruleresult.Type, output return ruleresult.Skip, "boards.txt has no boards" } - nonCompliantBoardIDs := boardIDValuePatternMismatch(projectdata.BoardsTxtBoardIds(), "upload\\.maximum_size", compliancelevel.Specification) + nonCompliantBoardIDs := boardIDValuePatternMismatch(projectdata.BoardsTxtBoardIds(), "upload(\\..+)?\\.maximum_size", compliancelevel.Specification) if len(nonCompliantBoardIDs) > 0 { return ruleresult.Fail, strings.Join(nonCompliantBoardIDs, ", ") @@ -360,7 +362,7 @@ func BoardsTxtBoardIDUploadMaximumDataSizeMissing() (result ruleresult.Type, out return ruleresult.Skip, "boards.txt has no visible boards" } - nonCompliantBoardIDs := boardIDMissingRequiredProperty(projectdata.BoardsTxtVisibleBoardIds(), "upload.maximum_data_size") + nonCompliantBoardIDs := boardIDMissingRequiredProperty(projectdata.BoardsTxtVisibleBoardIds(), "upload.maximum_data_size", false) if len(nonCompliantBoardIDs) > 0 { return ruleresult.Fail, strings.Join(nonCompliantBoardIDs, ", ") @@ -379,7 +381,7 @@ func BoardsTxtBoardIDUploadMaximumDataSizeInvalid() (result ruleresult.Type, out return ruleresult.Skip, "boards.txt has no boards" } - nonCompliantBoardIDs := boardIDValuePatternMismatch(projectdata.BoardsTxtBoardIds(), "upload\\.maximum_data_size", compliancelevel.Specification) + nonCompliantBoardIDs := boardIDValuePatternMismatch(projectdata.BoardsTxtBoardIds(), "upload(\\..+)?\\.maximum_data_size", compliancelevel.Specification) if len(nonCompliantBoardIDs) > 0 { return ruleresult.Fail, strings.Join(nonCompliantBoardIDs, ", ") @@ -398,7 +400,7 @@ func BoardsTxtBoardIDUploadUse1200bpsTouchInvalid() (result ruleresult.Type, out return ruleresult.Skip, "boards.txt has no boards" } - nonCompliantBoardIDs := boardIDValueEnumMismatch(projectdata.BoardsTxtBoardIds(), "upload\\.use_1200bps_touch", compliancelevel.Specification) + nonCompliantBoardIDs := boardIDValueEnumMismatch(projectdata.BoardsTxtBoardIds(), "upload(\\..+)?\\.use_1200bps_touch", compliancelevel.Specification) if len(nonCompliantBoardIDs) > 0 { return ruleresult.Fail, strings.Join(nonCompliantBoardIDs, ", ") @@ -417,7 +419,7 @@ func BoardsTxtBoardIDUploadWaitForUploadPortInvalid() (result ruleresult.Type, o return ruleresult.Skip, "boards.txt has no boards" } - nonCompliantBoardIDs := boardIDValueEnumMismatch(projectdata.BoardsTxtBoardIds(), "upload\\.wait_for_upload_port", compliancelevel.Specification) + nonCompliantBoardIDs := boardIDValueEnumMismatch(projectdata.BoardsTxtBoardIds(), "upload(\\..+)?\\.wait_for_upload_port", compliancelevel.Specification) if len(nonCompliantBoardIDs) > 0 { return ruleresult.Fail, strings.Join(nonCompliantBoardIDs, ", ") @@ -1648,7 +1650,7 @@ func PlatformTxtUploadParamsVerboseMissing() (result ruleresult.Type, output str return ruleresult.Skip, "platform.txt has no tools" } - nonCompliantTools := toolNameMissingRequiredProperty("upload/params\\.verbose", compliancelevel.Specification) + nonCompliantTools := toolNameMissingRequiredProperty("upload/params/verbose", compliancelevel.Specification) if len(nonCompliantTools) > 0 { return ruleresult.Fail, strings.Join(nonCompliantTools, ", ") @@ -1657,7 +1659,7 @@ func PlatformTxtUploadParamsVerboseMissing() (result ruleresult.Type, output str return ruleresult.Pass, "" } -// PlatformTxtUploadParamsQuietMissing checks if any of the programmers are missing upload.params.quiet properties. +// PlatformTxtUploadParamsQuietMissing checks if any of the tools are missing upload.params.quiet properties. func PlatformTxtUploadParamsQuietMissing() (result ruleresult.Type, output string) { if !projectdata.PlatformTxtExists() { return ruleresult.Skip, "Platform has no platform.txt" @@ -1671,7 +1673,7 @@ func PlatformTxtUploadParamsQuietMissing() (result ruleresult.Type, output strin return ruleresult.Skip, "platform.txt has no tools" } - nonCompliantTools := toolNameMissingRequiredProperty("upload/params\\.quiet", compliancelevel.Specification) + nonCompliantTools := toolNameMissingRequiredProperty("upload/params/quiet", compliancelevel.Specification) if len(nonCompliantTools) > 0 { return ruleresult.Fail, strings.Join(nonCompliantTools, ", ") @@ -1680,7 +1682,128 @@ func PlatformTxtUploadParamsQuietMissing() (result ruleresult.Type, output strin return ruleresult.Pass, "" } -// PlatformTxtUploadPatternMissing checks if any of the programmers are missing upload.pattern properties. +// PlatformTxtPluggableDiscoveryRequiredInvalid checks if any of the pluggable discovery tool references have invalid format. +func PlatformTxtPluggableDiscoveryRequiredInvalid() (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 !containsKeyOrParent(projectdata.PlatformTxt(), "pluggable_discovery.required") { + return ruleresult.Skip, "Property not present" + } + + if schema.PropertyPatternMismatch("pluggable_discovery/required", projectdata.PlatformTxtSchemaValidationResult()[compliancelevel.Specification]) { + return ruleresult.Fail, "" + } + + return ruleresult.Pass, "" +} + +// PlatformTxtPluggableDiscoveryDiscoveryIDPatternMissing checks if any of the manual installation pluggable discoveries +// are missing pattern properties. +func PlatformTxtPluggableDiscoveryDiscoveryIDPatternMissing() (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 len(projectdata.PlatformTxtPluggableDiscoveryNames()) == 0 { + return ruleresult.Skip, "platform.txt has no manual installation pluggable discoveries" + } + + nonCompliant := []string{} + for _, discovery := range projectdata.PlatformTxtPluggableDiscoveryNames() { + if schema.RequiredPropertyMissing( + fmt.Sprintf("pluggable_discovery/%s/pattern", discovery), + projectdata.PlatformTxtSchemaValidationResult()[compliancelevel.Specification], + ) { + nonCompliant = append(nonCompliant, discovery) + } + } + + 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() { + return ruleresult.Skip, "Platform has no platform.txt" + } + + if projectdata.PlatformTxtLoadError() != nil { + return ruleresult.NotRun, "Couldn't load platform.txt" + } + + if len(projectdata.PlatformTxtUserProvidedFieldNames()) == 0 { + return ruleresult.Skip, "Property not present" + } + + nonCompliant := []string{} + for _, toolName := range projectdata.PlatformTxtToolNames() { + for _, fieldName := range projectdata.PlatformTxtUserProvidedFieldNames()[toolName] { + if schema.PropertyGreaterThanMaxLength(fmt.Sprintf("tools/%s/upload/field/%s", toolName, fieldName), projectdata.PlatformTxtSchemaValidationResult()[compliancelevel.Strict]) { + nonCompliant = append(nonCompliant, fmt.Sprintf("%s >> %s", toolName, fieldName)) + } + } + } + + if len(nonCompliant) > 0 { + return ruleresult.Fail, strings.Join(nonCompliant, ", ") + } + + return ruleresult.Pass, "" +} + +// PlatformTxtUploadFieldFieldNameSecretInvalid checks if any of the platform.txt tools.UPLOAD_RECIPE_ID.upload.field.FIELD_NAME.secret property values have invalid format. +func PlatformTxtUploadFieldFieldNameSecretInvalid() (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 len(projectdata.PlatformTxtUserProvidedFieldNames()) == 0 { + return ruleresult.Skip, "Property not present" + } + + found := false + nonCompliant := []string{} + for _, toolName := range projectdata.PlatformTxtToolNames() { + for _, fieldName := range projectdata.PlatformTxtUserProvidedFieldNames()[toolName] { + if projectdata.PlatformTxt().ContainsKey(fmt.Sprintf("tools.%s.upload.field.%s.secret", toolName, fieldName)) { + found = true + if schema.PropertyEnumMismatch(fmt.Sprintf("tools/%s/upload/field/%s\\.secret", toolName, fieldName), projectdata.PlatformTxtSchemaValidationResult()[compliancelevel.Strict]) { + nonCompliant = append(nonCompliant, fmt.Sprintf("%s >> %s", toolName, fieldName)) + } + } + } + } + + if !found { + return ruleresult.Skip, "Property not present" + } + + if len(nonCompliant) > 0 { + return ruleresult.Fail, strings.Join(nonCompliant, ", ") + } + + return ruleresult.Pass, "" +} + +// PlatformTxtUploadPatternMissing checks if any of the tools are missing upload.pattern properties. func PlatformTxtUploadPatternMissing() (result ruleresult.Type, output string) { if !projectdata.PlatformTxtExists() { return ruleresult.Skip, "Platform has no platform.txt" @@ -1717,7 +1840,7 @@ func PlatformTxtProgramParamsVerboseMissing() (result ruleresult.Type, output st return ruleresult.Skip, "platform.txt has no tools" } - nonCompliantTools := toolNameMissingRequiredProperty("program/params\\.verbose", compliancelevel.Specification) + nonCompliantTools := toolNameMissingRequiredProperty("program/params/verbose", compliancelevel.Specification) if len(nonCompliantTools) > 0 { return ruleresult.Fail, strings.Join(nonCompliantTools, ", ") @@ -1726,7 +1849,7 @@ func PlatformTxtProgramParamsVerboseMissing() (result ruleresult.Type, output st return ruleresult.Pass, "" } -// PlatformTxtProgramParamsQuietMissing checks if any of the programmers are missing program.params.quiet properties. +// PlatformTxtProgramParamsQuietMissing checks if any of the tools are missing program.params.quiet properties. func PlatformTxtProgramParamsQuietMissing() (result ruleresult.Type, output string) { if !projectdata.PlatformTxtExists() { return ruleresult.Skip, "Platform has no platform.txt" @@ -1740,7 +1863,7 @@ func PlatformTxtProgramParamsQuietMissing() (result ruleresult.Type, output stri return ruleresult.Skip, "platform.txt has no tools" } - nonCompliantTools := toolNameMissingRequiredProperty("program/params\\.quiet", compliancelevel.Specification) + nonCompliantTools := toolNameMissingRequiredProperty("program/params/quiet", compliancelevel.Specification) if len(nonCompliantTools) > 0 { return ruleresult.Fail, strings.Join(nonCompliantTools, ", ") @@ -1749,7 +1872,7 @@ func PlatformTxtProgramParamsQuietMissing() (result ruleresult.Type, output stri return ruleresult.Pass, "" } -// PlatformTxtProgramPatternMissing checks if any of the programmers are missing program.pattern properties. +// PlatformTxtProgramPatternMissing checks if any of the tools are missing program.pattern properties. func PlatformTxtProgramPatternMissing() (result ruleresult.Type, output string) { if !projectdata.PlatformTxtExists() { return ruleresult.Skip, "Platform has no platform.txt" @@ -1786,7 +1909,7 @@ func PlatformTxtEraseParamsVerboseMissing() (result ruleresult.Type, output stri return ruleresult.Skip, "platform.txt has no tools" } - nonCompliantTools := toolNameMissingRequiredProperty("erase/params\\.verbose", compliancelevel.Specification) + nonCompliantTools := toolNameMissingRequiredProperty("erase/params/verbose", compliancelevel.Specification) if len(nonCompliantTools) > 0 { return ruleresult.Fail, strings.Join(nonCompliantTools, ", ") @@ -1795,7 +1918,7 @@ func PlatformTxtEraseParamsVerboseMissing() (result ruleresult.Type, output stri return ruleresult.Pass, "" } -// PlatformTxtEraseParamsQuietMissing checks if any of the programmers are missing erase.params.quiet properties. +// PlatformTxtEraseParamsQuietMissing checks if any of the tools are missing erase.params.quiet properties. func PlatformTxtEraseParamsQuietMissing() (result ruleresult.Type, output string) { if !projectdata.PlatformTxtExists() { return ruleresult.Skip, "Platform has no platform.txt" @@ -1809,7 +1932,7 @@ func PlatformTxtEraseParamsQuietMissing() (result ruleresult.Type, output string return ruleresult.Skip, "platform.txt has no tools" } - nonCompliantTools := toolNameMissingRequiredProperty("erase/params\\.quiet", compliancelevel.Specification) + nonCompliantTools := toolNameMissingRequiredProperty("erase/params/quiet", compliancelevel.Specification) if len(nonCompliantTools) > 0 { return ruleresult.Fail, strings.Join(nonCompliantTools, ", ") @@ -1818,7 +1941,7 @@ func PlatformTxtEraseParamsQuietMissing() (result ruleresult.Type, output string return ruleresult.Pass, "" } -// PlatformTxtErasePatternMissing checks if any of the programmers are missing erase.pattern properties. +// PlatformTxtErasePatternMissing checks if any of the tools are missing erase.pattern properties. func PlatformTxtErasePatternMissing() (result ruleresult.Type, output string) { if !projectdata.PlatformTxtExists() { return ruleresult.Skip, "Platform has no platform.txt" @@ -1855,7 +1978,7 @@ func PlatformTxtBootloaderParamsVerboseMissing() (result ruleresult.Type, output return ruleresult.Skip, "platform.txt has no tools" } - nonCompliantTools := toolNameMissingRequiredProperty("bootloader/params\\.verbose", compliancelevel.Specification) + nonCompliantTools := toolNameMissingRequiredProperty("bootloader/params/verbose", compliancelevel.Specification) if len(nonCompliantTools) > 0 { return ruleresult.Fail, strings.Join(nonCompliantTools, ", ") @@ -1864,7 +1987,7 @@ func PlatformTxtBootloaderParamsVerboseMissing() (result ruleresult.Type, output return ruleresult.Pass, "" } -// PlatformTxtBootloaderParamsQuietMissing checks if any of the programmers are missing bootloader.params.quiet properties. +// PlatformTxtBootloaderParamsQuietMissing checks if any of the tools are missing bootloader.params.quiet properties. func PlatformTxtBootloaderParamsQuietMissing() (result ruleresult.Type, output string) { if !projectdata.PlatformTxtExists() { return ruleresult.Skip, "Platform has no platform.txt" @@ -1878,7 +2001,7 @@ func PlatformTxtBootloaderParamsQuietMissing() (result ruleresult.Type, output s return ruleresult.Skip, "platform.txt has no tools" } - nonCompliantTools := toolNameMissingRequiredProperty("bootloader/params\\.quiet", compliancelevel.Specification) + nonCompliantTools := toolNameMissingRequiredProperty("bootloader/params/quiet", compliancelevel.Specification) if len(nonCompliantTools) > 0 { return ruleresult.Fail, strings.Join(nonCompliantTools, ", ") @@ -1887,7 +2010,7 @@ func PlatformTxtBootloaderParamsQuietMissing() (result ruleresult.Type, output s return ruleresult.Pass, "" } -// PlatformTxtBootloaderPatternMissing checks if any of the programmers are missing bootloader.pattern properties. +// PlatformTxtBootloaderPatternMissing checks if any of the tools are missing bootloader.pattern properties. func PlatformTxtBootloaderPatternMissing() (result ruleresult.Type, output string) { if !projectdata.PlatformTxtExists() { return ruleresult.Skip, "Platform has no platform.txt" @@ -1916,12 +2039,20 @@ Unlike iDMissingRequiredProperty(), this function does a direct check on the pro This is necessary because JSON schema does not have the capability to account for the custom board options system. This function should not be used in cases where the JSON schema does cover a required property. */ -func boardIDMissingRequiredProperty(boardIDs []string, propertyName string) []string { +func boardIDMissingRequiredProperty(boardIDs []string, propertyName string, parentOK bool) []string { + containsKey := func(key string) bool { + if parentOK { + return containsKeyOrParent(projectdata.BoardsTxt(), key) + } + + return projectdata.BoardsTxt().ContainsKey(key) + } + nonCompliantBoardIDs := []string{} for _, boardID := range boardIDs { logrus.Tracef("Board ID: %s", boardID) boardIDHasProperty := func(boardID string, propertyName string) bool { - if projectdata.BoardsTxt().ContainsKey(boardID + "." + propertyName) { + if containsKey(boardID + "." + propertyName) { logrus.Trace("Property defined at top level\n") return true // The board has a first level definition of the property. No need to check custom board options. @@ -1938,7 +2069,7 @@ func boardIDMissingRequiredProperty(boardIDs []string, propertyName string) []st boardOptionProperties := boardMenuProperties.SubTree(boardMenuID) boardOptionIDs := boardOptionProperties.FirstLevelKeys() for _, boardOptionID := range boardOptionIDs { - if !boardOptionProperties.ContainsKey(boardOptionID + "." + propertyName) { + if !containsKey(boardOptionID + "." + propertyName) { logrus.Tracef("Option ID %s doesn't provide property\n", boardOptionID) menuProvidesProperty = false // Every option associated with the menuID must define the property. break @@ -2013,6 +2144,12 @@ func toolNameMissingRequiredProperty(propertyNameQuery string, complianceLevel c return nonCompliantTools } +// containsKeyOrParent returns whether the given properties contain a key of the given name, or whether the given key is +// a first level of a key in the properties. +func containsKeyOrParent(propertiesMap *properties.Map, key string) bool { + return propertiesMap.ContainsKey(key) || propertiesMap.SubTree(key).Size() > 0 +} + // iDMissingRequiredProperty returns the list of first level keys missing the given required property. func iDMissingRequiredProperty(iDs []string, propertyNameQuery string, validationResult schema.ValidationResult) []string { nonCompliantIDs := []string{} diff --git a/internal/rule/rulefunction/platform_test.go b/internal/rule/rulefunction/platform_test.go index e7277977..da7aca93 100644 --- a/internal/rule/rulefunction/platform_test.go +++ b/internal/rule/rulefunction/platform_test.go @@ -967,6 +967,56 @@ func TestPlatformTxtRecipeSizeRegexDataMissing(t *testing.T) { checkPlatformRuleFunction(PlatformTxtRecipeSizeRegexDataMissing, testTables, t) } +func TestPlatformTxtPluggableDiscoveryRequiredInvalid(t *testing.T) { + testTables := []platformRuleFunctionTestTable{ + {"Missing", "missing-platform.txt", ruleresult.Skip, ""}, + {"Invalid", "invalid-platform.txt", ruleresult.NotRun, ""}, + {"Property absent", "no-pluggable-discoveries-platform.txt", ruleresult.Skip, ""}, + {"Property invalid (root prop)", "invalid-pluggable-discovery-required-platform.txt", ruleresult.Fail, "^$"}, + {"Property invalid (list prop)", "invalid-pluggable-discovery-required-n-platform.txt", ruleresult.Fail, "^$"}, + {"Valid", "valid-platform.txt", ruleresult.Pass, ""}, + } + + checkPlatformRuleFunction(PlatformTxtPluggableDiscoveryRequiredInvalid, testTables, t) +} + +func TestPlatformTxtPluggableDiscoveryDiscoveryIDPatternMissing(t *testing.T) { + testTables := []platformRuleFunctionTestTable{ + {"Missing", "missing-platform.txt", ruleresult.Skip, ""}, + {"Invalid", "invalid-platform.txt", ruleresult.NotRun, ""}, + {"No pluggable discoveries", "no-pluggable-discoveries-platform.txt", ruleresult.Skip, ""}, + {"Property missing", "pluggable-discovery-discovery-id-pattern-missing-platform.txt", ruleresult.Fail, "^foo_discovery, baz_discovery$"}, + {"Valid", "valid-with-manual-installation-pluggable-discoveries-platform.txt", ruleresult.Pass, ""}, + } + + checkPlatformRuleFunction(PlatformTxtPluggableDiscoveryDiscoveryIDPatternMissing, testTables, t) +} + +func TestPlatformTxtUploadFieldFieldNameGTMaxLength(t *testing.T) { + testTables := []platformRuleFunctionTestTable{ + {"Missing", "missing-platform.txt", ruleresult.Skip, ""}, + {"Invalid", "invalid-platform.txt", ruleresult.NotRun, ""}, + {"No field", "no-user-defined-field-platform.txt", ruleresult.Skip, ""}, + {"Property GT max", "user-defined-field-GT-platform.txt", ruleresult.Fail, "^avrdude >> foo_field_name, bossac >> bar_field_name$"}, + {"Valid", "valid-platform.txt", ruleresult.Pass, ""}, + } + + checkPlatformRuleFunction(PlatformTxtUploadFieldFieldNameGTMaxLength, testTables, t) +} + +func TestPlatformTxtUploadFieldFieldNameSecretInvalid(t *testing.T) { + testTables := []platformRuleFunctionTestTable{ + {"Missing", "missing-platform.txt", ruleresult.Skip, ""}, + {"Invalid", "invalid-platform.txt", ruleresult.NotRun, ""}, + {"No field", "no-user-defined-field-platform.txt", ruleresult.Skip, ""}, + {"No field secret", "no-user-defined-field-secret-platform.txt", ruleresult.Skip, ""}, + {"Property invalid", "user-defined-field-secret-invalid-platform.txt", ruleresult.Fail, "^avrdude >> foo_field_name, footool >> qux_field_name$"}, + {"Valid", "valid-platform.txt", ruleresult.Pass, ""}, + } + + checkPlatformRuleFunction(PlatformTxtUploadFieldFieldNameSecretInvalid, testTables, t) +} + func TestPlatformTxtUploadPatternMissing(t *testing.T) { testTables := []platformRuleFunctionTestTable{ {"Missing", "missing-platform.txt", ruleresult.Skip, ""}, diff --git a/internal/rule/rulefunction/testdata/platforms/boardID-upload-tool-LT-boards.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/boardID-upload-tool-LT-boards.txt/boards.txt index 098c8075..2cf60e7c 100644 --- a/internal/rule/rulefunction/testdata/platforms/boardID-upload-tool-LT-boards.txt/boards.txt +++ b/internal/rule/rulefunction/testdata/platforms/boardID-upload-tool-LT-boards.txt/boards.txt @@ -2,7 +2,7 @@ buno.name=Buno buno.build.board=BUNO buno.build.core=arduino buno.build.variant=standard -buno.upload.tool= +buno.upload.tool.serial= buno.upload.maximum_size=32256 buno.upload.maximum_data_size=2048 @@ -18,7 +18,7 @@ funo.name=Funo funo.build.board=FUNO funo.build.core=arduino funo.build.variant=standard -funo.upload.tool= +funo.menu.foo.bar.upload.tool.serial= funo.upload.maximum_size=32256 funo.upload.maximum_data_size=2048 diff --git a/internal/rule/rulefunction/testdata/platforms/boardID-upload-use_1200bps_touch-invalid-boards.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/boardID-upload-use_1200bps_touch-invalid-boards.txt/boards.txt index 27b68f20..d6f1024e 100644 --- a/internal/rule/rulefunction/testdata/platforms/boardID-upload-use_1200bps_touch-invalid-boards.txt/boards.txt +++ b/internal/rule/rulefunction/testdata/platforms/boardID-upload-use_1200bps_touch-invalid-boards.txt/boards.txt @@ -20,10 +20,10 @@ funo.name=Funo funo.build.board=FUNO funo.build.core=arduino funo.build.variant=standard -funo.upload.tool=avrdude +funo.upload.tool.serial=avrdude funo.upload.maximum_size=32256 funo.upload.maximum_data_size=2048 -funo.upload.use_1200bps_touch=foo +funo.upload.serial.use_1200bps_touch=foo zuno.name=Zuno zuno.build.board=ZUNO diff --git a/internal/rule/rulefunction/testdata/platforms/boardID-upload-wait_for_upload_port-invalid-boards.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/boardID-upload-wait_for_upload_port-invalid-boards.txt/boards.txt index 1100a9c8..db54b6c1 100644 --- a/internal/rule/rulefunction/testdata/platforms/boardID-upload-wait_for_upload_port-invalid-boards.txt/boards.txt +++ b/internal/rule/rulefunction/testdata/platforms/boardID-upload-wait_for_upload_port-invalid-boards.txt/boards.txt @@ -20,10 +20,10 @@ funo.name=Funo funo.build.board=FUNO funo.build.core=arduino funo.build.variant=standard -funo.upload.tool=avrdude +funo.upload.tool.serial=avrdude funo.upload.maximum_size=32256 funo.upload.maximum_data_size=2048 -funo.upload.wait_for_upload_port=foo +funo.upload.serial.wait_for_upload_port=foo zuno.name=Zuno zuno.build.board=ZUNO diff --git a/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-discovery-required-n-platform.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-discovery-required-n-platform.txt/boards.txt new file mode 100644 index 00000000..1866d3c4 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-discovery-required-n-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-discovery-required-n-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-discovery-required-n-platform.txt/platform.txt new file mode 100644 index 00000000..a5cb9730 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-discovery-required-n-platform.txt/platform.txt @@ -0,0 +1,54 @@ +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.1=asdf +pluggable_discovery.required.2=foo: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/rulefunction/testdata/platforms/invalid-pluggable-discovery-required-platform.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-discovery-required-platform.txt/boards.txt new file mode 100644 index 00000000..1866d3c4 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-discovery-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-discovery-required-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-discovery-required-platform.txt/platform.txt new file mode 100644 index 00000000..a4ca8bb8 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/invalid-pluggable-discovery-required-platform.txt/platform.txt @@ -0,0 +1,53 @@ +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=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/no-pluggable-discoveries-platform.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/no-pluggable-discoveries-platform.txt/boards.txt new file mode 100644 index 00000000..1866d3c4 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/no-pluggable-discoveries-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-discoveries-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/no-pluggable-discoveries-platform.txt/platform.txt new file mode 100644 index 00000000..dec708ad --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/no-pluggable-discoveries-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/no-user-defined-field-platform.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/no-user-defined-field-platform.txt/boards.txt new file mode 100644 index 00000000..1866d3c4 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/no-user-defined-field-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-user-defined-field-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/no-user-defined-field-platform.txt/platform.txt new file mode 100644 index 00000000..c672acdb --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/no-user-defined-field-platform.txt/platform.txt @@ -0,0 +1,54 @@ +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 +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/no-user-defined-field-secret-platform.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/no-user-defined-field-secret-platform.txt/boards.txt new file mode 100644 index 00000000..1866d3c4 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/no-user-defined-field-secret-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-user-defined-field-secret-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/no-user-defined-field-secret-platform.txt/platform.txt new file mode 100644 index 00000000..1eb51ea8 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/no-user-defined-field-secret-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.required.0=builtin:serial-discovery +pluggable_discovery.required.1=builtin:mdns-discovery +tools.avrdude.upload.field.foo_field_name=Some field label +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/pluggable-discovery-discovery-id-pattern-missing-platform.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/pluggable-discovery-discovery-id-pattern-missing-platform.txt/boards.txt new file mode 100644 index 00000000..1866d3c4 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/pluggable-discovery-discovery-id-pattern-missing-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-discovery-discovery-id-pattern-missing-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/pluggable-discovery-discovery-id-pattern-missing-platform.txt/platform.txt new file mode 100644 index 00000000..d25b65ff --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/pluggable-discovery-discovery-id-pattern-missing-platform.txt/platform.txt @@ -0,0 +1,55 @@ +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.bar=asdf +pluggable_discovery.bar_discovery.pattern=zxcv +pluggable_discovery.baz_discovery.qux=sdfg +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/user-defined-field-GT-platform.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/user-defined-field-GT-platform.txt/boards.txt new file mode 100644 index 00000000..1866d3c4 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/user-defined-field-GT-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/user-defined-field-GT-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/user-defined-field-GT-platform.txt/platform.txt new file mode 100644 index 00000000..bb9e4388 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/user-defined-field-GT-platform.txt/platform.txt @@ -0,0 +1,61 @@ +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 +tools.avrdude.upload.field.foo_field_name=012345678901234567890123456789012345678901234567890123456789 +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=012345678901234567890123456789012345678901234567890123456789 +tools.bossac.upload.field.baz_field_name=Some field label of OK length +tools.bossac.upload.params.verbose=-v +tools.bossac.upload.params.quiet=-q -q +tools.bossac.upload.pattern=asdf +tools.footool.upload.params.verbose=-v +tools.footool.upload.params.quiet=-q -q +tools.footool.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/user-defined-field-secret-invalid-platform.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/user-defined-field-secret-invalid-platform.txt/boards.txt new file mode 100644 index 00000000..1866d3c4 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/user-defined-field-secret-invalid-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/user-defined-field-secret-invalid-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/user-defined-field-secret-invalid-platform.txt/platform.txt new file mode 100644 index 00000000..746491dd --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/user-defined-field-secret-invalid-platform.txt/platform.txt @@ -0,0 +1,64 @@ +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 +tools.avrdude.upload.field.foo_field_name=Some field label +tools.avrdude.upload.field.foo_field_name.secret=foo +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.footool.upload.field.baz_field_name=Some other field label +tools.footool.upload.field.baz_field_name.secret=false +tools.footool.upload.field.qux_field_name=Some other other field label +tools.footool.upload.field.qux_field_name.secret=1234 +tools.footool.upload.params.verbose=-v +tools.footool.upload.params.quiet=-q -q +tools.footool.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-boards.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/valid-boards.txt/boards.txt index 1866d3c4..8f48a305 100644 --- a/internal/rule/rulefunction/testdata/platforms/valid-boards.txt/boards.txt +++ b/internal/rule/rulefunction/testdata/platforms/valid-boards.txt/boards.txt @@ -2,9 +2,9 @@ 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 +buno.upload.tool.serial=avrdude uno.name=Arduino Uno uno.build.board=UNO 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 dec708ad..ff72f156 100644 --- a/internal/rule/rulefunction/testdata/platforms/valid-platform.txt/platform.txt +++ b/internal/rule/rulefunction/testdata/platforms/valid-platform.txt/platform.txt @@ -26,9 +26,14 @@ 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.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 diff --git a/internal/rule/rulefunction/testdata/platforms/valid-with-manual-installation-pluggable-discoveries-platform.txt/boards.txt b/internal/rule/rulefunction/testdata/platforms/valid-with-manual-installation-pluggable-discoveries-platform.txt/boards.txt new file mode 100644 index 00000000..1866d3c4 --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/valid-with-manual-installation-pluggable-discoveries-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-discoveries-platform.txt/platform.txt b/internal/rule/rulefunction/testdata/platforms/valid-with-manual-installation-pluggable-discoveries-platform.txt/platform.txt new file mode 100644 index 00000000..fdc29f4c --- /dev/null +++ b/internal/rule/rulefunction/testdata/platforms/valid-with-manual-installation-pluggable-discoveries-platform.txt/platform.txt @@ -0,0 +1,53 @@ +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 +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 96acd7b8..d007d082 100644 --- a/internal/rule/schema/schemadata/bindata.go +++ b/internal/rule/schema/schemadata/bindata.go @@ -220,6 +220,13 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ }, "serial.disableRTS": { "$ref": "#/definitions/propertiesObjects/boardIDSerialDisableRTS/permissive/object" + } + } + }, + { + "patternProperties": { + "^upload.tool(\\..+)?$": { + "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/permissive/object" }, "upload.maximum_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumSize/permissive/object" @@ -227,22 +234,15 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ "upload.maximum_data_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumDataSize/permissive/object" }, - "upload.protocol": { + "upload(\\..+)?\\.protocol": { "$ref": "#/definitions/propertiesObjects/boardIDUploadProtocol/permissive/object" }, - "upload.tool": { - "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/permissive/object" - }, - "upload.use_1200bps_touch": { + "upload(\\..+)?\\.use_1200bps_touch": { "$ref": "#/definitions/propertiesObjects/boardIDUploadUse1200bpsTouch/permissive/object" }, - "upload.wait_for_upload_port": { + "upload(\\..+)?\\.wait_for_upload_port": { "$ref": "#/definitions/propertiesObjects/boardIDUploadWaitForUploadPort/permissive/object" - } - } - }, - { - "patternProperties": { + }, "^[vp]id\\.[0-9]+$": { "$ref": "#/definitions/propertiesObjects/boardIDXidN/permissive/object" } @@ -285,6 +285,13 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ }, "serial.disableRTS": { "$ref": "#/definitions/propertiesObjects/boardIDSerialDisableRTS/specification/object" + } + } + }, + { + "patternProperties": { + "^upload.tool(\\..+)?$": { + "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/specification/object" }, "upload.maximum_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumSize/specification/object" @@ -292,22 +299,15 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ "upload.maximum_data_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumDataSize/specification/object" }, - "upload.protocol": { + "upload(\\..+)?\\.protocol": { "$ref": "#/definitions/propertiesObjects/boardIDUploadProtocol/specification/object" }, - "upload.tool": { - "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/specification/object" - }, - "upload.use_1200bps_touch": { + "upload(\\..+)?\\.use_1200bps_touch": { "$ref": "#/definitions/propertiesObjects/boardIDUploadUse1200bpsTouch/specification/object" }, - "upload.wait_for_upload_port": { + "upload(\\..+)?\\.wait_for_upload_port": { "$ref": "#/definitions/propertiesObjects/boardIDUploadWaitForUploadPort/specification/object" - } - } - }, - { - "patternProperties": { + }, "^[vp]id\\.[0-9]+$": { "$ref": "#/definitions/propertiesObjects/boardIDXidN/specification/object" } @@ -350,6 +350,13 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ }, "serial.disableRTS": { "$ref": "#/definitions/propertiesObjects/boardIDSerialDisableRTS/strict/object" + } + } + }, + { + "patternProperties": { + "^upload.tool(\\..+)?$": { + "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/strict/object" }, "upload.maximum_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumSize/strict/object" @@ -357,22 +364,15 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ "upload.maximum_data_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumDataSize/strict/object" }, - "upload.protocol": { + "upload(\\..+)?\\.protocol": { "$ref": "#/definitions/propertiesObjects/boardIDUploadProtocol/strict/object" }, - "upload.tool": { - "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/strict/object" - }, - "upload.use_1200bps_touch": { + "upload(\\..+)?\\.use_1200bps_touch": { "$ref": "#/definitions/propertiesObjects/boardIDUploadUse1200bpsTouch/strict/object" }, - "upload.wait_for_upload_port": { + "upload(\\..+)?\\.wait_for_upload_port": { "$ref": "#/definitions/propertiesObjects/boardIDUploadWaitForUploadPort/strict/object" - } - } - }, - { - "patternProperties": { + }, "^[vp]id\\.[0-9]+$": { "$ref": "#/definitions/propertiesObjects/boardIDXidN/strict/object" } @@ -699,6 +699,13 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ }, "serial.disableRTS": { "$ref": "#/definitions/propertiesObjects/boardIDSerialDisableRTS/permissive/object" + } + } + }, + { + "patternProperties": { + "^upload.tool(\\..+)?$": { + "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/permissive/object" }, "upload.maximum_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumSize/permissive/object" @@ -706,22 +713,15 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ "upload.maximum_data_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumDataSize/permissive/object" }, - "upload.protocol": { + "upload(\\..+)?\\.protocol": { "$ref": "#/definitions/propertiesObjects/boardIDUploadProtocol/permissive/object" }, - "upload.tool": { - "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/permissive/object" - }, - "upload.use_1200bps_touch": { + "upload(\\..+)?\\.use_1200bps_touch": { "$ref": "#/definitions/propertiesObjects/boardIDUploadUse1200bpsTouch/permissive/object" }, - "upload.wait_for_upload_port": { + "upload(\\..+)?\\.wait_for_upload_port": { "$ref": "#/definitions/propertiesObjects/boardIDUploadWaitForUploadPort/permissive/object" - } - } - }, - { - "patternProperties": { + }, "^[vp]id\\.[0-9]+$": { "$ref": "#/definitions/propertiesObjects/boardIDXidN/permissive/object" } @@ -752,6 +752,13 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ }, "serial.disableRTS": { "$ref": "#/definitions/propertiesObjects/boardIDSerialDisableRTS/specification/object" + } + } + }, + { + "patternProperties": { + "^upload.tool(\\..+)?$": { + "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/specification/object" }, "upload.maximum_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumSize/specification/object" @@ -759,22 +766,15 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ "upload.maximum_data_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumDataSize/specification/object" }, - "upload.protocol": { + "upload(\\..+)?\\.protocol": { "$ref": "#/definitions/propertiesObjects/boardIDUploadProtocol/specification/object" }, - "upload.tool": { - "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/specification/object" - }, - "upload.use_1200bps_touch": { + "upload(\\..+)?\\.use_1200bps_touch": { "$ref": "#/definitions/propertiesObjects/boardIDUploadUse1200bpsTouch/specification/object" }, - "upload.wait_for_upload_port": { + "upload(\\..+)?\\.wait_for_upload_port": { "$ref": "#/definitions/propertiesObjects/boardIDUploadWaitForUploadPort/specification/object" - } - } - }, - { - "patternProperties": { + }, "^[vp]id\\.[0-9]+$": { "$ref": "#/definitions/propertiesObjects/boardIDXidN/specification/object" } @@ -805,6 +805,13 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ }, "serial.disableRTS": { "$ref": "#/definitions/propertiesObjects/boardIDSerialDisableRTS/strict/object" + } + } + }, + { + "patternProperties": { + "^upload.tool(\\..+)?$": { + "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/strict/object" }, "upload.maximum_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumSize/strict/object" @@ -812,22 +819,15 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ "upload.maximum_data_size": { "$ref": "#/definitions/propertiesObjects/boardIDUploadMaximumDataSize/strict/object" }, - "upload.protocol": { + "upload(\\..+)?\\.protocol": { "$ref": "#/definitions/propertiesObjects/boardIDUploadProtocol/strict/object" }, - "upload.tool": { - "$ref": "#/definitions/propertiesObjects/boardIDUploadTool/strict/object" - }, - "upload.use_1200bps_touch": { + "upload(\\..+)?\\.use_1200bps_touch": { "$ref": "#/definitions/propertiesObjects/boardIDUploadUse1200bpsTouch/strict/object" }, - "upload.wait_for_upload_port": { + "upload(\\..+)?\\.wait_for_upload_port": { "$ref": "#/definitions/propertiesObjects/boardIDUploadWaitForUploadPort/strict/object" - } - } - }, - { - "patternProperties": { + }, "^[vp]id\\.[0-9]+$": { "$ref": "#/definitions/propertiesObjects/boardIDXidN/strict/object" } @@ -848,7 +848,7 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ "type": "string" }, { - "$ref": "#/definitions/enumObjects/booleanString" + "$ref": "general-definitions-schema.json#/definitions/enumObjects/booleanString" } ] } @@ -889,7 +889,7 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ "type": "string" }, { - "$ref": "#/definitions/enumObjects/booleanString" + "$ref": "general-definitions-schema.json#/definitions/enumObjects/booleanString" } ] } @@ -1091,7 +1091,7 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ "type": "string" }, { - "$ref": "#/definitions/enumObjects/booleanString" + "$ref": "general-definitions-schema.json#/definitions/enumObjects/booleanString" } ] } @@ -1132,7 +1132,7 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ "type": "string" }, { - "$ref": "#/definitions/enumObjects/booleanString" + "$ref": "general-definitions-schema.json#/definitions/enumObjects/booleanString" } ] } @@ -1290,11 +1290,6 @@ var _arduinoBoardsTxtDefinitionsSchemaJson = []byte(`{ } } } - }, - "enumObjects": { - "booleanString": { - "enum": ["true", "false"] - } } } } @@ -4780,7 +4775,7 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ } } }, - "tools": { + "pluggableDiscovery": { "base": { "object": { "allOf": [ @@ -4794,15 +4789,17 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/tools/base/object" + "$ref": "#/definitions/propertiesObjects/pluggableDiscovery/base/object" }, { - "patternProperties": { - "^.+$": { - "$ref": "#/definitions/propertiesObjects/toolsToolName/permissive/object" + "properties": { + "required": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequired/permissive/object" } }, - "additionalProperties": false + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryDiscoveryName/permissive/object" + } } ] } @@ -4811,15 +4808,17 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/tools/base/object" + "$ref": "#/definitions/propertiesObjects/pluggableDiscovery/base/object" }, { - "patternProperties": { - "^.+$": { - "$ref": "#/definitions/propertiesObjects/toolsToolName/specification/object" + "properties": { + "required": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequired/specification/object" } }, - "additionalProperties": false + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryDiscoveryName/specification/object" + } } ] } @@ -4828,21 +4827,23 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/tools/base/object" + "$ref": "#/definitions/propertiesObjects/pluggableDiscovery/base/object" }, { - "patternProperties": { - "^.+$": { - "$ref": "#/definitions/propertiesObjects/toolsToolName/strict/object" + "properties": { + "required": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequired/strict/object" } }, - "additionalProperties": false + "additionalProperties": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryDiscoveryName/strict/object" + } } ] } } }, - "toolsToolName": { + "pluggableDiscoveryDiscoveryName": { "base": { "object": { "allOf": [ @@ -4856,23 +4857,10 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolName/base/object" + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryDiscoveryName/base/object" }, { - "properties": { - "upload": { - "$ref": "#/definitions/propertiesObjects/toolsToolNameUpload/permissive/object" - }, - "program": { - "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/permissive/object" - }, - "erase": { - "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/permissive/object" - }, - "bootloader": { - "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/permissive/object" - } - } + "$ref": "#/definitions/requiredObjects/pluggableDiscoveryDiscoveryName/permissive/object" } ] } @@ -4881,23 +4869,10 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolName/base/object" + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryDiscoveryName/base/object" }, { - "properties": { - "upload": { - "$ref": "#/definitions/propertiesObjects/toolsToolNameUpload/specification/object" - }, - "program": { - "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/specification/object" - }, - "erase": { - "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/specification/object" - }, - "bootloader": { - "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/specification/object" - } - } + "$ref": "#/definitions/requiredObjects/pluggableDiscoveryDiscoveryName/specification/object" } ] } @@ -4906,34 +4881,21 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolName/base/object" + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryDiscoveryName/base/object" }, { - "properties": { - "upload": { - "$ref": "#/definitions/propertiesObjects/toolsToolNameUpload/strict/object" - }, - "program": { - "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/strict/object" - }, - "erase": { - "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/strict/object" - }, - "bootloader": { - "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/strict/object" - } - } + "$ref": "#/definitions/requiredObjects/pluggableDiscoveryDiscoveryName/strict/object" } ] } } }, - "toolsToolNameUpload": { + "pluggableDiscoveryRequired": { "base": { "object": { "allOf": [ { - "type": "object" + "type": "array" } ] } @@ -4942,10 +4904,12 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolNameUpload/base/object" + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequired/base/object" }, { - "$ref": "#/definitions/requiredObjects/toolsToolNameUpload/permissive/object" + "items": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequiredN/permissive/object" + } } ] } @@ -4954,10 +4918,12 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolNameUpload/base/object" + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequired/base/object" }, { - "$ref": "#/definitions/requiredObjects/toolsToolNameUpload/specification/object" + "items": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequiredN/specification/object" + } } ] } @@ -4966,21 +4932,26 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolNameUpload/base/object" + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequired/base/object" }, { - "$ref": "#/definitions/requiredObjects/toolsToolNameUpload/strict/object" + "items": { + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequiredN/strict/object" + } } ] } } }, - "toolsToolNameProgram": { + "pluggableDiscoveryRequiredN": { "base": { "object": { "allOf": [ { - "type": "object" + "type": "string" + }, + { + "pattern": "^.+:.+$" } ] } @@ -4989,10 +4960,7 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/base/object" - }, - { - "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/permissive/object" + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequiredN/base/object" } ] } @@ -5001,10 +4969,7 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/base/object" - }, - { - "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/specification/object" + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequiredN/base/object" } ] } @@ -5013,16 +4978,13 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/base/object" - }, - { - "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/strict/object" + "$ref": "#/definitions/propertiesObjects/pluggableDiscoveryRequiredN/base/object" } ] } } }, - "toolsToolNameErase": { + "tools": { "base": { "object": { "allOf": [ @@ -5036,10 +4998,15 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/base/object" + "$ref": "#/definitions/propertiesObjects/tools/base/object" }, { - "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/permissive/object" + "patternProperties": { + "^.+$": { + "$ref": "#/definitions/propertiesObjects/toolsToolName/permissive/object" + } + }, + "additionalProperties": false } ] } @@ -5048,10 +5015,15 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/base/object" + "$ref": "#/definitions/propertiesObjects/tools/base/object" }, { - "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/specification/object" + "patternProperties": { + "^.+$": { + "$ref": "#/definitions/propertiesObjects/toolsToolName/specification/object" + } + }, + "additionalProperties": false } ] } @@ -5060,16 +5032,21 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/base/object" + "$ref": "#/definitions/propertiesObjects/tools/base/object" }, { - "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/strict/object" + "patternProperties": { + "^.+$": { + "$ref": "#/definitions/propertiesObjects/toolsToolName/strict/object" + } + }, + "additionalProperties": false } ] } } }, - "toolsToolNameBootloader": { + "toolsToolName": { "base": { "object": { "allOf": [ @@ -5083,10 +5060,23 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/base/object" + "$ref": "#/definitions/propertiesObjects/toolsToolName/base/object" }, { - "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/permissive/object" + "properties": { + "upload": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUpload/permissive/object" + }, + "program": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/permissive/object" + }, + "erase": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/permissive/object" + }, + "bootloader": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/permissive/object" + } + } } ] } @@ -5095,10 +5085,23 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/base/object" + "$ref": "#/definitions/propertiesObjects/toolsToolName/base/object" }, { - "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/specification/object" + "properties": { + "upload": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUpload/specification/object" + }, + "program": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/specification/object" + }, + "erase": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/specification/object" + }, + "bootloader": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/specification/object" + } + } } ] } @@ -5107,10 +5110,492 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ "object": { "allOf": [ { - "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/base/object" + "$ref": "#/definitions/propertiesObjects/toolsToolName/base/object" }, { - "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/strict/object" + "properties": { + "upload": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUpload/strict/object" + }, + "program": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/strict/object" + }, + "erase": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/strict/object" + }, + "bootloader": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/strict/object" + } + } + } + ] + } + } + }, + "toolsToolNameUpload": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUpload/base/object" + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameUpload/permissive/object" + }, + { + "properties": { + "field": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadField/permissive/object" + } + } + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUpload/base/object" + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameUpload/specification/object" + }, + { + "properties": { + "field": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadField/specification/object" + } + } + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUpload/base/object" + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameUpload/strict/object" + }, + { + "properties": { + "field": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadField/strict/object" + } + } + } + ] + } + } + }, + "toolsToolNameUploadField": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadField/base/object" + }, + { + "patternProperties": { + "^.+([^.].*|\\.([^s].*)?|\\.se([^c].*)?|\\.sec([^r].*)?|\\.secr([^e].*)?|\\.secre([^t].*)?|\\.secret.+)$": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldName/permissive/object" + }, + "^.+\\.secret$": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldNameSecret/permissive/object" + } + } + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadField/base/object" + }, + { + "patternProperties": { + "^.+([^.].*|\\.([^s].*)?|\\.se([^c].*)?|\\.sec([^r].*)?|\\.secr([^e].*)?|\\.secre([^t].*)?|\\.secret.+)$": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldName/specification/object" + }, + "^.+\\.secret$": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldNameSecret/specification/object" + } + } + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadField/base/object" + }, + { + "patternProperties": { + "^.+([^.].*|\\.([^s].*)?|\\.se([^c].*)?|\\.sec([^r].*)?|\\.secr([^e].*)?|\\.secre([^t].*)?|\\.secret.+)$": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldName/strict/object" + }, + "^.+\\.secret$": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldNameSecret/strict/object" + } + } + } + ] + } + } + }, + "toolsToolNameUploadFieldFieldName": { + "base": { + "object": { + "allOf": [ + { + "type": "string" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldName/base/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldName/base/object" + }, + { + "maxLength": 50 + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldName/specification/object" + } + ] + } + } + }, + "toolsToolNameUploadFieldFieldNameSecret": { + "base": { + "object": { + "allOf": [ + { + "type": "string" + }, + { + "$ref": "general-definitions-schema.json#/definitions/enumObjects/booleanString" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldNameSecret/base/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldNameSecret/base/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameUploadFieldFieldNameSecret/base/object" + } + ] + } + } + }, + "toolsToolNameProgram": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/base/object" + }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/permissive/object" + } + } + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/permissive/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/base/object" + }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/specification/object" + } + } + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/specification/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameProgram/base/object" + }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/strict/object" + } + } + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/strict/object" + } + ] + } + } + }, + "toolsToolNameErase": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/base/object" + }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/permissive/object" + } + } + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/permissive/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/base/object" + }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/specification/object" + } + } + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/specification/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameErase/base/object" + }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/strict/object" + } + } + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/strict/object" + } + ] + } + } + }, + "toolsToolNameBootloader": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/base/object" + }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/permissive/object" + } + } + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/permissive/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/base/object" + }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/specification/object" + } + } + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/specification/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameBootloader/base/object" + }, + { + "properties": { + "params": { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/strict/object" + } + } + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionName/strict/object" + } + ] + } + } + }, + "toolsToolNameActionNameParams": { + "base": { + "object": { + "allOf": [ + { + "type": "object" + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/base/object" + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionNameParams/permissive/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/base/object" + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionNameParams/specification/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/propertiesObjects/toolsToolNameActionNameParams/base/object" + }, + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionNameParams/strict/object" } ] } @@ -5225,12 +5710,50 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ } } }, + "pluggableDiscoveryDiscoveryName": { + "base": { + "object": { + "allOf": [ + { + "required": ["pattern"] + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/requiredObjects/pluggableDiscoveryDiscoveryName/base/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/requiredObjects/pluggableDiscoveryDiscoveryName/base/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/requiredObjects/pluggableDiscoveryDiscoveryName/base/object" + } + ] + } + } + }, "toolsToolNameActionName": { "base": { "object": { "allOf": [ { - "required": ["params.verbose", "params.quiet", "pattern"] + "required": ["params", "pattern"] } ] } @@ -5263,6 +5786,44 @@ var _arduinoPlatformTxtDefinitionsSchemaJson = []byte(`{ } } }, + "toolsToolNameActionNameParams": { + "base": { + "object": { + "allOf": [ + { + "required": ["verbose", "quiet"] + } + ] + } + }, + "permissive": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionNameParams/base/object" + } + ] + } + }, + "specification": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionNameParams/base/object" + } + ] + } + }, + "strict": { + "object": { + "allOf": [ + { + "$ref": "#/definitions/requiredObjects/toolsToolNameActionNameParams/base/object" + } + ] + } + } + }, "toolsToolNameUpload": { "base": { "object": { @@ -5377,6 +5938,9 @@ var _arduinoPlatformTxtPermissiveSchemaJson = []byte(`{ "recipe.size.pattern": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/recipeSizePattern/permissive/object" }, + "pluggable_discovery": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableDiscovery/permissive/object" + }, "tools": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/tools/permissive/object" } @@ -5463,6 +6027,9 @@ var _arduinoPlatformTxtSchemaJson = []byte(`{ "recipe.size.pattern": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/recipeSizePattern/specification/object" }, + "pluggable_discovery": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableDiscovery/specification/object" + }, "tools": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/tools/specification/object" } @@ -5549,6 +6116,9 @@ var _arduinoPlatformTxtStrictSchemaJson = []byte(`{ "recipe.size.pattern": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/recipeSizePattern/strict/object" }, + "pluggable_discovery": { + "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/pluggableDiscovery/strict/object" + }, "tools": { "$ref": "arduino-platform-txt-definitions-schema.json#/definitions/propertiesObjects/tools/strict/object" } @@ -5919,6 +6489,11 @@ var _generalDefinitionsSchemaJson = []byte(`{ "pattern": "^[aA][rR][dD][uU][iI][nN][oO].*$" } } + }, + "enumObjects": { + "booleanString": { + "enum": ["true", "false"] + } } } }