Add test cases

This commit is contained in:
Masaaki Goshima 2021-04-19 22:54:10 +09:00
parent 7dd33b9060
commit e0b5ba8df4
3 changed files with 92 additions and 25 deletions

View File

@ -43,13 +43,32 @@ func Compact(buf *bytes.Buffer, src []byte, escape bool) error {
} }
func compact(dst, src []byte, escape bool) ([]byte, error) { func compact(dst, src []byte, escape bool) ([]byte, error) {
buf, _, err := compactValue(dst, src, 0, escape) buf, cursor, err := compactValue(dst, src, 0, escape)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := validateEndBuf(src, cursor); err != nil {
return nil, err
}
return buf, nil return buf, nil
} }
func validateEndBuf(src []byte, cursor int64) error {
for {
switch src[cursor] {
case ' ', '\t', '\n', '\r':
cursor++
continue
case nul:
return nil
}
return errors.ErrSyntax(
fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]),
cursor+1,
)
}
}
func skipWhiteSpace(buf []byte, cursor int64) int64 { func skipWhiteSpace(buf []byte, cursor int64) int64 {
LOOP: LOOP:
if isWhiteSpace[buf[cursor]] { if isWhiteSpace[buf[cursor]] {
@ -90,12 +109,9 @@ func compactValue(dst, src []byte, cursor int64, escape bool) ([]byte, int64, er
} }
func compactObject(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) { func compactObject(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) {
switch src[cursor] { if src[cursor] == '{' {
case 'n':
return compactNull(dst, src, cursor)
case '{':
dst = append(dst, '{') dst = append(dst, '{')
default: } else {
return nil, 0, errors.ErrExpected("expected { character for object value", cursor) return nil, 0, errors.ErrExpected("expected { character for object value", cursor)
} }
cursor = skipWhiteSpace(src, cursor+1) cursor = skipWhiteSpace(src, cursor+1)
@ -135,12 +151,9 @@ func compactObject(dst, src []byte, cursor int64, escape bool) ([]byte, int64, e
} }
func compactArray(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) { func compactArray(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) {
switch src[cursor] { if src[cursor] == '[' {
case 'n':
return compactNull(dst, src, cursor)
case '[':
dst = append(dst, '[') dst = append(dst, '[')
default: } else {
return nil, 0, errors.ErrExpected("expected [ character for array value", cursor) return nil, 0, errors.ErrExpected("expected [ character for array value", cursor)
} }
cursor = skipWhiteSpace(src, cursor+1) cursor = skipWhiteSpace(src, cursor+1)

View File

@ -26,10 +26,13 @@ func Indent(buf *bytes.Buffer, src []byte, prefix, indentStr string) error {
} }
func doIndent(dst, src []byte, prefix, indentStr string, escape bool) ([]byte, error) { func doIndent(dst, src []byte, prefix, indentStr string, escape bool) ([]byte, error) {
buf, _, err := indentValue(dst, src, 0, 0, []byte(prefix), []byte(indentStr), escape) buf, cursor, err := indentValue(dst, src, 0, 0, []byte(prefix), []byte(indentStr), escape)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := validateEndBuf(src, cursor); err != nil {
return nil, err
}
return buf, nil return buf, nil
} }
@ -78,12 +81,9 @@ func indentObject(
prefix []byte, prefix []byte,
indentBytes []byte, indentBytes []byte,
escape bool) ([]byte, int64, error) { escape bool) ([]byte, int64, error) {
switch src[cursor] { if src[cursor] == '{' {
case 'n':
return compactNull(dst, src, cursor)
case '{':
dst = append(dst, '{') dst = append(dst, '{')
default: } else {
return nil, 0, errors.ErrExpected("expected { character for object value", cursor) return nil, 0, errors.ErrExpected("expected { character for object value", cursor)
} }
cursor = skipWhiteSpace(src, cursor+1) cursor = skipWhiteSpace(src, cursor+1)
@ -139,12 +139,9 @@ func indentArray(
prefix []byte, prefix []byte,
indentBytes []byte, indentBytes []byte,
escape bool) ([]byte, int64, error) { escape bool) ([]byte, int64, error) {
switch src[cursor] { if src[cursor] == '[' {
case 'n':
return compactNull(dst, src, cursor)
case '[':
dst = append(dst, '[') dst = append(dst, '[')
default: } else {
return nil, 0, errors.ErrExpected("expected [ character for array value", cursor) return nil, 0, errors.ErrExpected("expected [ character for array value", cursor)
} }
cursor = skipWhiteSpace(src, cursor+1) cursor = skipWhiteSpace(src, cursor+1)

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
stdjson "encoding/json"
"math" "math"
"math/rand" "math/rand"
"reflect" "reflect"
@ -81,9 +82,34 @@ func TestCompact(t *testing.T) {
} }
} }
t.Run("invalid", func(t *testing.T) { t.Run("invalid", func(t *testing.T) {
for _, src := range []string{
`invalid`,
`}`,
`]`,
`{"a":1}}`,
`{"a" 1}`,
`{"a": 1 "b": 2}`,
`["a" "b"]`,
`"\`,
`{"a":"\\""}`,
`tr`,
`{"a": tru, "b": 1}`,
`fal`,
`{"a": fals, "b": 1}`,
`nu`,
`{"a": nul, "b": 1}`,
`1.234.567`,
`[nul]`,
`{} 1`,
} {
buf.Reset() buf.Reset()
if err := json.Compact(&buf, []byte(`invalid`)); err == nil { if err := stdjson.Compact(&buf, []byte(src)); err == nil {
t.Fatal(err) t.Fatal("invalid test case")
}
buf.Reset()
if err := json.Compact(&buf, []byte(src)); err == nil {
t.Fatalf("%q: expected error", src)
}
} }
}) })
} }
@ -125,6 +151,37 @@ func TestIndent(t *testing.T) {
t.Errorf("Indent(%#q) = %#q, want %#q", tt.compact, s, tt.indent) t.Errorf("Indent(%#q) = %#q, want %#q", tt.compact, s, tt.indent)
} }
} }
t.Run("invalid", func(t *testing.T) {
for _, src := range []string{
`invalid`,
`}`,
`]`,
`{"a":1}}`,
`{"a" 1}`,
`{"a": 1 "b": 2}`,
`["a" "b"]`,
`"\`,
`{"a":"\\""}`,
`tr`,
`{"a": tru, "b": 1}`,
`fal`,
`{"a": fals, "b": 1}`,
`nu`,
`{"a": nul, "b": 1}`,
`1.234.567`,
`[nul]`,
`{} 1`,
} {
buf.Reset()
if err := stdjson.Indent(&buf, []byte(src), "", " "); err == nil {
t.Fatal("invalid test case")
}
buf.Reset()
if err := json.Indent(&buf, []byte(src), "", " "); err == nil {
t.Fatalf("%q: expected error", src)
}
}
})
} }
// Tests of a large random structure. // Tests of a large random structure.