package toml import ( "fmt" "testing" ) func TestString(t *testing.T) { for _, test := range []parseToASTTest{ {`x=no start quote"`, `{}`, `unexpected input (expected a value) at line 1, column 3`}, {`x="basic s\tring"`, `{"x": "basic s\tring"}`, ``}, {"x=\"\"\"\n basic multi-line\n string value\n\"\"\"", `{"x": " basic multi-line\n string value\n"}`, ``}, {`x='literal s\tring'`, `{"x": "literal s\\tring"}`, ``}, {"x='''\n literal multi-line\n string value\n'''", `{"x": " literal multi-line\n string value\n"}`, ``}, } { p := newParser() testParseToAST(t, p, p.startKeyValuePair, test) } } func TestBasipString(t *testing.T) { for _, test := range []parseToASTTest{ {`x="no end quote`, `{}`, `unexpected end of file (expected closing quotation marks) at line 1, column 16`}, {`x=""`, `{"x": ""}`, ``}, {`x="simple string"`, `{"x": "simple string"}`, ``}, {`x="with\tsome\r\nvalid escapes\b"`, `{"x": "with\tsome\r\nvalid escapes\b"}`, ``}, {`x="with an \invalid escape"`, `{}`, `invalid escape sequence at line 1, column 12`}, {`x="A cool UTF8 ƃuıɹʇs"`, `{"x": "A cool UTF8 ƃuıɹʇs"}`, ``}, {`x="A string with UTF8 escape \u2318"`, `{"x": "A string with UTF8 escape ⌘"}`, ``}, {"x=\"Invalid character for UTF \xcd\"", `{}`, `invalid UTF8 rune at line 1, column 30`}, {"x=\"Character that mus\t be escaped\"", `{}`, `invalid character in string value: '\t' (must be escaped) at line 1, column 22`}, {"x=\"Character that must be escaped \u0000\"", `{}`, `invalid character in string value: '\x00' (must be escaped) at line 1, column 35`}, {"x=\"Character that must be escaped \x7f\"", `{}`, `invalid character in string value: '\u007f' (must be escaped) at line 1, column 35`}, } { p := newParser() testParseToAST(t, p, p.startKeyValuePair, test) } } func TestMultiLineBasipString(t *testing.T) { for _, test := range []parseToASTTest{ {`x="""missing close quote""`, `{}`, `unexpected end of file (expected closing three quotation marks) at line 1, column 27`}, {`x=""""""`, `{"x": ""}`, ``}, {"x=\"\"\"\n\"\"\"", `{"x": ""}`, ``}, {"x=\"\"\"\r\n\r\n\"\"\"", `{"x": "\n"}`, ``}, {`x="""\"\"\"\""""`, `{"x": "\"\"\"\""}`, ``}, {"x=\"\"\"\nThe quick brown \\\n\n\n \t fox jumps over \\\n\t the lazy dog.\\\n \"\"\"", `{"x": "The quick brown fox jumps over the lazy dog."}`, ``}, {"x=\"\"\"No control chars \f allowed\"\"\"", `{}`, `invalid character in multi-line basic string: '\f' (must be escaped) at line 1, column 23`}, {"x=\"\"\"Escaping control chars\\nis valid\"\"\"", `{"x": "Escaping control chars\nis valid"}`, ``}, {"x=\"\"\"Invalid escaping \\is not allowed\"\"\"", `{}`, `invalid escape sequence at line 1, column 23`}, {"x=\"\"\"Invalid rune \xcd\"\"\"", `{}`, `invalid UTF8 rune at line 1, column 19`}, } { p := newParser() testParseToAST(t, p, p.startKeyValuePair, test) } } func TestLiteralString(t *testing.T) { for _, test := range []parseToASTTest{ {`x='missing close quote`, `{}`, `unexpected end of file (expected closing single quote) at line 1, column 23`}, {`x=''`, `{"x": ""}`, ``}, {`x='simple'`, `{"x": "simple"}`, ``}, {`x='C:\Users\nodejs\templates'`, `{"x": "C:\\Users\\nodejs\\templates"}`, ``}, {`x='\\ServerX\admin$\system32\'`, `{"x": "\\\\ServerX\\admin$\\system32\\"}`, ``}, {`x='Tom "Dubs" Preston-Werner'`, `{"x": "Tom \"Dubs\" Preston-Werner"}`, ``}, {`x='<\i\c*\s*>'`, `{"x": "<\\i\\c*\\s*>"}`, ``}, {"x='No cont\rol chars allowed'", `{}`, `invalid character in string value: '\r' (no control chars allowed, except for tab) at line 1, column 11`}, {"x='Except\tfor\ttabs'", `{"x": "Except\tfor\ttabs"}`, ``}, {"x='Invalid rune \xcd'", `{}`, `invalid UTF8 rune at line 1, column 17`}, } { p := newParser() testParseToAST(t, p, p.startKeyValuePair, test) } } func TestMultiLineLiteralString(t *testing.T) { for _, test := range []parseToASTTest{ {`x='''missing close quote''`, `{}`, `unexpected end of file (expected closing three single quotes) at line 1, column 27`}, {`x=''''''`, `{"x": ""}`, ``}, {"x='''\n'''", `{"x": ""}`, ``}, {`x='''I [dw]on't need \d{2} apples'''`, `{"x": "I [dw]on't need \\d{2} apples"}`, ``}, {"x='''\nThere can\nbe newlines\r\nand \ttabs!\r\n'''", `{"x": "There can\nbe newlines\nand \ttabs!\n"}`, ``}, {"x='''No other \f control characters'''", `{}`, `invalid character in literal string: '\f' (no control chars allowed, except for tab and newline) at line 1, column 15`}, {"x='''No invalid runes allowed \xcd'''", `{}`, `invalid UTF8 rune at line 1, column 31`}, } { p := newParser() testParseToAST(t, p, p.startKeyValuePair, test) } } func TestBasipStringWithUnescapedControlCharacters(t *testing.T) { // A quick check for almost all characters that must be escaped. // The missing one (\x7f) is covered in the previous test. for i := 0x00; i <= 0x1F; i++ { p := newParser() input := fmt.Sprintf(`x="%c"`, rune(i)) expected := fmt.Sprintf(`invalid character in string value: %q (must be escaped) at line 1, column 4`, rune(i)) testParseToAST(t, p, p.startKeyValuePair, parseToASTTest{input, "{}", expected}) } }