From 9575cd083a3570d5c7bc522fc8f32bf0360d1da9 Mon Sep 17 00:00:00 2001 From: Moritz Poldrack Date: Wed, 25 Oct 2023 23:53:43 +0200 Subject: [PATCH] remove io/ioutil Since ioutil has been deprecated, replace the calls to ioutil with the functions that are now called anyways. --- benchmark/bench_datasets_test.go | 3 +- benchmark/benchmark_test.go | 8 +- cmd/tomltestgen/main.go | 7 +- fuzz_test.go | 4 +- internal/cli/cli.go | 5 +- internal/cli/cli_test.go | 21 +- toml_testgen_test.go | 1431 ++++++++++++++++++++++++++---- unmarshaler.go | 3 +- 8 files changed, 1287 insertions(+), 195 deletions(-) diff --git a/benchmark/bench_datasets_test.go b/benchmark/bench_datasets_test.go index ca974fd6..a392c29b 100644 --- a/benchmark/bench_datasets_test.go +++ b/benchmark/bench_datasets_test.go @@ -3,7 +3,6 @@ package benchmark_test import ( "compress/gzip" "encoding/json" - "io/ioutil" "os" "path/filepath" "testing" @@ -74,7 +73,7 @@ func fixture(tb testing.TB, path string) []byte { gz, err := gzip.NewReader(f) require.NoError(tb, err) - buf, err := ioutil.ReadAll(gz) + buf, err := os.ReadAll(gz) require.NoError(tb, err) return buf } diff --git a/benchmark/benchmark_test.go b/benchmark/benchmark_test.go index a51476cd..70f8f4a1 100644 --- a/benchmark/benchmark_test.go +++ b/benchmark/benchmark_test.go @@ -2,7 +2,7 @@ package benchmark_test import ( "bytes" - "io/ioutil" + "os" "testing" "time" @@ -59,7 +59,7 @@ func BenchmarkUnmarshal(b *testing.B) { }) b.Run("ReferenceFile", func(b *testing.B) { - bytes, err := ioutil.ReadFile("benchmark.toml") + bytes, err := os.ReadFile("benchmark.toml") if err != nil { b.Fatal(err) } @@ -165,7 +165,7 @@ func BenchmarkMarshal(b *testing.B) { }) b.Run("ReferenceFile", func(b *testing.B) { - bytes, err := ioutil.ReadFile("benchmark.toml") + bytes, err := os.ReadFile("benchmark.toml") if err != nil { b.Fatal(err) } @@ -344,7 +344,7 @@ type benchmarkDoc struct { } func TestUnmarshalReferenceFile(t *testing.T) { - bytes, err := ioutil.ReadFile("benchmark.toml") + bytes, err := os.ReadFile("benchmark.toml") require.NoError(t, err) d := benchmarkDoc{} err = toml.Unmarshal(bytes, &d) diff --git a/cmd/tomltestgen/main.go b/cmd/tomltestgen/main.go index ff2dfd5b..fe52a862 100644 --- a/cmd/tomltestgen/main.go +++ b/cmd/tomltestgen/main.go @@ -13,7 +13,6 @@ import ( "fmt" "go/format" "io" - "io/ioutil" "log" "net/http" "os" @@ -72,7 +71,7 @@ func downloadTmpFile(url string) string { } defer resp.Body.Close() - tmpfile, err := ioutil.TempFile("", "toml-test-*.zip") + tmpfile, err := os.CreateTemp("", "toml-test-*.zip") if err != nil { panic(err) } @@ -113,7 +112,7 @@ func readFileFromZip(f *zip.File) string { panic(err) } defer reader.Close() - bytes, err := ioutil.ReadAll(reader) + bytes, err := io.ReadAll(reader) if err != nil { panic(err) } @@ -216,7 +215,7 @@ func main() { return } - err = os.WriteFile(*out, outputBytes, 0644) + err = os.WriteFile(*out, outputBytes, 0o644) if err != nil { panic(err) } diff --git a/fuzz_test.go b/fuzz_test.go index c340f83f..04f1169f 100644 --- a/fuzz_test.go +++ b/fuzz_test.go @@ -4,7 +4,7 @@ package toml_test import ( - "io/ioutil" + "os" "strings" "testing" @@ -13,7 +13,7 @@ import ( ) func FuzzUnmarshal(f *testing.F) { - file, err := ioutil.ReadFile("benchmark/benchmark.toml") + file, err := os.ReadFile("benchmark/benchmark.toml") if err != nil { panic(err) } diff --git a/internal/cli/cli.go b/internal/cli/cli.go index 0fdde196..6627b5fc 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -6,7 +6,6 @@ import ( "flag" "fmt" "io" - "io/ioutil" "os" "github.com/pelletier/go-toml/v2" @@ -72,7 +71,7 @@ func (p *Program) runAllFilesInPlace(files []string) error { } func (p *Program) runFileInPlace(path string) error { - in, err := ioutil.ReadFile(path) + in, err := os.ReadFile(path) if err != nil { return err } @@ -84,5 +83,5 @@ func (p *Program) runFileInPlace(path string) error { return err } - return ioutil.WriteFile(path, out.Bytes(), 0600) + return os.WriteFile(path, out.Bytes(), 0o600) } diff --git a/internal/cli/cli_test.go b/internal/cli/cli_test.go index 429fa730..11a5a5b9 100644 --- a/internal/cli/cli_test.go +++ b/internal/cli/cli_test.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "os" "path" "strings" @@ -64,7 +63,7 @@ func TestProcessMainStdinDecodeErr(t *testing.T) { } func TestProcessMainFileExists(t *testing.T) { - tmpfile, err := ioutil.TempFile("", "example") + tmpfile, err := os.CreateTemp("", "example") require.NoError(t, err) defer os.Remove(tmpfile.Name()) _, err = tmpfile.Write([]byte(`some data`)) @@ -96,16 +95,16 @@ func TestProcessMainFileDoesNotExist(t *testing.T) { } func TestProcessMainFilesInPlace(t *testing.T) { - dir, err := ioutil.TempDir("", "") + dir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(dir) path1 := path.Join(dir, "file1") path2 := path.Join(dir, "file2") - err = ioutil.WriteFile(path1, []byte("content 1"), 0600) + err = os.WriteFile(path1, []byte("content 1"), 0o600) require.NoError(t, err) - err = ioutil.WriteFile(path2, []byte("content 2"), 0600) + err = os.WriteFile(path2, []byte("content 2"), 0o600) require.NoError(t, err) p := Program{ @@ -117,11 +116,11 @@ func TestProcessMainFilesInPlace(t *testing.T) { require.Equal(t, 0, exit) - v1, err := ioutil.ReadFile(path1) + v1, err := os.ReadFile(path1) require.NoError(t, err) require.Equal(t, "1", string(v1)) - v2, err := ioutil.ReadFile(path2) + v2, err := os.ReadFile(path2) require.NoError(t, err) require.Equal(t, "2", string(v2)) } @@ -138,13 +137,13 @@ func TestProcessMainFilesInPlaceErrRead(t *testing.T) { } func TestProcessMainFilesInPlaceFailFn(t *testing.T) { - dir, err := ioutil.TempDir("", "") + dir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(dir) path1 := path.Join(dir, "file1") - err = ioutil.WriteFile(path1, []byte("content 1"), 0600) + err = os.WriteFile(path1, []byte("content 1"), 0o600) require.NoError(t, err) p := Program{ @@ -156,13 +155,13 @@ func TestProcessMainFilesInPlaceFailFn(t *testing.T) { require.Equal(t, -1, exit) - v1, err := ioutil.ReadFile(path1) + v1, err := os.ReadFile(path1) require.NoError(t, err) require.Equal(t, "content 1", string(v1)) } func dummyFileFn(r io.Reader, w io.Writer) error { - b, err := ioutil.ReadAll(r) + b, err := io.ReadAll(r) if err != nil { return err } diff --git a/toml_testgen_test.go b/toml_testgen_test.go index 9f8d29d4..d5e59b4c 100644 --- a/toml_testgen_test.go +++ b/toml_testgen_test.go @@ -1,17 +1,82 @@ -// Generated by tomltestgen for toml-test ref master on 2022-04-07T20:09:42-04:00 +// Generated by tomltestgen for toml-test ref master on 2023-10-25T23:48:00+02:00 package toml_test import ( "testing" ) -func TestTOMLTest_Invalid_Array_MissingSeparator(t *testing.T) { +func TestTOMLTest_Invalid_Array_DoubleComma1(t *testing.T) { + input := "double-comma-1 = [1,,2]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_DoubleComma2(t *testing.T) { + input := "double-comma-2 = [1,2,,]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_ExtendDefinedAot(t *testing.T) { + input := "[[tab.arr]]\n[tab]\narr.val1=1\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_ExtendingTable(t *testing.T) { + input := "a = [{ b = 1 }]\n\n# Cannot extend tables within static arrays\n# https://github.com/toml-lang/toml/issues/908\n[a.c]\nfoo = 1\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_MissingSeparator1(t *testing.T) { + input := "arrr = [true false]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_MissingSeparator2(t *testing.T) { input := "wrong = [ 1 2 3 ]\n" testgenInvalid(t, input) } +func TestTOMLTest_Invalid_Array_NoClose1(t *testing.T) { + input := "no-close-1 = [ 1, 2, 3\n" + testgenInvalid(t, input) +} + func TestTOMLTest_Invalid_Array_NoClose2(t *testing.T) { - input := "x = [42 #\n" + input := "no-close-2 = [1,\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_NoClose3(t *testing.T) { + input := "no-close-3 = [42 #]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_NoClose4(t *testing.T) { + input := "no-close-4 = [{ key = 42\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_NoClose5(t *testing.T) { + input := "no-close-5 = [{ key = 42}\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_NoClose6(t *testing.T) { + input := "no-close-6 = [{ key = 42 #}]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_NoClose7(t *testing.T) { + input := "no-close-7 = [{ key = 42} #]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_NoClose8(t *testing.T) { + input := "no-close-8 = [\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_NoCloseTable1(t *testing.T) { + input := "x = [{ key = 42\n" testgenInvalid(t, input) } @@ -20,13 +85,28 @@ func TestTOMLTest_Invalid_Array_NoCloseTable2(t *testing.T) { testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Array_NoCloseTable(t *testing.T) { - input := "x = [{ key = 42\n" +func TestTOMLTest_Invalid_Array_NoComma1(t *testing.T) { + input := "no-comma-1 = [true false]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_NoComma2(t *testing.T) { + input := "no-comma-2 = [ 1 2 3 ]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_NoComma3(t *testing.T) { + input := "no-comma-3 = [ 1 #,]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Array_OnlyComma1(t *testing.T) { + input := "only-comma-1 = [,]\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Array_NoClose(t *testing.T) { - input := "long_array = [ 1, 2, 3\n" +func TestTOMLTest_Invalid_Array_OnlyComma2(t *testing.T) { + input := "only-comma-2 = [,,]\n" testgenInvalid(t, input) } @@ -56,57 +136,77 @@ func TestTOMLTest_Invalid_Array_TextInArray(t *testing.T) { } func TestTOMLTest_Invalid_Bool_AlmostFalseWithExtra(t *testing.T) { - input := "a = falsify\n" + input := "almost-false-with-extra = falsify\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Bool_AlmostFalse(t *testing.T) { - input := "a = fals\n" + input := "almost-false = fals\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Bool_AlmostTrueWithExtra(t *testing.T) { - input := "a = truthy\n" + input := "almost-true-with-extra = truthy\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Bool_AlmostTrue(t *testing.T) { - input := "a = tru\n" + input := "almost-true = tru\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Bool_CapitalizedFalse(t *testing.T) { + input := "capitalized-false = False\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Bool_CapitalizedTrue(t *testing.T) { + input := "capitalized-true = True\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Bool_JustF(t *testing.T) { - input := "a = f\n" + input := "just-f = f\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Bool_JustT(t *testing.T) { - input := "a = t\n" + input := "just-t = t\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Bool_MixedCaseFalse(t *testing.T) { + input := "mixed-case-false = falsE\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Bool_MixedCaseTrue(t *testing.T) { + input := "mixed-case-true = trUe\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Bool_MixedCase(t *testing.T) { - input := "valid = False\n" + input := "mixed-case = valid = False\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Bool_StartingSameFalse(t *testing.T) { - input := "a = falsey\n" + input := "starting-same-false = falsey\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Bool_StartingSameTrue(t *testing.T) { - input := "a = truer\n" + input := "starting-same-true = truer\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Bool_WrongCaseFalse(t *testing.T) { - input := "b = FALSE\n" + input := "wrong-case-false = FALSE\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Bool_WrongCaseTrue(t *testing.T) { - input := "a = TRUE\n" + input := "wrong-case-true = TRUE\n" testgenInvalid(t, input) } @@ -116,12 +216,12 @@ func TestTOMLTest_Invalid_Control_BareCr(t *testing.T) { } func TestTOMLTest_Invalid_Control_BareFormfeed(t *testing.T) { - input := "bare-formfeed = \f\n" + input := "bare-formfeed = \f\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_BareNull(t *testing.T) { - input := "bare-null = \"some value\" \x00\n" + input := "bare-null = \"some value\" \x00\n" testgenInvalid(t, input) } @@ -131,37 +231,47 @@ func TestTOMLTest_Invalid_Control_BareVerticalTab(t *testing.T) { } func TestTOMLTest_Invalid_Control_CommentCr(t *testing.T) { - input := "comment-cr = \"Carriage return in comment\" # \ra=1\n" + input := "comment-cr = \"Carriage return in comment\" # \ra=1\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_CommentDel(t *testing.T) { - input := "comment-del = \"0x7f\" # \u007f\n" + input := "comment-del = \"0x7f\" # \x7f\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Control_CommentFf(t *testing.T) { + input := "comment-ff = \"0x7f\" # \f\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_CommentLf(t *testing.T) { - input := "comment-lf = \"ctrl-P\" # \x10\n" + input := "comment-lf = \"ctrl-P\" # \x10\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_CommentNull(t *testing.T) { - input := "comment-null = \"null\" # \x00\n" + input := "comment-null = \"null\" # \x00\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_CommentUs(t *testing.T) { - input := "comment-us = \"ctrl-_\" # \x1f\n" + input := "comment-us = \"ctrl-_\" # \x1f\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Control_MultiCr(t *testing.T) { + input := "multi-cr = \"\"\"null\r\"\"\"\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_MultiDel(t *testing.T) { - input := "multi-del = \"\"\"null\u007f\"\"\"\n" + input := "multi-del = \"\"\"null\x7f\"\"\"\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_MultiLf(t *testing.T) { - input := "multi-lf = \"\"\"null\x10\"\"\"\n" + input := "multi-lf = \"\"\"null\x10\"\"\"\n" testgenInvalid(t, input) } @@ -171,17 +281,22 @@ func TestTOMLTest_Invalid_Control_MultiNull(t *testing.T) { } func TestTOMLTest_Invalid_Control_MultiUs(t *testing.T) { - input := "multi-us = \"\"\"null\x1f\"\"\"\n" + input := "multi-us = \"\"\"null\x1f\"\"\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Control_RawmultiCd(t *testing.T) { + input := "rawmulti-cd = '''null\r'''\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_RawmultiDel(t *testing.T) { - input := "rawmulti-del = '''null\u007f'''\n" + input := "rawmulti-del = '''null\x7f'''\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_RawmultiLf(t *testing.T) { - input := "rawmulti-lf = '''null\x10'''\n" + input := "rawmulti-lf = '''null\x10'''\n" testgenInvalid(t, input) } @@ -191,17 +306,22 @@ func TestTOMLTest_Invalid_Control_RawmultiNull(t *testing.T) { } func TestTOMLTest_Invalid_Control_RawmultiUs(t *testing.T) { - input := "rawmulti-us = '''null\x1f'''\n" + input := "rawmulti-us = '''null\x1f'''\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Control_RawstringCr(t *testing.T) { + input := "rawstring-cr = 'null\r'\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_RawstringDel(t *testing.T) { - input := "rawstring-del = 'null\u007f'\n" + input := "rawstring-del = 'null\x7f'\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_RawstringLf(t *testing.T) { - input := "rawstring-lf = 'null\x10'\n" + input := "rawstring-lf = 'null\x10'\n" testgenInvalid(t, input) } @@ -211,22 +331,27 @@ func TestTOMLTest_Invalid_Control_RawstringNull(t *testing.T) { } func TestTOMLTest_Invalid_Control_RawstringUs(t *testing.T) { - input := "rawstring-us = 'null\x1f'\n" + input := "rawstring-us = 'null\x1f'\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_StringBs(t *testing.T) { - input := "string-bs = \"backspace\b\"\n" + input := "string-bs = \"backspace\b\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Control_StringCr(t *testing.T) { + input := "string-cr = \"null\r\"\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_StringDel(t *testing.T) { - input := "string-del = \"null\u007f\"\n" + input := "string-del = \"null\x7f\"\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Control_StringLf(t *testing.T) { - input := "string-lf = \"null\x10\"\n" + input := "string-lf = \"null\x10\"\n" testgenInvalid(t, input) } @@ -236,7 +361,17 @@ func TestTOMLTest_Invalid_Control_StringNull(t *testing.T) { } func TestTOMLTest_Invalid_Control_StringUs(t *testing.T) { - input := "string-us = \"null\x1f\"\n" + input := "string-us = \"null\x1f\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Datetime_Feb29(t *testing.T) { + input := "\"not a leap year\" = 2100-02-29T15:15:15Z\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Datetime_Feb30(t *testing.T) { + input := "\"only 28 or 29 days in february\" = 1988-02-30T15:15:15Z\n" testgenInvalid(t, input) } @@ -270,6 +405,11 @@ func TestTOMLTest_Invalid_Datetime_MonthUnder(t *testing.T) { testgenInvalid(t, input) } +func TestTOMLTest_Invalid_Datetime_NoLeadsMonth(t *testing.T) { + input := "# Month \"7\" instead of \"07\"; the leading zero is required.\nno-leads = 1987-7-05T17:45:00Z\n" + testgenInvalid(t, input) +} + func TestTOMLTest_Invalid_Datetime_NoLeadsWithMilli(t *testing.T) { input := "# Day \"5\" instead of \"05\"; the leading zero is required.\nwith-milli = 1987-07-5T17:45:00.12Z\n" testgenInvalid(t, input) @@ -295,18 +435,13 @@ func TestTOMLTest_Invalid_Datetime_SecondOver(t *testing.T) { testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Datetime_TimeNoLeads2(t *testing.T) { - input := "# Leading 0 is always required.\nd = 01:32:0\n" - testgenInvalid(t, input) -} - func TestTOMLTest_Invalid_Datetime_TimeNoLeads(t *testing.T) { - input := "# Leading 0 is always required.\nd = 1:32:00\n" + input := "# Leading 0 is always required.\nd = 2023-10-01T1:32:00Z\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Datetime_TrailingT(t *testing.T) { - input := "# Date cannot end with trailing T\nd = 2006-01-30T\n" +func TestTOMLTest_Invalid_Encoding_BadCodepoint(t *testing.T) { + input := "# Invalid codepoint U+D800 : \xed\xa0\x80\n" testgenInvalid(t, input) } @@ -320,6 +455,21 @@ func TestTOMLTest_Invalid_Encoding_BadUtf8InComment(t *testing.T) { testgenInvalid(t, input) } +func TestTOMLTest_Invalid_Encoding_BadUtf8InMultilineLiteral(t *testing.T) { + input := "# The following line contains an invalid UTF-8 sequence.\nbad = '''\xc3'''\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Encoding_BadUtf8InMultiline(t *testing.T) { + input := "# The following line contains an invalid UTF-8 sequence.\nbad = \"\"\"\xc3\"\"\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Encoding_BadUtf8InStringLiteral(t *testing.T) { + input := "# The following line contains an invalid UTF-8 sequence.\nbad = '\xc3'\n" + testgenInvalid(t, input) +} + func TestTOMLTest_Invalid_Encoding_BadUtf8InString(t *testing.T) { input := "# The following line contains an invalid UTF-8 sequence.\nbad = \"\xc3\"\n" testgenInvalid(t, input) @@ -386,7 +536,12 @@ func TestTOMLTest_Invalid_Float_ExpPoint2(t *testing.T) { } func TestTOMLTest_Invalid_Float_ExpTrailingUs(t *testing.T) { - input := "exp-trailing-us = 1e_23_\n" + input := "exp-trailing-us = 1e23_\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Float_InfCapital(t *testing.T) { + input := "v = Inf\n" testgenInvalid(t, input) } @@ -445,6 +600,11 @@ func TestTOMLTest_Invalid_Float_LeadingZero(t *testing.T) { testgenInvalid(t, input) } +func TestTOMLTest_Invalid_Float_NanCapital(t *testing.T) { + input := "v = NaN\n" + testgenInvalid(t, input) +} + func TestTOMLTest_Invalid_Float_NanIncomplete1(t *testing.T) { input := "nan-incomplete-1 = na\n" testgenInvalid(t, input) @@ -480,8 +640,13 @@ func TestTOMLTest_Invalid_Float_TrailingPoint(t *testing.T) { testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Float_TrailingUsExp(t *testing.T) { - input := "# trailing underscore in integer part is not allowed\ntrailing-us-exp = 1_e2\n# trailing underscore in float part is not allowed\ntrailing-us-exp2 = 1.2_e2\n" +func TestTOMLTest_Invalid_Float_TrailingUsExp1(t *testing.T) { + input := "trailing-us-exp-1 = 1_e2\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Float_TrailingUsExp2(t *testing.T) { + input := "trailing-us-exp-2 = 1.2_e2\n" testgenInvalid(t, input) } @@ -500,8 +665,8 @@ func TestTOMLTest_Invalid_Float_UsBeforePoint(t *testing.T) { testgenInvalid(t, input) } -func TestTOMLTest_Invalid_InlineTable_Add(t *testing.T) { - input := "a={}\n# Inline tables are immutable and can't be extended\n[a.b]\n" +func TestTOMLTest_Invalid_InlineTable_BadKeySyntax(t *testing.T) { + input := "tbl = { a = 1, [b] }\n" testgenInvalid(t, input) } @@ -510,16 +675,41 @@ func TestTOMLTest_Invalid_InlineTable_DoubleComma(t *testing.T) { testgenInvalid(t, input) } -func TestTOMLTest_Invalid_InlineTable_DuplicateKey(t *testing.T) { +func TestTOMLTest_Invalid_InlineTable_DuplicateKey1(t *testing.T) { input := "# Duplicate keys within an inline table are invalid\na={b=1, b=2}\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_InlineTable_Empty(t *testing.T) { +func TestTOMLTest_Invalid_InlineTable_DuplicateKey2(t *testing.T) { + input := "table1 = { table2.dupe = 1, table2.dupe = 2 }\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_DuplicateKey3(t *testing.T) { + input := "tbl = { fruit = { apple.color = \"red\" }, fruit.apple.texture = { smooth = true } }\n\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_DuplicateKey4(t *testing.T) { + input := "tbl = { a.b = \"a_b\", a.b.c = \"a_b_c\" }\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_Empty1(t *testing.T) { input := "t = {,}\n" testgenInvalid(t, input) } +func TestTOMLTest_Invalid_InlineTable_Empty2(t *testing.T) { + input := "t = {,\n}\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_Empty3(t *testing.T) { + input := "t = {\n,\n}\n" + testgenInvalid(t, input) +} + func TestTOMLTest_Invalid_InlineTable_Linebreak1(t *testing.T) { input := "# No newlines are allowed between the curly braces unless they are valid within\n# a value.\nsimple = { a = 1 \n}\n" testgenInvalid(t, input) @@ -540,16 +730,71 @@ func TestTOMLTest_Invalid_InlineTable_Linebreak4(t *testing.T) { testgenInvalid(t, input) } -func TestTOMLTest_Invalid_InlineTable_NoComma(t *testing.T) { +func TestTOMLTest_Invalid_InlineTable_NoClose1(t *testing.T) { + input := "a={\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_NoClose2(t *testing.T) { + input := "a={b=1\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_NoComma1(t *testing.T) { input := "t = {x = 3 y = 4}\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_InlineTable_Overwrite(t *testing.T) { +func TestTOMLTest_Invalid_InlineTable_NoComma2(t *testing.T) { + input := "arrr = { comma-missing = true valid-toml = false }\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_Overwrite1(t *testing.T) { input := "a.b=0\n# Since table \"a\" is already defined, it can't be replaced by an inline table.\na={}\n" testgenInvalid(t, input) } +func TestTOMLTest_Invalid_InlineTable_Overwrite2(t *testing.T) { + input := "a={}\n# Inline tables are immutable and can't be extended\n[a.b]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_Overwrite3(t *testing.T) { + input := "a = { b = 1 }\na.b = 2\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_Overwrite4(t *testing.T) { + input := "inline-t = { nest = {} }\n\n[[inline-t.nest]]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_Overwrite5(t *testing.T) { + input := "inline-t = { nest = {} }\n\n[inline-t.nest]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_Overwrite6(t *testing.T) { + input := "a = { b = 1, b.c = 2 }\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_Overwrite7(t *testing.T) { + input := "tab = { inner.table = [{}], inner.table.val = \"bad\" }" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_Overwrite8(t *testing.T) { + input := "tab = { inner = { dog = \"best\" }, inner.cat = \"worst\" }" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_InlineTable_Overwrite9(t *testing.T) { + input := "[tab.nested]\ninline-t = { nest = {} }\n\n[tab]\nnested.inline-t.nest = 2\n" + testgenInvalid(t, input) +} + func TestTOMLTest_Invalid_InlineTable_TrailingComma(t *testing.T) { input := "# A terminating comma (also called trailing comma) is not permitted after the\n# last key/value pair in an inline table\nabc = { abc = 123, }\n" testgenInvalid(t, input) @@ -605,6 +850,16 @@ func TestTOMLTest_Invalid_Integer_InvalidBin(t *testing.T) { testgenInvalid(t, input) } +func TestTOMLTest_Invalid_Integer_InvalidHex1(t *testing.T) { + input := "invalid-hex-1 = 0xaafz\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Integer_InvalidHex2(t *testing.T) { + input := "invalid-hex-2 = 0xgabba00f1\n" + testgenInvalid(t, input) +} + func TestTOMLTest_Invalid_Integer_InvalidHex(t *testing.T) { input := "invalid-hex = 0xaafz\n" testgenInvalid(t, input) @@ -616,12 +871,12 @@ func TestTOMLTest_Invalid_Integer_InvalidOct(t *testing.T) { } func TestTOMLTest_Invalid_Integer_LeadingUsBin(t *testing.T) { - input := "leading-us-bin = _0o1\n" + input := "leading-us-bin = _0b1\n" testgenInvalid(t, input) } func TestTOMLTest_Invalid_Integer_LeadingUsHex(t *testing.T) { - input := "leading-us-hex = _0o1\n" + input := "leading-us-hex = _0x1\n" testgenInvalid(t, input) } @@ -676,7 +931,7 @@ func TestTOMLTest_Invalid_Integer_NegativeHex(t *testing.T) { } func TestTOMLTest_Invalid_Integer_NegativeOct(t *testing.T) { - input := "negative-oct = -0o99\n" + input := "negative-oct = -0o755\n" testgenInvalid(t, input) } @@ -691,7 +946,7 @@ func TestTOMLTest_Invalid_Integer_PositiveHex(t *testing.T) { } func TestTOMLTest_Invalid_Integer_PositiveOct(t *testing.T) { - input := "positive-oct = +0o99\n" + input := "positive-oct = +0o755\n" testgenInvalid(t, input) } @@ -755,7 +1010,12 @@ func TestTOMLTest_Invalid_Key_BareInvalidCharacter(t *testing.T) { testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Key_DottedRedefineTable(t *testing.T) { +func TestTOMLTest_Invalid_Key_DottedRedefineTable1(t *testing.T) { + input := "a = false\na.b = true\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Key_DottedRedefineTable2(t *testing.T) { input := "# Defined a.b as int\na.b = 1\n# Tries to access it as table: error\na.b.c = 2\n" testgenInvalid(t, input) } @@ -775,6 +1035,11 @@ func TestTOMLTest_Invalid_Key_Empty(t *testing.T) { testgenInvalid(t, input) } +func TestTOMLTest_Invalid_Key_EndInEscape(t *testing.T) { + input := "\"backslash is the last char\\\n" + testgenInvalid(t, input) +} + func TestTOMLTest_Invalid_Key_Escape(t *testing.T) { input := "\\u00c0 = \"latin capital letter A with grave\"\n" testgenInvalid(t, input) @@ -810,6 +1075,16 @@ func TestTOMLTest_Invalid_Key_PartialQuoted(t *testing.T) { testgenInvalid(t, input) } +func TestTOMLTest_Invalid_Key_QuotedUnclosed1(t *testing.T) { + input := "\"key = x\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Key_QuotedUnclosed2(t *testing.T) { + input := "\"key\n" + testgenInvalid(t, input) +} + func TestTOMLTest_Invalid_Key_SingleOpenBracket(t *testing.T) { input := "[\n" testgenInvalid(t, input) @@ -830,6 +1105,11 @@ func TestTOMLTest_Invalid_Key_StartBracket(t *testing.T) { testgenInvalid(t, input) } +func TestTOMLTest_Invalid_Key_StartDot(t *testing.T) { + input := ".key = 1\n" + testgenInvalid(t, input) +} + func TestTOMLTest_Invalid_Key_TwoEquals(t *testing.T) { input := "key= = 1\n" testgenInvalid(t, input) @@ -855,202 +1135,542 @@ func TestTOMLTest_Invalid_Key_WithoutValue2(t *testing.T) { testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BadByteEscape(t *testing.T) { - input := "naughty = \"\\xAg\"\n" +func TestTOMLTest_Invalid_Key_WithoutValue3(t *testing.T) { + input := "\"key\"\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BadCodepoint(t *testing.T) { - input := "invalid-codepoint = \"This string contains a non scalar unicode codepoint \\uD801\"\n" +func TestTOMLTest_Invalid_Key_WithoutValue4(t *testing.T) { + input := "\"key\" = \n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BadConcat(t *testing.T) { - input := "no_concat = \"first\" \"second\"\n" +func TestTOMLTest_Invalid_Key_WithoutValue5(t *testing.T) { + input := "fs.fw\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BadEscape1(t *testing.T) { - input := "invalid-escape = \"This string has a bad \\a escape character.\"\n" +func TestTOMLTest_Invalid_Key_WithoutValue6(t *testing.T) { + input := "fs.fw =\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BadEscape2(t *testing.T) { - input := "invalid-escape = \"This string has a bad \\ escape character.\"\n\n" +func TestTOMLTest_Invalid_Key_WithoutValue7(t *testing.T) { + input := "fs.\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BadMultiline(t *testing.T) { - input := "multi = \"first line\nsecond line\"\n" +func TestTOMLTest_Invalid_LocalDate_Feb29(t *testing.T) { + input := "\"not a leap year\" = 2100-02-29\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BadSlashEscape(t *testing.T) { - input := "invalid-escape = \"This string has a bad \\/ escape character.\"\n" +func TestTOMLTest_Invalid_LocalDate_Feb30(t *testing.T) { + input := "\"only 28 or 29 days in february\" = 1988-02-30\n\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BadUniEsc(t *testing.T) { - input := "str = \"val\\ue\"\n" +func TestTOMLTest_Invalid_LocalDate_MdayOver(t *testing.T) { + input := "# date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on\n# ; month/year\nd = 2006-01-32\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BasicByteEscapes(t *testing.T) { - input := "answer = \"\\x33\"\n" +func TestTOMLTest_Invalid_LocalDate_MdayUnder(t *testing.T) { + input := "# date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on\n# ; month/year\nd = 2006-01-00\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BasicMultilineOutOfRangeUnicodeEscape1(t *testing.T) { - input := "a = \"\"\"\\UFFFFFFFF\"\"\"\n" +func TestTOMLTest_Invalid_LocalDate_MonthOver(t *testing.T) { + input := "# date-month = 2DIGIT ; 01-12\nd = 2006-13-01\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BasicMultilineOutOfRangeUnicodeEscape2(t *testing.T) { - input := "a = \"\"\"\\U00D80000\"\"\"\n" +func TestTOMLTest_Invalid_LocalDate_MonthUnder(t *testing.T) { + input := "# date-month = 2DIGIT ; 01-12\nd = 2007-00-01\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BasicMultilineQuotes(t *testing.T) { - input := "str5 = \"\"\"Here are three quotation marks: \"\"\".\"\"\"\n" +func TestTOMLTest_Invalid_LocalDate_NoLeadsWithMilli(t *testing.T) { + input := "# Day \"5\" instead of \"05\"; the leading zero is required.\nwith-milli = 1987-07-5\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BasicMultilineUnknownEscape(t *testing.T) { - input := "a = \"\"\"\\@\"\"\"\n" +func TestTOMLTest_Invalid_LocalDate_NoLeads(t *testing.T) { + input := "# Month \"7\" instead of \"07\"; the leading zero is required.\nno-leads = 1987-7-05\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BasicOutOfRangeUnicodeEscape1(t *testing.T) { - input := "a = \"\\UFFFFFFFF\"\n" +func TestTOMLTest_Invalid_LocalDate_TrailingT(t *testing.T) { + input := "# Date cannot end with trailing T\nd = 2006-01-30T\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BasicOutOfRangeUnicodeEscape2(t *testing.T) { - input := "a = \"\\U00D80000\"\n" +func TestTOMLTest_Invalid_LocalDatetime_Feb29(t *testing.T) { + input := "\"not a leap year\" = 2100-02-29T15:15:15\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_BasicUnknownEscape(t *testing.T) { - input := "a = \"\\@\"\n" +func TestTOMLTest_Invalid_LocalDatetime_Feb30(t *testing.T) { + input := "\"only 28 or 29 days in february\" = 1988-02-30T15:15:15\n\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_LiteralMultilineQuotes1(t *testing.T) { - input := "a = '''6 apostrophes: ''''''\n\n" +func TestTOMLTest_Invalid_LocalDatetime_HourOver(t *testing.T) { + input := "# time-hour = 2DIGIT ; 00-23\nd = 2006-01-01T24:00:00\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_LiteralMultilineQuotes2(t *testing.T) { - input := "a = '''15 apostrophes: ''''''''''''''''''\n" +func TestTOMLTest_Invalid_LocalDatetime_MdayOver(t *testing.T) { + input := "# date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on\n# ; month/year\nd = 2006-01-32T00:00:00\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_MissingQuotes(t *testing.T) { - input := "name = value\n" +func TestTOMLTest_Invalid_LocalDatetime_MdayUnder(t *testing.T) { + input := "# date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on\n# ; month/year\nd = 2006-01-00T00:00:00\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_MultilineBadEscape1(t *testing.T) { - input := "k = \"\"\"t\\a\"\"\"\n\n" +func TestTOMLTest_Invalid_LocalDatetime_MinuteOver(t *testing.T) { + input := "# time-minute = 2DIGIT ; 00-59\nd = 2006-01-01T00:60:00\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_MultilineBadEscape2(t *testing.T) { - input := "# \\ is not a valid escape.\nk = \"\"\"t\\ t\"\"\"\n" +func TestTOMLTest_Invalid_LocalDatetime_MonthOver(t *testing.T) { + input := "# date-month = 2DIGIT ; 01-12\nd = 2006-13-01T00:00:00\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_MultilineBadEscape3(t *testing.T) { - input := "# \\ is not a valid escape.\nk = \"\"\"t\\ \"\"\"\n\n" +func TestTOMLTest_Invalid_LocalDatetime_MonthUnder(t *testing.T) { + input := "# date-month = 2DIGIT ; 01-12\nd = 2007-00-01T00:00:00\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_MultilineEscapeSpace(t *testing.T) { - input := "a = \"\"\"\n foo \\ \\n\n bar\"\"\"\n" +func TestTOMLTest_Invalid_LocalDatetime_NoLeadsWithMilli(t *testing.T) { + input := "# Day \"5\" instead of \"05\"; the leading zero is required.\nwith-milli = 1987-07-5T17:45:00.12\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_MultilineNoClose2(t *testing.T) { - input := "x=\"\"\"\n" +func TestTOMLTest_Invalid_LocalDatetime_NoLeads(t *testing.T) { + input := "# Month \"7\" instead of \"07\"; the leading zero is required.\nno-leads = 1987-7-05T17:45:00\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_MultilineNoClose(t *testing.T) { - input := "invalid = \"\"\"\n this will fail\n" +func TestTOMLTest_Invalid_LocalDatetime_NoSecs(t *testing.T) { + input := "# No seconds in time.\nno-secs = 1987-07-05T17:45\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_MultilineQuotes1(t *testing.T) { - input := "a = \"\"\"6 quotes: \"\"\"\"\"\"\n" +func TestTOMLTest_Invalid_LocalDatetime_NoT(t *testing.T) { + input := "# No \"t\" or \"T\" between the date and time.\nno-t = 1987-07-0517:45:00\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_NoClose(t *testing.T) { - input := "no-ending-quote = \"One time, at band camp\n" +func TestTOMLTest_Invalid_LocalDatetime_SecondOver(t *testing.T) { + input := "# time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second\n# ; rules\nd = 2006-01-01T00:00:61\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_TextAfterString(t *testing.T) { - input := "string = \"Is there life after strings?\" No.\n" +func TestTOMLTest_Invalid_LocalDatetime_TimeNoLeads(t *testing.T) { + input := "# Leading 0 is always required.\nd = 2023-10-01T1:32:00Z\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_String_WrongClose(t *testing.T) { - input := "bad-ending-quote = \"double and single'\n" +func TestTOMLTest_Invalid_LocalTime_HourOver(t *testing.T) { + input := "# time-hour = 2DIGIT ; 00-23\nd = 24:00:00\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Table_AppendWithDottedKeys1(t *testing.T) { - input := "# First a.b.c defines a table: a.b.c = {z=9}\n#\n# Then we define a.b.c.t = \"str\" to add a str to the above table, making it:\n#\n# a.b.c = {z=9, t=\"...\"}\n#\n# While this makes sense, logically, it was decided this is not valid TOML as\n# it's too confusing/convoluted.\n# \n# See: https://github.com/toml-lang/toml/issues/846\n# https://github.com/toml-lang/toml/pull/859\n\n[a.b.c]\n z = 9\n\n[a]\n b.c.t = \"Using dotted keys to add to [a.b.c] after explicitly defining it above is not allowed\"\n" +func TestTOMLTest_Invalid_LocalTime_MinuteOver(t *testing.T) { + input := "# time-minute = 2DIGIT ; 00-59\nd = 00:60:00\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Table_AppendWithDottedKeys2(t *testing.T) { - input := "# This is the same issue as in injection-1.toml, except that nests one level\n# deeper. See that file for a more complete description.\n\n[a.b.c.d]\n z = 9\n\n[a]\n b.c.d.k.t = \"Using dotted keys to add to [a.b.c.d] after explicitly defining it above is not allowed\"\n" +func TestTOMLTest_Invalid_LocalTime_NoSecs(t *testing.T) { + input := "# No seconds in time.\nno-secs = 17:45\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Table_ArrayEmpty(t *testing.T) { - input := "[[]]\nname = \"Born to Run\"\n" +func TestTOMLTest_Invalid_LocalTime_SecondOver(t *testing.T) { + input := "# time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second\n# ; rules\nd = 00:00:61\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Table_ArrayImplicit(t *testing.T) { - input := "# This test is a bit tricky. It should fail because the first use of\n# `[[albums.songs]]` without first declaring `albums` implies that `albums`\n# must be a table. The alternative would be quite weird. Namely, it wouldn't\n# comply with the TOML spec: \"Each double-bracketed sub-table will belong to \n# the most *recently* defined table element *above* it.\"\n#\n# This is in contrast to the *valid* test, table-array-implicit where\n# `[[albums.songs]]` works by itself, so long as `[[albums]]` isn't declared\n# later. (Although, `[albums]` could be.)\n[[albums.songs]]\nname = \"Glory Days\"\n\n[[albums]]\nname = \"Born in the USA\"\n" +func TestTOMLTest_Invalid_LocalTime_TimeNoLeads2(t *testing.T) { + input := "# Leading 0 is always required.\nd = 01:32:0\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Table_ArrayMissingBracket(t *testing.T) { - input := "[[albums]\nname = \"Born to Run\"\n" +func TestTOMLTest_Invalid_LocalTime_TimeNoLeads(t *testing.T) { + input := "# Leading 0 is always required.\nd = 1:32:00\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Table_DuplicateKeyDottedTable(t *testing.T) { - input := "[fruit]\napple.color = \"red\"\n\n[fruit.apple] # INVALID\n" +func TestTOMLTest_Invalid_Spec_InlineTable20(t *testing.T) { + input := "[product]\ntype = { name = \"Nail\" }\ntype.edible = false # INVALID\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Table_DuplicateKeyDottedTable2(t *testing.T) { - input := "[fruit]\napple.taste.sweet = true\n\n[fruit.apple.taste] # INVALID\n" +func TestTOMLTest_Invalid_Spec_InlineTable30(t *testing.T) { + input := "[product]\ntype.name = \"Nail\"\ntype = { edible = false } # INVALID\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Table_DuplicateKeyTable(t *testing.T) { - input := "[fruit]\ntype = \"apple\"\n\n[fruit.type]\napple = \"yes\"\n" +func TestTOMLTest_Invalid_Spec_KeyValuePair1(t *testing.T) { + input := "key = # INVALID\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Table_DuplicateTableArray(t *testing.T) { - input := "[tbl]\n[[tbl]]\n" +func TestTOMLTest_Invalid_Spec_Keys2(t *testing.T) { + input := "= \"no key name\" # INVALID\n\"\" = \"blank\" # VALID but discouraged\n'' = 'blank' # VALID but discouraged\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Table_DuplicateTableArray2(t *testing.T) { - input := "[[tbl]]\n[tbl]\n" +func TestTOMLTest_Invalid_Spec_String40(t *testing.T) { + input := "str4 = \"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"\nstr5 = \"\"\"Here are three quotation marks: \"\"\".\"\"\" # INVALID\nstr5 = \"\"\"Here are three quotation marks: \"\"\\\".\"\"\"\nstr6 = \"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"\n\n# \"This,\" she said, \"is just a pointless statement.\"\nstr7 = \"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Table_Duplicate(t *testing.T) { +func TestTOMLTest_Invalid_Spec_String70(t *testing.T) { + input := "quot15 = '''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"'''\n\napos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID\napos15 = \"Here are fifteen apostrophes: '''''''''''''''\"\n\n# 'That,' she said, 'is still pointless.'\nstr = ''''That,' she said, 'is still pointless.''''\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Spec_Table90(t *testing.T) { + input := "[fruit]\napple.color = \"red\"\napple.taste.sweet = true\n\n[fruit.apple] # INVALID\n# [fruit.apple.taste] # INVALID\n\n[fruit.apple.texture] # you can add sub-tables\nsmooth = true\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Spec_Table91(t *testing.T) { + input := "[fruit]\napple.color = \"red\"\napple.taste.sweet = true\n\n# [fruit.apple] # INVALID\n[fruit.apple.taste] # INVALID\n\n[fruit.apple.texture] # you can add sub-tables\nsmooth = true\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadByteEscape(t *testing.T) { + input := "naughty = \"\\xAg\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadConcat(t *testing.T) { + input := "no_concat = \"first\" \"second\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadEscape1(t *testing.T) { + input := "invalid-escape = \"This string has a bad \\a escape character.\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadEscape2(t *testing.T) { + input := "invalid-escape = \"This string has a bad \\ escape character.\"\n\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadEscape3(t *testing.T) { + input := "backslash = \"\\\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadHexEsc1(t *testing.T) { + input := "bad-hex-esc-1 = \"\\x0g\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadHexEsc2(t *testing.T) { + input := "bad-hex-esc-2 = \"\\xG0\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadHexEsc3(t *testing.T) { + input := "bad-hex-esc-3 = \"\\x\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadHexEsc4(t *testing.T) { + input := "bad-hex-esc-4 = \"\\x 50\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadHexEsc5(t *testing.T) { + input := "bad-hex-esc-5 = \"\\x 50\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadMultiline(t *testing.T) { + input := "multi = \"first line\nsecond line\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadSlashEscape(t *testing.T) { + input := "invalid-escape = \"This string has a bad \\/ escape character.\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadUniEsc1(t *testing.T) { + input := "bad-uni-esc-1 = \"val\\ue\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadUniEsc2(t *testing.T) { + input := "bad-uni-esc-2 = \"val\\Ux\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadUniEsc3(t *testing.T) { + input := "bad-uni-esc-3 = \"val\\U0000000\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadUniEsc4(t *testing.T) { + input := "bad-uni-esc-4 = \"val\\U0000\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadUniEsc5(t *testing.T) { + input := "bad-uni-esc-5 = \"val\\Ugggggggg\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadUniEsc6(t *testing.T) { + input := "bad-uni-esc-6 = \"This string contains a non scalar unicode codepoint \\uD801\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BadUniEsc7(t *testing.T) { + input := "bad-uni-esc-7 = \"\\uabag\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BasicByteEscapes(t *testing.T) { + input := "answer = \"\\x33\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BasicMultilineOutOfRangeUnicodeEscape1(t *testing.T) { + input := "a = \"\"\"\\UFFFFFFFF\"\"\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BasicMultilineOutOfRangeUnicodeEscape2(t *testing.T) { + input := "a = \"\"\"\\U00D80000\"\"\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BasicMultilineQuotes(t *testing.T) { + input := "str5 = \"\"\"Here are three quotation marks: \"\"\".\"\"\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BasicMultilineUnknownEscape(t *testing.T) { + input := "a = \"\"\"\\@\"\"\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BasicOutOfRangeUnicodeEscape1(t *testing.T) { + input := "a = \"\\UFFFFFFFF\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BasicOutOfRangeUnicodeEscape2(t *testing.T) { + input := "a = \"\\U00D80000\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_BasicUnknownEscape(t *testing.T) { + input := "a = \"\\@\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_LiteralMultilineQuotes1(t *testing.T) { + input := "a = '''6 apostrophes: ''''''\n\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_LiteralMultilineQuotes2(t *testing.T) { + input := "a = '''15 apostrophes: ''''''''''''''''''\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MissingQuotes(t *testing.T) { + input := "name = value\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineBadEscape1(t *testing.T) { + input := "k = \"\"\"t\\a\"\"\"\n\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineBadEscape2(t *testing.T) { + input := "# \\ is not a valid escape.\nk = \"\"\"t\\ t\"\"\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineBadEscape3(t *testing.T) { + input := "# \\ is not a valid escape.\nk = \"\"\"t\\ \"\"\"\n\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineBadEscape4(t *testing.T) { + input := "backslash = \"\"\"\\\"\"\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineEscapeSpace1(t *testing.T) { + input := "a = \"\"\"\n foo \\ \\n\n bar\"\"\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineEscapeSpace2(t *testing.T) { + input := "bee = \"\"\"\nhee \\\n\ngee \\ \"\"\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineLitNoClose1(t *testing.T) { + input := "invalid = '''\n this will fail\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineLitNoClose2(t *testing.T) { + input := "x='''\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineLitNoClose3(t *testing.T) { + input := "not-closed= '''\ndiibaa\nblibae ete\neteta\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineLitNoClose4(t *testing.T) { + input := "bee = '''\nhee\ngee ''\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineNoClose1(t *testing.T) { + input := "invalid = \"\"\"\n this will fail\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineNoClose2(t *testing.T) { + input := "x=\"\"\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineNoClose3(t *testing.T) { + input := "not-closed= \"\"\"\ndiibaa\nblibae ete\neteta\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineNoClose4(t *testing.T) { + input := "bee = \"\"\"\nhee\ngee \"\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineNoClose5(t *testing.T) { + input := "bee = \"\"\"\nhee\ngee\\\t \n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_MultilineQuotes1(t *testing.T) { + input := "a = \"\"\"6 quotes: \"\"\"\"\"\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_NoClose1(t *testing.T) { + input := "no-ending-quote = \"One time, at band camp\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_NoClose2(t *testing.T) { + input := "\"a-string\".must-be = \"closed\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_NoClose3(t *testing.T) { + input := "no-ending-quote = 'One time, at band camp\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_NoClose4(t *testing.T) { + input := "'a-string'.must-be = 'closed\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_TextAfterString(t *testing.T) { + input := "string = \"Is there life after strings?\" No.\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_String_WrongClose(t *testing.T) { + input := "bad-ending-quote = \"double and single'\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_AppendToArrayWithDottedKeys(t *testing.T) { + input := "[[a.b]]\n\n[a]\nb.y = 2\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_AppendWithDottedKeys1(t *testing.T) { + input := "# First a.b.c defines a table: a.b.c = {z=9}\n#\n# Then we define a.b.c.t = \"str\" to add a str to the above table, making it:\n#\n# a.b.c = {z=9, t=\"...\"}\n#\n# While this makes sense, logically, it was decided this is not valid TOML as\n# it's too confusing/convoluted.\n# \n# See: https://github.com/toml-lang/toml/issues/846\n# https://github.com/toml-lang/toml/pull/859\n\n[a.b.c]\n z = 9\n\n[a]\n b.c.t = \"Using dotted keys to add to [a.b.c] after explicitly defining it above is not allowed\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_AppendWithDottedKeys2(t *testing.T) { + input := "# This is the same issue as in injection-1.toml, except that nests one level\n# deeper. See that file for a more complete description.\n\n[a.b.c.d]\n z = 9\n\n[a]\n b.c.d.k.t = \"Using dotted keys to add to [a.b.c.d] after explicitly defining it above is not allowed\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_ArrayEmpty(t *testing.T) { + input := "[[]]\nname = \"Born to Run\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_ArrayImplicit(t *testing.T) { + input := "# This test is a bit tricky. It should fail because the first use of\n# `[[albums.songs]]` without first declaring `albums` implies that `albums`\n# must be a table. The alternative would be quite weird. Namely, it wouldn't\n# comply with the TOML spec: \"Each double-bracketed sub-table will belong to \n# the most *recently* defined table element *above* it.\"\n#\n# This is in contrast to the *valid* test, table-array-implicit where\n# `[[albums.songs]]` works by itself, so long as `[[albums]]` isn't declared\n# later. (Although, `[albums]` could be.)\n[[albums.songs]]\nname = \"Glory Days\"\n\n[[albums]]\nname = \"Born in the USA\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_ArrayNoClose1(t *testing.T) { + input := "[[albums]\nname = \"Born to Run\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_ArrayNoClose2(t *testing.T) { + input := "[[closing-bracket.missing]\nblaa=2\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_DuplicateKeyDottedArray(t *testing.T) { + input := "[fruit]\napple.color = \"red\"\n\n[[fruit.apple]]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_DuplicateKeyDottedTable(t *testing.T) { + input := "[fruit]\napple.color = \"red\"\n\n[fruit.apple] # INVALID\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_DuplicateKeyDottedTable2(t *testing.T) { + input := "[fruit]\napple.taste.sweet = true\n\n[fruit.apple.taste] # INVALID\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_DuplicateKeyTable(t *testing.T) { + input := "[fruit]\ntype = \"apple\"\n\n[fruit.type]\napple = \"yes\"\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_DuplicateTableArray(t *testing.T) { + input := "[tbl]\n[[tbl]]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_DuplicateTableArray2(t *testing.T) { + input := "[[tbl]]\n[tbl]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_Duplicate(t *testing.T) { input := "[a]\nb = 1\n\n[a]\nc = 2\n" testgenInvalid(t, input) } @@ -1085,16 +1705,61 @@ func TestTOMLTest_Invalid_Table_NestedBracketsOpen(t *testing.T) { testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Table_QuotedNoClose(t *testing.T) { - input := "[\"where will it end]\nname = value\n" +func TestTOMLTest_Invalid_Table_NoClose1(t *testing.T) { + input := "[where will it end\nname = value\n\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_NoClose2(t *testing.T) { + input := "[closing-bracket.missingö\nblaa=2\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_NoClose3(t *testing.T) { + input := "[\"where will it end]\nname = value\n\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_NoClose4(t *testing.T) { + input := "[\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_NoClose5(t *testing.T) { + input := "[fwfw.wafw\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_OverwriteArrayInParent(t *testing.T) { + input := "[[parent-table.arr]]\n[parent-table]\nnot-arr = 1\narr = 2\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_OverwriteBoolWithArray(t *testing.T) { + input := "a=true\n[[a]]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_OverwriteWithDeepTable(t *testing.T) { + input := "a=1\n[a.b.c.d]\n" testgenInvalid(t, input) } -func TestTOMLTest_Invalid_Table_Redefine(t *testing.T) { +func TestTOMLTest_Invalid_Table_Redefine1(t *testing.T) { input := "# Define b as int, and try to use it as a table: error\n[a]\nb = 1\n\n[a.b]\nc = 2\n" testgenInvalid(t, input) } +func TestTOMLTest_Invalid_Table_Redefine2(t *testing.T) { + input := "[t1]\nt2.t3.v = 0\n[t1.t2]\n" + testgenInvalid(t, input) +} + +func TestTOMLTest_Invalid_Table_Redefine3(t *testing.T) { + input := "[t1]\nt2.t3.v = 0\n[t1.t2.t3]\n" + testgenInvalid(t, input) +} + func TestTOMLTest_Invalid_Table_Rrbrace(t *testing.T) { input := "[[table] ]\n" testgenInvalid(t, input) @@ -1115,6 +1780,12 @@ func TestTOMLTest_Invalid_Table_WithPound(t *testing.T) { testgenInvalid(t, input) } +func TestTOMLTest_Valid_Array_ArraySubtables(t *testing.T) { + input := "[[arr]]\n[arr.subtab]\nval=1\n\n[[arr]]\n[arr.subtab]\nval=2\n" + jsonRef := "{\n \"arr\": [\n {\n \"subtab\": {\n \"val\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n }\n },\n {\n \"subtab\": {\n \"val\": {\n \"type\": \"integer\",\n \"value\": \"2\"\n }\n }\n }\n ]\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Array_Array(t *testing.T) { input := "ints = [1, 2, 3, ]\nfloats = [1.1, 2.1, 3.1]\nstrings = [\"a\", \"b\", \"c\"]\ndates = [\n 1987-07-05T17:45:00Z,\n 1979-05-27T07:32:00Z,\n 2006-06-01T11:00:00Z,\n]\ncomments = [\n 1,\n 2, #this is ok\n]\n" jsonRef := "{\n \"comments\": [\n {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"2\"\n }\n ],\n \"dates\": [\n {\n \"type\": \"datetime\",\n \"value\": \"1987-07-05T17:45:00Z\"\n },\n {\n \"type\": \"datetime\",\n \"value\": \"1979-05-27T07:32:00Z\"\n },\n {\n \"type\": \"datetime\",\n \"value\": \"2006-06-01T11:00:00Z\"\n }\n ],\n \"floats\": [\n {\n \"type\": \"float\",\n \"value\": \"1.1\"\n },\n {\n \"type\": \"float\",\n \"value\": \"2.1\"\n },\n {\n \"type\": \"float\",\n \"value\": \"3.1\"\n }\n ],\n \"ints\": [\n {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"2\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"3\"\n }\n ],\n \"strings\": [\n {\n \"type\": \"string\",\n \"value\": \"a\"\n },\n {\n \"type\": \"string\",\n \"value\": \"b\"\n },\n {\n \"type\": \"string\",\n \"value\": \"c\"\n }\n ]\n}\n" @@ -1158,8 +1829,8 @@ func TestTOMLTest_Valid_Array_MixedIntString(t *testing.T) { } func TestTOMLTest_Valid_Array_MixedStringTable(t *testing.T) { - input := "contributors = [\n \"Foo Bar \",\n { name = \"Baz Qux\", email = \"bazqux@example.com\", url = \"https://example.com/bazqux\" }\n]\n" - jsonRef := "{\n \"contributors\": [\n {\n \"type\": \"string\",\n \"value\": \"Foo Bar \\u003cfoo@example.com\\u003e\"\n },\n {\n \"email\": {\n \"type\": \"string\",\n \"value\": \"bazqux@example.com\"\n },\n \"name\": {\n \"type\": \"string\",\n \"value\": \"Baz Qux\"\n },\n \"url\": {\n \"type\": \"string\",\n \"value\": \"https://example.com/bazqux\"\n }\n }\n ]\n}\n" + input := "contributors = [\n \"Foo Bar \",\n { name = \"Baz Qux\", email = \"bazqux@example.com\", url = \"https://example.com/bazqux\" }\n]\n\n# Start with a table as the first element. This tests a case that some libraries\n# might have where they will check if the first entry is a table/map/hash/assoc\n# array and then encode it as a table array. This was a reasonable thing to do\n# before TOML 1.0 since arrays could only contain one type, but now it's no\n# longer.\nmixed = [{k=\"a\"}, \"b\", 1]\n" + jsonRef := "{\n \"contributors\": [\n {\n \"type\": \"string\",\n \"value\": \"Foo Bar \\u003cfoo@example.com\\u003e\"\n },\n {\n \"email\": {\n \"type\": \"string\",\n \"value\": \"bazqux@example.com\"\n },\n \"name\": {\n \"type\": \"string\",\n \"value\": \"Baz Qux\"\n },\n \"url\": {\n \"type\": \"string\",\n \"value\": \"https://example.com/bazqux\"\n }\n }\n ],\n \"mixed\": [\n {\n \"k\": {\n \"type\": \"string\",\n \"value\": \"a\"\n }\n },\n {\n \"type\": \"string\",\n \"value\": \"b\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n ]\n}\n" testgenValid(t, input, jsonRef) } @@ -1187,6 +1858,12 @@ func TestTOMLTest_Valid_Array_Nospaces(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Array_OpenParentTable(t *testing.T) { + input := "[[parent-table.arr]]\n[[parent-table.arr]]\n[parent-table]\nnot-arr = 1\n" + jsonRef := "{\n \"parent-table\": {\n \"arr\": [\n {},\n {}\n ],\n \"not-arr\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Array_StringQuoteComma2(t *testing.T) { input := "title = [ \" \\\", \",]\n" jsonRef := "{\n \"title\": [\n {\n \"type\": \"string\",\n \"value\": \" \\\", \"\n }\n ]\n}\n" @@ -1199,6 +1876,12 @@ func TestTOMLTest_Valid_Array_StringQuoteComma(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Array_StringWithComma2(t *testing.T) { + input := "title = [\n\"\"\"Client: XXXX,\nJob: XXXX\"\"\",\n\"Code: XXXX\"\n]\n" + jsonRef := "{\n \"title\": [\n {\n \"type\": \"string\",\n \"value\": \"Client: XXXX,\\nJob: XXXX\"\n },\n {\n \"type\": \"string\",\n \"value\": \"Code: XXXX\"\n }\n ]\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Array_StringWithComma(t *testing.T) { input := "title = [\n\"Client: XXXX, Job: XXXX\",\n\"Code: XXXX\"\n]\n" jsonRef := "{\n \"title\": [\n {\n \"type\": \"string\",\n \"value\": \"Client: XXXX, Job: XXXX\"\n },\n {\n \"type\": \"string\",\n \"value\": \"Code: XXXX\"\n }\n ]\n}\n" @@ -1217,12 +1900,24 @@ func TestTOMLTest_Valid_Array_TableArrayStringBackslash(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Array_TrailingComma(t *testing.T) { + input := "arr-1 = [1,]\n\narr-2 = [2,3,]\n\narr-3 = [4,\n]\n\narr-4 = [\n\t5,\n\t6,\n]\n" + jsonRef := "{\n \"arr-1\": [\n {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n ],\n \"arr-2\": [\n {\n \"type\": \"integer\",\n \"value\": \"2\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"3\"\n }\n ],\n \"arr-3\": [\n {\n \"type\": \"integer\",\n \"value\": \"4\"\n }\n ],\n \"arr-4\": [\n {\n \"type\": \"integer\",\n \"value\": \"5\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"6\"\n }\n ]\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Bool_Bool(t *testing.T) { input := "t = true\nf = false\n" jsonRef := "{\n \"f\": {\n \"type\": \"bool\",\n \"value\": \"false\"\n },\n \"t\": {\n \"type\": \"bool\",\n \"value\": \"true\"\n }\n}\n" testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Comment_AfterLiteralNoWs(t *testing.T) { + input := "inf=inf#infinity\nnan=nan#not a number\ntrue=true#true\nfalse=false#false\n" + jsonRef := "{\n \"false\": {\n \"type\": \"bool\",\n \"value\": \"false\"\n },\n \"inf\": {\n \"type\": \"float\",\n \"value\": \"inf\"\n },\n \"nan\": {\n \"type\": \"float\",\n \"value\": \"nan\"\n },\n \"true\": {\n \"type\": \"bool\",\n \"value\": \"true\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Comment_AtEof(t *testing.T) { input := "# This is a full-line comment\nkey = \"value\" # This is a comment at the end of a line\n" jsonRef := "{\n \"key\": {\n \"type\": \"string\",\n \"value\": \"value\"\n }\n}\n" @@ -1237,7 +1932,7 @@ func TestTOMLTest_Valid_Comment_AtEof2(t *testing.T) { func TestTOMLTest_Valid_Comment_Everywhere(t *testing.T) { input := "# Top comment.\n # Top comment.\n# Top comment.\n\n# [no-extraneous-groups-please]\n\n[group] # Comment\nanswer = 42 # Comment\n# no-extraneous-keys-please = 999\n# Inbetween comment.\nmore = [ # Comment\n # What about multiple # comments?\n # Can you handle it?\n #\n # Evil.\n# Evil.\n 42, 42, # Comments within arrays are fun.\n # What about multiple # comments?\n # Can you handle it?\n #\n # Evil.\n# Evil.\n# ] Did I fool you?\n] # Hopefully not.\n\n# Make sure the space between the datetime and \"#\" isn't lexed.\ndt = 1979-05-27T07:32:12-07:00 # c\nd = 1979-05-27 # Comment\n" - jsonRef := "{\n \"group\": {\n \"answer\": {\n \"type\": \"integer\",\n \"value\": \"42\"\n },\n \"dt\": {\n \"type\": \"datetime\",\n \"value\": \"1979-05-27T07:32:12-07:00\"\n },\n \"d\": {\n \"type\": \"date-local\",\n \"value\": \"1979-05-27\"\n },\n \"more\": [\n {\n \"type\": \"integer\",\n \"value\": \"42\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"42\"\n }\n ]\n }\n}\n" + jsonRef := "{\n \"group\": {\n \"answer\": {\n \"type\": \"integer\",\n \"value\": \"42\"\n },\n \"d\": {\n \"type\": \"date-local\",\n \"value\": \"1979-05-27\"\n },\n \"dt\": {\n \"type\": \"datetime\",\n \"value\": \"1979-05-27T07:32:12-07:00\"\n },\n \"more\": [\n {\n \"type\": \"integer\",\n \"value\": \"42\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"42\"\n }\n ]\n }\n}\n" testgenValid(t, input, jsonRef) } @@ -1247,6 +1942,12 @@ func TestTOMLTest_Valid_Comment_Noeol(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Comment_Nonascii(t *testing.T) { + input := "# ~ \u0080 ÿ \ud7ff \ue000 \uffff 𐀀 \U0010ffff\n" + jsonRef := "{}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Comment_Tricky(t *testing.T) { input := "[section]#attached comment\n#[notsection]\none = \"11\"#cmt\ntwo = \"22#\"\nthree = '#'\n\nfour = \"\"\"# no comment\n# nor this\n#also not comment\"\"\"#is_comment\n\nfive = 5.5#66\nsix = 6#7\n8 = \"eight\"\n#nine = 99\nten = 10e2#1\neleven = 1.11e1#23\n\n[\"hash#tag\"]\n\"#!\" = \"hash bang\"\narr3 = [ \"#\", '#', \"\"\"###\"\"\" ]\narr4 = [ 1,# 9, 9,\n2#,9\n,#9\n3#]\n,4]\narr5 = [[[[#[\"#\"],\n[\"#\"]]]]#]\n]\ntbl1 = { \"#\" = '}#'}#}}\n\n\n" jsonRef := "{\n \"hash#tag\": {\n \"#!\": {\n \"type\": \"string\",\n \"value\": \"hash bang\"\n },\n \"arr3\": [\n {\n \"type\": \"string\",\n \"value\": \"#\"\n },\n {\n \"type\": \"string\",\n \"value\": \"#\"\n },\n {\n \"type\": \"string\",\n \"value\": \"###\"\n }\n ],\n \"arr4\": [\n {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"2\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"3\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"4\"\n }\n ],\n \"arr5\": [\n [\n [\n [\n [\n {\n \"type\": \"string\",\n \"value\": \"#\"\n }\n ]\n ]\n ]\n ]\n ],\n \"tbl1\": {\n \"#\": {\n \"type\": \"string\",\n \"value\": \"}#\"\n }\n }\n },\n \"section\": {\n \"8\": {\n \"type\": \"string\",\n \"value\": \"eight\"\n },\n \"eleven\": {\n \"type\": \"float\",\n \"value\": \"11.1\"\n },\n \"five\": {\n \"type\": \"float\",\n \"value\": \"5.5\"\n },\n \"four\": {\n \"type\": \"string\",\n \"value\": \"# no comment\\n# nor this\\n#also not comment\"\n },\n \"one\": {\n \"type\": \"string\",\n \"value\": \"11\"\n },\n \"six\": {\n \"type\": \"integer\",\n \"value\": \"6\"\n },\n \"ten\": {\n \"type\": \"float\",\n \"value\": \"1000.0\"\n },\n \"three\": {\n \"type\": \"string\",\n \"value\": \"#\"\n },\n \"two\": {\n \"type\": \"string\",\n \"value\": \"22#\"\n }\n }\n}\n" @@ -1259,6 +1960,18 @@ func TestTOMLTest_Valid_Datetime_Datetime(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Datetime_Edge(t *testing.T) { + input := "first-offset = 0001-01-01 00:00:00Z\nfirst-local = 0001-01-01 00:00:00\nfirst-date = 0001-01-01\n\nlast-offset = 9999-12-31 23:59:59Z\nlast-local = 9999-12-31 23:59:59\nlast-date = 9999-12-31\n" + jsonRef := "{\n \"first-date\": {\n \"type\": \"date-local\",\n \"value\": \"0001-01-01\"\n },\n \"first-local\": {\n \"type\": \"datetime-local\",\n \"value\": \"0001-01-01T00:00:00\"\n },\n \"first-offset\": {\n \"type\": \"datetime\",\n \"value\": \"0001-01-01T00:00:00Z\"\n },\n \"last-date\": {\n \"type\": \"date-local\",\n \"value\": \"9999-12-31\"\n },\n \"last-local\": {\n \"type\": \"datetime-local\",\n \"value\": \"9999-12-31T23:59:59\"\n },\n \"last-offset\": {\n \"type\": \"datetime\",\n \"value\": \"9999-12-31T23:59:59Z\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Datetime_LeapYear(t *testing.T) { + input := "2000-datetime = 2000-02-29 15:15:15Z\n2000-datetime-local = 2000-02-29 15:15:15\n2000-date = 2000-02-29\n\n2024-datetime = 2024-02-29 15:15:15Z\n2024-datetime-local = 2024-02-29 15:15:15\n2024-date = 2024-02-29\n" + jsonRef := "{\n \"2000-date\": {\n \"type\": \"date-local\",\n \"value\": \"2000-02-29\"\n },\n \"2000-datetime\": {\n \"type\": \"datetime\",\n \"value\": \"2000-02-29T15:15:15Z\"\n },\n \"2000-datetime-local\": {\n \"type\": \"datetime-local\",\n \"value\": \"2000-02-29T15:15:15\"\n },\n \"2024-date\": {\n \"type\": \"date-local\",\n \"value\": \"2024-02-29\"\n },\n \"2024-datetime\": {\n \"type\": \"datetime\",\n \"value\": \"2024-02-29T15:15:15Z\"\n },\n \"2024-datetime-local\": {\n \"type\": \"datetime-local\",\n \"value\": \"2024-02-29T15:15:15\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Datetime_LocalDate(t *testing.T) { input := "bestdayever = 1987-07-05\n" jsonRef := "{\n \"bestdayever\": {\n \"type\": \"date-local\",\n \"value\": \"1987-07-05\"\n }\n}\n" @@ -1278,8 +1991,14 @@ func TestTOMLTest_Valid_Datetime_Local(t *testing.T) { } func TestTOMLTest_Valid_Datetime_Milliseconds(t *testing.T) { - input := "utc1 = 1987-07-05T17:45:56.1234Z\nutc2 = 1987-07-05T17:45:56.6Z\nwita1 = 1987-07-05T17:45:56.1234+08:00\nwita2 = 1987-07-05T17:45:56.6+08:00\n" - jsonRef := "{\n \"utc1\": {\n \"type\": \"datetime\",\n \"value\": \"1987-07-05T17:45:56.1234Z\"\n },\n \"utc2\": {\n \"type\": \"datetime\",\n \"value\": \"1987-07-05T17:45:56.6000Z\"\n },\n \"wita1\": {\n \"type\": \"datetime\",\n \"value\": \"1987-07-05T17:45:56.1234+08:00\"\n },\n \"wita2\": {\n \"type\": \"datetime\",\n \"value\": \"1987-07-05T17:45:56.6000+08:00\"\n }\n}\n" + input := "utc1 = 1987-07-05T17:45:56.123Z\nutc2 = 1987-07-05T17:45:56.6Z\nwita1 = 1987-07-05T17:45:56.123+08:00\nwita2 = 1987-07-05T17:45:56.6+08:00\n" + jsonRef := "{\n \"utc1\": {\n \"type\": \"datetime\",\n \"value\": \"1987-07-05T17:45:56.123Z\"\n },\n \"utc2\": {\n \"type\": \"datetime\",\n \"value\": \"1987-07-05T17:45:56.600Z\"\n },\n \"wita1\": {\n \"type\": \"datetime\",\n \"value\": \"1987-07-05T17:45:56.123+08:00\"\n },\n \"wita2\": {\n \"type\": \"datetime\",\n \"value\": \"1987-07-05T17:45:56.600+08:00\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Datetime_NoSeconds(t *testing.T) { + input := "# Seconds are optional in date-time and time.\nwithout-seconds-1 = 13:37\nwithout-seconds-2 = 1979-05-27 07:32Z\nwithout-seconds-3 = 1979-05-27 07:32-07:00\nwithout-seconds-4 = 1979-05-27T07:32\n" + jsonRef := "{\n \"without-seconds-1\": {\n \"type\": \"time-local\",\n \"value\": \"13:37:00\"\n },\n \"without-seconds-2\": {\n \"type\": \"datetime\",\n \"value\": \"1979-05-27T07:32:00Z\"\n },\n \"without-seconds-3\": {\n \"type\": \"datetime\",\n \"value\": \"1979-05-27T07:32:00-07:00\"\n },\n \"without-seconds-4\": {\n \"type\": \"datetime-local\",\n \"value\": \"1979-05-27T07:32:00\"\n }\n}\n" testgenValid(t, input, jsonRef) } @@ -1333,7 +2052,7 @@ func TestTOMLTest_Valid_Float_Underscore(t *testing.T) { func TestTOMLTest_Valid_Float_Zero(t *testing.T) { input := "zero = 0.0\nsigned-pos = +0.0\nsigned-neg = -0.0\nexponent = 0e0\nexponent-two-0 = 0e00\nexponent-signed-pos = +0e0\nexponent-signed-neg = -0e0\n" - jsonRef := "{\n \"zero\": {\n \"type\": \"float\",\n \"value\": \"0\"\n },\n \"signed-pos\": {\n \"type\": \"float\",\n \"value\": \"0\"\n },\n \"signed-neg\": {\n \"type\": \"float\",\n \"value\": \"0\"\n },\n \"exponent\": {\n \"type\": \"float\",\n \"value\": \"0\"\n },\n \"exponent-two-0\": {\n \"type\": \"float\",\n \"value\": \"0\"\n },\n \"exponent-signed-pos\": {\n \"type\": \"float\",\n \"value\": \"0\"\n },\n \"exponent-signed-neg\": {\n \"type\": \"float\",\n \"value\": \"0\"\n }\n}\n" + jsonRef := "{\n \"exponent\": {\n \"type\": \"float\",\n \"value\": \"0\"\n },\n \"exponent-signed-neg\": {\n \"type\": \"float\",\n \"value\": \"-0\"\n },\n \"exponent-signed-pos\": {\n \"type\": \"float\",\n \"value\": \"0\"\n },\n \"exponent-two-0\": {\n \"type\": \"float\",\n \"value\": \"0\"\n },\n \"signed-neg\": {\n \"type\": \"float\",\n \"value\": \"-0\"\n },\n \"signed-pos\": {\n \"type\": \"float\",\n \"value\": \"0\"\n },\n \"zero\": {\n \"type\": \"float\",\n \"value\": \"0\"\n }\n}\n" testgenValid(t, input, jsonRef) } @@ -1368,8 +2087,8 @@ func TestTOMLTest_Valid_InlineTable_Bool(t *testing.T) { } func TestTOMLTest_Valid_InlineTable_Empty(t *testing.T) { - input := "empty1 = {}\nempty2 = { }\nempty_in_array = [ { not_empty = 1 }, {} ]\nempty_in_array2 = [{},{not_empty=1}]\nmany_empty = [{},{},{}]\nnested_empty = {\"empty\"={}}\n" - jsonRef := "{\n \"empty1\": {},\n \"empty2\": {},\n \"empty_in_array\": [\n {\n \"not_empty\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n },\n {}\n ],\n \"empty_in_array2\": [\n {},\n {\n \"not_empty\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n }\n ],\n \"many_empty\": [\n {},\n {},\n {}\n ],\n \"nested_empty\": {\n \"empty\": {}\n }\n}\n" + input := "empty1 = {}\nempty2 = { }\nempty_in_array = [ { not_empty = 1 }, {} ]\nempty_in_array2 = [{},{not_empty=1}]\nmany_empty = [{},{},{}]\nnested_empty = {\"empty\"={}}\nwith_cmt ={ }#nothing here\n" + jsonRef := "{\n \"empty1\": {},\n \"empty2\": {},\n \"empty_in_array\": [\n {\n \"not_empty\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n },\n {}\n ],\n \"empty_in_array2\": [\n {},\n {\n \"not_empty\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n }\n ],\n \"many_empty\": [\n {},\n {},\n {}\n ],\n \"nested_empty\": {\n \"empty\": {}\n },\n \"with_cmt\": {}\n}\n" testgenValid(t, input, jsonRef) } @@ -1403,6 +2122,18 @@ func TestTOMLTest_Valid_InlineTable_Nest(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_InlineTable_Newline(t *testing.T) { + input := "# TOML 1.1 supports newlines in inline tables and trailing commas.\n\ntrailing-comma-1 = {\n\tc = 1,\n}\ntrailing-comma-2 = { c = 1, }\n\ntbl-1 = {\n\thello = \"world\",\n\t1 = 2,\n\tarr = [1,\n\t 2,\n\t 3,\n\t ],\n\ttbl = {\n\t\t k = 1,\n\t}\n}\n\ntbl-2 = {\n\tk = \"\"\"\n\tHello\n\t\"\"\"\n}\n" + jsonRef := "{\n \"tbl-1\": {\n \"1\": {\n \"type\": \"integer\",\n \"value\": \"2\"\n },\n \"arr\": [\n {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"2\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"3\"\n }\n ],\n \"hello\": {\n \"type\": \"string\",\n \"value\": \"world\"\n },\n \"tbl\": {\n \"k\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n }\n },\n \"tbl-2\": {\n \"k\": {\n \"type\": \"string\",\n \"value\": \"\\tHello\\n\\t\"\n }\n },\n \"trailing-comma-1\": {\n \"c\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n },\n \"trailing-comma-2\": {\n \"c\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_InlineTable_Spaces(t *testing.T) { + input := "# https://github.com/toml-lang/toml-test/issues/146\nclap-1 = { version = \"4\" , features = [\"derive\", \"cargo\"] }\n\n# Contains some literal tabs!\nclap-2 = { version = \"4\"\t \t,\t \tfeatures = [ \"derive\" \t , \t \"cargo\" ] , nest = { \t \"a\" = 'x' , \t 'b' = [ 1.5 , 9.0 ] } }\n" + jsonRef := "{\n \"clap-1\": {\n \"features\": [\n {\n \"type\": \"string\",\n \"value\": \"derive\"\n },\n {\n \"type\": \"string\",\n \"value\": \"cargo\"\n }\n ],\n \"version\": {\n \"type\": \"string\",\n \"value\": \"4\"\n }\n },\n \"clap-2\": {\n \"features\": [\n {\n \"type\": \"string\",\n \"value\": \"derive\"\n },\n {\n \"type\": \"string\",\n \"value\": \"cargo\"\n }\n ],\n \"nest\": {\n \"a\": {\n \"type\": \"string\",\n \"value\": \"x\"\n },\n \"b\": [\n {\n \"type\": \"float\",\n \"value\": \"1.5\"\n },\n {\n \"type\": \"float\",\n \"value\": \"9\"\n }\n ]\n },\n \"version\": {\n \"type\": \"string\",\n \"value\": \"4\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Integer_Integer(t *testing.T) { input := "answer = 42\nposanswer = +42\nneganswer = -42\nzero = 0\n" jsonRef := "{\n \"answer\": {\n \"type\": \"integer\",\n \"value\": \"42\"\n },\n \"neganswer\": {\n \"type\": \"integer\",\n \"value\": \"-42\"\n },\n \"posanswer\": {\n \"type\": \"integer\",\n \"value\": \"42\"\n },\n \"zero\": {\n \"type\": \"integer\",\n \"value\": \"0\"\n }\n}\n" @@ -1445,18 +2176,36 @@ func TestTOMLTest_Valid_Key_CaseSensitive(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Key_DottedEmpty(t *testing.T) { + input := "''.x = \"empty.x\"\nx.\"\" = \"x.empty\"\n[a]\n\"\".'' = \"empty.empty\"\n" + jsonRef := "{\n \"\": {\n \"x\": {\n \"type\": \"string\",\n \"value\": \"empty.x\"\n }\n },\n \"a\": {\n \"\": {\n \"\": {\n \"type\": \"string\",\n \"value\": \"empty.empty\"\n }\n }\n },\n \"x\": {\n \"\": {\n \"type\": \"string\",\n \"value\": \"x.empty\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Key_Dotted(t *testing.T) { input := "# Note: this file contains literal tab characters.\n\nname.first = \"Arthur\"\n\"name\".'last' = \"Dent\"\n\nmany.dots.here.dot.dot.dot = 42\n\n# Space are ignored, and key parts can be quoted.\ncount.a = 1\ncount . b = 2\n\"count\".\"c\" = 3\n\"count\" . \"d\" = 4\n'count'.'e' = 5\n'count' . 'f' = 6\n\"count\".'g' = 7\n\"count\" . 'h' = 8\ncount.'i' = 9\ncount \t.\t 'j'\t = 10\n\"count\".k = 11\n\"count\" . l = 12\n\n[tbl]\na.b.c = 42.666\n\n[a.few.dots]\npolka.dot = \"again?\"\npolka.dance-with = \"Dot\"\n\n[[arr]]\na.b.c=1\na.b.d=2\n\n[[arr]]\na.b.c=3\na.b.d=4\n" jsonRef := "{\n \"a\": {\n \"few\": {\n \"dots\": {\n \"polka\": {\n \"dance-with\": {\n \"type\": \"string\",\n \"value\": \"Dot\"\n },\n \"dot\": {\n \"type\": \"string\",\n \"value\": \"again?\"\n }\n }\n }\n }\n },\n \"arr\": [\n {\n \"a\": {\n \"b\": {\n \"c\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n \"d\": {\n \"type\": \"integer\",\n \"value\": \"2\"\n }\n }\n }\n },\n {\n \"a\": {\n \"b\": {\n \"c\": {\n \"type\": \"integer\",\n \"value\": \"3\"\n },\n \"d\": {\n \"type\": \"integer\",\n \"value\": \"4\"\n }\n }\n }\n }\n ],\n \"count\": {\n \"a\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n \"b\": {\n \"type\": \"integer\",\n \"value\": \"2\"\n },\n \"c\": {\n \"type\": \"integer\",\n \"value\": \"3\"\n },\n \"d\": {\n \"type\": \"integer\",\n \"value\": \"4\"\n },\n \"e\": {\n \"type\": \"integer\",\n \"value\": \"5\"\n },\n \"f\": {\n \"type\": \"integer\",\n \"value\": \"6\"\n },\n \"g\": {\n \"type\": \"integer\",\n \"value\": \"7\"\n },\n \"h\": {\n \"type\": \"integer\",\n \"value\": \"8\"\n },\n \"i\": {\n \"type\": \"integer\",\n \"value\": \"9\"\n },\n \"j\": {\n \"type\": \"integer\",\n \"value\": \"10\"\n },\n \"k\": {\n \"type\": \"integer\",\n \"value\": \"11\"\n },\n \"l\": {\n \"type\": \"integer\",\n \"value\": \"12\"\n }\n },\n \"many\": {\n \"dots\": {\n \"here\": {\n \"dot\": {\n \"dot\": {\n \"dot\": {\n \"type\": \"integer\",\n \"value\": \"42\"\n }\n }\n }\n }\n }\n },\n \"name\": {\n \"first\": {\n \"type\": \"string\",\n \"value\": \"Arthur\"\n },\n \"last\": {\n \"type\": \"string\",\n \"value\": \"Dent\"\n }\n },\n \"tbl\": {\n \"a\": {\n \"b\": {\n \"c\": {\n \"type\": \"float\",\n \"value\": \"42.666\"\n }\n }\n }\n }\n}\n" testgenValid(t, input, jsonRef) } -func TestTOMLTest_Valid_Key_Empty(t *testing.T) { +func TestTOMLTest_Valid_Key_Empty1(t *testing.T) { input := "\"\" = \"blank\"\n" jsonRef := "{\n \"\": {\n \"type\": \"string\",\n \"value\": \"blank\"\n }\n}\n" testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Key_Empty2(t *testing.T) { + input := "'' = \"blank\"\n" + jsonRef := "{\n \"\": {\n \"type\": \"string\",\n \"value\": \"blank\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Key_Empty3(t *testing.T) { + input := "''=0\n" + jsonRef := "{\n \"\": {\n \"type\": \"integer\",\n \"value\": \"0\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Key_EqualsNospace(t *testing.T) { input := "answer=42\n" jsonRef := "{\n \"answer\": {\n \"type\": \"integer\",\n \"value\": \"42\"\n }\n}\n" @@ -1464,8 +2213,8 @@ func TestTOMLTest_Valid_Key_EqualsNospace(t *testing.T) { } func TestTOMLTest_Valid_Key_Escapes(t *testing.T) { - input := "\"\\n\" = \"newline\"\n\"\\u00c0\" = \"latin capital letter A with grave\"\n\"\\\"\" = \"just a quote\"\n\n[\"backsp\\b\\b\"]\n\n[\"\\\"quoted\\\"\"]\nquote = true\n\n[\"a.b\".\"\\u00c0\"]\n" - jsonRef := "{\n \"\\n\": {\n \"type\": \"string\",\n \"value\": \"newline\"\n },\n \"\\\"\": {\n \"type\": \"string\",\n \"value\": \"just a quote\"\n },\n \"\\\"quoted\\\"\": {\n \"quote\": {\n \"type\": \"bool\",\n \"value\": \"true\"\n }\n },\n \"a.b\": {\n \"À\": {}\n },\n \"backsp\\u0008\\u0008\": {},\n \"À\": {\n \"type\": \"string\",\n \"value\": \"latin capital letter A with grave\"\n }\n}\n" + input := "\"\\n\" = \"newline\"\n\"\\b\" = \"bell\"\n\"\\u00c0\" = \"latin capital letter A with grave\"\n\"\\\"\" = \"just a quote\"\n\n[\"backsp\\b\\b\"]\n\n[\"\\\"quoted\\\"\"]\nquote = true\n\n[\"a.b\".\"\\u00c0\"]\n" + jsonRef := "{\n \"\\u0008\": {\n \"type\": \"string\",\n \"value\": \"bell\"\n },\n \"\\n\": {\n \"type\": \"string\",\n \"value\": \"newline\"\n },\n \"\\\"\": {\n \"type\": \"string\",\n \"value\": \"just a quote\"\n },\n \"\\\"quoted\\\"\": {\n \"quote\": {\n \"type\": \"bool\",\n \"value\": \"true\"\n }\n },\n \"a.b\": {\n \"À\": {}\n },\n \"backsp\\u0008\\u0008\": {},\n \"À\": {\n \"type\": \"string\",\n \"value\": \"latin capital letter A with grave\"\n }\n}\n" testgenValid(t, input, jsonRef) } @@ -1487,15 +2236,21 @@ func TestTOMLTest_Valid_Key_QuotedDots(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Key_QuotedUnicode(t *testing.T) { + input := "\n\"\\u0000\" = \"null\"\n'\\u0000' = \"different key\"\n\"\\u0008 \\u000c \\U00000041 \\u007f \\u0080 \\u00ff \\ud7ff \\ue000 \\uffff \\U00010000 \\U0010ffff\" = \"escaped key\"\n\n\"~ \u0080 ÿ \ud7ff \ue000 \uffff 𐀀 \U0010ffff\" = \"basic key\"\n'l ~ \u0080 ÿ \ud7ff \ue000 \uffff 𐀀 \U0010ffff' = \"literal key\"\n" + jsonRef := "{\n \"\\u0000\": {\n \"type\": \"string\",\n \"value\": \"null\"\n },\n \"\\u0008 \\u000c A \x7f \u0080 ÿ \ud7ff \ue000 \uffff 𐀀 \U0010ffff\": {\n \"type\": \"string\",\n \"value\": \"escaped key\"\n },\n \"\\\\u0000\": {\n \"type\": \"string\",\n \"value\": \"different key\"\n },\n \"l ~ \u0080 ÿ \ud7ff \ue000 \uffff 𐀀 \U0010ffff\": {\n \"type\": \"string\",\n \"value\": \"literal key\"\n },\n \"~ \u0080 ÿ \ud7ff \ue000 \uffff 𐀀 \U0010ffff\": {\n \"type\": \"string\",\n \"value\": \"basic key\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Key_Space(t *testing.T) { - input := "\"a b\" = 1\n" - jsonRef := "{\n \"a b\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n}\n" + input := "# Keep whitespace inside quotes keys at all positions.\n\"a b\" = 1\n\" c d \" = 2\n\n[ \" tbl \" ]\n\"\\ttab\\ttab\\t\" = \"tab\"\n" + jsonRef := "{\n \" c d \": {\n \"type\": \"integer\",\n \"value\": \"2\"\n },\n \" tbl \": {\n \"\\ttab\\ttab\\t\": {\n \"type\": \"string\",\n \"value\": \"tab\"\n }\n },\n \"a b\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n}\n" testgenValid(t, input, jsonRef) } func TestTOMLTest_Valid_Key_SpecialChars(t *testing.T) { - input := "\"~!@$^&*()_+-`1234567890[]|/?><.,;:'\" = 1\n" - jsonRef := "{\n \"~!@$^\\u0026*()_+-`1234567890[]|/?\\u003e\\u003c.,;:'\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n}\n" + input := "\"=~!@$^&*()_+-`1234567890[]|/?><.,;:'=\" = 1\n" + jsonRef := "{\n \"=~!@$^\\u0026*()_+-`1234567890[]|/?\\u003e\\u003c.,;:'=\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n}\n" testgenValid(t, input, jsonRef) } @@ -1505,6 +2260,18 @@ func TestTOMLTest_Valid_Key_SpecialWord(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Key_Unicode(t *testing.T) { + input := "# TOML 1.1 supports Unicode for bare keys.\n\n€ = 'Euro'\n😂 = \"rofl\"\na\u200db = \"zwj\"\nÅÅ = \"U+00C5 U+0041 U+030A\"\n\n[中文]\n中文 = {中文 = \"Chinese language\"}\n\n[[tiếng-Việt]]\ntiəŋ˧˦.viət̚˧˨ʔ = \"north\"\n\n[[tiếng-Việt]]\ntiəŋ˦˧˥.viək̚˨˩ʔ = \"central\"\n" + jsonRef := "{\n \"a\u200db\": {\n \"type\": \"string\",\n \"value\": \"zwj\"\n },\n \"tiếng-Việt\": [\n {\n \"tiəŋ˧˦\": {\n \"viət̚˧˨ʔ\": {\n \"type\": \"string\",\n \"value\": \"north\"\n }\n }\n },\n {\n \"tiəŋ˦˧˥\": {\n \"viək̚˨˩ʔ\": {\n \"type\": \"string\",\n \"value\": \"central\"\n }\n }\n }\n ],\n \"ÅÅ\": {\n \"type\": \"string\",\n \"value\": \"U+00C5 U+0041 U+030A\"\n },\n \"€\": {\n \"type\": \"string\",\n \"value\": \"Euro\"\n },\n \"中文\": {\n \"中文\": {\n \"中文\": {\n \"type\": \"string\",\n \"value\": \"Chinese language\"\n }\n }\n },\n \"😂\": {\n \"type\": \"string\",\n \"value\": \"rofl\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Key_Zero(t *testing.T) { + input := "0=0\n" + jsonRef := "{\n \"0\": {\n \"type\": \"integer\",\n \"value\": \"0\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_NewlineCrlf(t *testing.T) { input := "os = \"DOS\"\r\nnewline = \"crlf\"\r\n" jsonRef := "{\n \"newline\": {\n \"type\": \"string\",\n \"value\": \"crlf\"\n },\n \"os\": {\n \"type\": \"string\",\n \"value\": \"DOS\"\n }\n}\n" @@ -1529,6 +2296,294 @@ func TestTOMLTest_Valid_SpecExample1(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Spec_Array0(t *testing.T) { + input := "integers = [ 1, 2, 3 ]\ncolors = [ \"red\", \"yellow\", \"green\" ]\nnested_arrays_of_ints = [ [ 1, 2 ], [3, 4, 5] ]\nnested_mixed_array = [ [ 1, 2 ], [\"a\", \"b\", \"c\"] ]\nstring_array = [ \"all\", 'strings', \"\"\"are the same\"\"\", '''type''' ]\n\n# Mixed-type arrays are allowed\nnumbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]\ncontributors = [\n \"Foo Bar \",\n { name = \"Baz Qux\", email = \"bazqux@example.com\", url = \"https://example.com/bazqux\" }\n]\n" + jsonRef := "{\n \"colors\": [\n {\n \"type\": \"string\",\n \"value\": \"red\"\n },\n {\n \"type\": \"string\",\n \"value\": \"yellow\"\n },\n {\n \"type\": \"string\",\n \"value\": \"green\"\n }\n ],\n \"contributors\": [\n {\n \"type\": \"string\",\n \"value\": \"Foo Bar \\u003cfoo@example.com\\u003e\"\n },\n {\n \"email\": {\n \"type\": \"string\",\n \"value\": \"bazqux@example.com\"\n },\n \"name\": {\n \"type\": \"string\",\n \"value\": \"Baz Qux\"\n },\n \"url\": {\n \"type\": \"string\",\n \"value\": \"https://example.com/bazqux\"\n }\n }\n ],\n \"integers\": [\n {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"2\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"3\"\n }\n ],\n \"nested_arrays_of_ints\": [\n [\n {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"2\"\n }\n ],\n [\n {\n \"type\": \"integer\",\n \"value\": \"3\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"4\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"5\"\n }\n ]\n ],\n \"nested_mixed_array\": [\n [\n {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"2\"\n }\n ],\n [\n {\n \"type\": \"string\",\n \"value\": \"a\"\n },\n {\n \"type\": \"string\",\n \"value\": \"b\"\n },\n {\n \"type\": \"string\",\n \"value\": \"c\"\n }\n ]\n ],\n \"numbers\": [\n {\n \"type\": \"float\",\n \"value\": \"0.1\"\n },\n {\n \"type\": \"float\",\n \"value\": \"0.2\"\n },\n {\n \"type\": \"float\",\n \"value\": \"0.5\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"2\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"5\"\n }\n ],\n \"string_array\": [\n {\n \"type\": \"string\",\n \"value\": \"all\"\n },\n {\n \"type\": \"string\",\n \"value\": \"strings\"\n },\n {\n \"type\": \"string\",\n \"value\": \"are the same\"\n },\n {\n \"type\": \"string\",\n \"value\": \"type\"\n }\n ]\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Array1(t *testing.T) { + input := "integers2 = [\n 1, 2, 3\n]\n\nintegers3 = [\n 1,\n 2, # this is ok\n]\n" + jsonRef := "{\n \"integers2\": [\n {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"2\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"3\"\n }\n ],\n \"integers3\": [\n {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n {\n \"type\": \"integer\",\n \"value\": \"2\"\n }\n ]\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_ArrayOfTables0(t *testing.T) { + input := "[[products]]\nname = \"Hammer\"\nsku = 738594937\n\n[[products]] # empty table within the array\n\n[[products]]\nname = \"Nail\"\nsku = 284758393\n\ncolor = \"gray\"\n" + jsonRef := "{\n \"products\": [\n {\n \"name\": {\n \"type\": \"string\",\n \"value\": \"Hammer\"\n },\n \"sku\": {\n \"type\": \"integer\",\n \"value\": \"738594937\"\n }\n },\n {},\n {\n \"color\": {\n \"type\": \"string\",\n \"value\": \"gray\"\n },\n \"name\": {\n \"type\": \"string\",\n \"value\": \"Nail\"\n },\n \"sku\": {\n \"type\": \"integer\",\n \"value\": \"284758393\"\n }\n }\n ]\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_ArrayOfTables1(t *testing.T) { + input := "[[fruits]]\nname = \"apple\"\n\n[fruits.physical] # subtable\ncolor = \"red\"\nshape = \"round\"\n\n[[fruits.varieties]] # nested array of tables\nname = \"red delicious\"\n\n[[fruits.varieties]]\nname = \"granny smith\"\n\n\n[[fruits]]\nname = \"banana\"\n\n[[fruits.varieties]]\nname = \"plantain\"\n" + jsonRef := "{\n \"fruits\": [\n {\n \"name\": {\n \"type\": \"string\",\n \"value\": \"apple\"\n },\n \"physical\": {\n \"color\": {\n \"type\": \"string\",\n \"value\": \"red\"\n },\n \"shape\": {\n \"type\": \"string\",\n \"value\": \"round\"\n }\n },\n \"varieties\": [\n {\n \"name\": {\n \"type\": \"string\",\n \"value\": \"red delicious\"\n }\n },\n {\n \"name\": {\n \"type\": \"string\",\n \"value\": \"granny smith\"\n }\n }\n ]\n },\n {\n \"name\": {\n \"type\": \"string\",\n \"value\": \"banana\"\n },\n \"varieties\": [\n {\n \"name\": {\n \"type\": \"string\",\n \"value\": \"plantain\"\n }\n }\n ]\n }\n ]\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_ArrayOfTables2(t *testing.T) { + input := "points = [ { x = 1, y = 2, z = 3 },\n { x = 7, y = 8, z = 9 },\n { x = 2, y = 4, z = 8 } ]\n" + jsonRef := "{\n \"points\": [\n {\n \"x\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n \"y\": {\n \"type\": \"integer\",\n \"value\": \"2\"\n },\n \"z\": {\n \"type\": \"integer\",\n \"value\": \"3\"\n }\n },\n {\n \"x\": {\n \"type\": \"integer\",\n \"value\": \"7\"\n },\n \"y\": {\n \"type\": \"integer\",\n \"value\": \"8\"\n },\n \"z\": {\n \"type\": \"integer\",\n \"value\": \"9\"\n }\n },\n {\n \"x\": {\n \"type\": \"integer\",\n \"value\": \"2\"\n },\n \"y\": {\n \"type\": \"integer\",\n \"value\": \"4\"\n },\n \"z\": {\n \"type\": \"integer\",\n \"value\": \"8\"\n }\n }\n ]\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Boolean0(t *testing.T) { + input := "bool1 = true\nbool2 = false\n" + jsonRef := "{\n \"bool1\": {\n \"type\": \"bool\",\n \"value\": \"true\"\n },\n \"bool2\": {\n \"type\": \"bool\",\n \"value\": \"false\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Comment0(t *testing.T) { + input := "# This is a full-line comment\nkey = \"value\" # This is a comment at the end of a line\nanother = \"# This is not a comment\"\n" + jsonRef := "{\n \"another\": {\n \"type\": \"string\",\n \"value\": \"# This is not a comment\"\n },\n \"key\": {\n \"type\": \"string\",\n \"value\": \"value\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Float0(t *testing.T) { + input := "# fractional\nflt1 = +1.0\nflt2 = 3.1415\nflt3 = -0.01\n\n# exponent\nflt4 = 5e+22\nflt5 = 1e06\nflt6 = -2E-2\n\n# both\nflt7 = 6.626e-34\n" + jsonRef := "{\n \"flt1\": {\n \"type\": \"float\",\n \"value\": \"1\"\n },\n \"flt2\": {\n \"type\": \"float\",\n \"value\": \"3.1415\"\n },\n \"flt3\": {\n \"type\": \"float\",\n \"value\": \"-0.01\"\n },\n \"flt4\": {\n \"type\": \"float\",\n \"value\": \"5e+22\"\n },\n \"flt5\": {\n \"type\": \"float\",\n \"value\": \"1e+06\"\n },\n \"flt6\": {\n \"type\": \"float\",\n \"value\": \"-0.02\"\n },\n \"flt7\": {\n \"type\": \"float\",\n \"value\": \"6.626e-34\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Float1(t *testing.T) { + input := "flt8 = 224_617.445_991_228\n" + jsonRef := "{\n \"flt8\": {\n \"type\": \"float\",\n \"value\": \"224617.445991228\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Float2(t *testing.T) { + input := "# infinity\nsf1 = inf # positive infinity\nsf2 = +inf # positive infinity\nsf3 = -inf # negative infinity\n\n# not a number\nsf4 = nan # actual sNaN/qNaN encoding is implementation-specific\nsf5 = +nan # same as `nan`\nsf6 = -nan # valid, actual encoding is implementation-specific\n" + jsonRef := "{\n \"sf1\": {\n \"type\": \"float\",\n \"value\": \"+inf\"\n },\n \"sf2\": {\n \"type\": \"float\",\n \"value\": \"+inf\"\n },\n \"sf3\": {\n \"type\": \"float\",\n \"value\": \"-inf\"\n },\n \"sf4\": {\n \"type\": \"float\",\n \"value\": \"nan\"\n },\n \"sf5\": {\n \"type\": \"float\",\n \"value\": \"nan\"\n },\n \"sf6\": {\n \"type\": \"float\",\n \"value\": \"nan\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_InlineTable0(t *testing.T) { + input := "name = { first = \"Tom\", last = \"Preston-Werner\" }\npoint = { x = 1, y = 2 }\nanimal = { type.name = \"pug\" }\n" + jsonRef := "{\n \"animal\": {\n \"type\": {\n \"name\": {\n \"type\": \"string\",\n \"value\": \"pug\"\n }\n }\n },\n \"name\": {\n \"first\": {\n \"type\": \"string\",\n \"value\": \"Tom\"\n },\n \"last\": {\n \"type\": \"string\",\n \"value\": \"Preston-Werner\"\n }\n },\n \"point\": {\n \"x\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n \"y\": {\n \"type\": \"integer\",\n \"value\": \"2\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_InlineTable1(t *testing.T) { + input := "[name]\nfirst = \"Tom\"\nlast = \"Preston-Werner\"\n\n[point]\nx = 1\ny = 2\n\n[animal]\ntype.name = \"pug\"\n" + jsonRef := "{\n \"animal\": {\n \"type\": {\n \"name\": {\n \"type\": \"string\",\n \"value\": \"pug\"\n }\n }\n },\n \"name\": {\n \"first\": {\n \"type\": \"string\",\n \"value\": \"Tom\"\n },\n \"last\": {\n \"type\": \"string\",\n \"value\": \"Preston-Werner\"\n }\n },\n \"point\": {\n \"x\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n },\n \"y\": {\n \"type\": \"integer\",\n \"value\": \"2\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_InlineTable2(t *testing.T) { + input := "[product]\ntype = { name = \"Nail\" }\n# type.edible = false # INVALID\n" + jsonRef := "{\n \"product\": {\n \"type\": {\n \"name\": {\n \"type\": \"string\",\n \"value\": \"Nail\"\n }\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_InlineTable3(t *testing.T) { + input := "[product]\ntype.name = \"Nail\"\n# type = { edible = false } # INVALID\n" + jsonRef := "{\n \"product\": {\n \"type\": {\n \"name\": {\n \"type\": \"string\",\n \"value\": \"Nail\"\n }\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Integer0(t *testing.T) { + input := "int1 = +99\nint2 = 42\nint3 = 0\nint4 = -17\n" + jsonRef := "{\n \"int1\": {\n \"type\": \"integer\",\n \"value\": \"99\"\n },\n \"int2\": {\n \"type\": \"integer\",\n \"value\": \"42\"\n },\n \"int3\": {\n \"type\": \"integer\",\n \"value\": \"0\"\n },\n \"int4\": {\n \"type\": \"integer\",\n \"value\": \"-17\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Integer1(t *testing.T) { + input := "int5 = 1_000\nint6 = 5_349_221\nint7 = 53_49_221 # Indian number system grouping\nint8 = 1_2_3_4_5 # VALID but discouraged\n" + jsonRef := "{\n \"int5\": {\n \"type\": \"integer\",\n \"value\": \"1000\"\n },\n \"int6\": {\n \"type\": \"integer\",\n \"value\": \"5349221\"\n },\n \"int7\": {\n \"type\": \"integer\",\n \"value\": \"5349221\"\n },\n \"int8\": {\n \"type\": \"integer\",\n \"value\": \"12345\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Integer2(t *testing.T) { + input := "# hexadecimal with prefix `0x`\nhex1 = 0xDEADBEEF\nhex2 = 0xdeadbeef\nhex3 = 0xdead_beef\n\n# octal with prefix `0o`\noct1 = 0o01234567\noct2 = 0o755 # useful for Unix file permissions\n\n# binary with prefix `0b`\nbin1 = 0b11010110\n" + jsonRef := "{\n \"bin1\": {\n \"type\": \"integer\",\n \"value\": \"214\"\n },\n \"hex1\": {\n \"type\": \"integer\",\n \"value\": \"3735928559\"\n },\n \"hex2\": {\n \"type\": \"integer\",\n \"value\": \"3735928559\"\n },\n \"hex3\": {\n \"type\": \"integer\",\n \"value\": \"3735928559\"\n },\n \"oct1\": {\n \"type\": \"integer\",\n \"value\": \"342391\"\n },\n \"oct2\": {\n \"type\": \"integer\",\n \"value\": \"493\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_KeyValuePair0(t *testing.T) { + input := "key = \"value\"\n" + jsonRef := "{\n \"key\": {\n \"type\": \"string\",\n \"value\": \"value\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Keys0(t *testing.T) { + input := "key = \"value\"\nbare_key = \"value\"\nbare-key = \"value\"\n1234 = \"value\"\n" + jsonRef := "{\n \"1234\": {\n \"type\": \"string\",\n \"value\": \"value\"\n },\n \"bare-key\": {\n \"type\": \"string\",\n \"value\": \"value\"\n },\n \"bare_key\": {\n \"type\": \"string\",\n \"value\": \"value\"\n },\n \"key\": {\n \"type\": \"string\",\n \"value\": \"value\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Keys1(t *testing.T) { + input := "\"127.0.0.1\" = \"value\"\n\"character encoding\" = \"value\"\n\"ʎǝʞ\" = \"value\"\n'key2' = \"value\"\n'quoted \"value\"' = \"value\"\n" + jsonRef := "{\n \"127.0.0.1\": {\n \"type\": \"string\",\n \"value\": \"value\"\n },\n \"character encoding\": {\n \"type\": \"string\",\n \"value\": \"value\"\n },\n \"key2\": {\n \"type\": \"string\",\n \"value\": \"value\"\n },\n \"quoted \\\"value\\\"\": {\n \"type\": \"string\",\n \"value\": \"value\"\n },\n \"ʎǝʞ\": {\n \"type\": \"string\",\n \"value\": \"value\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Keys3(t *testing.T) { + input := "name = \"Orange\"\nphysical.color = \"orange\"\nphysical.shape = \"round\"\nsite.\"google.com\" = true\n" + jsonRef := "{\n \"name\": {\n \"type\": \"string\",\n \"value\": \"Orange\"\n },\n \"physical\": {\n \"color\": {\n \"type\": \"string\",\n \"value\": \"orange\"\n },\n \"shape\": {\n \"type\": \"string\",\n \"value\": \"round\"\n }\n },\n \"site\": {\n \"google.com\": {\n \"type\": \"bool\",\n \"value\": \"true\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Keys4(t *testing.T) { + input := "fruit.name = \"banana\" # this is best practice\nfruit. color = \"yellow\" # same as fruit.color\nfruit . flavor = \"banana\" # same as fruit.flavor\n" + jsonRef := "{\n \"fruit\": {\n \"color\": {\n \"type\": \"string\",\n \"value\": \"yellow\"\n },\n \"flavor\": {\n \"type\": \"string\",\n \"value\": \"banana\"\n },\n \"name\": {\n \"type\": \"string\",\n \"value\": \"banana\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Keys5(t *testing.T) { + input := "# VALID BUT DISCOURAGED\n\napple.type = \"fruit\"\norange.type = \"fruit\"\n\napple.skin = \"thin\"\norange.skin = \"thick\"\n\napple.color = \"red\"\norange.color = \"orange\"\n" + jsonRef := "{\n \"apple\": {\n \"color\": {\n \"type\": \"string\",\n \"value\": \"red\"\n },\n \"skin\": {\n \"type\": \"string\",\n \"value\": \"thin\"\n },\n \"type\": {\n \"type\": \"string\",\n \"value\": \"fruit\"\n }\n },\n \"orange\": {\n \"color\": {\n \"type\": \"string\",\n \"value\": \"orange\"\n },\n \"skin\": {\n \"type\": \"string\",\n \"value\": \"thick\"\n },\n \"type\": {\n \"type\": \"string\",\n \"value\": \"fruit\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Keys6(t *testing.T) { + input := "# RECOMMENDED\n\napple.type = \"fruit\"\napple.skin = \"thin\"\napple.color = \"red\"\n\norange.type = \"fruit\"\norange.skin = \"thick\"\norange.color = \"orange\"\n" + jsonRef := "{\n \"apple\": {\n \"color\": {\n \"type\": \"string\",\n \"value\": \"red\"\n },\n \"skin\": {\n \"type\": \"string\",\n \"value\": \"thin\"\n },\n \"type\": {\n \"type\": \"string\",\n \"value\": \"fruit\"\n }\n },\n \"orange\": {\n \"color\": {\n \"type\": \"string\",\n \"value\": \"orange\"\n },\n \"skin\": {\n \"type\": \"string\",\n \"value\": \"thick\"\n },\n \"type\": {\n \"type\": \"string\",\n \"value\": \"fruit\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Keys7(t *testing.T) { + input := "3.14159 = \"pi\"\n" + jsonRef := "{\n \"3\": {\n \"14159\": {\n \"type\": \"string\",\n \"value\": \"pi\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_LocalDate0(t *testing.T) { + input := "ld1 = 1979-05-27\n" + jsonRef := "{\n \"ld1\": {\n \"type\": \"date-local\",\n \"value\": \"1979-05-27\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_LocalDateTime0(t *testing.T) { + input := "ldt1 = 1979-05-27T07:32:00\nldt2 = 1979-05-27T00:32:00.999999\n" + jsonRef := "{\n \"ldt1\": {\n \"type\": \"datetime-local\",\n \"value\": \"1979-05-27T07:32:00\"\n },\n \"ldt2\": {\n \"type\": \"datetime-local\",\n \"value\": \"1979-05-27T00:32:00.999999\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_LocalTime0(t *testing.T) { + input := "lt1 = 07:32:00\nlt2 = 00:32:00.999999\n" + jsonRef := "{\n \"lt1\": {\n \"type\": \"time-local\",\n \"value\": \"07:32:00\"\n },\n \"lt2\": {\n \"type\": \"time-local\",\n \"value\": \"00:32:00.999999\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_OffsetDateTime0(t *testing.T) { + input := "odt1 = 1979-05-27T07:32:00Z\nodt2 = 1979-05-27T00:32:00-07:00\nodt3 = 1979-05-27T00:32:00.999999-07:00\n" + jsonRef := "{\n \"odt1\": {\n \"type\": \"datetime\",\n \"value\": \"1979-05-27T07:32:00Z\"\n },\n \"odt2\": {\n \"type\": \"datetime\",\n \"value\": \"1979-05-27T00:32:00-07:00\"\n },\n \"odt3\": {\n \"type\": \"datetime\",\n \"value\": \"1979-05-27T00:32:00.999999-07:00\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_OffsetDateTime1(t *testing.T) { + input := "odt4 = 1979-05-27 07:32:00Z\n" + jsonRef := "{\n \"odt4\": {\n \"type\": \"datetime\",\n \"value\": \"1979-05-27T07:32:00Z\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_String0(t *testing.T) { + input := "str = \"I'm a string. \\\"You can quote me\\\". Name\\tJos\\u00E9\\nLocation\\tSF.\"\n" + jsonRef := "{\n \"str\": {\n \"type\": \"string\",\n \"value\": \"I'm a string. \\\"You can quote me\\\". Name\\tJosé\\nLocation\\tSF.\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_String1(t *testing.T) { + input := "str1 = \"\"\"\nRoses are red\nViolets are blue\"\"\"\n" + jsonRef := "{\n \"str1\": {\n \"type\": \"string\",\n \"value\": \"Roses are red\\nViolets are blue\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_String2(t *testing.T) { + input := "# On a Unix system, the above multi-line string will most likely be the same as:\nstr2 = \"Roses are red\\nViolets are blue\"\n\n# On a Windows system, it will most likely be equivalent to:\nstr3 = \"Roses are red\\r\\nViolets are blue\"\n" + jsonRef := "{\n \"str2\": {\n \"type\": \"string\",\n \"value\": \"Roses are red\\nViolets are blue\"\n },\n \"str3\": {\n \"type\": \"string\",\n \"value\": \"Roses are red\\r\\nViolets are blue\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_String3(t *testing.T) { + input := "# The following strings are byte-for-byte equivalent:\nstr1 = \"The quick brown fox jumps over the lazy dog.\"\n\nstr2 = \"\"\"\nThe quick brown \\\n\n\n fox jumps over \\\n the lazy dog.\"\"\"\n\nstr3 = \"\"\"\\\n The quick brown \\\n fox jumps over \\\n the lazy dog.\\\n \"\"\"\n" + jsonRef := "{\n \"str1\": {\n \"type\": \"string\",\n \"value\": \"The quick brown fox jumps over the lazy dog.\"\n },\n \"str2\": {\n \"type\": \"string\",\n \"value\": \"The quick brown fox jumps over the lazy dog.\"\n },\n \"str3\": {\n \"type\": \"string\",\n \"value\": \"The quick brown fox jumps over the lazy dog.\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_String4(t *testing.T) { + input := "str4 = \"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"\n# str5 = \"\"\"Here are three quotation marks: \"\"\".\"\"\" # INVALID\nstr5 = \"\"\"Here are three quotation marks: \"\"\\\".\"\"\"\nstr6 = \"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"\n\n# \"This,\" she said, \"is just a pointless statement.\"\nstr7 = \"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"\n" + jsonRef := "{\n \"str4\": {\n \"type\": \"string\",\n \"value\": \"Here are two quotation marks: \\\"\\\". Simple enough.\"\n },\n \"str5\": {\n \"type\": \"string\",\n \"value\": \"Here are three quotation marks: \\\"\\\"\\\".\"\n },\n \"str6\": {\n \"type\": \"string\",\n \"value\": \"Here are fifteen quotation marks: \\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\".\"\n },\n \"str7\": {\n \"type\": \"string\",\n \"value\": \"\\\"This,\\\" she said, \\\"is just a pointless statement.\\\"\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_String5(t *testing.T) { + input := "# What you see is what you get.\nwinpath = 'C:\\Users\\nodejs\\templates'\nwinpath2 = '\\\\ServerX\\admin$\\system32\\'\nquoted = 'Tom \"Dubs\" Preston-Werner'\nregex = '<\\i\\c*\\s*>'\n" + jsonRef := "{\n \"quoted\": {\n \"type\": \"string\",\n \"value\": \"Tom \\\"Dubs\\\" Preston-Werner\"\n },\n \"regex\": {\n \"type\": \"string\",\n \"value\": \"\\u003c\\\\i\\\\c*\\\\s*\\u003e\"\n },\n \"winpath\": {\n \"type\": \"string\",\n \"value\": \"C:\\\\Users\\\\nodejs\\\\templates\"\n },\n \"winpath2\": {\n \"type\": \"string\",\n \"value\": \"\\\\\\\\ServerX\\\\admin$\\\\system32\\\\\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_String6(t *testing.T) { + input := "regex2 = '''I [dw]on't need \\d{2} apples'''\nlines = '''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''\n" + jsonRef := "{\n \"lines\": {\n \"type\": \"string\",\n \"value\": \"The first newline is\\ntrimmed in raw strings.\\n All other whitespace\\n is preserved.\\n\"\n },\n \"regex2\": {\n \"type\": \"string\",\n \"value\": \"I [dw]on't need \\\\d{2} apples\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_String7(t *testing.T) { + input := "quot15 = '''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"'''\n\n# apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID\napos15 = \"Here are fifteen apostrophes: '''''''''''''''\"\n\n# 'That,' she said, 'is still pointless.'\nstr = ''''That,' she said, 'is still pointless.''''\n" + jsonRef := "{\n \"apos15\": {\n \"type\": \"string\",\n \"value\": \"Here are fifteen apostrophes: '''''''''''''''\"\n },\n \"quot15\": {\n \"type\": \"string\",\n \"value\": \"Here are fifteen quotation marks: \\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\"\n },\n \"str\": {\n \"type\": \"string\",\n \"value\": \"'That,' she said, 'is still pointless.'\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Table0(t *testing.T) { + input := "[table]\n" + jsonRef := "{\n \"table\": {}\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Table1(t *testing.T) { + input := "[table-1]\nkey1 = \"some string\"\nkey2 = 123\n\n[table-2]\nkey1 = \"another string\"\nkey2 = 456\n" + jsonRef := "{\n \"table-1\": {\n \"key1\": {\n \"type\": \"string\",\n \"value\": \"some string\"\n },\n \"key2\": {\n \"type\": \"integer\",\n \"value\": \"123\"\n }\n },\n \"table-2\": {\n \"key1\": {\n \"type\": \"string\",\n \"value\": \"another string\"\n },\n \"key2\": {\n \"type\": \"integer\",\n \"value\": \"456\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Table2(t *testing.T) { + input := "[dog.\"tater.man\"]\ntype.name = \"pug\"\n" + jsonRef := "{\n \"dog\": {\n \"tater.man\": {\n \"type\": {\n \"name\": {\n \"type\": \"string\",\n \"value\": \"pug\"\n }\n }\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Table3(t *testing.T) { + input := "[a.b.c] # this is best practice\n[ d.e.f ] # same as [d.e.f]\n[ g . h . i ] # same as [g.h.i]\n[ j . \"ʞ\" . 'l' ] # same as [j.\"ʞ\".'l']\n" + jsonRef := "{\n \"a\": {\n \"b\": {\n \"c\": {}\n }\n },\n \"d\": {\n \"e\": {\n \"f\": {}\n }\n },\n \"g\": {\n \"h\": {\n \"i\": {}\n }\n },\n \"j\": {\n \"ʞ\": {\n \"l\": {}\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Table4(t *testing.T) { + input := "# [x] you\n# [x.y] don't\n# [x.y.z] need these\n[x.y.z.w] # for this to work\n\n[x] # defining a super-table afterward is ok\n" + jsonRef := "{\n \"x\": {\n \"y\": {\n \"z\": {\n \"w\": {}\n }\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Table5(t *testing.T) { + input := "# VALID BUT DISCOURAGED\n[fruit.apple]\n[animal]\n[fruit.orange]\n" + jsonRef := "{\n \"animal\": {},\n \"fruit\": {\n \"apple\": {},\n \"orange\": {}\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Table6(t *testing.T) { + input := "# RECOMMENDED\n[fruit.apple]\n[fruit.orange]\n[animal]\n" + jsonRef := "{\n \"animal\": {},\n \"fruit\": {\n \"apple\": {},\n \"orange\": {}\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Table7(t *testing.T) { + input := "# Top-level table begins.\nname = \"Fido\"\nbreed = \"pug\"\n\n# Top-level table ends.\n[owner]\nname = \"Regina Dogman\"\nmember_since = 1999-08-04\n" + jsonRef := "{\n \"breed\": {\n \"type\": \"string\",\n \"value\": \"pug\"\n },\n \"name\": {\n \"type\": \"string\",\n \"value\": \"Fido\"\n },\n \"owner\": {\n \"member_since\": {\n \"type\": \"date-local\",\n \"value\": \"1999-08-04\"\n },\n \"name\": {\n \"type\": \"string\",\n \"value\": \"Regina Dogman\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Table8(t *testing.T) { + input := "fruit.apple.color = \"red\"\n# Defines a table named fruit\n# Defines a table named fruit.apple\n\nfruit.apple.taste.sweet = true\n# Defines a table named fruit.apple.taste\n# fruit and fruit.apple were already created\n" + jsonRef := "{\n \"fruit\": {\n \"apple\": {\n \"color\": {\n \"type\": \"string\",\n \"value\": \"red\"\n },\n \"taste\": {\n \"sweet\": {\n \"type\": \"bool\",\n \"value\": \"true\"\n }\n }\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Spec_Table9(t *testing.T) { + input := "[fruit]\napple.color = \"red\"\napple.taste.sweet = true\n\n# [fruit.apple] # INVALID\n# [fruit.apple.taste] # INVALID\n\n[fruit.apple.texture] # you can add sub-tables\nsmooth = true\n" + jsonRef := "{\n \"fruit\": {\n \"apple\": {\n \"color\": {\n \"type\": \"string\",\n \"value\": \"red\"\n },\n \"taste\": {\n \"sweet\": {\n \"type\": \"bool\",\n \"value\": \"true\"\n }\n },\n \"texture\": {\n \"smooth\": {\n \"type\": \"bool\",\n \"value\": \"true\"\n }\n }\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_String_DoubleQuoteEscape(t *testing.T) { input := "test = \"\\\"one\\\"\"\n" jsonRef := "{\n \"test\": {\n \"type\": \"string\",\n \"value\": \"\\\"one\\\"\"\n }\n}\n" @@ -1541,6 +2596,12 @@ func TestTOMLTest_Valid_String_Empty(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_String_EndsInWhitespaceEscape(t *testing.T) { + input := "beee = \"\"\"\nheeee\ngeeee\\ \n\n\n \"\"\"\n" + jsonRef := "{\n \"beee\": {\n \"type\": \"string\",\n \"value\": \"heeee\\ngeeee\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_String_EscapeEsc(t *testing.T) { input := "esc = \"\\e There is no escape! \\e\"\n" jsonRef := "{\n \"esc\": {\n \"type\": \"string\",\n \"value\": \"\\u001b There is no escape! \\u001b\"\n }\n}\n" @@ -1561,7 +2622,13 @@ func TestTOMLTest_Valid_String_EscapedEscape(t *testing.T) { func TestTOMLTest_Valid_String_Escapes(t *testing.T) { input := "backspace = \"This string has a \\b backspace character.\"\ntab = \"This string has a \\t tab character.\"\nnewline = \"This string has a \\n new line character.\"\nformfeed = \"This string has a \\f form feed character.\"\ncarriage = \"This string has a \\r carriage return character.\"\nquote = \"This string has a \\\" quote character.\"\nbackslash = \"This string has a \\\\ backslash character.\"\nnotunicode1 = \"This string does not have a unicode \\\\u escape.\"\nnotunicode2 = \"This string does not have a unicode \\u005Cu escape.\"\nnotunicode3 = \"This string does not have a unicode \\\\u0075 escape.\"\nnotunicode4 = \"This string does not have a unicode \\\\\\u0075 escape.\"\ndelete = \"This string has a \\u007F delete control code.\"\nunitseparator = \"This string has a \\u001F unit separator control code.\"\n" - jsonRef := "{\n \"backslash\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\ backslash character.\"\n },\n \"backspace\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\u0008 backspace character.\"\n },\n \"carriage\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\r carriage return character.\"\n },\n \"delete\": {\n \"type\": \"string\",\n \"value\": \"This string has a \u007f delete control code.\"\n },\n \"formfeed\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\u000c form feed character.\"\n },\n \"newline\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\n new line character.\"\n },\n \"notunicode1\": {\n \"type\": \"string\",\n \"value\": \"This string does not have a unicode \\\\u escape.\"\n },\n \"notunicode2\": {\n \"type\": \"string\",\n \"value\": \"This string does not have a unicode \\\\u escape.\"\n },\n \"notunicode3\": {\n \"type\": \"string\",\n \"value\": \"This string does not have a unicode \\\\u0075 escape.\"\n },\n \"notunicode4\": {\n \"type\": \"string\",\n \"value\": \"This string does not have a unicode \\\\u escape.\"\n },\n \"quote\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\" quote character.\"\n },\n \"tab\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\t tab character.\"\n },\n \"unitseparator\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\u001f unit separator control code.\"\n }\n}\n" + jsonRef := "{\n \"backslash\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\ backslash character.\"\n },\n \"backspace\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\u0008 backspace character.\"\n },\n \"carriage\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\r carriage return character.\"\n },\n \"delete\": {\n \"type\": \"string\",\n \"value\": \"This string has a \x7f delete control code.\"\n },\n \"formfeed\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\u000c form feed character.\"\n },\n \"newline\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\n new line character.\"\n },\n \"notunicode1\": {\n \"type\": \"string\",\n \"value\": \"This string does not have a unicode \\\\u escape.\"\n },\n \"notunicode2\": {\n \"type\": \"string\",\n \"value\": \"This string does not have a unicode \\\\u escape.\"\n },\n \"notunicode3\": {\n \"type\": \"string\",\n \"value\": \"This string does not have a unicode \\\\u0075 escape.\"\n },\n \"notunicode4\": {\n \"type\": \"string\",\n \"value\": \"This string does not have a unicode \\\\u escape.\"\n },\n \"quote\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\" quote character.\"\n },\n \"tab\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\t tab character.\"\n },\n \"unitseparator\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\u001f unit separator control code.\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_String_HexEscape(t *testing.T) { + input := "# \\x for the first 255 codepoints\n\nwhitespace = \"\\x20 \\x09 \\x1b \\x0d\\x0a\"\nbs = \"\\x7f\"\nnul = \"\\x00\"\nhello = \"\\x68\\x65\\x6c\\x6c\\x6f\\x0a\"\nhigher-than-127 = \"S\\xf8rmirb\\xe6ren\"\n\nmultiline = \"\"\"\n\\x20 \\x09 \\x1b \\x0d\\x0a\n\\x7f\n\\x00\n\\x68\\x65\\x6c\\x6c\\x6f\\x0a\n\\x53\\xF8\\x72\\x6D\\x69\\x72\\x62\\xE6\\x72\\x65\\x6E\n\"\"\"\n\n# Not inside literals.\nliteral = '\\x20 \\x09 \\x0d\\x0a'\nmultiline-literal = '''\n\\x20 \\x09 \\x0d\\x0a\n'''\n" + jsonRef := "{\n \"bs\": {\n \"type\": \"string\",\n \"value\": \"\x7f\"\n },\n \"hello\": {\n \"type\": \"string\",\n \"value\": \"hello\\n\"\n },\n \"higher-than-127\": {\n \"type\": \"string\",\n \"value\": \"Sørmirbæren\"\n },\n \"literal\": {\n \"type\": \"string\",\n \"value\": \"\\\\x20 \\\\x09 \\\\x0d\\\\x0a\"\n },\n \"multiline\": {\n \"type\": \"string\",\n \"value\": \" \\t \\u001b \\r\\n\\n\x7f\\n\\u0000\\nhello\\n\\nSørmirbæren\\n\"\n },\n \"multiline-literal\": {\n \"type\": \"string\",\n \"value\": \"\\\\x20 \\\\x09 \\\\x0d\\\\x0a\\n\"\n },\n \"nul\": {\n \"type\": \"string\",\n \"value\": \"\\u0000\"\n },\n \"whitespace\": {\n \"type\": \"string\",\n \"value\": \" \\t \\u001b \\r\\n\"\n }\n}\n" testgenValid(t, input, jsonRef) } @@ -1572,8 +2639,8 @@ func TestTOMLTest_Valid_String_MultilineEscapedCrlf(t *testing.T) { } func TestTOMLTest_Valid_String_MultilineQuotes(t *testing.T) { - input := "# Make sure that quotes inside multiline strings are allowed, including right\n# after the opening '''/\"\"\" and before the closing '''/\"\"\"\n\nlit_one = ''''one quote''''\nlit_two = '''''two quotes'''''\nlit_one_space = ''' 'one quote' '''\nlit_two_space = ''' ''two quotes'' '''\n\none = \"\"\"\"one quote\"\"\"\"\ntwo = \"\"\"\"\"two quotes\"\"\"\"\"\none_space = \"\"\" \"one quote\" \"\"\"\ntwo_space = \"\"\" \"\"two quotes\"\" \"\"\"\n\nmismatch1 = \"\"\"aaa'''bbb\"\"\"\nmismatch2 = '''aaa\"\"\"bbb'''\n\n# Three opening \"\"\", then one escaped \", then two \"\" (allowed), and then three\n# closing \"\"\"\nescaped = \"\"\"lol\\\"\"\"\"\"\"\n" - jsonRef := "{\n \"escaped\": {\n \"type\": \"string\",\n \"value\": \"lol\\\"\\\"\\\"\"\n },\n \"lit_one\": {\n \"type\": \"string\",\n \"value\": \"'one quote'\"\n },\n \"lit_one_space\": {\n \"type\": \"string\",\n \"value\": \" 'one quote' \"\n },\n \"lit_two\": {\n \"type\": \"string\",\n \"value\": \"''two quotes''\"\n },\n \"lit_two_space\": {\n \"type\": \"string\",\n \"value\": \" ''two quotes'' \"\n },\n \"mismatch1\": {\n \"type\": \"string\",\n \"value\": \"aaa'''bbb\"\n },\n \"mismatch2\": {\n \"type\": \"string\",\n \"value\": \"aaa\\\"\\\"\\\"bbb\"\n },\n \"one\": {\n \"type\": \"string\",\n \"value\": \"\\\"one quote\\\"\"\n },\n \"one_space\": {\n \"type\": \"string\",\n \"value\": \" \\\"one quote\\\" \"\n },\n \"two\": {\n \"type\": \"string\",\n \"value\": \"\\\"\\\"two quotes\\\"\\\"\"\n },\n \"two_space\": {\n \"type\": \"string\",\n \"value\": \" \\\"\\\"two quotes\\\"\\\" \"\n }\n}\n" + input := "# Make sure that quotes inside multiline strings are allowed, including right\n# after the opening '''/\"\"\" and before the closing '''/\"\"\"\n\nlit_one = ''''one quote''''\nlit_two = '''''two quotes'''''\nlit_one_space = ''' 'one quote' '''\nlit_two_space = ''' ''two quotes'' '''\n\none = \"\"\"\"one quote\"\"\"\"\ntwo = \"\"\"\"\"two quotes\"\"\"\"\"\none_space = \"\"\" \"one quote\" \"\"\"\ntwo_space = \"\"\" \"\"two quotes\"\" \"\"\"\n\nmismatch1 = \"\"\"aaa'''bbb\"\"\"\nmismatch2 = '''aaa\"\"\"bbb'''\n\n# Three opening \"\"\", then one escaped \", then two \"\" (allowed), and then three\n# closing \"\"\"\nescaped = \"\"\"lol\\\"\"\"\"\"\"\n\nfive-quotes = \"\"\"\nClosing with five quotes\n\"\"\"\"\"\nfour-quotes = \"\"\"\nClosing with four quotes\n\"\"\"\"\n" + jsonRef := "{\n \"escaped\": {\n \"type\": \"string\",\n \"value\": \"lol\\\"\\\"\\\"\"\n },\n \"five-quotes\": {\n \"type\": \"string\",\n \"value\": \"Closing with five quotes\\n\\\"\\\"\"\n },\n \"four-quotes\": {\n \"type\": \"string\",\n \"value\": \"Closing with four quotes\\n\\\"\"\n },\n \"lit_one\": {\n \"type\": \"string\",\n \"value\": \"'one quote'\"\n },\n \"lit_one_space\": {\n \"type\": \"string\",\n \"value\": \" 'one quote' \"\n },\n \"lit_two\": {\n \"type\": \"string\",\n \"value\": \"''two quotes''\"\n },\n \"lit_two_space\": {\n \"type\": \"string\",\n \"value\": \" ''two quotes'' \"\n },\n \"mismatch1\": {\n \"type\": \"string\",\n \"value\": \"aaa'''bbb\"\n },\n \"mismatch2\": {\n \"type\": \"string\",\n \"value\": \"aaa\\\"\\\"\\\"bbb\"\n },\n \"one\": {\n \"type\": \"string\",\n \"value\": \"\\\"one quote\\\"\"\n },\n \"one_space\": {\n \"type\": \"string\",\n \"value\": \" \\\"one quote\\\" \"\n },\n \"two\": {\n \"type\": \"string\",\n \"value\": \"\\\"\\\"two quotes\\\"\\\"\"\n },\n \"two_space\": {\n \"type\": \"string\",\n \"value\": \" \\\"\\\"two quotes\\\"\\\" \"\n }\n}\n" testgenValid(t, input, jsonRef) } @@ -1589,15 +2656,21 @@ func TestTOMLTest_Valid_String_Nl(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_String_QuotedUnicode(t *testing.T) { + input := "\nescaped_string = \"\\u0000 \\u0008 \\u000c \\U00000041 \\u007f \\u0080 \\u00ff \\ud7ff \\ue000 \\uffff \\U00010000 \\U0010ffff\"\nnot_escaped_string = '\\u0000 \\u0008 \\u000c \\U00000041 \\u007f \\u0080 \\u00ff \\ud7ff \\ue000 \\uffff \\U00010000 \\U0010ffff'\n\nbasic_string = \"~ \u0080 ÿ \ud7ff \ue000 \uffff 𐀀 \U0010ffff\"\nliteral_string = '~ \u0080 ÿ \ud7ff \ue000 \uffff 𐀀 \U0010ffff'\n" + jsonRef := "{\n \"basic_string\": {\n \"type\": \"string\",\n \"value\": \"~ \u0080 ÿ \ud7ff \ue000 \uffff 𐀀 \U0010ffff\"\n },\n \"escaped_string\": {\n \"type\": \"string\",\n \"value\": \"\\u0000 \\u0008 \\u000c A \x7f \u0080 ÿ \ud7ff \ue000 \uffff 𐀀 \U0010ffff\"\n },\n \"literal_string\": {\n \"type\": \"string\",\n \"value\": \"~ \u0080 ÿ \ud7ff \ue000 \uffff 𐀀 \U0010ffff\"\n },\n \"not_escaped_string\": {\n \"type\": \"string\",\n \"value\": \"\\\\u0000 \\\\u0008 \\\\u000c \\\\U00000041 \\\\u007f \\\\u0080 \\\\u00ff \\\\ud7ff \\\\ue000 \\\\uffff \\\\U00010000 \\\\U0010ffff\"\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_String_RawMultiline(t *testing.T) { - input := "# Single ' should be allowed.\noneline = '''This string has a ' quote character.'''\n\n# A newline immediately following the opening delimiter will be trimmed.\nfirstnl = '''\nThis string has a ' quote character.'''\n\n# All other whitespace and newline characters remain intact.\nmultiline = '''\nThis string\nhas ' a quote character\nand more than\none newline\nin it.'''\n" - jsonRef := "{\n \"firstnl\": {\n \"type\": \"string\",\n \"value\": \"This string has a ' quote character.\"\n },\n \"multiline\": {\n \"type\": \"string\",\n \"value\": \"This string\\nhas ' a quote character\\nand more than\\none newline\\nin it.\"\n },\n \"oneline\": {\n \"type\": \"string\",\n \"value\": \"This string has a ' quote character.\"\n }\n}\n" + input := "# Single ' should be allowed.\noneline = '''This string has a ' quote character.'''\n\n# A newline immediately following the opening delimiter will be trimmed.\nfirstnl = '''\nThis string has a ' quote character.'''\n\n# All other whitespace and newline characters remain intact.\nmultiline = '''\nThis string\nhas ' a quote character\nand more than\none newline\nin it.'''\n\n# Tab character in literal string does not need to be escaped\nmultiline_with_tab = '''First line\n\t Followed by a tab'''\n\nthis-str-has-apostrophes='''' there's one already\n'' two more\n'''''\n" + jsonRef := "{\n \"firstnl\": {\n \"type\": \"string\",\n \"value\": \"This string has a ' quote character.\"\n },\n \"multiline\": {\n \"type\": \"string\",\n \"value\": \"This string\\nhas ' a quote character\\nand more than\\none newline\\nin it.\"\n },\n \"multiline_with_tab\": {\n \"type\": \"string\",\n \"value\": \"First line\\n\\t Followed by a tab\"\n },\n \"oneline\": {\n \"type\": \"string\",\n \"value\": \"This string has a ' quote character.\"\n },\n \"this-str-has-apostrophes\": {\n \"type\": \"string\",\n \"value\": \"' there's one already\\n'' two more\\n''\"\n }\n}\n" testgenValid(t, input, jsonRef) } func TestTOMLTest_Valid_String_Raw(t *testing.T) { - input := "backspace = 'This string has a \\b backspace character.'\ntab = 'This string has a \\t tab character.'\nnewline = 'This string has a \\n new line character.'\nformfeed = 'This string has a \\f form feed character.'\ncarriage = 'This string has a \\r carriage return character.'\nslash = 'This string has a \\/ slash character.'\nbackslash = 'This string has a \\\\ backslash character.'\n" - jsonRef := "{\n \"backslash\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\\\\\ backslash character.\"\n },\n \"backspace\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\b backspace character.\"\n },\n \"carriage\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\r carriage return character.\"\n },\n \"formfeed\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\f form feed character.\"\n },\n \"newline\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\n new line character.\"\n },\n \"slash\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\/ slash character.\"\n },\n \"tab\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\t tab character.\"\n }\n}\n" + input := "backspace = 'This string has a \\b backspace character.'\ntab = 'This string has a \\t tab character.'\nunescaped_tab = 'This string has an \t unescaped tab character.'\nnewline = 'This string has a \\n new line character.'\nformfeed = 'This string has a \\f form feed character.'\ncarriage = 'This string has a \\r carriage return character.'\nslash = 'This string has a \\/ slash character.'\nbackslash = 'This string has a \\\\ backslash character.'\n" + jsonRef := "{\n \"backslash\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\\\\\ backslash character.\"\n },\n \"backspace\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\b backspace character.\"\n },\n \"carriage\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\r carriage return character.\"\n },\n \"formfeed\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\f form feed character.\"\n },\n \"newline\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\n new line character.\"\n },\n \"slash\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\/ slash character.\"\n },\n \"tab\": {\n \"type\": \"string\",\n \"value\": \"This string has a \\\\t tab character.\"\n },\n \"unescaped_tab\": {\n \"type\": \"string\",\n \"value\": \"This string has an \\t unescaped tab character.\"\n }\n}\n" testgenValid(t, input, jsonRef) } @@ -1608,8 +2681,8 @@ func TestTOMLTest_Valid_String_Simple(t *testing.T) { } func TestTOMLTest_Valid_String_UnicodeEscape(t *testing.T) { - input := "answer4 = \"\\u03B4\"\nanswer8 = \"\\U000003B4\"\n" - jsonRef := "{\n \"answer4\": {\n \"type\": \"string\",\n \"value\": \"δ\"\n },\n \"answer8\": {\n \"type\": \"string\",\n \"value\": \"δ\"\n }\n}\n" + input := "delta-1 = \"\\u03B4\"\ndelta-2 = \"\\U000003B4\"\na = \"\\u0061\"\nb = \"\\u0062\"\nc = \"\\U00000063\"\nnull-1 = \"\\u0000\"\nnull-2 = \"\\U00000000\"\n\nml-delta-1 = \"\"\"\\u03B4\"\"\"\nml-delta-2 = \"\"\"\\U000003B4\"\"\"\nml-a = \"\"\"\\u0061\"\"\"\nml-b = \"\"\"\\u0062\"\"\"\nml-c = \"\"\"\\U00000063\"\"\"\nml-null-1 = \"\"\"\\u0000\"\"\"\nml-null-2 = \"\"\"\\U00000000\"\"\"\n" + jsonRef := "{\n \"a\": {\n \"type\": \"string\",\n \"value\": \"a\"\n },\n \"b\": {\n \"type\": \"string\",\n \"value\": \"b\"\n },\n \"c\": {\n \"type\": \"string\",\n \"value\": \"c\"\n },\n \"delta-1\": {\n \"type\": \"string\",\n \"value\": \"δ\"\n },\n \"delta-2\": {\n \"type\": \"string\",\n \"value\": \"δ\"\n },\n \"ml-a\": {\n \"type\": \"string\",\n \"value\": \"a\"\n },\n \"ml-b\": {\n \"type\": \"string\",\n \"value\": \"b\"\n },\n \"ml-c\": {\n \"type\": \"string\",\n \"value\": \"c\"\n },\n \"ml-delta-1\": {\n \"type\": \"string\",\n \"value\": \"δ\"\n },\n \"ml-delta-2\": {\n \"type\": \"string\",\n \"value\": \"δ\"\n },\n \"ml-null-1\": {\n \"type\": \"string\",\n \"value\": \"\\u0000\"\n },\n \"ml-null-2\": {\n \"type\": \"string\",\n \"value\": \"\\u0000\"\n },\n \"null-1\": {\n \"type\": \"string\",\n \"value\": \"\\u0000\"\n },\n \"null-2\": {\n \"type\": \"string\",\n \"value\": \"\\u0000\"\n }\n}\n" testgenValid(t, input, jsonRef) } @@ -1625,6 +2698,12 @@ func TestTOMLTest_Valid_String_WithPound(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Table_ArrayImplicitAndExplicitAfter(t *testing.T) { + input := "[[a.b]]\nx = 1\n\n[a]\ny = 2\n" + jsonRef := "{\n \"a\": {\n \"b\": [\n {\n \"x\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n }\n ],\n \"y\": {\n \"type\": \"integer\",\n \"value\": \"2\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Table_ArrayImplicit(t *testing.T) { input := "[[albums.songs]]\nname = \"Glory Days\"\n" jsonRef := "{\n \"albums\": {\n \"songs\": [\n {\n \"name\": {\n \"type\": \"string\",\n \"value\": \"Glory Days\"\n }\n }\n ]\n }\n}\n" @@ -1655,6 +2734,18 @@ func TestTOMLTest_Valid_Table_ArrayTableArray(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Table_ArrayWithinDotted(t *testing.T) { + input := "[fruit]\napple.color = \"red\"\n\n[[fruit.apple.seeds]]\nsize = 2\n" + jsonRef := "{\n \"fruit\": {\n \"apple\": {\n \"color\": {\n \"type\": \"string\",\n \"value\": \"red\"\n },\n \"seeds\": [\n {\n \"size\": {\n \"type\": \"integer\",\n \"value\": \"2\"\n }\n }\n ]\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + +func TestTOMLTest_Valid_Table_EmptyName(t *testing.T) { + input := "['']\nx = 1\n\n[\"\".a]\nx = 2\n\n[a.'']\nx = 3\n" + jsonRef := "{\n \"\": {\n \"a\": {\n \"x\": {\n \"type\": \"integer\",\n \"value\": \"2\"\n }\n },\n \"x\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n },\n \"a\": {\n \"\": {\n \"x\": {\n \"type\": \"integer\",\n \"value\": \"3\"\n }\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Table_Empty(t *testing.T) { input := "[a]\n" jsonRef := "{\n \"a\": {}\n}\n" @@ -1663,7 +2754,7 @@ func TestTOMLTest_Valid_Table_Empty(t *testing.T) { func TestTOMLTest_Valid_Table_Keyword(t *testing.T) { input := "[true]\n\n[false]\n\n[inf]\n\n[nan]\n\n\n" - jsonRef := "{\n \"true\": {},\n \"false\": {},\n \"inf\": {},\n \"nan\": {}\n}\n" + jsonRef := "{\n \"false\": {},\n \"inf\": {},\n \"nan\": {},\n \"true\": {}\n}\n" testgenValid(t, input, jsonRef) } @@ -1685,6 +2776,12 @@ func TestTOMLTest_Valid_Table_SubEmpty(t *testing.T) { testgenValid(t, input, jsonRef) } +func TestTOMLTest_Valid_Table_Sub(t *testing.T) { + input := "[a]\nkey = 1\n\n# a.extend is a key inside the \"a\" table.\n[a.extend]\nkey = 2\n\n[a.extend.more]\nkey = 3\n" + jsonRef := "{\n \"a\": {\n \"extend\": {\n \"key\": {\n \"type\": \"integer\",\n \"value\": \"2\"\n },\n \"more\": {\n \"key\": {\n \"type\": \"integer\",\n \"value\": \"3\"\n }\n }\n },\n \"key\": {\n \"type\": \"integer\",\n \"value\": \"1\"\n }\n }\n}\n" + testgenValid(t, input, jsonRef) +} + func TestTOMLTest_Valid_Table_Whitespace(t *testing.T) { input := "[\"valid key\"]\n" jsonRef := "{\n \"valid key\": {}\n}\n" diff --git a/unmarshaler.go b/unmarshaler.go index 868c74c1..72df7cc5 100644 --- a/unmarshaler.go +++ b/unmarshaler.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "math" "reflect" "strings" @@ -96,7 +95,7 @@ func (d *Decoder) DisallowUnknownFields() *Decoder { // Inline Table -> same as Table // Array of Tables -> same as Array and Table func (d *Decoder) Decode(v interface{}) error { - b, err := ioutil.ReadAll(d.r) + b, err := io.ReadAll(d.r) if err != nil { return fmt.Errorf("toml: %w", err) }