Repository: goccy/go-yaml
Pull request #293 (2022-04-29 17:39:27)

Fix large literals type inference on 32 bits
Some tests are failing because some large literal integers are meant to be stored on 64 bits, but are stored on 32 on 32 bits architectures. This causes the value to overflow:
```
# github.com/goccy/go-yaml_test [github.com/goccy/go-yaml.test]
./decode_test.go:92:32: cannot use -9223372036854775808 (untyped int constant) as int value in map literal (overflows)
./decode_test.go:112:24: cannot use 4294967296 (untyped int constant) as int value in map literal (overflows)
./encode_test.go:68:24: cannot use 4294967296 (untyped int constant) as int value in map literal (overflows)
```

This commit fixes this issue by using explicit int64 typing.

goccy: Could you fix it with a type cast without using temporary variables ?
codecov-commenter: # [Codecov](https://codecov.io/gh/goccy/go-yaml/pull/293?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Masaaki+Goshima) Report
> Merging [#293](https://codecov.io/gh/goccy/go-yaml/pull/293?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Masaaki+Goshima) (b4fe0c2) into [master](https://codecov.io/gh/goccy/go-yaml/commit/e4f32a26722ce33ac79a7b4ad88c26fd0b9c2995?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Masaaki+Goshima) (e4f32a2) will **not change** coverage.
> The diff coverage is `n/a`.


```diff
@@           Coverage Diff           @@
##           master     #293   +/-   ##
=======================================
  Coverage   75.93%   75.93%           
=======================================
  Files          13       13           
  Lines        4305     4305           
=======================================
  Hits         3269     3269           
  Misses        799      799           
  Partials      237      237           
```


Patch:
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index 324c9e8..6db01ec 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -10,7 +10,7 @@ jobs:
     strategy:
       matrix:
         os: [ "ubuntu-latest", "macos-latest", "windows-latest" ]
-        go-version: [ "1.16", "1.17", "1.18" ]
+        go-version: [ "1.15", "1.16", "1.17" ]
     runs-on: ${{ matrix.os }}
     steps:
     - name: setup Go ${{ matrix.go-version }}
@@ -29,7 +29,7 @@ jobs:
       - name: setup Go
         uses: actions/setup-go@v2
         with:
-          go-version: 1.18
+          go-version: 1.17
       - name: checkout
         uses: actions/checkout@v2
       - name: build
@@ -46,7 +46,7 @@ jobs:
       - name: setup Go
         uses: actions/setup-go@v2
         with:
-          go-version: 1.18
+          go-version: 1.17
       - name: checkout
         uses: actions/checkout@v2
       - name: measure coverage
diff --git a/ast/ast.go b/ast/ast.go
index 415fad4..fa3e5e0 100644
--- a/ast/ast.go
+++ b/ast/ast.go
@@ -266,7 +266,7 @@ func readNode(p []byte, node Node) (int, error) {
 		return 0, io.EOF
 	}
 	size := min(remain, len(p))
-	for idx, b := range []byte(s[readLen : readLen+size]) {
+	for idx, b := range s[readLen : readLen+size] {
 		p[idx] = byte(b)
 	}
 	node.addReadLen(size)
diff --git a/decode.go b/decode.go
index d519b78..5d1f63a 100644
--- a/decode.go
+++ b/decode.go
@@ -367,10 +367,10 @@ func (d *Decoder) fileToNode(f *ast.File) ast.Node {
 	return nil
 }
 
-func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type, src ast.Node) (reflect.Value, error) {
+func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type) (reflect.Value, error) {
 	if typ.Kind() != reflect.String {
 		if !v.Type().ConvertibleTo(typ) {
-			return reflect.Zero(typ), errTypeMismatch(typ, v.Type(), src.GetToken())
+			return reflect.Zero(typ), errTypeMismatch(typ, v.Type())
 		}
 		return v.Convert(typ), nil
 	}
@@ -386,7 +386,7 @@ func (d *Decoder) convertValue(v reflect.Value, typ reflect.Type, src ast.Node)
 		return reflect.ValueOf(fmt.Sprint(v.Bool())), nil
 	}
 	if !v.Type().ConvertibleTo(typ) {
-		return reflect.Zero(typ), errTypeMismatch(typ, v.Type(), src.GetToken())
+		return reflect.Zero(typ), errTypeMismatch(typ, v.Type())
 	}
 	return v.Convert(typ), nil
 }
@@ -404,8 +404,21 @@ func errOverflow(dstType reflect.Type, num string) *overflowError {
 	return &overflowError{dstType: dstType, srcNum: num}
 }
 
-func errTypeMismatch(dstType, srcType reflect.Type, token *token.Token) *errors.TypeError {
-	return &errors.TypeError{DstType: dstType, SrcType: srcType, Token: token}
+type typeError struct {
+	dstType         reflect.Type
+	srcType         reflect.Type
+	structFieldName *string
+}
+
+func (e *typeError) Error() string {
+	if e.structFieldName != nil {
+		return fmt.Sprintf("cannot unmarshal %s into Go struct field %s of type %s", e.srcType, *e.structFieldName, e.dstType)
+	}
+	return fmt.Sprintf("cannot unmarshal %s into Go value of type %s", e.srcType, e.dstType)
+}
+
+func errTypeMismatch(dstType, srcType reflect.Type) *typeError {
+	return &typeError{dstType: dstType, srcType: srcType}
 }
 
 type unknownFieldError struct {
@@ -696,7 +709,7 @@ func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.No
 				return nil
 			}
 		default:
-			return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken())
+			return errTypeMismatch(valueType, reflect.TypeOf(v))
 		}
 		return errOverflow(valueType, fmt.Sprint(v))
 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
@@ -718,13 +731,13 @@ func (d *Decoder) decodeValue(ctx context.Context, dst reflect.Value, src ast.No
 				return nil
 			}
 		default:
-			return errTypeMismatch(valueType, reflect.TypeOf(v), src.GetToken())
+			return errTypeMismatch(valueType, reflect.TypeOf(v))
 		}
 		return errOverflow(valueType, fmt.Sprint(v))
 	}
 	v := reflect.ValueOf(d.nodeToValue(src))
 	if v.IsValid() {
-		convertedValue, err := d.convertValue(v, dst.Type(), src)
+		convertedValue, err := d.convertValue(v, dst.Type())
 		if err != nil {
 			return errors.Wrapf(err, "failed to convert value")
 		}
@@ -892,7 +905,7 @@ func (d *Decoder) castToTime(src ast.Node) (time.Time, error) {
 	}
 	s, ok := v.(string)
 	if !ok {
-		return time.Time{}, errTypeMismatch(reflect.TypeOf(time.Time{}), reflect.TypeOf(v), src.GetToken())
+		return time.Time{}, errTypeMismatch(reflect.TypeOf(time.Time{}), reflect.TypeOf(v))
 	}
 	for _, format := range allowedTimestampFormats {
 		t, err := time.Parse(format, s)
@@ -924,7 +937,7 @@ func (d *Decoder) castToDuration(src ast.Node) (time.Duration, error) {
 	}
 	s, ok := v.(string)
 	if !ok {
-		return 0, errTypeMismatch(reflect.TypeOf(time.Duration(0)), reflect.TypeOf(v), src.GetToken())
+		return 0, errTypeMismatch(reflect.TypeOf(time.Duration(0)), reflect.TypeOf(v))
 	}
 	t, err := time.ParseDuration(s)
 	if err != nil {
@@ -1039,14 +1052,14 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N
 				if foundErr != nil {
 					continue
 				}
-				var te *errors.TypeError
+				var te *typeError
 				if xerrors.As(err, &te) {
-					if te.StructFieldName != nil {
-						fieldName := fmt.Sprintf("%s.%s", structType.Name(), *te.StructFieldName)
-						te.StructFieldName = &fieldName
+					if te.structFieldName != nil {
+						fieldName := fmt.Sprintf("%s.%s", structType.Name(), *te.structFieldName)
+						te.structFieldName = &fieldName
 					} else {
 						fieldName := fmt.Sprintf("%s.%s", structType.Name(), field.Name)
-						te.StructFieldName = &fieldName
+						te.structFieldName = &fieldName
 					}
 					foundErr = te
 					continue
@@ -1075,10 +1088,10 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N
 			if foundErr != nil {
 				continue
 			}
-			var te *errors.TypeError
+			var te *typeError
 			if xerrors.As(err, &te) {
 				fieldName := fmt.Sprintf("%s.%s", structType.Name(), field.Name)
-				te.StructFieldName = &fieldName
+				te.structFieldName = &fieldName
 				foundErr = te
 			} else {
 				foundErr = err
diff --git a/go.mod b/go.mod
index 3356ece..4d99408 100644
--- a/go.mod
+++ b/go.mod
@@ -6,6 +6,5 @@ require (
 	github.com/fatih/color v1.10.0
 	github.com/go-playground/validator/v10 v10.4.1
 	github.com/mattn/go-colorable v0.1.8
-	golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 // indirect
 	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
 )
diff --git a/go.sum b/go.sum
index 112c438..8ce2a41 100644
--- a/go.sum
+++ b/go.sum
@@ -30,8 +30,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
 golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12 h1:QyVthZKMsyaQwBTJE04jdNN0Pp5Fn9Qga0mrgxyERQM=
-golang.org/x/sys v0.0.0-20220406163625-3f8b81556e12/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/internal/errors/error.go b/internal/errors/error.go
index 7f1ea9a..c7b1103 100644
--- a/internal/errors/error.go
+++ b/internal/errors/error.go
@@ -3,7 +3,6 @@ package errors
 import (
 	"bytes"
 	"fmt"
-	"reflect"
 
 	"github.com/goccy/go-yaml/printer"
 	"github.com/goccy/go-yaml/token"
@@ -68,10 +67,10 @@ type wrapError struct {
 	frame   xerrors.Frame
 }
 
-type FormatErrorPrinter struct {
+type myprinter struct {
 	xerrors.Printer
-	Colored    bool
-	InclSource bool
+	colored    bool
+	inclSource bool
 }
 
 func (e *wrapError) As(target interface{}) bool {
@@ -91,15 +90,15 @@ func (e *wrapError) Unwrap() error {
 }
 
 func (e *wrapError) PrettyPrint(p xerrors.Printer, colored, inclSource bool) error {
-	return e.FormatError(&FormatErrorPrinter{Printer: p, Colored: colored, InclSource: inclSource})
+	return e.FormatError(&myprinter{Printer: p, colored: colored, inclSource: inclSource})
 }
 
 func (e *wrapError) FormatError(p xerrors.Printer) error {
-	if _, ok := p.(*FormatErrorPrinter); !ok {
-		p = &FormatErrorPrinter{
+	if _, ok := p.(*myprinter); !ok {
+		p = &myprinter{
 			Printer:    p,
-			Colored:    defaultColorize,
-			InclSource: defaultIncludeSource,
+			colored:    defaultColorize,
+			inclSource: defaultIncludeSource,
 		}
 	}
 	if e.verb == 'v' && e.state.Flag('+') {
@@ -172,16 +171,16 @@ type syntaxError struct {
 }
 
 func (e *syntaxError) PrettyPrint(p xerrors.Printer, colored, inclSource bool) error {
-	return e.FormatError(&FormatErrorPrinter{Printer: p, Colored: colored, InclSource: inclSource})
+	return e.FormatError(&myprinter{Printer: p, colored: colored, inclSource: inclSource})
 }
 
 func (e *syntaxError) FormatError(p xerrors.Printer) error {
 	var pp printer.Printer
 
 	var colored, inclSource bool
-	if fep, ok := p.(*FormatErrorPrinter); ok {
-		colored = fep.Colored
-		inclSource = fep.InclSource
+	if mp, ok := p.(*myprinter); ok {
+		colored = mp.colored
+		inclSource = mp.inclSource
 	}
 
 	pos := fmt.Sprintf("[%d:%d] ", e.token.Position.Line, e.token.Position.Column)
@@ -221,40 +220,3 @@ func (e *syntaxError) Error() string {
 	e.PrettyPrint(&Sink{&buf}, defaultColorize, defaultIncludeSource)
 	return buf.String()
 }
-
-type TypeError struct {
-	DstType         reflect.Type
-	SrcType         reflect.Type
-	StructFieldName *string
-	Token           *token.Token
-}
-
-func (e *TypeError) Error() string {
-	if e.StructFieldName != nil {
-		return fmt.Sprintf("cannot unmarshal %s into Go struct field %s of type %s", e.SrcType, *e.StructFieldName, e.DstType)
-	}
-	return fmt.Sprintf("cannot unmarshal %s into Go value of type %s", e.SrcType, e.DstType)
-}
-
-func (e *TypeError) PrettyPrint(p xerrors.Printer, colored, inclSource bool) error {
-	return e.FormatError(&FormatErrorPrinter{Printer: p, Colored: colored, InclSource: inclSource})
-}
-
-func (e *TypeError) FormatError(p xerrors.Printer) error {
-	var pp printer.Printer
-
-	var colored, inclSource bool
-	if fep, ok := p.(*FormatErrorPrinter); ok {
-		colored = fep.Colored
-		inclSource = fep.InclSource
-	}
-
-	pos := fmt.Sprintf("[%d:%d] ", e.Token.Position.Line, e.Token.Position.Column)
-	msg := pp.PrintErrorMessage(fmt.Sprintf("%s%s", pos, e.Error()), colored)
-	if inclSource {
-		msg += "\n" + pp.PrintErrorToken(e.Token, colored)
-	}
-	p.Print(msg)
-
-	return nil
-}
diff --git a/token/token.go b/token/token.go
index 796b522..f46730b 100644
--- a/token/token.go
+++ b/token/token.go
@@ -12,41 +12,41 @@ const (
 	// SequenceEntryCharacter character for sequence entry
 	SequenceEntryCharacter Character = '-'
 	// MappingKeyCharacter character for mapping key
-	MappingKeyCharacter Character = '?'
+	MappingKeyCharacter = '?'
 	// MappingValueCharacter character for mapping value
-	MappingValueCharacter Character = ':'
+	MappingValueCharacter = ':'
 	// CollectEntryCharacter character for collect entry
-	CollectEntryCharacter Character = ','
+	CollectEntryCharacter = ','
 	// SequenceStartCharacter character for sequence start
-	SequenceStartCharacter Character = '['
+	SequenceStartCharacter = '['
 	// SequenceEndCharacter character for sequence end
-	SequenceEndCharacter Character = ']'
+	SequenceEndCharacter = ']'
 	// MappingStartCharacter character for mapping start
-	MappingStartCharacter Character = '{'
+	MappingStartCharacter = '{'
 	// MappingEndCharacter character for mapping end
-	MappingEndCharacter Character = '}'
+	MappingEndCharacter = '}'
 	// CommentCharacter character for comment
-	CommentCharacter Character = '#'
+	CommentCharacter = '#'
 	// AnchorCharacter character for anchor
-	AnchorCharacter Character = '&'
+	AnchorCharacter = '&'
 	// AliasCharacter character for alias
-	AliasCharacter Character = '*'
+	AliasCharacter = '*'
 	// TagCharacter character for tag
-	TagCharacter Character = '!'
+	TagCharacter = '!'
 	// LiteralCharacter character for literal
-	LiteralCharacter Character = '|'
+	LiteralCharacter = '|'
 	// FoldedCharacter character for folded
-	FoldedCharacter Character = '>'
+	FoldedCharacter = '>'
 	// SingleQuoteCharacter character for single quote
-	SingleQuoteCharacter Character = '\''
+	SingleQuoteCharacter = '\''
 	// DoubleQuoteCharacter character for double quote
-	DoubleQuoteCharacter Character = '"'
+	DoubleQuoteCharacter = '"'
 	// DirectiveCharacter character for directive
-	DirectiveCharacter Character = '%'
+	DirectiveCharacter = '%'
 	// SpaceCharacter character for space
-	SpaceCharacter Character = ' '
+	SpaceCharacter = ' '
 	// LineBreakCharacter character for line break
-	LineBreakCharacter Character = '\n'
+	LineBreakCharacter = '\n'
 )
 
 // Type type identifier for token


Test patch:
diff --git a/ast/ast_test.go b/ast/ast_test.go
index e7022b6..5e5b37e 100644
--- a/ast/ast_test.go
+++ b/ast/ast_test.go
@@ -1,10 +1,6 @@
 package ast
 
-import (
-	"testing"
-
-	"github.com/goccy/go-yaml/token"
-)
+import "testing"
 
 func TestEscapeSingleQuote(t *testing.T) {
 	expected := `'Victor''s victory'`
@@ -13,24 +9,3 @@ func TestEscapeSingleQuote(t *testing.T) {
 		t.Fatalf("expected:%s\ngot:%s", expected, got)
 	}
 }
-
-func TestReadNode(t *testing.T) {
-	t.Run("utf-8", func(t *testing.T) {
-		value := "éɛทᛞ⠻チ▓🦄"
-		node := &StringNode{
-			BaseNode: &BaseNode{},
-			Token:    &token.Token{},
-			Value:    value,
-		}
-		expectedSize := len(value)
-		gotBuffer := make([]byte, expectedSize)
-		expectedBuffer := []byte(value)
-		gotSize, _ := readNode(gotBuffer, node)
-		if gotSize != expectedSize {
-			t.Fatalf("expected size:%d\ngot:%d", expectedSize, gotSize)
-		}
-		if string(gotBuffer) != string(expectedBuffer) {
-			t.Fatalf("expected buffer:%s\ngot:%s", expectedBuffer, gotBuffer)
-		}
-	})
-}
diff --git a/decode_test.go b/decode_test.go
index 4d93f1f..555bcaa 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -89,7 +89,7 @@ func TestDecoder(t *testing.T) {
 		},
 		{
 			"v: -0b1000000000000000000000000000000000000000000000000000000000000000",
-			map[string]interface{}{"v": -9223372036854775808},
+			map[string]interface{}{"v": int64(-9223372036854775808)},
 		},
 		{
 			"v: 0xA",
@@ -109,7 +109,7 @@ func TestDecoder(t *testing.T) {
 		},
 		{
 			"v: 4294967296\n",
-			map[string]int{"v": 4294967296},
+			map[string]int64{"v": int64(4294967296)},
 		},
 		{
 			"v: 0.1\n",
@@ -200,7 +200,7 @@ func TestDecoder(t *testing.T) {
 			map[string]uint{"v": 42},
 		}, {
 			"v: 4294967296",
-			map[string]uint64{"v": 4294967296},
+			map[string]uint64{"v": uint64(4294967296)},
 		},
 
 		// int
@@ -1074,8 +1074,8 @@ func TestDecoder_TypeConversionError(t *testing.T) {
 				t.Fatal("expected to error")
 			}
 			msg := "cannot unmarshal string into Go struct field T.A of type int"
-			if !strings.Contains(err.Error(), msg) {
-				t.Fatalf("expected error message: %s to contain: %s", err.Error(), msg)
+			if err.Error() != msg {
+				t.Fatalf("unexpected error message: %s. expect: %s", err.Error(), msg)
 			}
 		})
 		t.Run("string to bool", func(t *testing.T) {
@@ -1085,8 +1085,8 @@ func TestDecoder_TypeConversionError(t *testing.T) {
 				t.Fatal("expected to error")
 			}
 			msg := "cannot unmarshal string into Go struct field T.D of type bool"
-			if !strings.Contains(err.Error(), msg) {
-				t.Fatalf("expected error message: %s to contain: %s", err.Error(), msg)
+			if err.Error() != msg {
+				t.Fatalf("unexpected error message: %s. expect: %s", err.Error(), msg)
 			}
 		})
 		t.Run("string to int at inline", func(t *testing.T) {
@@ -1096,8 +1096,8 @@ func TestDecoder_TypeConversionError(t *testing.T) {
 				t.Fatal("expected to error")
 			}
 			msg := "cannot unmarshal string into Go struct field U.T.A of type int"
-			if !strings.Contains(err.Error(), msg) {
-				t.Fatalf("expected error message: %s to contain: %s", err.Error(), msg)
+			if err.Error() != msg {
+				t.Fatalf("unexpected error message: %s. expect: %s", err.Error(), msg)
 			}
 		})
 	})
@@ -1109,8 +1109,8 @@ func TestDecoder_TypeConversionError(t *testing.T) {
 				t.Fatal("expected to error")
 			}
 			msg := "cannot unmarshal string into Go value of type int"
-			if !strings.Contains(err.Error(), msg) {
-				t.Fatalf("expected error message: %s to contain: %s", err.Error(), msg)
+			if err.Error() != msg {
+				t.Fatalf("unexpected error message: %s. expect: %s", err.Error(), msg)
 			}
 			if len(v) == 0 || len(v["v"]) == 0 {
 				t.Fatal("failed to decode value")
@@ -1126,8 +1126,8 @@ func TestDecoder_TypeConversionError(t *testing.T) {
 				t.Fatal("expected to error")
 			}
 			msg := "cannot unmarshal string into Go value of type int"
-			if !strings.Contains(err.Error(), msg) {
-				t.Fatalf("expected error message: %s to contain: %s", err.Error(), msg)
+			if err.Error() != msg {
+				t.Fatalf("unexpected error message: %s. expect: %s", err.Error(), msg)
 			}
 			if len(v) == 0 || len(v["v"]) == 0 {
 				t.Fatal("failed to decode value")
@@ -1145,8 +1145,8 @@ func TestDecoder_TypeConversionError(t *testing.T) {
 				t.Fatal("expected to error")
 			}
 			msg := "cannot unmarshal -42 into Go value of type uint ( overflow )"
-			if !strings.Contains(err.Error(), msg) {
-				t.Fatalf("expected error message: %s to contain: %s", err.Error(), msg)
+			if err.Error() != msg {
+				t.Fatalf("unexpected error message: %s. expect: %s", err.Error(), msg)
 			}
 			if v["v"] != 0 {
 				t.Fatal("failed to decode value")
@@ -1159,8 +1159,8 @@ func TestDecoder_TypeConversionError(t *testing.T) {
 				t.Fatal("expected to error")
 			}
 			msg := "cannot unmarshal -4294967296 into Go value of type uint64 ( overflow )"
-			if !strings.Contains(err.Error(), msg) {
-				t.Fatalf("expected error message: %s to contain: %s", err.Error(), msg)
+			if err.Error() != msg {
+				t.Fatalf("unexpected error message: %s. expect: %s", err.Error(), msg)
 			}
 			if v["v"] != 0 {
 				t.Fatal("failed to decode value")
@@ -1173,8 +1173,8 @@ func TestDecoder_TypeConversionError(t *testing.T) {
 				t.Fatal("expected to error")
 			}
 			msg := "cannot unmarshal 4294967297 into Go value of type int32 ( overflow )"
-			if !strings.Contains(err.Error(), msg) {
-				t.Fatalf("expected error message: %s to contain: %s", err.Error(), msg)
+			if err.Error() != msg {
+				t.Fatalf("unexpected error message: %s. expect: %s", err.Error(), msg)
 			}
 			if v["v"] != 0 {
 				t.Fatal("failed to decode value")
@@ -1187,8 +1187,8 @@ func TestDecoder_TypeConversionError(t *testing.T) {
 				t.Fatal("expected to error")
 			}
 			msg := "cannot unmarshal 128 into Go value of type int8 ( overflow )"
-			if !strings.Contains(err.Error(), msg) {
-				t.Fatalf("expected error message: %s to contain: %s", err.Error(), msg)
+			if err.Error() != msg {
+				t.Fatalf("unexpected error message: %s. expect: %s", err.Error(), msg)
 			}
 			if v["v"] != 0 {
 				t.Fatal("failed to decode value")
@@ -1207,8 +1207,8 @@ func TestDecoder_TypeConversionError(t *testing.T) {
 				t.Fatal("expected to error")
 			}
 			msg := "cannot unmarshal uint64 into Go struct field T.A of type time.Time"
-			if !strings.Contains(err.Error(), msg) {
-				t.Fatalf("expected error message: %s to contain: %s", err.Error(), msg)
+			if err.Error() != msg {
+				t.Fatalf("unexpected error message: %s. expect: %s", err.Error(), msg)
 			}
 		})
 		t.Run("string to duration", func(t *testing.T) {
@@ -1218,8 +1218,8 @@ func TestDecoder_TypeConversionError(t *testing.T) {
 				t.Fatal("expected to error")
 			}
 			msg := `time: invalid duration "str"`
-			if !strings.Contains(err.Error(), msg) {
-				t.Fatalf("expected error message: %s to contain: %s", err.Error(), msg)
+			if err.Error() != msg {
+				t.Fatalf("unexpected error message: %s. expect: %s", err.Error(), msg)
 			}
 		})
 		t.Run("int to duration", func(t *testing.T) {
@@ -1229,8 +1229,8 @@ func TestDecoder_TypeConversionError(t *testing.T) {
 				t.Fatal("expected to error")
 			}
 			msg := "cannot unmarshal uint64 into Go struct field T.B of type time.Duration"
-			if !strings.Contains(err.Error(), msg) {
-				t.Fatalf("expected error message: %s to contain: %s", err.Error(), msg)
+			if err.Error() != msg {
+				t.Fatalf("unexpected error message: %s. expect: %s", err.Error(), msg)
 			}
 		})
 	})
diff --git a/encode_test.go b/encode_test.go
index 0a6f1fe..2edb9a2 100644
--- a/encode_test.go
+++ b/encode_test.go
@@ -65,7 +65,7 @@ func TestEncoder(t *testing.T) {
 		},
 		{
 			"v: 4294967296\n",
-			map[string]int{"v": 4294967296},
+			map[string]int64{"v": int64(4294967296)},
 			nil,
 		},
 		{
diff --git a/path_test.go b/path_test.go
index f6aac6d..c1ea183 100644
--- a/path_test.go
+++ b/path_test.go
@@ -281,19 +281,19 @@ func TestPath_Merge(t *testing.T) {
 		expected string
 	}{
 		{
-			path: "$.c",
-			dst: `
+			"$.c",
+			`
 a: 1
 b: 2
 c:
   d: 3
   e: 4
 `,
-			src: `
+			`
 f: 5
 g: 6
 `,
-			expected: `
+			`
 a: 1
 b: 2
 c:
@@ -304,20 +304,20 @@ c:
 `,
 		},
 		{
-			path: "$.a.b",
-			dst: `
+			"$.a.b",
+			`
 a:
   b:
    - 1
    - 2
 `,
-			src: `
+			`
 - 3
 - map:
    - 4
    - 5
 `,
-			expected: `
+			`
 a:
   b:
    - 1
@@ -397,30 +397,30 @@ func TestPath_Replace(t *testing.T) {
 		expected string
 	}{
 		{
-			path: "$.a",
-			dst: `
+			"$.a",
+			`
 a: 1
 b: 2
 `,
-			src: `3`,
-			expected: `
+			`3`,
+			`
 a: 3
 b: 2
 `,
 		},
 		{
-			path: "$.b",
-			dst: `
+			"$.b",
+			`
 b: 1
 c: 2
 `,
-			src: `
+			`
 d: e
 f:
   g: h
   i: j
 `,
-			expected: `
+			`
 b:
   d: e
   f:
@@ -430,15 +430,15 @@ c: 2
 `,
 		},
 		{
-			path: "$.a.b[0]",
-			dst: `
+			"$.a.b[0]",
+			`
 a:
   b:
   - hello
 c: 2
 `,
-			src: `world`,
-			expected: `
+			`world`,
+			`
 a:
   b:
   - world
@@ -447,8 +447,8 @@ c: 2
 		},
 
 		{
-			path: "$.books[*].author",
-			dst: `
+			"$.books[*].author",
+			`
 books:
   - name: book_a
     author: none
@@ -462,8 +462,8 @@ pictures:
 building:
   author: none
 `,
-			src: `ken`,
-			expected: `
+			`ken`,
+			`
 books:
   - name: book_a
     author: ken
@@ -479,8 +479,8 @@ building:
 `,
 		},
 		{
-			path: "$..author",
-			dst: `
+			"$..author",
+			`
 books:
   - name: book_a
     author: none
@@ -494,8 +494,8 @@ pictures:
 building:
   author: none
 `,
-			src: `ken`,
-			expected: `
+			`ken`,
+			`
 books:
   - name: book_a
     author: ken