Skip to content

Commit f0d12c4

Browse files
committed
Make schema.Validate() general purpose
In order to work with the nested data structures of the platform configuration files, it's necessary to modify this function. Although the necessary properties.Map conversion could be done by schema.Validate(), this will not support working with the package index. So it's best to make it support all requirements now, rather than having to modify it yet again.
1 parent aa137d4 commit f0d12c4

File tree

3 files changed

+48
-32
lines changed

3 files changed

+48
-32
lines changed

internal/project/library/libraryproperties/libraryproperties.go

+11-3
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,17 @@ func Validate(libraryProperties *properties.Map) map[compliancelevel.Type]schema
4646
schemaObject[compliancelevel.Strict] = schema.Compile("arduino-library-properties-strict-schema.json", referencedSchemaFilenames, schemadata.Asset)
4747
}
4848

49-
validationResults[compliancelevel.Permissive] = schema.Validate(libraryProperties, schemaObject[compliancelevel.Permissive])
50-
validationResults[compliancelevel.Specification] = schema.Validate(libraryProperties, schemaObject[compliancelevel.Specification])
51-
validationResults[compliancelevel.Strict] = schema.Validate(libraryProperties, schemaObject[compliancelevel.Strict])
49+
// Convert the library.properties data from the native properties.Map type to the interface type required by the schema
50+
// validation package.
51+
libraryPropertiesMap := libraryProperties.AsMap()
52+
libraryPropertiesInterface := make(map[string]interface{}, len(libraryPropertiesMap))
53+
for k, v := range libraryPropertiesMap {
54+
libraryPropertiesInterface[k] = v
55+
}
56+
57+
validationResults[compliancelevel.Permissive] = schema.Validate(libraryPropertiesInterface, schemaObject[compliancelevel.Permissive])
58+
validationResults[compliancelevel.Specification] = schema.Validate(libraryPropertiesInterface, schemaObject[compliancelevel.Specification])
59+
validationResults[compliancelevel.Strict] = schema.Validate(libraryPropertiesInterface, schemaObject[compliancelevel.Strict])
5260

5361
return validationResults
5462
}

internal/rule/schema/schema.go

+1-10
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"io/ioutil"
2525
"path"
2626

27-
"github.com/arduino/go-properties-orderedmap"
2827
"github.com/ory/jsonschema/v3"
2928
"github.com/sirupsen/logrus"
3029
"github.com/xeipuuv/gojsonreference"
@@ -80,15 +79,7 @@ func Compile(schemaFilename string, referencedSchemaFilenames []string, dataLoad
8079

8180
// Validate validates an instance against a JSON schema and returns nil if it was success, or the
8281
// jsonschema.ValidationError object otherwise.
83-
func Validate(instanceObject *properties.Map, schemaObject Schema) ValidationResult {
84-
// Convert the instance data from the native properties.Map type to the interface type required by the schema
85-
// validation package.
86-
instanceObjectMap := instanceObject.AsMap()
87-
instanceInterface := make(map[string]interface{}, len(instanceObjectMap))
88-
for k, v := range instanceObjectMap {
89-
instanceInterface[k] = v
90-
}
91-
82+
func Validate(instanceInterface map[string]interface{}, schemaObject Schema) ValidationResult {
9283
validationError := schemaObject.Compiled.ValidateInterface(instanceInterface)
9384
result, _ := validationError.(*jsonschema.ValidationError)
9485
validationResult := ValidationResult{

internal/rule/schema/schema_test.go

+36-19
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,23 @@ func init() {
4646
)
4747
}
4848

49+
// propertiesToMap converts properties.Map data structures to map[string]interface.
50+
func propertiesToMap(propertiesInput *properties.Map) map[string]interface{} {
51+
mapOutput := make(map[string]interface{})
52+
keys := propertiesInput.FirstLevelKeys()
53+
for _, key := range keys {
54+
subTree := propertiesInput.SubTree(key)
55+
if subTree.Size() > 0 {
56+
// This key contains a map, recurse it.
57+
mapOutput[key] = propertiesToMap(subTree)
58+
} else {
59+
// This key contains a string, no more recursion is possible.
60+
mapOutput[key] = propertiesInput.Get(key)
61+
}
62+
}
63+
return mapOutput
64+
}
65+
4966
func TestCompile(t *testing.T) {
5067
require.Panics(t, func() {
5168
Compile("valid-schema-with-references.json", []string{"nonexistent.json"}, testdata.Asset)
@@ -82,87 +99,87 @@ func TestCompile(t *testing.T) {
8299
func TestValidate(t *testing.T) {
83100
schemaObject := Compile("valid-schema.json", []string{}, testdata.Asset)
84101
propertiesMap := properties.NewFromHashmap(validMap)
85-
validationResult := Validate(propertiesMap, schemaObject)
102+
validationResult := Validate(propertiesToMap(propertiesMap), schemaObject)
86103
require.Nil(t, validationResult.Result)
87104

88-
validationResult = Validate(propertiesMap, validSchemaWithReferences)
105+
validationResult = Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
89106
require.Nil(t, validationResult.Result)
90107

91108
propertiesMap.Set("property1", "a")
92-
validationResult = Validate(propertiesMap, schemaObject)
109+
validationResult = Validate(propertiesToMap(propertiesMap), schemaObject)
93110
require.Equal(t, "#/property1", validationResult.Result.InstancePtr)
94111
require.Equal(t, "#/properties/property1/minLength", validationResult.Result.SchemaPtr)
95112
}
96113

97114
func TestRequiredPropertyMissing(t *testing.T) {
98115
propertiesMap := properties.NewFromHashmap(validMap)
99-
validationResult := Validate(propertiesMap, validSchemaWithReferences)
116+
validationResult := Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
100117
require.False(t, RequiredPropertyMissing("property1", validationResult))
101118

102119
propertiesMap.Remove("property1")
103-
validationResult = Validate(propertiesMap, validSchemaWithReferences)
120+
validationResult = Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
104121
require.True(t, RequiredPropertyMissing("property1", validationResult))
105122
}
106123

107124
func TestPropertyPatternMismatch(t *testing.T) {
108125
propertiesMap := properties.NewFromHashmap(validMap)
109-
validationResult := Validate(propertiesMap, validSchemaWithReferences)
126+
validationResult := Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
110127
require.False(t, PropertyPatternMismatch("property2", validationResult))
111128

112129
propertiesMap.Set("property2", "fOo")
113-
validationResult = Validate(propertiesMap, validSchemaWithReferences)
130+
validationResult = Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
114131
require.True(t, PropertyPatternMismatch("property2", validationResult))
115132

116133
require.False(t, PropertyPatternMismatch("property1", validationResult))
117134
}
118135

119136
func TestPropertyLessThanMinLength(t *testing.T) {
120137
propertiesMap := properties.NewFromHashmap(validMap)
121-
validationResult := Validate(propertiesMap, validSchemaWithReferences)
138+
validationResult := Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
122139
require.False(t, PropertyLessThanMinLength("property1", validationResult))
123140

124141
propertiesMap.Set("property1", "a")
125-
validationResult = Validate(propertiesMap, validSchemaWithReferences)
142+
validationResult = Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
126143
require.True(t, PropertyLessThanMinLength("property1", validationResult))
127144
}
128145

129146
func TestPropertyGreaterThanMaxLength(t *testing.T) {
130147
propertiesMap := properties.NewFromHashmap(validMap)
131-
validationResult := Validate(propertiesMap, validSchemaWithReferences)
148+
validationResult := Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
132149
require.False(t, PropertyGreaterThanMaxLength("property1", validationResult))
133150

134151
propertiesMap.Set("property1", "12345")
135-
validationResult = Validate(propertiesMap, validSchemaWithReferences)
152+
validationResult = Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
136153
require.True(t, PropertyGreaterThanMaxLength("property1", validationResult))
137154
}
138155

139156
func TestPropertyEnumMismatch(t *testing.T) {
140157
propertiesMap := properties.NewFromHashmap(validMap)
141-
validationResult := Validate(propertiesMap, validSchemaWithReferences)
158+
validationResult := Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
142159
require.False(t, PropertyEnumMismatch("property3", validationResult))
143160

144161
propertiesMap.Set("property3", "invalid")
145-
validationResult = Validate(propertiesMap, validSchemaWithReferences)
162+
validationResult = Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
146163
require.True(t, PropertyEnumMismatch("property3", validationResult))
147164
}
148165

149166
func TestMisspelledOptionalPropertyFound(t *testing.T) {
150167
propertiesMap := properties.NewFromHashmap(validMap)
151-
validationResult := Validate(propertiesMap, validSchemaWithReferences)
168+
validationResult := Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
152169
require.False(t, MisspelledOptionalPropertyFound(validationResult))
153170

154171
propertiesMap.Set("porperties", "foo")
155-
validationResult = Validate(propertiesMap, validSchemaWithReferences)
172+
validationResult = Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
156173
require.True(t, MisspelledOptionalPropertyFound(validationResult))
157174
}
158175

159176
func TestValidationErrorMatch(t *testing.T) {
160177
propertiesMap := properties.NewFromHashmap(validMap)
161-
validationResult := Validate(propertiesMap, validSchemaWithReferences)
178+
validationResult := Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
162179
require.False(t, ValidationErrorMatch("", "", "", "", validationResult))
163180

164181
propertiesMap.Set("property2", "fOo")
165-
validationResult = Validate(propertiesMap, validSchemaWithReferences)
182+
validationResult = Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
166183
require.False(t, ValidationErrorMatch("nomatch", "nomatch", "nomatch", "nomatch", validationResult))
167184
require.False(t, ValidationErrorMatch("^#/property2$", "nomatch", "nomatch", "nomatch", validationResult))
168185
require.False(t, ValidationErrorMatch("^#/property2$", "/pattern$", "nomatch", "nomatch", validationResult))
@@ -171,12 +188,12 @@ func TestValidationErrorMatch(t *testing.T) {
171188
require.True(t, ValidationErrorMatch("", "", "", "", validationResult))
172189

173190
propertiesMap.Set("property3", "bAz")
174-
validationResult = Validate(propertiesMap, validSchemaWithReferences)
191+
validationResult = Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
175192
require.True(t, ValidationErrorMatch("^#/property3$", "/pattern$", "", "", validationResult), "Match pointer below logic inversion keyword")
176193

177194
propertiesMap = properties.NewFromHashmap(validMap)
178195
propertiesMap.Remove("property1")
179-
validationResult = Validate(propertiesMap, validSchemaWithReferences)
196+
validationResult = Validate(propertiesToMap(propertiesMap), validSchemaWithReferences)
180197
require.False(t, ValidationErrorMatch("nomatch", "nomatch", "nomatch", "nomatch", validationResult))
181198
require.True(t, ValidationErrorMatch("", "", "", "^#/property1$", validationResult))
182199
}

0 commit comments

Comments
 (0)