Miek Gieben | 40c7449 | 2011-01-20 12:51:15 -0500 | [diff] [blame] | 1 | // Copyright 2009 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 base32 |
| 6 | |
| 7 | import ( |
| 8 | "bytes" |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame^] | 9 | "io" |
Miek Gieben | 40c7449 | 2011-01-20 12:51:15 -0500 | [diff] [blame] | 10 | "io/ioutil" |
Miek Gieben | 40c7449 | 2011-01-20 12:51:15 -0500 | [diff] [blame] | 11 | "testing" |
| 12 | ) |
| 13 | |
| 14 | type testpair struct { |
| 15 | decoded, encoded string |
| 16 | } |
| 17 | |
| 18 | var pairs = []testpair{ |
| 19 | // RFC 4648 examples |
| 20 | {"", ""}, |
| 21 | {"f", "MY======"}, |
| 22 | {"fo", "MZXQ===="}, |
| 23 | {"foo", "MZXW6==="}, |
| 24 | {"foob", "MZXW6YQ="}, |
| 25 | {"fooba", "MZXW6YTB"}, |
| 26 | {"foobar", "MZXW6YTBOI======"}, |
| 27 | |
Miek Gieben | 40c7449 | 2011-01-20 12:51:15 -0500 | [diff] [blame] | 28 | // Wikipedia examples, converted to base32 |
| 29 | {"sure.", "ON2XEZJO"}, |
| 30 | {"sure", "ON2XEZI="}, |
| 31 | {"sur", "ON2XE==="}, |
| 32 | {"su", "ON2Q===="}, |
| 33 | {"leasure.", "NRSWC43VOJSS4==="}, |
| 34 | {"easure.", "MVQXG5LSMUXA===="}, |
| 35 | {"asure.", "MFZXK4TFFY======"}, |
| 36 | {"sure.", "ON2XEZJO"}, |
| 37 | } |
| 38 | |
| 39 | var bigtest = testpair{ |
| 40 | "Twas brillig, and the slithy toves", |
| 41 | "KR3WC4ZAMJZGS3DMNFTSYIDBNZSCA5DIMUQHG3DJORUHSIDUN53GK4Y=", |
| 42 | } |
| 43 | |
| 44 | func testEqual(t *testing.T, msg string, args ...interface{}) bool { |
| 45 | if args[len(args)-2] != args[len(args)-1] { |
| 46 | t.Errorf(msg, args...) |
| 47 | return false |
| 48 | } |
| 49 | return true |
| 50 | } |
| 51 | |
| 52 | func TestEncode(t *testing.T) { |
| 53 | for _, p := range pairs { |
| 54 | buf := make([]byte, StdEncoding.EncodedLen(len(p.decoded))) |
| 55 | StdEncoding.Encode(buf, []byte(p.decoded)) |
| 56 | testEqual(t, "Encode(%q) = %q, want %q", p.decoded, string(buf), p.encoded) |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | func TestEncoder(t *testing.T) { |
| 61 | for _, p := range pairs { |
| 62 | bb := &bytes.Buffer{} |
| 63 | encoder := NewEncoder(StdEncoding, bb) |
| 64 | encoder.Write([]byte(p.decoded)) |
| 65 | encoder.Close() |
| 66 | testEqual(t, "Encode(%q) = %q, want %q", p.decoded, bb.String(), p.encoded) |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | func TestEncoderBuffering(t *testing.T) { |
| 71 | input := []byte(bigtest.decoded) |
| 72 | for bs := 1; bs <= 12; bs++ { |
| 73 | bb := &bytes.Buffer{} |
| 74 | encoder := NewEncoder(StdEncoding, bb) |
| 75 | for pos := 0; pos < len(input); pos += bs { |
| 76 | end := pos + bs |
| 77 | if end > len(input) { |
| 78 | end = len(input) |
| 79 | } |
| 80 | n, err := encoder.Write(input[pos:end]) |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame^] | 81 | testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil)) |
Miek Gieben | 40c7449 | 2011-01-20 12:51:15 -0500 | [diff] [blame] | 82 | testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos) |
| 83 | } |
| 84 | err := encoder.Close() |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame^] | 85 | testEqual(t, "Close gave error %v, want %v", err, error(nil)) |
Miek Gieben | 40c7449 | 2011-01-20 12:51:15 -0500 | [diff] [blame] | 86 | testEqual(t, "Encoding/%d of %q = %q, want %q", bs, bigtest.decoded, bb.String(), bigtest.encoded) |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | func TestDecode(t *testing.T) { |
| 91 | for _, p := range pairs { |
| 92 | dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded))) |
| 93 | count, end, err := StdEncoding.decode(dbuf, []byte(p.encoded)) |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame^] | 94 | testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, error(nil)) |
Miek Gieben | 40c7449 | 2011-01-20 12:51:15 -0500 | [diff] [blame] | 95 | testEqual(t, "Decode(%q) = length %v, want %v", p.encoded, count, len(p.decoded)) |
| 96 | if len(p.encoded) > 0 { |
| 97 | testEqual(t, "Decode(%q) = end %v, want %v", p.encoded, end, (p.encoded[len(p.encoded)-1] == '=')) |
| 98 | } |
| 99 | testEqual(t, "Decode(%q) = %q, want %q", p.encoded, |
| 100 | string(dbuf[0:count]), |
| 101 | p.decoded) |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | func TestDecoder(t *testing.T) { |
| 106 | for _, p := range pairs { |
| 107 | decoder := NewDecoder(StdEncoding, bytes.NewBufferString(p.encoded)) |
| 108 | dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded))) |
| 109 | count, err := decoder.Read(dbuf) |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame^] | 110 | if err != nil && err != io.EOF { |
Miek Gieben | 40c7449 | 2011-01-20 12:51:15 -0500 | [diff] [blame] | 111 | t.Fatal("Read failed", err) |
| 112 | } |
| 113 | testEqual(t, "Read from %q = length %v, want %v", p.encoded, count, len(p.decoded)) |
| 114 | testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded) |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame^] | 115 | if err != io.EOF { |
Miek Gieben | 40c7449 | 2011-01-20 12:51:15 -0500 | [diff] [blame] | 116 | count, err = decoder.Read(dbuf) |
| 117 | } |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame^] | 118 | testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF) |
Miek Gieben | 40c7449 | 2011-01-20 12:51:15 -0500 | [diff] [blame] | 119 | } |
| 120 | } |
| 121 | |
| 122 | func TestDecoderBuffering(t *testing.T) { |
| 123 | for bs := 1; bs <= 12; bs++ { |
| 124 | decoder := NewDecoder(StdEncoding, bytes.NewBufferString(bigtest.encoded)) |
| 125 | buf := make([]byte, len(bigtest.decoded)+12) |
| 126 | var total int |
| 127 | for total = 0; total < len(bigtest.decoded); { |
| 128 | n, err := decoder.Read(buf[total : total+bs]) |
Russ Cox | c2049d2 | 2011-11-01 22:04:37 -0400 | [diff] [blame^] | 129 | testEqual(t, "Read from %q at pos %d = %d, %v, want _, %v", bigtest.encoded, total, n, err, error(nil)) |
Miek Gieben | 40c7449 | 2011-01-20 12:51:15 -0500 | [diff] [blame] | 130 | total += n |
| 131 | } |
| 132 | testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded) |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | func TestDecodeCorrupt(t *testing.T) { |
| 137 | type corrupt struct { |
| 138 | e string |
| 139 | p int |
| 140 | } |
| 141 | examples := []corrupt{ |
| 142 | {"!!!!", 0}, |
| 143 | {"x===", 0}, |
| 144 | {"AA=A====", 2}, |
| 145 | {"AAA=AAAA", 3}, |
| 146 | {"MMMMMMMMM", 8}, |
| 147 | {"MMMMMM", 0}, |
| 148 | } |
| 149 | |
| 150 | for _, e := range examples { |
| 151 | dbuf := make([]byte, StdEncoding.DecodedLen(len(e.e))) |
| 152 | _, err := StdEncoding.Decode(dbuf, []byte(e.e)) |
| 153 | switch err := err.(type) { |
| 154 | case CorruptInputError: |
| 155 | testEqual(t, "Corruption in %q at offset %v, want %v", e.e, int(err), e.p) |
| 156 | default: |
| 157 | t.Error("Decoder failed to detect corruption in", e) |
| 158 | } |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | func TestBig(t *testing.T) { |
| 163 | n := 3*1000 + 1 |
| 164 | raw := make([]byte, n) |
| 165 | const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" |
| 166 | for i := 0; i < n; i++ { |
| 167 | raw[i] = alpha[i%len(alpha)] |
| 168 | } |
| 169 | encoded := new(bytes.Buffer) |
| 170 | w := NewEncoder(StdEncoding, encoded) |
| 171 | nn, err := w.Write(raw) |
| 172 | if nn != n || err != nil { |
| 173 | t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n) |
| 174 | } |
| 175 | err = w.Close() |
| 176 | if err != nil { |
| 177 | t.Fatalf("Encoder.Close() = %v want nil", err) |
| 178 | } |
| 179 | decoded, err := ioutil.ReadAll(NewDecoder(StdEncoding, encoded)) |
| 180 | if err != nil { |
| 181 | t.Fatalf("ioutil.ReadAll(NewDecoder(...)): %v", err) |
| 182 | } |
| 183 | |
| 184 | if !bytes.Equal(raw, decoded) { |
| 185 | var i int |
| 186 | for i = 0; i < len(decoded) && i < len(raw); i++ { |
| 187 | if decoded[i] != raw[i] { |
| 188 | break |
| 189 | } |
| 190 | } |
| 191 | t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i) |
| 192 | } |
| 193 | } |