From bb472f95324e3de0a1fb23f4baf80537bc5a3803 Mon Sep 17 00:00:00 2001 From: per1234 Date: Thu, 10 Jun 2021 16:35:34 -0700 Subject: [PATCH 1/2] Reformat package index projectdata test table to accomodate more fields Several new fields must be added to the test table. The previous sparse formatting will not be suitable for the quantity of data the test tables will need to hold. --- .../project/projectdata/packageindex_test.go | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/internal/project/projectdata/packageindex_test.go b/internal/project/projectdata/packageindex_test.go index 372381c0e..b0e890340 100644 --- a/internal/project/projectdata/packageindex_test.go +++ b/internal/project/projectdata/packageindex_test.go @@ -42,9 +42,27 @@ func TestInitializeForPackageIndex(t *testing.T) { packageIndexLoadErrorAssertion assert.ValueAssertionFunc packageIndexCLILoadErrorAssertion assert.ValueAssertionFunc }{ - {"Valid", packageIndexTestDataPath.Join("valid-package-index", "package_foo_index.json"), assert.NotNil, assert.Nil, assert.Nil}, - {"Invalid package index", packageIndexTestDataPath.Join("invalid-package-index", "package_foo_index.json"), assert.Nil, assert.NotNil, assert.NotNil}, - {"Invalid JSON", packageIndexTestDataPath.Join("invalid-JSON", "package_foo_index.json"), assert.Nil, assert.NotNil, assert.NotNil}, + { + testName: "Valid", + path: packageIndexTestDataPath.Join("valid-package-index", "package_foo_index.json"), + packageIndexAssertion: assert.NotNil, + packageIndexLoadErrorAssertion: assert.Nil, + packageIndexCLILoadErrorAssertion: assert.Nil, + }, + { + testName: "Invalid package index", + path: packageIndexTestDataPath.Join("invalid-package-index", "package_foo_index.json"), + packageIndexAssertion: assert.Nil, + packageIndexLoadErrorAssertion: assert.NotNil, + packageIndexCLILoadErrorAssertion: assert.NotNil, + }, + { + testName: "Invalid JSON", + path: packageIndexTestDataPath.Join("invalid-JSON", "package_foo_index.json"), + packageIndexAssertion: assert.Nil, + packageIndexLoadErrorAssertion: assert.NotNil, + packageIndexCLILoadErrorAssertion: assert.NotNil, + }, } for _, testTable := range testTables { From 4921733f23d30a5c68d20353f763d177ab826505 Mon Sep 17 00:00:00 2001 From: per1234 Date: Fri, 11 Jun 2021 00:24:52 -0700 Subject: [PATCH 2/2] Provide object-level project index data to rules Data checking rules for package indexes need to iterate over its object-level components. To facilitate this, slices of such objects accompanied by the necessary metadata are generated as package index project data. --- internal/project/projectdata/packageindex.go | 98 +++++++++++++++ .../project/projectdata/packageindex_test.go | 118 +++++++++++++++++- .../package_foo_index.json | 107 +++++++++++++++- 3 files changed, 317 insertions(+), 6 deletions(-) diff --git a/internal/project/projectdata/packageindex.go b/internal/project/projectdata/packageindex.go index 4cd65bb0b..a47bfd0f0 100644 --- a/internal/project/projectdata/packageindex.go +++ b/internal/project/projectdata/packageindex.go @@ -16,16 +16,45 @@ package projectdata import ( + "fmt" + clipackageindex "github.com/arduino/arduino-cli/arduino/cores/packageindex" "github.com/arduino/arduino-lint/internal/project/packageindex" ) +// PackageIndexData is the type for package index data. +type PackageIndexData struct { + ID string // Identifier for display to humans + JSONPointer string // Path to the data in the JSON document + Object map[string]interface{} // The data of the object +} + // InitializeForPackageIndex gathers the package index rule data for the specified project. func InitializeForPackageIndex() { packageIndex, packageIndexLoadError = packageindex.Properties(ProjectPath()) if ProjectPath() != nil { _, packageIndexCLILoadError = clipackageindex.LoadIndex(ProjectPath()) } + + packageIndexPackages = nil + packageIndexPlatforms = nil + packageIndexTools = nil + packageIndexSystems = nil + if packageIndexLoadError == nil { + packageIndexPackages = getPackageIndexData(PackageIndex(), "", "packages", "", "name", "") + + for _, packageData := range PackageIndexPackages() { + packageIndexPlatforms = append(packageIndexPlatforms, getPackageIndexData(packageData.Object, packageData.JSONPointer, "platforms", packageData.ID+":", "architecture", "version")...) + } + + for _, packageData := range PackageIndexPackages() { + packageIndexTools = append(packageIndexTools, getPackageIndexData(packageData.Object, packageData.JSONPointer, "tools", packageData.ID+":", "name", "version")...) + } + + for _, toolData := range PackageIndexTools() { + packageIndexSystems = append(packageIndexSystems, getPackageIndexData(toolData.Object, toolData.JSONPointer, "systems", toolData.ID+" - ", "host", "")...) + } + } } var packageIndex map[string]interface{} @@ -48,3 +77,72 @@ var packageIndexCLILoadError error func PackageIndexCLILoadError() error { return packageIndexCLILoadError } + +var packageIndexPackages []PackageIndexData + +// PackageIndexPackages returns the slice of package data for the package index. +func PackageIndexPackages() []PackageIndexData { + return packageIndexPackages +} + +var packageIndexPlatforms []PackageIndexData + +// PackageIndexPlatforms returns the slice of platform data for the package index. +func PackageIndexPlatforms() []PackageIndexData { + return packageIndexPlatforms +} + +var packageIndexTools []PackageIndexData + +// PackageIndexTools returns the slice of tool data for the package index. +func PackageIndexTools() []PackageIndexData { + return packageIndexTools +} + +var packageIndexSystems []PackageIndexData + +// PackageIndexSystems returns the slice of system data for the package index. +func PackageIndexSystems() []PackageIndexData { + return packageIndexSystems +} + +func getPackageIndexData(interfaceObject map[string]interface{}, pointerPrefix string, dataKey string, iDPrefix string, iDKey string, versionKey string) []PackageIndexData { + var data []PackageIndexData + + interfaceSlice, ok := interfaceObject[dataKey].([]interface{}) + if !ok { + return data + } + + for index, interfaceElement := range interfaceSlice { + object, ok := interfaceElement.(map[string]interface{}) + if !ok { + continue + } + + var iD string + iDSuffix, ok := object[iDKey].(string) + if !ok { + continue + } + iD = iDPrefix + iDSuffix + if versionKey != "" { + iDVersion, ok := object[versionKey].(string) + if !ok { + continue + } + iD = iD + "@" + iDVersion + } + + data = append( + data, + PackageIndexData{ + ID: iD, + JSONPointer: fmt.Sprintf("%s/%s/%v", pointerPrefix, dataKey, index), + Object: object, + }, + ) + } + + return data +} diff --git a/internal/project/projectdata/packageindex_test.go b/internal/project/projectdata/packageindex_test.go index b0e890340..ba45d6d35 100644 --- a/internal/project/projectdata/packageindex_test.go +++ b/internal/project/projectdata/packageindex_test.go @@ -36,11 +36,19 @@ func init() { func TestInitializeForPackageIndex(t *testing.T) { testTables := []struct { - testName string - path *paths.Path - packageIndexAssertion assert.ValueAssertionFunc - packageIndexLoadErrorAssertion assert.ValueAssertionFunc - packageIndexCLILoadErrorAssertion assert.ValueAssertionFunc + testName string + path *paths.Path + packageIndexAssertion assert.ValueAssertionFunc + packageIndexLoadErrorAssertion assert.ValueAssertionFunc + packageIndexCLILoadErrorAssertion assert.ValueAssertionFunc + packageIndexPackagesAssertion assert.ValueAssertionFunc + packageIndexPackagesDataAssertion []PackageIndexData + packageIndexPlatformsAssertion assert.ValueAssertionFunc + packageIndexPlatformsDataAssertion []PackageIndexData + packageIndexToolsAssertion assert.ValueAssertionFunc + packageIndexToolsDataAssertion []PackageIndexData + packageIndexSystemsAssertion assert.ValueAssertionFunc + packageIndexSystemsDataAssertion []PackageIndexData }{ { testName: "Valid", @@ -48,6 +56,66 @@ func TestInitializeForPackageIndex(t *testing.T) { packageIndexAssertion: assert.NotNil, packageIndexLoadErrorAssertion: assert.Nil, packageIndexCLILoadErrorAssertion: assert.Nil, + packageIndexPackagesAssertion: assert.NotNil, + packageIndexPackagesDataAssertion: []PackageIndexData{ + { + ID: "myboard1", + JSONPointer: "/packages/0", + }, + { + ID: "myboard2", + JSONPointer: "/packages/1", + }, + }, + packageIndexPlatformsAssertion: assert.NotNil, + packageIndexPlatformsDataAssertion: []PackageIndexData{ + { + ID: "myboard1:avr@1.0.0", + JSONPointer: "/packages/0/platforms/0", + }, + { + ID: "myboard1:avr@1.0.1", + JSONPointer: "/packages/0/platforms/1", + }, + { + ID: "myboard2:samd@2.0.0", + JSONPointer: "/packages/1/platforms/0", + }, + { + ID: "myboard2:mbed@1.1.1", + JSONPointer: "/packages/1/platforms/1", + }, + }, + packageIndexToolsAssertion: assert.NotNil, + packageIndexToolsDataAssertion: []PackageIndexData{ + { + ID: "myboard2:openocd@0.10.0-arduino1-static", + JSONPointer: "/packages/1/tools/0", + }, + { + ID: "myboard2:CMSIS@4.0.0-atmel", + JSONPointer: "/packages/1/tools/1", + }, + }, + packageIndexSystemsAssertion: assert.NotNil, + packageIndexSystemsDataAssertion: []PackageIndexData{ + { + ID: "myboard2:openocd@0.10.0-arduino1-static - i386-apple-darwin11", + JSONPointer: "/packages/1/tools/0/systems/0", + }, + { + ID: "myboard2:openocd@0.10.0-arduino1-static - x86_64-linux-gnu", + JSONPointer: "/packages/1/tools/0/systems/1", + }, + { + ID: "myboard2:CMSIS@4.0.0-atmel - arm-linux-gnueabihf", + JSONPointer: "/packages/1/tools/1/systems/0", + }, + { + ID: "myboard2:CMSIS@4.0.0-atmel - i686-mingw32", + JSONPointer: "/packages/1/tools/1/systems/1", + }, + }, }, { testName: "Invalid package index", @@ -55,6 +123,10 @@ func TestInitializeForPackageIndex(t *testing.T) { packageIndexAssertion: assert.Nil, packageIndexLoadErrorAssertion: assert.NotNil, packageIndexCLILoadErrorAssertion: assert.NotNil, + packageIndexPackagesAssertion: assert.Nil, + packageIndexPlatformsAssertion: assert.Nil, + packageIndexToolsAssertion: assert.Nil, + packageIndexSystemsAssertion: assert.Nil, }, { testName: "Invalid JSON", @@ -62,6 +134,10 @@ func TestInitializeForPackageIndex(t *testing.T) { packageIndexAssertion: assert.Nil, packageIndexLoadErrorAssertion: assert.NotNil, packageIndexCLILoadErrorAssertion: assert.NotNil, + packageIndexPackagesAssertion: assert.Nil, + packageIndexPlatformsAssertion: assert.Nil, + packageIndexToolsAssertion: assert.Nil, + packageIndexSystemsAssertion: assert.Nil, }, } @@ -79,5 +155,37 @@ func TestInitializeForPackageIndex(t *testing.T) { if PackageIndexLoadError() == nil { testTable.packageIndexAssertion(t, PackageIndex(), testTable.testName) } + + testTable.packageIndexPackagesAssertion(t, PackageIndexPackages(), testTable.testName) + if PackageIndexPackages() != nil { + for index, packageIndexPackage := range PackageIndexPackages() { + assert.Equal(t, packageIndexPackage.ID, testTable.packageIndexPackagesDataAssertion[index].ID) + assert.Equal(t, packageIndexPackage.JSONPointer, testTable.packageIndexPackagesDataAssertion[index].JSONPointer) + } + } + + testTable.packageIndexPlatformsAssertion(t, PackageIndexPlatforms(), testTable.testName) + if PackageIndexPlatforms() != nil { + for index, packageIndexPlatform := range PackageIndexPlatforms() { + assert.Equal(t, packageIndexPlatform.ID, testTable.packageIndexPlatformsDataAssertion[index].ID) + assert.Equal(t, packageIndexPlatform.JSONPointer, testTable.packageIndexPlatformsDataAssertion[index].JSONPointer) + } + } + + testTable.packageIndexToolsAssertion(t, PackageIndexTools(), testTable.testName) + if PackageIndexTools() != nil { + for index, packageIndexTool := range PackageIndexTools() { + assert.Equal(t, packageIndexTool.ID, testTable.packageIndexToolsDataAssertion[index].ID) + assert.Equal(t, packageIndexTool.JSONPointer, testTable.packageIndexToolsDataAssertion[index].JSONPointer) + } + } + + testTable.packageIndexSystemsAssertion(t, PackageIndexSystems(), testTable.testName) + if PackageIndexSystems() != nil { + for index, packageIndexSystem := range PackageIndexSystems() { + assert.Equal(t, packageIndexSystem.ID, testTable.packageIndexSystemsDataAssertion[index].ID) + assert.Equal(t, packageIndexSystem.JSONPointer, testTable.packageIndexSystemsDataAssertion[index].JSONPointer) + } + } } } diff --git a/internal/project/projectdata/testdata/packageindexes/valid-package-index/package_foo_index.json b/internal/project/projectdata/testdata/packageindexes/valid-package-index/package_foo_index.json index 22e5b4522..3764ea590 100644 --- a/internal/project/projectdata/testdata/packageindexes/valid-package-index/package_foo_index.json +++ b/internal/project/projectdata/testdata/packageindexes/valid-package-index/package_foo_index.json @@ -1,7 +1,7 @@ { "packages": [ { - "name": "myboard", + "name": "myboard1", "maintainer": "Jane Developer", "websiteURL": "https://github.com/janedeveloper/myboard", "email": "jane@example.com", @@ -63,6 +63,111 @@ } ], "tools": [] + }, + { + "name": "myboard2", + "maintainer": "Jane Developer", + "websiteURL": "https://github.com/janedeveloper/myboard", + "email": "jane@example.com", + "help": { + "online": "http://example.com/forum/myboard" + }, + "platforms": [ + { + "name": "My Board", + "architecture": "samd", + "version": "2.0.0", + "category": "Contributed", + "help": { + "online": "http://example.com/forum/myboard" + }, + "url": "https://janedeveloper.github.io/myboard/myboard-1.0.0.zip", + "archiveFileName": "myboard-1.0.0.zip", + "checksum": "SHA-256:ec3ff8a1dc96d3ba6f432b9b837a35fd4174a34b3d2927de1d51010e8b94f9f1", + "size": "15005", + "boards": [{ "name": "My Board" }, { "name": "My Board Pro" }], + "toolsDependencies": [ + { + "packager": "arduino", + "name": "avr-gcc", + "version": "4.8.1-arduino5" + }, + { + "packager": "arduino", + "name": "avrdude", + "version": "6.0.1-arduino5" + } + ] + }, + { + "name": "My Board", + "architecture": "mbed", + "version": "1.1.1", + "category": "Contributed", + "help": { + "online": "http://example.com/forum/myboard" + }, + "url": "https://janedeveloper.github.io/myboard/myboard-1.0.1.zip", + "archiveFileName": "myboard-1.0.1.zip", + "checksum": "SHA-256:9c86ee28a7ce9fe33e8b07ec643316131e0031b0d22e63bb398902a5fdadbca9", + "size": "15125", + "boards": [{ "name": "My Board" }, { "name": "My Board Pro" }], + "toolsDependencies": [ + { + "packager": "arduino", + "name": "avr-gcc", + "version": "4.8.1-arduino5" + }, + { + "packager": "arduino", + "name": "avrdude", + "version": "6.0.1-arduino5" + } + ] + } + ], + "tools": [ + { + "name": "openocd", + "version": "0.10.0-arduino1-static", + "systems": [ + { + "host": "i386-apple-darwin11", + "url": "http://downloads.arduino.cc/arduino.org/OpenOCD-0.10.0-nrf52-osx-static.tar.gz", + "archiveFileName": "OpenOCD-0.10.0-nrf52-osx-static.tar.gz", + "size": "1529841", + "checksum": "SHA-256:46bd02c1d42c5d94c4936e4d4a0ff29697b621840be9a6f882e316203122049d" + }, + { + "host": "x86_64-linux-gnu", + "url": "http://downloads.arduino.cc/arduino.org/OpenOCD-0.10.0-nrf52-linux64-static.tar.gz", + "archiveFileName": "OpenOCD-0.10.0-nrf52-linux64-static.tar.gz", + "size": "1777984", + "checksum": "SHA-256:1c9ae77930dd7377d8c13f84abe7307b67fdcd6da74cc1ce269a79e138e7a00a" + } + ] + }, + { + "name": "CMSIS", + "version": "4.0.0-atmel", + "systems": [ + { + "host": "arm-linux-gnueabihf", + "url": "http://example.com", + "archiveFileName": "CMSIS-4.0.0.tar.bz2", + "checksum": "SHA-256:7d637d2d7a0c6bacc22065848a201db2fff124268e4a56868260d0f472b4bbb7", + "size": "17642623" + }, + { + "host": "i686-mingw32", + "url": "http://example.com", + "archiveFileName": "CMSIS-4.0.0.tar.bz2", + "checksum": "SHA-256:7d637d2d7a0c6bacc22065848a201db2fff124268e4a56868260d0f472b4bbb7", + "size": "17642623" + } + ] + } + ] } ] }