Skip to content

Commit

Permalink
chore: add tests for errors-extracting functions used in schema valid…
Browse files Browse the repository at this point in the history
…ation
  • Loading branch information
omissis committed Aug 16, 2022
1 parent 7540ba4 commit e8c3b15
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 16 deletions.
24 changes: 17 additions & 7 deletions cmd/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func (vc *validateCommand) Help() string {
}

func (vc *validateCommand) Run(args []string) int {
exitCode := 0
basePath := getWd()

vc.parseFlags()
Expand All @@ -42,13 +43,15 @@ func (vc *validateCommand) Run(args []string) int {
if err := schema.ValidateInterface(conf); err != nil {
vc.logValidationError(err, conf)

log.Fatal(err)
} else {
fmt.Println("ok")
exitCode = 1
}
}

return 0
if exitCode == 0 {
fmt.Println("ok")
}

return exitCode
}

func (vc *validateCommand) Synopsis() string {
Expand Down Expand Up @@ -100,15 +103,22 @@ func (vc *validateCommand) loadSchema(basePath string) *jsonschema.Schema {
func (vc *validateCommand) logValidationError(err error, conf any) {
ptrPaths := santhosh.GetPtrPaths(err.(*jsonschema.ValidationError))
for _, path := range ptrPaths {
value, err := json.Marshal(santhosh.GetValueAtPath(conf, path))
value, err := santhosh.GetValueAtPath(conf, path)
if err != nil {
log.Fatal(err)
}

mvalue, err := json.Marshal(value)
if err != nil {
log.Fatal(err)
}

log.Printf(
fmt.Printf(
"path '%s' contains an invalid configuration value: %+v\n",
santhosh.JoinPtrPath(path),
string(value),
string(mvalue),
)
}

fmt.Println(err)
}
6 changes: 3 additions & 3 deletions internal/arch/file/rule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ func Test_It_Checks_All_Conditions(t *testing.T) {
Because("I want to test all expressions together")

if !cmp.Equal(vs, tC.wantViolations, cmp.AllowUnexported(rule.Violation{}), cmpopts.EquateEmpty()) {
t.Errorf("Expected %v, got %v", tC.wantViolations, vs)
t.Errorf("expected %v, got %v", tC.wantViolations, vs)
}

if errs != nil {
t.Errorf("Expected errs to be nil, got: %+v", errs)
t.Errorf("expected errs to be nil, got: %+v", errs)
}
})
}
Expand All @@ -73,6 +73,6 @@ func Test_It_Adds_ErrRuleBuilderLocked_Only_Once(t *testing.T) {
rb.AddError(file.ErrRuleBuilderLocked)

if errs := rb.GetErrors(); len(errs) != 1 {
t.Errorf("Expected 1 error, got %d", len(errs))
t.Errorf("expected 1 error, got %d", len(errs))
}
}
25 changes: 19 additions & 6 deletions internal/schema/santhosh/errors.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package santhosh

import (
"errors"
"strconv"
"strings"

"github.com/santhosh-tekuri/jsonschema"
"golang.org/x/exp/slices"
)

var ErrObjTypeAssertion = errors.New("obj type assertion failed")

func JoinPtrPath(path []any) string {
strpath := "#"

Expand All @@ -23,17 +26,27 @@ func JoinPtrPath(path []any) string {
return strpath
}

func GetValueAtPath(obj any, path []any) any {
func GetValueAtPath(obj any, path []any) (any, error) {
for _, key := range path {
switch v := key.(type) {
case int:
obj = obj.([]any)[v]
tobj, ok := obj.([]any)
if !ok {
return nil, ErrObjTypeAssertion
}

obj = tobj[v]
case string:
obj = obj.(map[string]any)[v]
tobj, ok := obj.(map[string]any)
if !ok {
return nil, ErrObjTypeAssertion
}

obj = tobj[v]
}
}

return obj
return obj, nil
}

func GetPtrPaths(err error) [][]any {
Expand All @@ -45,13 +58,13 @@ func GetPtrPaths(err error) [][]any {
}

func extractPtrs(err *jsonschema.ValidationError) []string {
var ptrs []string
ptrs := []string{err.InstancePtr}

for _, cause := range err.Causes {
if len(cause.Causes) > 0 {
ptrs = append(ptrs, extractPtrs(cause)...)
} else {
ptrs = append(ptrs, err.InstancePtr)
ptrs = append(ptrs, cause.InstancePtr)
}
}

Expand Down
158 changes: 158 additions & 0 deletions internal/schema/santhosh/errors_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package santhosh_test

import (
"goarkitect/internal/schema/santhosh"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/santhosh-tekuri/jsonschema"
)

func Test_JoinPtrPath(t *testing.T) {
testCases := []struct {
desc string
path []any
want string
}{
{
desc: "empty path",
path: []any{},
want: "#",
},
{
desc: "strings-only path",
path: []any{"foo", "bar"},
want: "#/foo/bar",
},
{
desc: "ints-only path",
path: []any{0, 1, 2, 3},
want: "#/0/1/2/3",
},
{
desc: "strings and ints path",
path: []any{"foo", 3, "bar", 5},
want: "#/foo/3/bar/5",
},
{
desc: "no-strings and no-ints path",
path: []any{0.0, 'a', true},
want: "#",
},
}
for _, tC := range testCases {
t.Run(tC.desc, func(t *testing.T) {
got := santhosh.JoinPtrPath(tC.path)
if got != tC.want {
t.Errorf("got %v, want %v", got, tC.want)
}
})
}
}

func Test_GetValueAtPath(t *testing.T) {
testCases := []struct {
desc string
obj any
path []any
want any
wantErr error
}{
{
desc: "1-level obj",
obj: map[string]any{"foo": "bar"},
path: []any{"foo"},
want: "bar",
},
{
desc: "2-levels obj",
obj: map[string]any{
"foo": map[string]any{
"bar": 123,
},
},
path: []any{"foo", "bar"},
want: 123,
},
{
desc: "2-levels obj, mixed data types",
obj: []any{
map[string]any{"foo": []any{"foo", 123}},
},
path: []any{0, "foo", 1},
want: 123,
},
{
desc: "2-levels obj, mixed data types",
obj: map[string]any{
"foo": []any{
map[string]any{"bar": 123},
},
},
path: []any{"foo", 0, "bar"},
want: 123,
},
}
for _, tC := range testCases {
t.Run(tC.desc, func(t *testing.T) {
got, err := santhosh.GetValueAtPath(tC.obj, tC.path)
if got != tC.want {
t.Errorf("got %v, want %v", got, tC.want)
}
if err != tC.wantErr {
t.Errorf("got error %v, want %v", err, tC.wantErr)
}
})
}
}

func Test_GetPtrPaths(t *testing.T) {
testCases := []struct {
desc string
err *jsonschema.ValidationError
want [][]any
}{
{
desc: "get the value pointed by instance ptr",
err: &jsonschema.ValidationError{
Message: "missing properties: \"filePath\"",
InstancePtr: "#/rules/0/matcher",
SchemaURL: "/home/user/api/config_schema.json",
SchemaPtr: "#/definitions/fileMatcherOne/required",
},
want: [][]any{
{"rules", 0, "matcher"},
},
},
{
desc: "get the value pointed by instance ptr and its cause",
err: &jsonschema.ValidationError{
Message: "missing properties: \"filePath\"",
InstancePtr: "#/rules/0/matcher",
SchemaURL: "/home/user/api/config_schema.json",
SchemaPtr: "#/definitions/fileMatcherOne/required",
Causes: []*jsonschema.ValidationError{
{
Message: "wrong property: \"filePaths\"",
InstancePtr: "#/rules/0/matcher/filePaths",
SchemaURL: "/home/user/api/config_schema.json",
SchemaPtr: "#/definitions/fileMatcherOne/required",
},
},
},
want: [][]any{
{"rules", 0, "matcher"},
{"rules", 0, "matcher", "filePaths"},
},
},
}
for _, tC := range testCases {
t.Run(tC.desc, func(t *testing.T) {
got := santhosh.GetPtrPaths(tC.err)
if !cmp.Equal(got, tC.want, cmpopts.EquateEmpty()) {
t.Errorf("expected %v, got %v", tC.want, got)
}
})
}
}

0 comments on commit e8c3b15

Please # to comment.