github.com/joomcode/cue@v0.4.4-0.20221111115225-539fe3512047/cue/literal/string_test.go (about) 1 // Copyright 2019 CUE Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package literal 16 17 import ( 18 "fmt" 19 "testing" 20 ) 21 22 func TestUnquote(t *testing.T) { 23 testCases := []struct { 24 in, out string 25 err error 26 }{ 27 {`"Hello"`, "Hello", nil}, 28 {`'Hello'`, "Hello", nil}, 29 {`'Hellø'`, "Hellø", nil}, 30 {`"""` + "\n\t\tHello\n\t\t" + `"""`, "Hello", nil}, 31 {"'''\n\t\tHello\n\t\t'''", "Hello", nil}, 32 {"'''\n\t\tHello\n\n\t\t'''", "Hello\n", nil}, 33 {"'''\n\n\t\tHello\n\t\t'''", "\nHello", nil}, 34 {"'''\n\n\n\n\t\t'''", "\n\n", nil}, 35 {"'''\n\t\t'''", "", nil}, 36 {`"""` + "\n\raaa\n\rbbb\n\r" + `"""`, "aaa\nbbb", nil}, 37 {`'\a\b\f\n\r\t\v\'\\\/'`, "\a\b\f\n\r\t\v'\\/", nil}, 38 {`"\a\b\f\n\r\t\v\"\\\/"`, "\a\b\f\n\r\t\v\"\\/", nil}, 39 {`#"The sequence "\U0001F604" renders as \#U0001F604."#`, 40 `The sequence "\U0001F604" renders as 😄.`, 41 nil}, 42 {`" \U00010FfF"`, " \U00010fff", nil}, 43 {`"\u0061 "`, "a ", nil}, 44 {`'\x61\x55'`, "\x61\x55", nil}, 45 {`'\061\055'`, "\061\055", nil}, 46 {`'\377 '`, "\377 ", nil}, 47 {"'e\u0300\\n'", "e\u0300\n", nil}, 48 {`'\06\055'`, "", errSyntax}, 49 {`'\0'`, "", errSyntax}, 50 {`"\06\055"`, "", errSyntax}, // too short 51 {`'\777 '`, "", errSyntax}, // overflow 52 {`'\U012301'`, "", errSyntax}, // too short 53 {`'\U0123012G'`, "", errSyntax}, // invalid digit G 54 {`"\x04"`, "", errSyntax}, // not allowed in strings 55 {`'\U01230123'`, "", errSyntax}, // too large 56 57 // Surrogate pairs 58 {`"\uD834\uDD1E"`, "𝄞", nil}, 59 {`"\uDD1E\uD834"`, "", errSurrogate}, 60 {`"\uD834\uD834"`, "", errSurrogate}, 61 62 {`"\\"`, "\\", nil}, 63 {`"\'"`, "", errSyntax}, 64 {`"\q"`, "", errSyntax}, 65 {"'\n'", "", errSyntax}, 66 {"'---\n---'", "", errSyntax}, 67 {"'''\r'''", "", errMissingNewline}, 68 69 {`#"Hello"#`, "Hello", nil}, 70 {`#"Hello\v"#`, "Hello\\v", nil}, 71 {`#"Hello\#v\r"#`, "Hello\v\\r", nil}, 72 {`##"Hello\##v\r"##`, "Hello\v\\r", nil}, 73 {`##"Hello\##v"##`, "Hello\v", nil}, 74 {"#'''\n\t\tHello\\#v\n\t\t'''#", "Hello\v", nil}, 75 {"##'''\n\t\tHello\\#v\n\t\t'''##", "Hello\\#v", nil}, 76 {`#"""` + "\n\t\t\\#r\n\t\t" + `"""#`, "\r", nil}, 77 {`#""#`, "", nil}, 78 {`#" ""#`, ` "`, nil}, 79 {`#" """#`, ` ""`, nil}, 80 {`##" """# "##`, ` """# `, nil}, 81 {`##" """# "##`, ` """# `, nil}, 82 {`#"This is a "dog""#`, `This is a "dog"`, nil}, 83 {"#\"\"\"\n\"\n\"\"\"#", `"`, nil}, 84 {"#\"\"\"\n\"\"\"\n\"\"\"#", `"""`, nil}, 85 {"#\"\"\"\n\na\n\n\"\"\"#", "\na\n", nil}, 86 // Gobble extra \r 87 {"#\"\"\"\n\ra\n\r\"\"\"#", `a`, nil}, 88 {"#\"\"\"\n\r\n\ra\n\r\n\r\"\"\"#", "\na\n", nil}, 89 // Make sure this works for Windows. 90 {"#\"\"\"\r\n\r\na\r\n\r\n\"\"\"#", "\na\n", nil}, 91 {"#\"\"\"\r\n \r\n a\r\n \r\n \"\"\"#", "\na\n", nil}, 92 {"#\"\"\"\r\na\r\n\"\"\"#", `a`, nil}, 93 {"#\"\"\"\r\n\ra\r\n\r\"\"\"#", `a`, nil}, 94 {`####" \"####`, ` \`, nil}, 95 96 {"```", "", errSyntax}, 97 {"Hello", "", errSyntax}, 98 {`"Hello`, "", errUnmatchedQuote}, 99 {`"""Hello"""`, "", errMissingNewline}, 100 {"'''\n Hello\n '''", "", errInvalidWhitespace}, 101 {"'''\n a\n b\n '''", "", errInvalidWhitespace}, 102 {`"Hello""`, "", errSyntax}, 103 {`#"Hello"`, "", errUnmatchedQuote}, 104 {`#"Hello'#`, "", errUnmatchedQuote}, 105 {`#""" """#`, "", errMissingNewline}, 106 107 // TODO: should this be legal? 108 {`#"""#`, "", errMissingNewline}, 109 } 110 for i, tc := range testCases { 111 t.Run(fmt.Sprintf("%d/%s", i, tc.in), func(t *testing.T) { 112 if got, err := Unquote(tc.in); err != tc.err { 113 t.Errorf("error: got %q; want %q", err, tc.err) 114 } else if got != tc.out { 115 t.Errorf("value: got %q; want %q", got, tc.out) 116 } 117 }) 118 } 119 } 120 121 func TestInterpolation(t *testing.T) { 122 testCases := []struct { 123 quotes string 124 in string 125 out string 126 err error 127 }{ 128 {`""`, `foo\(`, "foo", nil}, 129 {`"""` + "\n" + `"""`, `foo`, "", errUnmatchedQuote}, 130 {`#""#`, `foo\#(`, "foo", nil}, 131 {`#""#`, `foo\(`, "", errUnmatchedQuote}, 132 {`""`, `foo\(bar`, "", errSyntax}, 133 {`""`, ``, "", errUnmatchedQuote}, 134 {`#""#`, `"`, "", errUnmatchedQuote}, 135 {`#""#`, `\`, "", errUnmatchedQuote}, 136 {`##""##`, `\'`, "", errUnmatchedQuote}, 137 } 138 for i, tc := range testCases { 139 t.Run(fmt.Sprintf("%d/%s/%s", i, tc.quotes, tc.in), func(t *testing.T) { 140 info, _, _, _ := ParseQuotes(tc.quotes, tc.quotes) 141 if got, err := info.Unquote(tc.in); err != tc.err { 142 t.Errorf("error: got %q; want %q", err, tc.err) 143 } else if got != tc.out { 144 t.Errorf("value: got %q; want %q", got, tc.out) 145 } 146 }) 147 } 148 } 149 150 func TestIsDouble(t *testing.T) { 151 testCases := []struct { 152 quotes string 153 double bool 154 }{ 155 {`""`, true}, 156 {`"""` + "\n" + `"""`, true}, 157 {`#""#`, true}, 158 {`''`, false}, 159 {`'''` + "\n" + `'''`, false}, 160 {`#''#`, false}, 161 } 162 for i, tc := range testCases { 163 t.Run(fmt.Sprintf("%d/%s", i, tc.quotes), func(t *testing.T) { 164 info, _, _, err := ParseQuotes(tc.quotes, tc.quotes) 165 if err != nil { 166 t.Fatal(err) 167 } 168 if got := info.IsDouble(); got != tc.double { 169 t.Errorf("got %v; want %v", got, tc.double) 170 } 171 }) 172 } 173 }