Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix json panic #251

Merged
merged 2 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions internal/ctxerr/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ func (c Context) CollectError(err *Error) *Error {
return err
}

// Skip it if already encountered as Re in JSON(`[$1,$1]`, Re(123))
for _, cur := range *c.Errors {
if cur == err {
return nil
}
}

// Else, accumulate...
*c.Errors = append(*c.Errors, err)
if c.MaxErrors >= 0 && len(*c.Errors) >= c.MaxErrors {
Expand Down
18 changes: 18 additions & 0 deletions internal/ctxerr/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,24 @@ func TestContextCollectError(t *testing.T) {
if len(errors) != 100 {
t.Errorf("Only %d errors accumulated instead of 100", len(errors))
}

//
// Do not collect 2 times the same error
errors = nil
ctx = ctxerr.Context{
Errors: &errors,
MaxErrors: -1,
}
ctx.CollectError(&ctxerr.Error{}) //nolint: errcheck
x := &ctxerr.Error{}
ctx.CollectError(x) //nolint: errcheck
ctx.CollectError(&ctxerr.Error{}) //nolint: errcheck
ctx.CollectError(x) //nolint: errcheck
ctx.CollectError(x) //nolint: errcheck
ctx.CollectError(&ctxerr.Error{}) //nolint: errcheck
if len(errors) != 4 {
t.Errorf("%d errors accumulated instead of 4", len(errors))
}
}

func TestCannotCompareError(t *testing.T) {
Expand Down
7 changes: 2 additions & 5 deletions td/td_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,7 @@ func (u tdJSONUnmarshaler) unmarshal(expectedJSON any, params []any) (any, *ctxe
var byTag map[string]any

for i, p := range params {
switch op := p.(type) {
case *tdTag:
if op, ok := p.(*tdTag); ok && op.err == nil {
if byTag[op.tag] != nil {
return nil, ctxerr.OpBad(u.Func, `2 params have the same tag "%s"`, op.tag)
}
Expand All @@ -141,10 +140,8 @@ func (u tdJSONUnmarshaler) unmarshal(expectedJSON any, params []any) (any, *ctxe
p = op.expectedValue.Interface()
}
byTag[op.tag] = newJSONNamedPlaceholder(op.tag, p)

default:
params[i] = newJSONNumPlaceholder(uint64(i+1), p)
}
params[i] = newJSONNumPlaceholder(uint64(i+1), p)
}

final, err := json.Parse(b, json.ParseOpts{
Expand Down
19 changes: 19 additions & 0 deletions td/td_json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@ func TestJSON(t *testing.T) {
td.Tag("age", td.Between(40, 45)),
td.Tag("gender", td.NotEmpty())))

// Tag placeholders + numeric placeholders
checkOK(t, []MyStruct{got, got},
td.JSON(`[
{"name":"$1","age":$age,"gender":"$3"},
{"name":"$1","age":$2,"gender":"$3"}
]`,
td.Re(`^Bo`), // $1
td.Tag("age", td.Between(40, 45)), // $2
"male")) // $3

// Tag placeholders + operators are not JSON marshallable
checkOK(t, got,
td.JSON(`$all`, td.Tag("all", map[string]any{
Expand All @@ -113,6 +123,15 @@ func TestJSON(t *testing.T) {
"gender": td.NotEmpty(),
})))

checkError(t, got,
td.JSON(`{"name":$1, "age":$1, "gender":$1}`,
td.Tag("!!", td.Ignore())),
expectedError{
Message: mustBe("bad usage of Tag operator"),
Summary: mustBe("Invalid tag, should match (Letter|_)(Letter|_|Number)*"),
Under: mustContain("under operator Tag"),
})

// Tag placeholders + nil
checkOK(t, nil, td.JSON(`$all`, td.Tag("all", nil)))

Expand Down
Loading