Add indent test

This commit is contained in:
Masaaki Goshima 2021-03-09 21:38:58 +09:00
parent 1657b0e50e
commit d42d09f9f9
16 changed files with 4563 additions and 3391 deletions

View File

@ -1838,7 +1838,7 @@ func TestCoverArray(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer var buf bytes.Buffer
enc := json.NewEncoder(&buf) enc := json.NewEncoder(&buf)

View File

@ -1774,11 +1774,11 @@ func TestCoverBool(t *testing.T) {
enc.SetIndent("", " ") enc.SetIndent("", " ")
} }
if err := enc.Encode(test.data); err != nil { if err := enc.Encode(test.data); err != nil {
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err) t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
} }
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
if buf.String() != stdresult { if buf.String() != stdresult {
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
} }
} }
} }

View File

@ -1765,7 +1765,7 @@ func TestCoverInt(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer var buf bytes.Buffer
enc := json.NewEncoder(&buf) enc := json.NewEncoder(&buf)

View File

@ -1838,7 +1838,7 @@ func TestCoverMap(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer var buf bytes.Buffer
enc := json.NewEncoder(&buf) enc := json.NewEncoder(&buf)

View File

@ -3525,7 +3525,7 @@ func TestCoverMarshalJSON(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer var buf bytes.Buffer
enc := json.NewEncoder(&buf) enc := json.NewEncoder(&buf)

View File

@ -3525,7 +3525,7 @@ func TestCoverMarshalText(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer var buf bytes.Buffer
enc := json.NewEncoder(&buf) enc := json.NewEncoder(&buf)

View File

@ -1838,7 +1838,7 @@ func TestCoverSlice(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer var buf bytes.Buffer
enc := json.NewEncoder(&buf) enc := json.NewEncoder(&buf)

View File

@ -1793,11 +1793,11 @@ func TestCoverString(t *testing.T) {
enc.SetIndent("", " ") enc.SetIndent("", " ")
} }
if err := enc.Encode(test.data); err != nil { if err := enc.Encode(test.data); err != nil {
t.Fatalf("%s(htmlEscape:%T): %v: %s", test.name, htmlEscape, test.data, err) t.Fatalf("%s(htmlEscape:%v,indent:%v): %v: %s", test.name, htmlEscape, indent, test.data, err)
} }
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
if buf.String() != stdresult { if buf.String() != stdresult {
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
} }
} }
} }

View File

@ -1774,11 +1774,11 @@ func TestCoverUint16(t *testing.T) {
enc.SetIndent("", " ") enc.SetIndent("", " ")
} }
if err := enc.Encode(test.data); err != nil { if err := enc.Encode(test.data); err != nil {
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err) t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
} }
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
if buf.String() != stdresult { if buf.String() != stdresult {
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
} }
} }
} }

View File

@ -9,6 +9,7 @@ import (
"math" "math"
"reflect" "reflect"
"strconv" "strconv"
"strings"
"sync" "sync"
"unsafe" "unsafe"
) )
@ -385,6 +386,33 @@ func encodeMarshalJSON(b []byte, v interface{}) ([]byte, error) {
return buf.Bytes(), nil return buf.Bytes(), nil
} }
func encodeMarshalJSONIndent(ctx *encodeRuntimeContext, b []byte, v interface{}, indent int) ([]byte, error) {
bb, err := v.(Marshaler).MarshalJSON()
if err != nil {
return nil, &MarshalerError{Type: reflect.TypeOf(v), Err: err}
}
if len(bb) == 0 {
return nil, errUnexpectedEndOfJSON(
fmt.Sprintf("error calling MarshalJSON for type %s", reflect.TypeOf(v)),
0,
)
}
var compactBuf bytes.Buffer
if err := compact(&compactBuf, bb, false); err != nil {
return nil, err
}
var indentBuf bytes.Buffer
if err := encodeWithIndent(
&indentBuf,
compactBuf.Bytes(),
string(ctx.prefix)+strings.Repeat(string(ctx.indentStr), ctx.baseIndent+indent),
string(ctx.indentStr),
); err != nil {
return nil, err
}
return append(b, indentBuf.Bytes()...), nil
}
func encodeMarshalText(b []byte, v interface{}) ([]byte, error) { func encodeMarshalText(b []byte, v interface{}) ([]byte, error) {
bytes, err := v.(encoding.TextMarshaler).MarshalText() bytes, err := v.(encoding.TextMarshaler).MarshalText()
if err != nil { if err != nil {
@ -392,3 +420,11 @@ func encodeMarshalText(b []byte, v interface{}) ([]byte, error) {
} }
return encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))), nil return encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))), nil
} }
func encodeMarshalTextIndent(b []byte, v interface{}) ([]byte, error) {
bytes, err := v.(encoding.TextMarshaler).MarshalText()
if err != nil {
return nil, &MarshalerError{Type: reflect.TypeOf(v), Err: err}
}
return encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))), nil
}

View File

@ -1327,6 +1327,7 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
} }
if field.Anonymous { if field.Anonymous {
valueCode.anonymousHead = true valueCode.anonymousHead = true
valueCode.decIndent()
} }
key := fmt.Sprintf(`"%s":`, tag.key) key := fmt.Sprintf(`"%s":`, tag.key)
escapedKey := fmt.Sprintf(`%s:`, string(encodeEscapedString([]byte{}, tag.key))) escapedKey := fmt.Sprintf(`%s:`, string(encodeEscapedString([]byte{}, tag.key)))

View File

@ -178,6 +178,18 @@ func (c *opcode) decOpcodeIndex() {
} }
} }
func (c *opcode) decIndent() {
for code := c; code.op != opEnd; {
code.indent--
switch code.op.codeType() {
case codeArrayElem, codeSliceElem, codeMapKey:
code = code.end
default:
code = code.next
}
}
}
func (c *opcode) dumpHead(code *opcode) string { func (c *opcode) dumpHead(code *opcode) string {
var length uintptr var length uintptr
if code.op.codeType() == codeArrayHead { if code.op.codeType() == codeArrayHead {
@ -412,6 +424,7 @@ func newArrayElemCode(ctx *encodeCompileContext, head *opcode, length int, size
elemIdx: head.elemIdx, elemIdx: head.elemIdx,
headIdx: head.headIdx, headIdx: head.headIdx,
length: uintptr(length), length: uintptr(length),
indent: ctx.indent,
size: size, size: size,
} }
} }

View File

@ -240,7 +240,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
case opSliceHead: case opSliceHead:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
slice := ptrToSlice(p) slice := ptrToSlice(p)
if p == 0 || uintptr(slice.data) == 0 { if p == 0 || slice.data == nil {
b = encodeNull(b) b = encodeNull(b)
b = encodeComma(b) b = encodeComma(b)
code = code.end.next code = code.end.next
@ -1723,7 +1723,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
fallthrough fallthrough
case opStructFieldHeadBoolPtr: case opStructFieldHeadBoolPtr:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 && code.indirect {
if !code.anonymousHead { if !code.anonymousHead {
b = encodeNull(b) b = encodeNull(b)
b = encodeComma(b) b = encodeComma(b)
@ -1759,7 +1759,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
fallthrough fallthrough
case opStructFieldHeadOmitEmptyBoolPtr: case opStructFieldHeadOmitEmptyBoolPtr:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 && code.indirect {
if !code.anonymousHead { if !code.anonymousHead {
b = encodeNull(b) b = encodeNull(b)
b = encodeComma(b) b = encodeComma(b)
@ -1793,7 +1793,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
fallthrough fallthrough
case opStructFieldHeadStringTagBoolPtr: case opStructFieldHeadStringTagBoolPtr:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 && code.indirect {
if !code.anonymousHead { if !code.anonymousHead {
b = encodeNull(b) b = encodeNull(b)
b = encodeComma(b) b = encodeComma(b)
@ -3349,15 +3349,15 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
} }
case opStructFieldSlice, opStructFieldStringTagSlice: case opStructFieldSlice, opStructFieldStringTagSlice:
b = append(b, code.key...) b = append(b, code.key...)
ptr := load(ctxptr, code.headIdx) p := load(ctxptr, code.headIdx)
p := ptr + code.offset p += code.offset
code = code.next code = code.next
store(ctxptr, code.idx, p) store(ctxptr, code.idx, p)
case opStructFieldOmitEmptySlice: case opStructFieldOmitEmptySlice:
ptr := load(ctxptr, code.headIdx) p := load(ctxptr, code.headIdx)
p := ptr + code.offset p += code.offset
slice := ptrToSlice(p) slice := ptrToSlice(p)
if p == 0 || uintptr(slice.data) == 0 { if p == 0 || slice.data == nil {
code = code.nextField code = code.nextField
} else { } else {
b = append(b, code.key...) b = append(b, code.key...)

View File

@ -1665,7 +1665,7 @@ func encodeRunEscaped(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, o
fallthrough fallthrough
case opStructFieldHeadBoolPtr: case opStructFieldHeadBoolPtr:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 && code.indirect {
if !code.anonymousHead { if !code.anonymousHead {
b = encodeNull(b) b = encodeNull(b)
b = encodeComma(b) b = encodeComma(b)
@ -1701,7 +1701,7 @@ func encodeRunEscaped(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, o
fallthrough fallthrough
case opStructFieldHeadOmitEmptyBoolPtr: case opStructFieldHeadOmitEmptyBoolPtr:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 && code.indirect {
if !code.anonymousHead { if !code.anonymousHead {
b = encodeNull(b) b = encodeNull(b)
b = encodeComma(b) b = encodeComma(b)
@ -1735,7 +1735,7 @@ func encodeRunEscaped(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, o
fallthrough fallthrough
case opStructFieldHeadStringTagBoolPtr: case opStructFieldHeadStringTagBoolPtr:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 && code.indirect {
if !code.anonymousHead { if !code.anonymousHead {
b = encodeNull(b) b = encodeNull(b)
b = encodeComma(b) b = encodeComma(b)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff