summaryrefslogtreecommitdiffstats
path: root/error_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'error_test.go')
-rw-r--r--error_test.go245
1 files changed, 245 insertions, 0 deletions
diff --git a/error_test.go b/error_test.go
new file mode 100644
index 0000000..cd95263
--- /dev/null
+++ b/error_test.go
@@ -0,0 +1,245 @@
+//go:build go1.16
+// +build go1.16
+
+package toml_test
+
+import (
+ "errors"
+ "fmt"
+ "io/fs"
+ "math"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/BurntSushi/toml"
+ tomltest "github.com/BurntSushi/toml/internal/toml-test"
+)
+
+func TestErrorPosition(t *testing.T) {
+ // Note: take care to use leading spaces (not tabs).
+ tests := []struct {
+ test, err string
+ }{
+ {"array/missing-separator.toml", `
+toml: error: expected a comma (',') or array terminator (']'), but got '2'
+
+At line 1, column 13:
+
+ 1 | wrong = [ 1 2 3 ]
+ ^`},
+
+ {"array/no-close-2.toml", `
+toml: error: expected a comma (',') or array terminator (']'), but got end of file
+
+At line 1, column 10:
+
+ 1 | x = [42 #
+ ^`},
+
+ {"array/tables-2.toml", `
+toml: error: Key 'fruit.variety' has already been defined.
+
+At line 9, column 3-8:
+
+ 7 |
+ 8 | # This table conflicts with the previous table
+ 9 | [fruit.variety]
+ ^^^^^`},
+ {"datetime/trailing-t.toml", `
+toml: error: Invalid TOML Datetime: "2006-01-30T".
+
+At line 2, column 4-15:
+
+ 1 | # Date cannot end with trailing T
+ 2 | d = 2006-01-30T
+ ^^^^^^^^^^^`},
+ }
+
+ fsys := tomltest.EmbeddedTests()
+ for _, tt := range tests {
+ t.Run(tt.test, func(t *testing.T) {
+ input, err := fs.ReadFile(fsys, "invalid/"+tt.test)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var x interface{}
+ _, err = toml.Decode(string(input), &x)
+ if err == nil {
+ t.Fatal("err is nil")
+ }
+
+ var pErr toml.ParseError
+ if !errors.As(err, &pErr) {
+ t.Errorf("err is not a ParseError: %T %[1]v", err)
+ }
+
+ tt.err = tt.err[1:] + "\n" // Remove first newline, and add trailing.
+ want := pErr.ErrorWithUsage()
+
+ if !strings.Contains(want, tt.err) {
+ t.Fatalf("\nwant:\n%s\nhave:\n%s", tt.err, want)
+ }
+ })
+ }
+}
+
+func TestParseError(t *testing.T) {
+ tests := []struct {
+ in interface{}
+ toml, err string
+ }{
+ {
+ &struct{ Int int8 }{},
+ "Int = 200",
+ `| toml: error: 200 is out of range for int8
+ |
+ | At line 1, column 6-9:
+ |
+ | 1 | Int = 200
+ | ^^^
+ | Error help:
+ |
+ | This number is too large; this may be an error in the TOML, but it can also be a
+ | bug in the program that uses too small of an integer.
+ |
+ | The maximum and minimum values are:
+ |
+ | size │ lowest │ highest
+ | ───────┼────────────────┼──────────
+ | int8 │ -128 │ 127
+ | int16 │ -32,768 │ 32,767
+ | int32 │ -2,147,483,648 │ 2,147,483,647
+ | int64 │ -9.2 × 10¹⁷ │ 9.2 × 10¹⁷
+ | uint8 │ 0 │ 255
+ | uint16 │ 0 │ 65535
+ | uint32 │ 0 │ 4294967295
+ | uint64 │ 0 │ 1.8 × 10¹⁸
+ |
+ | int refers to int32 on 32-bit systems and int64 on 64-bit systems.
+ `,
+ },
+ {
+ &struct{ Int int }{},
+ fmt.Sprintf("Int = %d", uint64(math.MaxInt64+1)),
+ `| toml: error: 9223372036854775808 is out of range for int64
+ |
+ | At line 1, column 6-25:
+ |
+ | 1 | Int = 9223372036854775808
+ | ^^^^^^^^^^^^^^^^^^^
+ | Error help:
+ |
+ | This number is too large; this may be an error in the TOML, but it can also be a
+ | bug in the program that uses too small of an integer.
+ |
+ | The maximum and minimum values are:
+ |
+ | size │ lowest │ highest
+ | ───────┼────────────────┼──────────
+ | int8 │ -128 │ 127
+ | int16 │ -32,768 │ 32,767
+ | int32 │ -2,147,483,648 │ 2,147,483,647
+ | int64 │ -9.2 × 10¹⁷ │ 9.2 × 10¹⁷
+ | uint8 │ 0 │ 255
+ | uint16 │ 0 │ 65535
+ | uint32 │ 0 │ 4294967295
+ | uint64 │ 0 │ 1.8 × 10¹⁸
+ |
+ | int refers to int32 on 32-bit systems and int64 on 64-bit systems.
+ `,
+ },
+ {
+ &struct{ Float float32 }{},
+ "Float = 1.1e99",
+ `
+ | toml: error: 1.1e+99 is out of range for float32
+ |
+ | At line 1, column 8-14:
+ |
+ | 1 | Float = 1.1e99
+ | ^^^^^^
+ | Error help:
+ |
+ | This number is too large; this may be an error in the TOML, but it can also be a
+ | bug in the program that uses too small of an integer.
+ |
+ | The maximum and minimum values are:
+ |
+ | size │ lowest │ highest
+ | ───────┼────────────────┼──────────
+ | int8 │ -128 │ 127
+ | int16 │ -32,768 │ 32,767
+ | int32 │ -2,147,483,648 │ 2,147,483,647
+ | int64 │ -9.2 × 10¹⁷ │ 9.2 × 10¹⁷
+ | uint8 │ 0 │ 255
+ | uint16 │ 0 │ 65535
+ | uint32 │ 0 │ 4294967295
+ | uint64 │ 0 │ 1.8 × 10¹⁸
+ |
+ | int refers to int32 on 32-bit systems and int64 on 64-bit systems.
+ `,
+ },
+
+ {
+ &struct{ D time.Duration }{},
+ `D = "99 bottles"`,
+ `
+ | toml: error: invalid duration: "99 bottles"
+ |
+ | At line 1, column 5-15:
+ |
+ | 1 | D = "99 bottles"
+ | ^^^^^^^^^^
+ | Error help:
+ |
+ | A duration must be as "number<unit>", without any spaces. Valid units are:
+ |
+ | ns nanoseconds (billionth of a second)
+ | us, µs microseconds (millionth of a second)
+ | ms milliseconds (thousands of a second)
+ | s seconds
+ | m minutes
+ | h hours
+ |
+ | You can combine multiple units; for example "5m10s" for 5 minutes and 10
+ | seconds.
+ `,
+ },
+ }
+
+ prep := func(s string) string {
+ lines := strings.Split(strings.TrimSpace(s), "\n")
+ for i := range lines {
+ if j := strings.IndexByte(lines[i], '|'); j >= 0 {
+ lines[i] = lines[i][j+1:]
+ lines[i] = strings.Replace(lines[i], " ", "", 1)
+ }
+ }
+ return strings.Join(lines, "\n") + "\n"
+ }
+
+ for _, tt := range tests {
+ t.Run("", func(t *testing.T) {
+ _, err := toml.Decode(tt.toml, tt.in)
+ if err == nil {
+ t.Fatalf("err is nil; decoded: %#v", tt.in)
+ }
+
+ var pErr toml.ParseError
+ if !errors.As(err, &pErr) {
+ t.Fatalf("err is not a ParseError: %#v", err)
+ }
+
+ tt.err = prep(tt.err)
+ have := pErr.ErrorWithUsage()
+
+ // have = strings.ReplaceAll(have, " ", "·")
+ // tt.err = strings.ReplaceAll(tt.err, " ", "·")
+ if have != tt.err {
+ t.Fatalf("\nwant:\n%s\nhave:\n%s", tt.err, have)
+ }
+ })
+ }
+}