Source file src/encoding/json/v2/errors_test.go

     1  // Copyright 2020 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build goexperiment.jsonv2
     6  
     7  package json
     8  
     9  import (
    10  	"archive/tar"
    11  	"bytes"
    12  	"errors"
    13  	"io"
    14  	"strings"
    15  	"testing"
    16  
    17  	"encoding/json/internal/jsonwire"
    18  	"encoding/json/jsontext"
    19  )
    20  
    21  func TestSemanticError(t *testing.T) {
    22  	tests := []struct {
    23  		err  error
    24  		want string
    25  	}{{
    26  		err:  &SemanticError{},
    27  		want: `json: cannot handle`,
    28  	}, {
    29  		err:  &SemanticError{JSONKind: 'n'},
    30  		want: `json: cannot handle JSON null`,
    31  	}, {
    32  		err:  &SemanticError{action: "unmarshal", JSONKind: 't'},
    33  		want: `json: cannot unmarshal JSON boolean`,
    34  	}, {
    35  		err:  &SemanticError{action: "unmarshal", JSONKind: 'x'},
    36  		want: `json: cannot unmarshal`, // invalid token kinds are ignored
    37  	}, {
    38  		err:  &SemanticError{action: "marshal", JSONKind: '"'},
    39  		want: `json: cannot marshal JSON string`,
    40  	}, {
    41  		err:  &SemanticError{GoType: T[bool]()},
    42  		want: `json: cannot handle Go bool`,
    43  	}, {
    44  		err:  &SemanticError{action: "marshal", GoType: T[int]()},
    45  		want: `json: cannot marshal from Go int`,
    46  	}, {
    47  		err:  &SemanticError{action: "unmarshal", GoType: T[uint]()},
    48  		want: `json: cannot unmarshal into Go uint`,
    49  	}, {
    50  		err:  &SemanticError{GoType: T[struct{ Alpha, Bravo, Charlie, Delta, Echo, Foxtrot, Golf, Hotel string }]()},
    51  		want: `json: cannot handle Go struct`,
    52  	}, {
    53  		err:  &SemanticError{GoType: T[struct{ Alpha, Bravo, Charlie, Delta, Echo, Foxtrot, Golf, Hotel, x string }]()},
    54  		want: `json: cannot handle Go v2.struct`,
    55  	}, {
    56  		err:  &SemanticError{JSONKind: '0', GoType: T[tar.Header]()},
    57  		want: `json: cannot handle JSON number with Go tar.Header`,
    58  	}, {
    59  		err:  &SemanticError{action: "unmarshal", JSONKind: '0', JSONValue: jsontext.Value(`1e1000`), GoType: T[int]()},
    60  		want: `json: cannot unmarshal JSON number 1e1000 into Go int`,
    61  	}, {
    62  		err:  &SemanticError{action: "marshal", JSONKind: '{', GoType: T[bytes.Buffer]()},
    63  		want: `json: cannot marshal JSON object from Go bytes.Buffer`,
    64  	}, {
    65  		err:  &SemanticError{action: "unmarshal", JSONKind: ']', GoType: T[strings.Reader]()},
    66  		want: `json: cannot unmarshal JSON array into Go strings.Reader`,
    67  	}, {
    68  		err:  &SemanticError{action: "unmarshal", JSONKind: '{', GoType: T[float64](), ByteOffset: 123},
    69  		want: `json: cannot unmarshal JSON object into Go float64 after offset 123`,
    70  	}, {
    71  		err:  &SemanticError{action: "marshal", JSONKind: 'f', GoType: T[complex128](), ByteOffset: 123, JSONPointer: "/foo/2/bar/3"},
    72  		want: `json: cannot marshal JSON boolean from Go complex128 within "/foo/2/bar/3"`,
    73  	}, {
    74  		err:  &SemanticError{action: "unmarshal", JSONKind: '}', GoType: T[io.Reader](), ByteOffset: 123, JSONPointer: "/foo/2/bar/3", Err: errors.New("some underlying error")},
    75  		want: `json: cannot unmarshal JSON object into Go io.Reader within "/foo/2/bar/3": some underlying error`,
    76  	}, {
    77  		err:  &SemanticError{Err: errors.New("some underlying error")},
    78  		want: `json: cannot handle: some underlying error`,
    79  	}, {
    80  		err:  &SemanticError{ByteOffset: 123},
    81  		want: `json: cannot handle after offset 123`,
    82  	}, {
    83  		err:  &SemanticError{JSONPointer: "/foo/2/bar/3"},
    84  		want: `json: cannot handle within "/foo/2/bar/3"`,
    85  	}, {
    86  		err:  &SemanticError{action: "unmarshal", JSONPointer: "/3", GoType: T[struct{ Fizz, Buzz string }](), Err: ErrUnknownName},
    87  		want: `json: cannot unmarshal into Go struct { Fizz string; Buzz string }: unknown object member name "3"`,
    88  	}, {
    89  		err:  &SemanticError{action: "unmarshal", JSONPointer: "/foo/2/bar/3", GoType: T[struct{ Foo string }](), Err: ErrUnknownName},
    90  		want: `json: cannot unmarshal into Go struct { Foo string }: unknown object member name "3" within "/foo/2/bar"`,
    91  	}, {
    92  		err:  &SemanticError{JSONPointer: "/foo/bar", ByteOffset: 16, GoType: T[string](), Err: &jsontext.SyntacticError{JSONPointer: "/foo/bar/baz", ByteOffset: 53, Err: jsonwire.ErrInvalidUTF8}},
    93  		want: `json: cannot handle Go string: invalid UTF-8 within "/foo/bar/baz" after offset 53`,
    94  	}, {
    95  		err:  &SemanticError{JSONPointer: "/fizz/bar", ByteOffset: 16, GoType: T[string](), Err: &jsontext.SyntacticError{JSONPointer: "/foo/bar/baz", ByteOffset: 53, Err: jsonwire.ErrInvalidUTF8}},
    96  		want: `json: cannot handle Go string within "/fizz/bar": invalid UTF-8 within "/foo/bar/baz" after offset 53`,
    97  	}, {
    98  		err:  &SemanticError{ByteOffset: 16, GoType: T[string](), Err: &jsontext.SyntacticError{JSONPointer: "/foo/bar/baz", ByteOffset: 53, Err: jsonwire.ErrInvalidUTF8}},
    99  		want: `json: cannot handle Go string: invalid UTF-8 within "/foo/bar/baz" after offset 53`,
   100  	}, {
   101  		err:  &SemanticError{ByteOffset: 85, GoType: T[string](), Err: &jsontext.SyntacticError{JSONPointer: "/foo/bar/baz", ByteOffset: 53, Err: jsonwire.ErrInvalidUTF8}},
   102  		want: `json: cannot handle Go string after offset 85: invalid UTF-8 within "/foo/bar/baz" after offset 53`,
   103  	}}
   104  
   105  	for _, tt := range tests {
   106  		got := tt.err.Error()
   107  		// Cleanup the error of non-deterministic rendering effects.
   108  		if strings.HasPrefix(got, errorPrefix+"unable to ") {
   109  			got = errorPrefix + "cannot " + strings.TrimPrefix(got, errorPrefix+"unable to ")
   110  		}
   111  		if got != tt.want {
   112  			t.Errorf("%#v.Error mismatch:\ngot  %v\nwant %v", tt.err, got, tt.want)
   113  		}
   114  	}
   115  }
   116  

View as plain text