Skip to content

Commit 991db89

Browse files
authored
Merge pull request #20 from arduino/per1234/parse-validation-results-file
Move schema validation result parsing code to dedicated file
2 parents 6a25f07 + 746d9d7 commit 991db89

File tree

2 files changed

+154
-130
lines changed

2 files changed

+154
-130
lines changed

Diff for: check/checkdata/schema/parsevalidationresult.go

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// This file is part of arduino-check.
2+
//
3+
// Copyright 2020 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-check.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to [email protected].
15+
16+
package schema
17+
18+
import (
19+
"encoding/json"
20+
"regexp"
21+
22+
"github.com/arduino/go-paths-helper"
23+
"github.com/ory/jsonschema/v3"
24+
"github.com/sirupsen/logrus"
25+
)
26+
27+
// RequiredPropertyMissing returns whether the given required property is missing from the document.
28+
func RequiredPropertyMissing(propertyName string, validationResult *jsonschema.ValidationError, schemasPath *paths.Path) bool {
29+
return ValidationErrorMatch("#", "/required$", "", "^#/"+propertyName+"$", validationResult, schemasPath)
30+
}
31+
32+
// PropertyPatternMismatch returns whether the given property did not match the regular expression defined in the JSON schema.
33+
func PropertyPatternMismatch(propertyName string, validationResult *jsonschema.ValidationError, schemasPath *paths.Path) bool {
34+
return ValidationErrorMatch("#/"+propertyName, "/pattern$", "", "", validationResult, schemasPath)
35+
}
36+
37+
// ValidationErrorMatch returns whether the given query matches against the JSON schema validation error.
38+
// See: https://godoc.org/github.com/ory/jsonschema#ValidationError
39+
func ValidationErrorMatch(
40+
instancePointerQuery,
41+
schemaPointerQuery,
42+
schemaPointerValueQuery,
43+
failureContextQuery string,
44+
validationResult *jsonschema.ValidationError,
45+
schemasPath *paths.Path,
46+
) bool {
47+
if validationResult == nil {
48+
// No error, so nothing to match
49+
logrus.Trace("Schema validation passed. No match is possible.")
50+
return false
51+
}
52+
53+
instancePointerRegexp := regexp.MustCompile(instancePointerQuery)
54+
schemaPointerRegexp := regexp.MustCompile(schemaPointerQuery)
55+
schemaPointerValueRegexp := regexp.MustCompile(schemaPointerValueQuery)
56+
failureContextRegexp := regexp.MustCompile(failureContextQuery)
57+
58+
return validationErrorMatch(
59+
instancePointerRegexp,
60+
schemaPointerRegexp,
61+
schemaPointerValueRegexp,
62+
failureContextRegexp,
63+
validationResult,
64+
schemasPath)
65+
}
66+
67+
func validationErrorMatch(
68+
instancePointerRegexp,
69+
schemaPointerRegexp,
70+
schemaPointerValueRegexp,
71+
failureContextRegexp *regexp.Regexp,
72+
validationError *jsonschema.ValidationError,
73+
schemasPath *paths.Path,
74+
) bool {
75+
logrus.Trace("--------Checking schema validation failure match--------")
76+
logrus.Tracef("Checking instance pointer: %s match with regexp: %s", validationError.InstancePtr, instancePointerRegexp)
77+
if instancePointerRegexp.MatchString(validationError.InstancePtr) {
78+
logrus.Tracef("Matched!")
79+
logrus.Tracef("Checking schema pointer: %s match with regexp: %s", validationError.SchemaPtr, schemaPointerRegexp)
80+
if schemaPointerRegexp.MatchString(validationError.SchemaPtr) {
81+
logrus.Tracef("Matched!")
82+
if validationErrorSchemaPointerValueMatch(schemaPointerValueRegexp, validationError, schemasPath) {
83+
logrus.Tracef("Matched!")
84+
logrus.Tracef("Checking failure context: %v match with regexp: %s", validationError.Context, failureContextRegexp)
85+
if validationErrorContextMatch(failureContextRegexp, validationError) {
86+
logrus.Tracef("Matched!")
87+
return true
88+
}
89+
}
90+
}
91+
}
92+
93+
// Recursively check all causes for a match.
94+
for _, validationErrorCause := range validationError.Causes {
95+
if validationErrorMatch(
96+
instancePointerRegexp,
97+
schemaPointerRegexp,
98+
schemaPointerValueRegexp,
99+
failureContextRegexp,
100+
validationErrorCause,
101+
schemasPath,
102+
) {
103+
return true
104+
}
105+
}
106+
107+
return false
108+
}
109+
110+
// validationErrorSchemaPointerValueMatch marshalls the data in the schema at the given JSON pointer and returns whether
111+
// it matches against the given regular expression.
112+
func validationErrorSchemaPointerValueMatch(
113+
schemaPointerValueRegexp *regexp.Regexp,
114+
validationError *jsonschema.ValidationError,
115+
schemasPath *paths.Path,
116+
) bool {
117+
marshalledSchemaPointerValue, err := json.Marshal(schemaPointerValue(validationError, schemasPath))
118+
logrus.Tracef("Checking schema pointer value: %s match with regexp: %s", marshalledSchemaPointerValue, schemaPointerValueRegexp)
119+
if err != nil {
120+
panic(err)
121+
}
122+
return schemaPointerValueRegexp.Match(marshalledSchemaPointerValue)
123+
}
124+
125+
// validationErrorContextMatch parses the validation error context data and returns whether it matches against the given
126+
// regular expression.
127+
func validationErrorContextMatch(failureContextRegexp *regexp.Regexp, validationError *jsonschema.ValidationError) bool {
128+
// This was added in the github.com/ory/jsonschema fork of github.com/santhosh-tekuri/jsonschema
129+
// It currently only provides context about the `required` keyword.
130+
switch contextObject := validationError.Context.(type) {
131+
case nil:
132+
return failureContextRegexp.MatchString("")
133+
case *jsonschema.ValidationErrorContextRequired:
134+
return validationErrorContextRequiredMatch(failureContextRegexp, contextObject)
135+
default:
136+
logrus.Errorf("Unhandled validation error context type: %T", validationError.Context)
137+
return failureContextRegexp.MatchString("")
138+
}
139+
}
140+
141+
// validationErrorContextRequiredMatch returns whether any of the JSON pointers of missing required properties match
142+
// against the given regular expression.
143+
func validationErrorContextRequiredMatch(
144+
failureContextRegexp *regexp.Regexp,
145+
contextObject *jsonschema.ValidationErrorContextRequired,
146+
) bool {
147+
// See: https://godoc.org/github.com/ory/jsonschema#ValidationErrorContextRequired
148+
for _, requiredPropertyPointer := range contextObject.Missing {
149+
if failureContextRegexp.MatchString(requiredPropertyPointer) {
150+
return true
151+
}
152+
}
153+
return false
154+
}

Diff for: check/checkdata/schema/schema.go

-130
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
"net/url"
2323
"path"
2424
"path/filepath"
25-
"regexp"
2625

2726
"github.com/arduino/go-paths-helper"
2827
"github.com/arduino/go-properties-orderedmap"
@@ -77,46 +76,6 @@ func Validate(instanceObject *properties.Map, schemaObject *jsonschema.Schema, s
7776
return result
7877
}
7978

80-
// RequiredPropertyMissing returns whether the given required property is missing from the document.
81-
func RequiredPropertyMissing(propertyName string, validationResult *jsonschema.ValidationError, schemasPath *paths.Path) bool {
82-
return ValidationErrorMatch("#", "/required$", "", "^#/"+propertyName+"$", validationResult, schemasPath)
83-
}
84-
85-
// PropertyPatternMismatch returns whether the given property did not match the regular expression defined in the JSON schema.
86-
func PropertyPatternMismatch(propertyName string, validationResult *jsonschema.ValidationError, schemasPath *paths.Path) bool {
87-
return ValidationErrorMatch("#/"+propertyName, "/pattern$", "", "", validationResult, schemasPath)
88-
}
89-
90-
// ValidationErrorMatch returns whether the given query matches against the JSON schema validation error.
91-
// See: https://godoc.org/github.com/ory/jsonschema#ValidationError
92-
func ValidationErrorMatch(
93-
instancePointerQuery,
94-
schemaPointerQuery,
95-
schemaPointerValueQuery,
96-
failureContextQuery string,
97-
validationResult *jsonschema.ValidationError,
98-
schemasPath *paths.Path,
99-
) bool {
100-
if validationResult == nil {
101-
// No error, so nothing to match
102-
logrus.Trace("Schema validation passed. No match is possible.")
103-
return false
104-
}
105-
106-
instancePointerRegexp := regexp.MustCompile(instancePointerQuery)
107-
schemaPointerRegexp := regexp.MustCompile(schemaPointerQuery)
108-
schemaPointerValueRegexp := regexp.MustCompile(schemaPointerValueQuery)
109-
failureContextRegexp := regexp.MustCompile(failureContextQuery)
110-
111-
return validationErrorMatch(
112-
instancePointerRegexp,
113-
schemaPointerRegexp,
114-
schemaPointerValueRegexp,
115-
failureContextRegexp,
116-
validationResult,
117-
schemasPath)
118-
}
119-
12079
// loadReferencedSchema adds a schema that is referenced by the parent schema to the compiler object.
12180
func loadReferencedSchema(compiler *jsonschema.Compiler, schemaFilename string, schemasPath *paths.Path) error {
12281
schemaPath := schemasPath.Join(schemaFilename)
@@ -225,92 +184,3 @@ func jsonPointerValue(jsonPointer string, filePath *paths.Path) interface{} {
225184
}
226185
return jsonPointerValue
227186
}
228-
229-
func validationErrorMatch(
230-
instancePointerRegexp,
231-
schemaPointerRegexp,
232-
schemaPointerValueRegexp,
233-
failureContextRegexp *regexp.Regexp,
234-
validationError *jsonschema.ValidationError,
235-
schemasPath *paths.Path,
236-
) bool {
237-
logrus.Trace("--------Checking schema validation failure match--------")
238-
logrus.Tracef("Checking instance pointer: %s match with regexp: %s", validationError.InstancePtr, instancePointerRegexp)
239-
if instancePointerRegexp.MatchString(validationError.InstancePtr) {
240-
logrus.Tracef("Matched!")
241-
logrus.Tracef("Checking schema pointer: %s match with regexp: %s", validationError.SchemaPtr, schemaPointerRegexp)
242-
if schemaPointerRegexp.MatchString(validationError.SchemaPtr) {
243-
logrus.Tracef("Matched!")
244-
if validationErrorSchemaPointerValueMatch(schemaPointerValueRegexp, validationError, schemasPath) {
245-
logrus.Tracef("Matched!")
246-
logrus.Tracef("Checking failure context: %v match with regexp: %s", validationError.Context, failureContextRegexp)
247-
if validationErrorContextMatch(failureContextRegexp, validationError) {
248-
logrus.Tracef("Matched!")
249-
return true
250-
}
251-
}
252-
}
253-
}
254-
255-
// Recursively check all causes for a match.
256-
for _, validationErrorCause := range validationError.Causes {
257-
if validationErrorMatch(
258-
instancePointerRegexp,
259-
schemaPointerRegexp,
260-
schemaPointerValueRegexp,
261-
failureContextRegexp,
262-
validationErrorCause,
263-
schemasPath,
264-
) {
265-
return true
266-
}
267-
}
268-
269-
return false
270-
}
271-
272-
// validationErrorSchemaPointerValueMatch marshalls the data in the schema at the given JSON pointer and returns whether
273-
// it matches against the given regular expression.
274-
func validationErrorSchemaPointerValueMatch(
275-
schemaPointerValueRegexp *regexp.Regexp,
276-
validationError *jsonschema.ValidationError,
277-
schemasPath *paths.Path,
278-
) bool {
279-
marshalledSchemaPointerValue, err := json.Marshal(schemaPointerValue(validationError, schemasPath))
280-
logrus.Tracef("Checking schema pointer value: %s match with regexp: %s", marshalledSchemaPointerValue, schemaPointerValueRegexp)
281-
if err != nil {
282-
panic(err)
283-
}
284-
return schemaPointerValueRegexp.Match(marshalledSchemaPointerValue)
285-
}
286-
287-
// validationErrorContextMatch parses the validation error context data and returns whether it matches against the given
288-
// regular expression.
289-
func validationErrorContextMatch(failureContextRegexp *regexp.Regexp, validationError *jsonschema.ValidationError) bool {
290-
// This was added in the github.com/ory/jsonschema fork of github.com/santhosh-tekuri/jsonschema
291-
// It currently only provides context about the `required` keyword.
292-
switch contextObject := validationError.Context.(type) {
293-
case nil:
294-
return failureContextRegexp.MatchString("")
295-
case *jsonschema.ValidationErrorContextRequired:
296-
return validationErrorContextRequiredMatch(failureContextRegexp, contextObject)
297-
default:
298-
logrus.Errorf("Unhandled validation error context type: %T", validationError.Context)
299-
return failureContextRegexp.MatchString("")
300-
}
301-
}
302-
303-
// validationErrorContextRequiredMatch returns whether any of the JSON pointers of missing required properties match
304-
// against the given regular expression.
305-
func validationErrorContextRequiredMatch(
306-
failureContextRegexp *regexp.Regexp,
307-
contextObject *jsonschema.ValidationErrorContextRequired,
308-
) bool {
309-
// See: https://godoc.org/github.com/ory/jsonschema#ValidationErrorContextRequired
310-
for _, requiredPropertyPointer := range contextObject.Missing {
311-
if failureContextRegexp.MatchString(requiredPropertyPointer) {
312-
return true
313-
}
314-
}
315-
return false
316-
}

0 commit comments

Comments
 (0)