1 package quotedprintable
2
3 import (
4 "bytes"
5 "errors"
6 "fmt"
7 "io"
8 "io/ioutil"
9 "strings"
10 "testing"
11 )
12
13 func ExampleWordEncoder_Encode() {
14 fmt.Println(QEncoding.Encode("utf-8", "¡Hola, señor!"))
15 fmt.Println(QEncoding.Encode("utf-8", "Hello!"))
16 fmt.Println(BEncoding.Encode("UTF-8", "¡Hola, señor!"))
17 fmt.Println(QEncoding.Encode("ISO-8859-1", "Caf\xE9"))
18
19
20
21
22
23 }
24
25 func ExampleWordDecoder_Decode() {
26 dec := new(WordDecoder)
27 header, err := dec.Decode("=?utf-8?q?=C2=A1Hola,_se=C3=B1or!?=")
28 if err != nil {
29 panic(err)
30 }
31 fmt.Println(header)
32
33 dec.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
34 switch charset {
35 case "x-case":
36
37
38
39 content, err := ioutil.ReadAll(input)
40 if err != nil {
41 return nil, err
42 }
43 return bytes.NewReader(bytes.ToUpper(content)), nil
44 }
45 return nil, fmt.Errorf("unhandled charset %q", charset)
46 }
47 header, err = dec.Decode("=?x-case?q?hello!?=")
48 if err != nil {
49 panic(err)
50 }
51 fmt.Println(header)
52
53
54
55 }
56
57 func ExampleWordDecoder_DecodeHeader() {
58 dec := new(WordDecoder)
59 header, err := dec.DecodeHeader("=?utf-8?q?=C3=89ric?= <eric@example.org>, =?utf-8?q?Ana=C3=AFs?= <anais@example.org>")
60 if err != nil {
61 panic(err)
62 }
63 fmt.Println(header)
64
65 header, err = dec.DecodeHeader("=?utf-8?q?=C2=A1Hola,?= =?utf-8?q?_se=C3=B1or!?=")
66 if err != nil {
67 panic(err)
68 }
69 fmt.Println(header)
70
71 dec.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
72 switch charset {
73 case "x-case":
74
75
76
77 content, err := ioutil.ReadAll(input)
78 if err != nil {
79 return nil, err
80 }
81 return bytes.NewReader(bytes.ToUpper(content)), nil
82 }
83 return nil, fmt.Errorf("unhandled charset %q", charset)
84 }
85 header, err = dec.DecodeHeader("=?x-case?q?hello_?= =?x-case?q?world!?=")
86 if err != nil {
87 panic(err)
88 }
89 fmt.Println(header)
90
91
92
93
94 }
95
96 func TestEncodeWord(t *testing.T) {
97 utf8, iso88591 := "utf-8", "iso-8859-1"
98 tests := []struct {
99 enc WordEncoder
100 charset string
101 src, exp string
102 }{
103 {QEncoding, utf8, "François-Jérôme", "=?utf-8?q?Fran=C3=A7ois-J=C3=A9r=C3=B4me?="},
104 {BEncoding, utf8, "Café", "=?utf-8?b?Q2Fmw6k=?="},
105 {QEncoding, iso88591, "La Seleção", "=?iso-8859-1?q?La_Sele=C3=A7=C3=A3o?="},
106 {QEncoding, utf8, "", ""},
107 {QEncoding, utf8, "A", "A"},
108 {QEncoding, iso88591, "a", "a"},
109 {QEncoding, utf8, "123 456", "123 456"},
110 {QEncoding, utf8, "\t !\"#$%&'()*+,-./ :;<>?@[\\]^_`{|}~", "\t !\"#$%&'()*+,-./ :;<>?@[\\]^_`{|}~"},
111 }
112
113 for _, test := range tests {
114 if s := test.enc.Encode(test.charset, test.src); s != test.exp {
115 t.Errorf("Encode(%q) = %q, want %q", test.src, s, test.exp)
116 }
117 }
118 }
119
120 func TestDecodeWord(t *testing.T) {
121 tests := []struct {
122 src, exp string
123 hasErr bool
124 }{
125 {"=?UTF-8?Q?=C2=A1Hola,_se=C3=B1or!?=", "¡Hola, señor!", false},
126 {"=?UTF-8?Q?Fran=C3=A7ois-J=C3=A9r=C3=B4me?=", "François-Jérôme", false},
127 {"=?UTF-8?q?ascii?=", "ascii", false},
128 {"=?utf-8?B?QW5kcsOp?=", "André", false},
129 {"=?ISO-8859-1?Q?Rapha=EBl_Dupont?=", "Raphaël Dupont", false},
130 {"=?utf-8?b?IkFudG9uaW8gSm9zw6kiIDxqb3NlQGV4YW1wbGUub3JnPg==?=", `"Antonio José" <jose@example.org>`, false},
131 {"=?UTF-8?A?Test?=", "", true},
132 {"=?UTF-8?Q?A=B?=", "", true},
133 {"=?UTF-8?Q?=A?=", "", true},
134 {"=?UTF-8?A?A?=", "", true},
135 }
136
137 for _, test := range tests {
138 dec := new(WordDecoder)
139 s, err := dec.Decode(test.src)
140 if test.hasErr && err == nil {
141 t.Errorf("Decode(%q) should return an error", test.src)
142 continue
143 }
144 if !test.hasErr && err != nil {
145 t.Errorf("Decode(%q): %v", test.src, err)
146 continue
147 }
148 if s != test.exp {
149 t.Errorf("Decode(%q) = %q, want %q", test.src, s, test.exp)
150 }
151 }
152 }
153
154 func TestDecodeHeader(t *testing.T) {
155 tests := []struct {
156 src, exp string
157 }{
158 {"=?UTF-8?Q?=C2=A1Hola,_se=C3=B1or!?=", "¡Hola, señor!"},
159 {"=?UTF-8?Q?Fran=C3=A7ois-J=C3=A9r=C3=B4me?=", "François-Jérôme"},
160 {"=?UTF-8?q?ascii?=", "ascii"},
161 {"=?utf-8?B?QW5kcsOp?=", "André"},
162 {"=?ISO-8859-1?Q?Rapha=EBl_Dupont?=", "Raphaël Dupont"},
163 {"Jean", "Jean"},
164 {"=?utf-8?b?IkFudG9uaW8gSm9zw6kiIDxqb3NlQGV4YW1wbGUub3JnPg==?=", `"Antonio José" <jose@example.org>`},
165 {"=?UTF-8?A?Test?=", "=?UTF-8?A?Test?="},
166 {"=?UTF-8?Q?A=B?=", "=?UTF-8?Q?A=B?="},
167 {"=?UTF-8?Q?=A?=", "=?UTF-8?Q?=A?="},
168 {"=?UTF-8?A?A?=", "=?UTF-8?A?A?="},
169
170 {"=?", "=?"},
171 {"=?UTF-8?", "=?UTF-8?"},
172 {"=?UTF-8?=", "=?UTF-8?="},
173 {"=?UTF-8?Q", "=?UTF-8?Q"},
174 {"=?UTF-8?Q?", "=?UTF-8?Q?"},
175 {"=?UTF-8?Q?=", "=?UTF-8?Q?="},
176 {"=?UTF-8?Q?A", "=?UTF-8?Q?A"},
177 {"=?UTF-8?Q?A?", "=?UTF-8?Q?A?"},
178
179 {"=?ISO-8859-1?Q?a?=", "a"},
180 {"=?ISO-8859-1?Q?a?= b", "a b"},
181 {"=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=", "ab"},
182 {"=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=", "ab"},
183 {"=?ISO-8859-1?Q?a?= \r\n\t =?ISO-8859-1?Q?b?=", "ab"},
184 {"=?ISO-8859-1?Q?a_b?=", "a b"},
185 }
186
187 for _, test := range tests {
188 dec := new(WordDecoder)
189 s, err := dec.DecodeHeader(test.src)
190 if err != nil {
191 t.Errorf("DecodeHeader(%q): %v", test.src, err)
192 }
193 if s != test.exp {
194 t.Errorf("DecodeHeader(%q) = %q, want %q", test.src, s, test.exp)
195 }
196 }
197 }
198
199 func TestCharsetDecoder(t *testing.T) {
200 tests := []struct {
201 src string
202 want string
203 charsets []string
204 content []string
205 }{
206 {"=?utf-8?b?Q2Fmw6k=?=", "Café", nil, nil},
207 {"=?ISO-8859-1?Q?caf=E9?=", "café", nil, nil},
208 {"=?US-ASCII?Q?foo_bar?=", "foo bar", nil, nil},
209 {"=?utf-8?Q?=?=", "=?utf-8?Q?=?=", nil, nil},
210 {"=?utf-8?Q?=A?=", "=?utf-8?Q?=A?=", nil, nil},
211 {
212 "=?ISO-8859-15?Q?f=F5=F6?= =?windows-1252?Q?b=E0r?=",
213 "f\xf5\xf6b\xe0r",
214 []string{"iso-8859-15", "windows-1252"},
215 []string{"f\xf5\xf6", "b\xe0r"},
216 },
217 }
218
219 for _, test := range tests {
220 i := 0
221 dec := &WordDecoder{
222 CharsetReader: func(charset string, input io.Reader) (io.Reader, error) {
223 if charset != test.charsets[i] {
224 t.Errorf("DecodeHeader(%q), got charset %q, want %q", test.src, charset, test.charsets[i])
225 }
226 content, err := ioutil.ReadAll(input)
227 if err != nil {
228 t.Errorf("DecodeHeader(%q), error in reader: %v", test.src, err)
229 }
230 got := string(content)
231 if got != test.content[i] {
232 t.Errorf("DecodeHeader(%q), got content %q, want %q", test.src, got, test.content[i])
233 }
234 i++
235
236 return strings.NewReader(got), nil
237 },
238 }
239 got, err := dec.DecodeHeader(test.src)
240 if err != nil {
241 t.Errorf("DecodeHeader(%q): %v", test.src, err)
242 }
243 if got != test.want {
244 t.Errorf("DecodeHeader(%q) = %q, want %q", test.src, got, test.want)
245 }
246 }
247 }
248
249 func TestCharsetDecoderError(t *testing.T) {
250 dec := &WordDecoder{
251 CharsetReader: func(charset string, input io.Reader) (io.Reader, error) {
252 return nil, errors.New("Test error")
253 },
254 }
255
256 if _, err := dec.DecodeHeader("=?charset?Q?foo?="); err == nil {
257 t.Error("DecodeHeader should return an error")
258 }
259 }
260
261 func BenchmarkQEncodeWord(b *testing.B) {
262 for i := 0; i < b.N; i++ {
263 QEncoding.Encode("UTF-8", "¡Hola, señor!")
264 }
265 }
266
267 func BenchmarkQDecodeWord(b *testing.B) {
268 dec := new(WordDecoder)
269
270 for i := 0; i < b.N; i++ {
271 dec.Decode("=?utf-8?q?=C2=A1Hola,_se=C3=B1or!?=")
272 }
273 }
274
275 func BenchmarkQDecodeHeader(b *testing.B) {
276 dec := new(WordDecoder)
277
278 for i := 0; i < b.N; i++ {
279 dec.Decode("=?utf-8?q?=C2=A1Hola,_se=C3=B1or!?=")
280 }
281 }
282
View as plain text