Home | History | Annotate | Download | only in quotedprintable
      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 quotedprintable
      6 
      7 import (
      8 	"bytes"
      9 	"io/ioutil"
     10 	"strings"
     11 	"testing"
     12 )
     13 
     14 func TestWriter(t *testing.T) {
     15 	testWriter(t, false)
     16 }
     17 
     18 func TestWriterBinary(t *testing.T) {
     19 	testWriter(t, true)
     20 }
     21 
     22 func testWriter(t *testing.T, binary bool) {
     23 	tests := []struct {
     24 		in, want, wantB string
     25 	}{
     26 		{in: "", want: ""},
     27 		{in: "foo bar", want: "foo bar"},
     28 		{in: "foo bar=", want: "foo bar=3D"},
     29 		{in: "foo bar\r", want: "foo bar\r\n", wantB: "foo bar=0D"},
     30 		{in: "foo bar\r\r", want: "foo bar\r\n\r\n", wantB: "foo bar=0D=0D"},
     31 		{in: "foo bar\n", want: "foo bar\r\n", wantB: "foo bar=0A"},
     32 		{in: "foo bar\r\n", want: "foo bar\r\n", wantB: "foo bar=0D=0A"},
     33 		{in: "foo bar\r\r\n", want: "foo bar\r\n\r\n", wantB: "foo bar=0D=0D=0A"},
     34 		{in: "foo bar ", want: "foo bar=20"},
     35 		{in: "foo bar\t", want: "foo bar=09"},
     36 		{in: "foo bar  ", want: "foo bar =20"},
     37 		{in: "foo bar \n", want: "foo bar=20\r\n", wantB: "foo bar =0A"},
     38 		{in: "foo bar \r", want: "foo bar=20\r\n", wantB: "foo bar =0D"},
     39 		{in: "foo bar \r\n", want: "foo bar=20\r\n", wantB: "foo bar =0D=0A"},
     40 		{in: "foo bar  \n", want: "foo bar =20\r\n", wantB: "foo bar  =0A"},
     41 		{in: "foo bar  \n ", want: "foo bar =20\r\n=20", wantB: "foo bar  =0A=20"},
     42 		{in: "Hola Seor!", want: "=C2=A1Hola Se=C3=B1or!"},
     43 		{
     44 			in:   "\t !\"#$%&'()*+,-./ :;<>?@[\\]^_`{|}~",
     45 			want: "\t !\"#$%&'()*+,-./ :;<>?@[\\]^_`{|}~",
     46 		},
     47 		{
     48 			in:   strings.Repeat("a", 75),
     49 			want: strings.Repeat("a", 75),
     50 		},
     51 		{
     52 			in:   strings.Repeat("a", 76),
     53 			want: strings.Repeat("a", 75) + "=\r\na",
     54 		},
     55 		{
     56 			in:   strings.Repeat("a", 72) + "=",
     57 			want: strings.Repeat("a", 72) + "=3D",
     58 		},
     59 		{
     60 			in:   strings.Repeat("a", 73) + "=",
     61 			want: strings.Repeat("a", 73) + "=\r\n=3D",
     62 		},
     63 		{
     64 			in:   strings.Repeat("a", 74) + "=",
     65 			want: strings.Repeat("a", 74) + "=\r\n=3D",
     66 		},
     67 		{
     68 			in:   strings.Repeat("a", 75) + "=",
     69 			want: strings.Repeat("a", 75) + "=\r\n=3D",
     70 		},
     71 		{
     72 			in:   strings.Repeat(" ", 73),
     73 			want: strings.Repeat(" ", 72) + "=20",
     74 		},
     75 		{
     76 			in:   strings.Repeat(" ", 74),
     77 			want: strings.Repeat(" ", 73) + "=\r\n=20",
     78 		},
     79 		{
     80 			in:   strings.Repeat(" ", 75),
     81 			want: strings.Repeat(" ", 74) + "=\r\n=20",
     82 		},
     83 		{
     84 			in:   strings.Repeat(" ", 76),
     85 			want: strings.Repeat(" ", 75) + "=\r\n=20",
     86 		},
     87 		{
     88 			in:   strings.Repeat(" ", 77),
     89 			want: strings.Repeat(" ", 75) + "=\r\n =20",
     90 		},
     91 	}
     92 
     93 	for _, tt := range tests {
     94 		buf := new(bytes.Buffer)
     95 		w := NewWriter(buf)
     96 
     97 		want := tt.want
     98 		if binary {
     99 			w.Binary = true
    100 			if tt.wantB != "" {
    101 				want = tt.wantB
    102 			}
    103 		}
    104 
    105 		if _, err := w.Write([]byte(tt.in)); err != nil {
    106 			t.Errorf("Write(%q): %v", tt.in, err)
    107 			continue
    108 		}
    109 		if err := w.Close(); err != nil {
    110 			t.Errorf("Close(): %v", err)
    111 			continue
    112 		}
    113 		got := buf.String()
    114 		if got != want {
    115 			t.Errorf("Write(%q), got:\n%q\nwant:\n%q", tt.in, got, want)
    116 		}
    117 	}
    118 }
    119 
    120 func TestRoundTrip(t *testing.T) {
    121 	buf := new(bytes.Buffer)
    122 	w := NewWriter(buf)
    123 	if _, err := w.Write(testMsg); err != nil {
    124 		t.Fatalf("Write: %v", err)
    125 	}
    126 	if err := w.Close(); err != nil {
    127 		t.Fatalf("Close: %v", err)
    128 	}
    129 
    130 	r := NewReader(buf)
    131 	gotBytes, err := ioutil.ReadAll(r)
    132 	if err != nil {
    133 		t.Fatalf("Error while reading from Reader: %v", err)
    134 	}
    135 	got := string(gotBytes)
    136 	if got != string(testMsg) {
    137 		t.Errorf("Encoding and decoding changed the message, got:\n%s", got)
    138 	}
    139 }
    140 
    141 // From http://fr.wikipedia.org/wiki/Quoted-Printable
    142 var testMsg = []byte("Quoted-Printable (QP) est un format d'encodage de donnes codes sur 8 bits, qui utilise exclusivement les caractres alphanumriques imprimables du code ASCII (7 bits).\r\n" +
    143 	"\r\n" +
    144 	"En effet, les diffrents codages comprennent de nombreux caractres qui ne sont pas reprsentables en ASCII (par exemple les caractres accentus), ainsi que des caractres dits  non-imprimables .\r\n" +
    145 	"\r\n" +
    146 	"L'encodage Quoted-Printable permet de remdier  ce problme, en procdant de la manire suivante :\r\n" +
    147 	"\r\n" +
    148 	"Un octet correspondant  un caractre imprimable de l'ASCII sauf le signe gal (donc un caractre de code ASCII entre 33 et 60 ou entre 62 et 126) ou aux caractres de saut de ligne (codes ASCII 13 et 10) ou une suite de tabulations et espaces non situes en fin de ligne (de codes ASCII respectifs 9 et 32) est reprsent tel quel.\r\n" +
    149 	"Un octet qui ne correspond pas  la dfinition ci-dessus (caractre non imprimable de l'ASCII, tabulation ou espaces non suivies d'un caractre imprimable avant la fin de la ligne ou signe gal) est reprsent par un signe gal, suivi de son numro, exprim en hexadcimal.\r\n" +
    150 	"Enfin, un signe gal suivi par un saut de ligne (donc la suite des trois caractres de codes ASCII 61, 13 et 10) peut tre insr n'importe o, afin de limiter la taille des lignes produites si ncessaire. Une limite de 76 caractres par ligne est gnralement respecte.\r\n")
    151 
    152 func BenchmarkWriter(b *testing.B) {
    153 	for i := 0; i < b.N; i++ {
    154 		w := NewWriter(ioutil.Discard)
    155 		w.Write(testMsg)
    156 		w.Close()
    157 	}
    158 }
    159