github.com/huandu/go@v0.0.0-20151114150818-04e615e41150/src/mime/encodedword_test.go (about)

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