Source file src/encoding/base32/base32_test.go

     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"
     9  	"errors"
    10  	"io"
    11  	"math"
    12  	"strconv"
    13  	"strings"
    14  	"testing"
    15  )
    16  
    17  type testpair struct {
    18  	decoded, encoded string
    19  }
    20  
    21  var pairs = []testpair{
    22  	// RFC 4648 examples
    23  	{"", ""},
    24  	{"f", "MY======"},
    25  	{"fo", "MZXQ===="},
    26  	{"foo", "MZXW6==="},
    27  	{"foob", "MZXW6YQ="},
    28  	{"fooba", "MZXW6YTB"},
    29  	{"foobar", "MZXW6YTBOI======"},
    30  
    31  	// Wikipedia examples, converted to base32
    32  	{"sure.", "ON2XEZJO"},
    33  	{"sure", "ON2XEZI="},
    34  	{"sur", "ON2XE==="},
    35  	{"su", "ON2Q===="},
    36  	{"leasure.", "NRSWC43VOJSS4==="},
    37  	{"easure.", "MVQXG5LSMUXA===="},
    38  	{"asure.", "MFZXK4TFFY======"},
    39  	{"sure.", "ON2XEZJO"},
    40  }
    41  
    42  var bigtest = testpair{
    43  	"Twas brillig, and the slithy toves",
    44  	"KR3WC4ZAMJZGS3DMNFTSYIDBNZSCA5DIMUQHG3DJORUHSIDUN53GK4Y=",
    45  }
    46  
    47  func testEqual(t *testing.T, msg string, args ...any) bool {
    48  	t.Helper()
    49  	if args[len(args)-2] != args[len(args)-1] {
    50  		t.Errorf(msg, args...)
    51  		return false
    52  	}
    53  	return true
    54  }
    55  
    56  func TestEncode(t *testing.T) {
    57  	for _, p := range pairs {
    58  		got := StdEncoding.EncodeToString([]byte(p.decoded))
    59  		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, p.encoded)
    60  		dst := StdEncoding.AppendEncode([]byte("lead"), []byte(p.decoded))
    61  		testEqual(t, `AppendEncode("lead", %q) = %q, want %q`, p.decoded, string(dst), "lead"+p.encoded)
    62  	}
    63  }
    64  
    65  func TestEncoder(t *testing.T) {
    66  	for _, p := range pairs {
    67  		bb := &strings.Builder{}
    68  		encoder := NewEncoder(StdEncoding, bb)
    69  		encoder.Write([]byte(p.decoded))
    70  		encoder.Close()
    71  		testEqual(t, "Encode(%q) = %q, want %q", p.decoded, bb.String(), p.encoded)
    72  	}
    73  }
    74  
    75  func TestEncoderBuffering(t *testing.T) {
    76  	input := []byte(bigtest.decoded)
    77  	for bs := 1; bs <= 12; bs++ {
    78  		bb := &strings.Builder{}
    79  		encoder := NewEncoder(StdEncoding, bb)
    80  		for pos := 0; pos < len(input); pos += bs {
    81  			end := pos + bs
    82  			if end > len(input) {
    83  				end = len(input)
    84  			}
    85  			n, err := encoder.Write(input[pos:end])
    86  			testEqual(t, "Write(%q) gave error %v, want %v", input[pos:end], err, error(nil))
    87  			testEqual(t, "Write(%q) gave length %v, want %v", input[pos:end], n, end-pos)
    88  		}
    89  		err := encoder.Close()
    90  		testEqual(t, "Close gave error %v, want %v", err, error(nil))
    91  		testEqual(t, "Encoding/%d of %q = %q, want %q", bs, bigtest.decoded, bb.String(), bigtest.encoded)
    92  	}
    93  }
    94  
    95  func TestDecode(t *testing.T) {
    96  	for _, p := range pairs {
    97  		dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
    98  		count, end, err := StdEncoding.decode(dbuf, []byte(p.encoded))
    99  		testEqual(t, "Decode(%q) = error %v, want %v", p.encoded, err, error(nil))
   100  		testEqual(t, "Decode(%q) = length %v, want %v", p.encoded, count, len(p.decoded))
   101  		if len(p.encoded) > 0 {
   102  			testEqual(t, "Decode(%q) = end %v, want %v", p.encoded, end, (p.encoded[len(p.encoded)-1] == '='))
   103  		}
   104  		testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
   105  
   106  		dbuf, err = StdEncoding.DecodeString(p.encoded)
   107  		testEqual(t, "DecodeString(%q) = error %v, want %v", p.encoded, err, error(nil))
   108  		testEqual(t, "DecodeString(%q) = %q, want %q", p.encoded, string(dbuf), p.decoded)
   109  
   110  		dst, err := StdEncoding.AppendDecode([]byte("lead"), []byte(p.encoded))
   111  		testEqual(t, "AppendDecode(%q) = error %v, want %v", p.encoded, err, error(nil))
   112  		testEqual(t, `AppendDecode("lead", %q) = %q, want %q`, p.encoded, string(dst), "lead"+p.decoded)
   113  
   114  		dst2, err := StdEncoding.AppendDecode(dst[:0:len(p.decoded)], []byte(p.encoded))
   115  		testEqual(t, "AppendDecode(%q) = error %v, want %v", p.encoded, err, error(nil))
   116  		testEqual(t, `AppendDecode("", %q) = %q, want %q`, p.encoded, string(dst2), p.decoded)
   117  		if len(dst) > 0 && len(dst2) > 0 && &dst[0] != &dst2[0] {
   118  			t.Errorf("unexpected capacity growth: got %d, want %d", cap(dst2), cap(dst))
   119  		}
   120  	}
   121  }
   122  
   123  func TestDecoder(t *testing.T) {
   124  	for _, p := range pairs {
   125  		decoder := NewDecoder(StdEncoding, strings.NewReader(p.encoded))
   126  		dbuf := make([]byte, StdEncoding.DecodedLen(len(p.encoded)))
   127  		count, err := decoder.Read(dbuf)
   128  		if err != nil && err != io.EOF {
   129  			t.Fatal("Read failed", err)
   130  		}
   131  		testEqual(t, "Read from %q = length %v, want %v", p.encoded, count, len(p.decoded))
   132  		testEqual(t, "Decoding of %q = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
   133  		if err != io.EOF {
   134  			_, err = decoder.Read(dbuf)
   135  		}
   136  		testEqual(t, "Read from %q = %v, want %v", p.encoded, err, io.EOF)
   137  	}
   138  }
   139  
   140  type badReader struct {
   141  	data   []byte
   142  	errs   []error
   143  	called int
   144  	limit  int
   145  }
   146  
   147  // Populates p with data, returns a count of the bytes written and an
   148  // error.  The error returned is taken from badReader.errs, with each
   149  // invocation of Read returning the next error in this slice, or io.EOF,
   150  // if all errors from the slice have already been returned.  The
   151  // number of bytes returned is determined by the size of the input buffer
   152  // the test passes to decoder.Read and will be a multiple of 8, unless
   153  // badReader.limit is non zero.
   154  func (b *badReader) Read(p []byte) (int, error) {
   155  	lim := len(p)
   156  	if b.limit != 0 && b.limit < lim {
   157  		lim = b.limit
   158  	}
   159  	if len(b.data) < lim {
   160  		lim = len(b.data)
   161  	}
   162  	for i := range p[:lim] {
   163  		p[i] = b.data[i]
   164  	}
   165  	b.data = b.data[lim:]
   166  	err := io.EOF
   167  	if b.called < len(b.errs) {
   168  		err = b.errs[b.called]
   169  	}
   170  	b.called++
   171  	return lim, err
   172  }
   173  
   174  // TestIssue20044 tests that decoder.Read behaves correctly when the caller
   175  // supplied reader returns an error.
   176  func TestIssue20044(t *testing.T) {
   177  	badErr := errors.New("bad reader error")
   178  	testCases := []struct {
   179  		r       badReader
   180  		res     string
   181  		err     error
   182  		dbuflen int
   183  	}{
   184  		// Check valid input data accompanied by an error is processed and the error is propagated.
   185  		{r: badReader{data: []byte("MY======"), errs: []error{badErr}},
   186  			res: "f", err: badErr},
   187  		// Check a read error accompanied by input data consisting of newlines only is propagated.
   188  		{r: badReader{data: []byte("\n\n\n\n\n\n\n\n"), errs: []error{badErr, nil}},
   189  			res: "", err: badErr},
   190  		// Reader will be called twice.  The first time it will return 8 newline characters.  The
   191  		// second time valid base32 encoded data and an error.  The data should be decoded
   192  		// correctly and the error should be propagated.
   193  		{r: badReader{data: []byte("\n\n\n\n\n\n\n\nMY======"), errs: []error{nil, badErr}},
   194  			res: "f", err: badErr, dbuflen: 8},
   195  		// Reader returns invalid input data (too short) and an error.  Verify the reader
   196  		// error is returned.
   197  		{r: badReader{data: []byte("MY====="), errs: []error{badErr}},
   198  			res: "", err: badErr},
   199  		// Reader returns invalid input data (too short) but no error.  Verify io.ErrUnexpectedEOF
   200  		// is returned.
   201  		{r: badReader{data: []byte("MY====="), errs: []error{nil}},
   202  			res: "", err: io.ErrUnexpectedEOF},
   203  		// Reader returns invalid input data and an error.  Verify the reader and not the
   204  		// decoder error is returned.
   205  		{r: badReader{data: []byte("Ma======"), errs: []error{badErr}},
   206  			res: "", err: badErr},
   207  		// Reader returns valid data and io.EOF.  Check data is decoded and io.EOF is propagated.
   208  		{r: badReader{data: []byte("MZXW6YTB"), errs: []error{io.EOF}},
   209  			res: "fooba", err: io.EOF},
   210  		// Check errors are properly reported when decoder.Read is called multiple times.
   211  		// decoder.Read will be called 8 times, badReader.Read will be called twice, returning
   212  		// valid data both times but an error on the second call.
   213  		{r: badReader{data: []byte("NRSWC43VOJSS4==="), errs: []error{nil, badErr}},
   214  			res: "leasure.", err: badErr, dbuflen: 1},
   215  		// Check io.EOF is properly reported when decoder.Read is called multiple times.
   216  		// decoder.Read will be called 8 times, badReader.Read will be called twice, returning
   217  		// valid data both times but io.EOF on the second call.
   218  		{r: badReader{data: []byte("NRSWC43VOJSS4==="), errs: []error{nil, io.EOF}},
   219  			res: "leasure.", err: io.EOF, dbuflen: 1},
   220  		// The following two test cases check that errors are propagated correctly when more than
   221  		// 8 bytes are read at a time.
   222  		{r: badReader{data: []byte("NRSWC43VOJSS4==="), errs: []error{io.EOF}},
   223  			res: "leasure.", err: io.EOF, dbuflen: 11},
   224  		{r: badReader{data: []byte("NRSWC43VOJSS4==="), errs: []error{badErr}},
   225  			res: "leasure.", err: badErr, dbuflen: 11},
   226  		// Check that errors are correctly propagated when the reader returns valid bytes in
   227  		// groups that are not divisible by 8.  The first read will return 11 bytes and no
   228  		// error.  The second will return 7 and an error.  The data should be decoded correctly
   229  		// and the error should be propagated.
   230  		{r: badReader{data: []byte("NRSWC43VOJSS4==="), errs: []error{nil, badErr}, limit: 11},
   231  			res: "leasure.", err: badErr},
   232  	}
   233  
   234  	for _, tc := range testCases {
   235  		input := tc.r.data
   236  		decoder := NewDecoder(StdEncoding, &tc.r)
   237  		var dbuflen int
   238  		if tc.dbuflen > 0 {
   239  			dbuflen = tc.dbuflen
   240  		} else {
   241  			dbuflen = StdEncoding.DecodedLen(len(input))
   242  		}
   243  		dbuf := make([]byte, dbuflen)
   244  		var err error
   245  		var res []byte
   246  		for err == nil {
   247  			var n int
   248  			n, err = decoder.Read(dbuf)
   249  			if n > 0 {
   250  				res = append(res, dbuf[:n]...)
   251  			}
   252  		}
   253  
   254  		testEqual(t, "Decoding of %q = %q, want %q", string(input), string(res), tc.res)
   255  		testEqual(t, "Decoding of %q err = %v, expected %v", string(input), err, tc.err)
   256  	}
   257  }
   258  
   259  // TestDecoderError verifies decode errors are propagated when there are no read
   260  // errors.
   261  func TestDecoderError(t *testing.T) {
   262  	for _, readErr := range []error{io.EOF, nil} {
   263  		input := "MZXW6YTb"
   264  		dbuf := make([]byte, StdEncoding.DecodedLen(len(input)))
   265  		br := badReader{data: []byte(input), errs: []error{readErr}}
   266  		decoder := NewDecoder(StdEncoding, &br)
   267  		n, err := decoder.Read(dbuf)
   268  		testEqual(t, "Read after EOF, n = %d, expected %d", n, 0)
   269  		if _, ok := err.(CorruptInputError); !ok {
   270  			t.Errorf("Corrupt input error expected.  Found %T", err)
   271  		}
   272  	}
   273  }
   274  
   275  // TestReaderEOF ensures decoder.Read behaves correctly when input data is
   276  // exhausted.
   277  func TestReaderEOF(t *testing.T) {
   278  	for _, readErr := range []error{io.EOF, nil} {
   279  		input := "MZXW6YTB"
   280  		br := badReader{data: []byte(input), errs: []error{nil, readErr}}
   281  		decoder := NewDecoder(StdEncoding, &br)
   282  		dbuf := make([]byte, StdEncoding.DecodedLen(len(input)))
   283  		n, err := decoder.Read(dbuf)
   284  		testEqual(t, "Decoding of %q err = %v, expected %v", input, err, error(nil))
   285  		n, err = decoder.Read(dbuf)
   286  		testEqual(t, "Read after EOF, n = %d, expected %d", n, 0)
   287  		testEqual(t, "Read after EOF, err = %v, expected %v", err, io.EOF)
   288  		n, err = decoder.Read(dbuf)
   289  		testEqual(t, "Read after EOF, n = %d, expected %d", n, 0)
   290  		testEqual(t, "Read after EOF, err = %v, expected %v", err, io.EOF)
   291  	}
   292  }
   293  
   294  func TestDecoderBuffering(t *testing.T) {
   295  	for bs := 1; bs <= 12; bs++ {
   296  		decoder := NewDecoder(StdEncoding, strings.NewReader(bigtest.encoded))
   297  		buf := make([]byte, len(bigtest.decoded)+12)
   298  		var total int
   299  		var n int
   300  		var err error
   301  		for total = 0; total < len(bigtest.decoded) && err == nil; {
   302  			n, err = decoder.Read(buf[total : total+bs])
   303  			total += n
   304  		}
   305  		if err != nil && err != io.EOF {
   306  			t.Errorf("Read from %q at pos %d = %d, unexpected error %v", bigtest.encoded, total, n, err)
   307  		}
   308  		testEqual(t, "Decoding/%d of %q = %q, want %q", bs, bigtest.encoded, string(buf[0:total]), bigtest.decoded)
   309  	}
   310  }
   311  
   312  func TestDecodeCorrupt(t *testing.T) {
   313  	testCases := []struct {
   314  		input  string
   315  		offset int // -1 means no corruption.
   316  	}{
   317  		{"", -1},
   318  		{"!!!!", 0},
   319  		{"x===", 0},
   320  		{"AA=A====", 2},
   321  		{"AAA=AAAA", 3},
   322  		{"MMMMMMMMM", 8},
   323  		{"MMMMMM", 0},
   324  		{"A=", 1},
   325  		{"AA=", 3},
   326  		{"AA==", 4},
   327  		{"AA===", 5},
   328  		{"AAAA=", 5},
   329  		{"AAAA==", 6},
   330  		{"AAAAA=", 6},
   331  		{"AAAAA==", 7},
   332  		{"A=======", 1},
   333  		{"AA======", -1},
   334  		{"AAA=====", 3},
   335  		{"AAAA====", -1},
   336  		{"AAAAA===", -1},
   337  		{"AAAAAA==", 6},
   338  		{"AAAAAAA=", -1},
   339  		{"AAAAAAAA", -1},
   340  	}
   341  	for _, tc := range testCases {
   342  		dbuf := make([]byte, StdEncoding.DecodedLen(len(tc.input)))
   343  		_, err := StdEncoding.Decode(dbuf, []byte(tc.input))
   344  		if tc.offset == -1 {
   345  			if err != nil {
   346  				t.Error("Decoder wrongly detected corruption in", tc.input)
   347  			}
   348  			continue
   349  		}
   350  		switch err := err.(type) {
   351  		case CorruptInputError:
   352  			testEqual(t, "Corruption in %q at offset %v, want %v", tc.input, int(err), tc.offset)
   353  		default:
   354  			t.Error("Decoder failed to detect corruption in", tc)
   355  		}
   356  	}
   357  }
   358  
   359  func TestBig(t *testing.T) {
   360  	n := 3*1000 + 1
   361  	raw := make([]byte, n)
   362  	const alpha = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
   363  	for i := 0; i < n; i++ {
   364  		raw[i] = alpha[i%len(alpha)]
   365  	}
   366  	encoded := new(bytes.Buffer)
   367  	w := NewEncoder(StdEncoding, encoded)
   368  	nn, err := w.Write(raw)
   369  	if nn != n || err != nil {
   370  		t.Fatalf("Encoder.Write(raw) = %d, %v want %d, nil", nn, err, n)
   371  	}
   372  	err = w.Close()
   373  	if err != nil {
   374  		t.Fatalf("Encoder.Close() = %v want nil", err)
   375  	}
   376  	decoded, err := io.ReadAll(NewDecoder(StdEncoding, encoded))
   377  	if err != nil {
   378  		t.Fatalf("io.ReadAll(NewDecoder(...)): %v", err)
   379  	}
   380  
   381  	if !bytes.Equal(raw, decoded) {
   382  		var i int
   383  		for i = 0; i < len(decoded) && i < len(raw); i++ {
   384  			if decoded[i] != raw[i] {
   385  				break
   386  			}
   387  		}
   388  		t.Errorf("Decode(Encode(%d-byte string)) failed at offset %d", n, i)
   389  	}
   390  }
   391  
   392  func testStringEncoding(t *testing.T, expected string, examples []string) {
   393  	for _, e := range examples {
   394  		buf, err := StdEncoding.DecodeString(e)
   395  		if err != nil {
   396  			t.Errorf("Decode(%q) failed: %v", e, err)
   397  			continue
   398  		}
   399  		if s := string(buf); s != expected {
   400  			t.Errorf("Decode(%q) = %q, want %q", e, s, expected)
   401  		}
   402  	}
   403  }
   404  
   405  func TestNewLineCharacters(t *testing.T) {
   406  	// Each of these should decode to the string "sure", without errors.
   407  	examples := []string{
   408  		"ON2XEZI=",
   409  		"ON2XEZI=\r",
   410  		"ON2XEZI=\n",
   411  		"ON2XEZI=\r\n",
   412  		"ON2XEZ\r\nI=",
   413  		"ON2X\rEZ\nI=",
   414  		"ON2X\nEZ\rI=",
   415  		"ON2XEZ\nI=",
   416  		"ON2XEZI\n=",
   417  	}
   418  	testStringEncoding(t, "sure", examples)
   419  
   420  	// Each of these should decode to the string "foobar", without errors.
   421  	examples = []string{
   422  		"MZXW6YTBOI======",
   423  		"MZXW6YTBOI=\r\n=====",
   424  	}
   425  	testStringEncoding(t, "foobar", examples)
   426  }
   427  
   428  func TestDecoderIssue4779(t *testing.T) {
   429  	encoded := `JRXXEZLNEBUXA43VNUQGI33MN5ZCA43JOQQGC3LFOQWCAY3PNZZWKY3UMV2HK4
   430  RAMFSGS4DJONUWG2LOM4QGK3DJOQWCA43FMQQGI3YKMVUXK43NN5SCA5DFNVYG64RANFXGG2LENFSH
   431  K3TUEB2XIIDMMFRG64TFEBSXIIDEN5WG64TFEBWWCZ3OMEQGC3DJOF2WCLRAKV2CAZLONFWQUYLEEB
   432  WWS3TJNUQHMZLONFQW2LBAOF2WS4ZANZXXG5DSOVSCAZLYMVZGG2LUMF2GS33OEB2WY3DBNVRW6IDM
   433  MFRG64TJOMQG42LTNEQHK5AKMFWGS4LVNFYCAZLYEBSWCIDDN5WW233EN4QGG33OONSXC5LBOQXCAR
   434  DVNFZSAYLVORSSA2LSOVZGKIDEN5WG64RANFXAU4TFOBZGK2DFNZSGK4TJOQQGS3RAOZXWY5LQORQX
   435  IZJAOZSWY2LUEBSXG43FEBRWS3DMOVWSAZDPNRXXEZJAMV2SAZTVM5UWC5BANZ2WY3DBBJYGC4TJMF
   436  2HK4ROEBCXQY3FOB2GK5LSEBZWS3TUEBXWGY3BMVRWC5BAMN2XA2LEMF2GC5BANZXW4IDQOJXWSZDF
   437  NZ2CYIDTOVXHIIDJNYFGG5LMOBQSA4LVNEQG6ZTGNFRWSYJAMRSXGZLSOVXHIIDNN5WGY2LUEBQW42
   438  LNEBUWIIDFON2CA3DBMJXXE5LNFY==
   439  ====`
   440  	encodedShort := strings.ReplaceAll(encoded, "\n", "")
   441  
   442  	dec := NewDecoder(StdEncoding, strings.NewReader(encoded))
   443  	res1, err := io.ReadAll(dec)
   444  	if err != nil {
   445  		t.Errorf("ReadAll failed: %v", err)
   446  	}
   447  
   448  	dec = NewDecoder(StdEncoding, strings.NewReader(encodedShort))
   449  	var res2 []byte
   450  	res2, err = io.ReadAll(dec)
   451  	if err != nil {
   452  		t.Errorf("ReadAll failed: %v", err)
   453  	}
   454  
   455  	if !bytes.Equal(res1, res2) {
   456  		t.Error("Decoded results not equal")
   457  	}
   458  }
   459  
   460  func BenchmarkEncode(b *testing.B) {
   461  	data := make([]byte, 8192)
   462  	buf := make([]byte, StdEncoding.EncodedLen(len(data)))
   463  	b.SetBytes(int64(len(data)))
   464  	for i := 0; i < b.N; i++ {
   465  		StdEncoding.Encode(buf, data)
   466  	}
   467  }
   468  
   469  func BenchmarkEncodeToString(b *testing.B) {
   470  	data := make([]byte, 8192)
   471  	b.SetBytes(int64(len(data)))
   472  	for i := 0; i < b.N; i++ {
   473  		StdEncoding.EncodeToString(data)
   474  	}
   475  }
   476  
   477  func BenchmarkDecode(b *testing.B) {
   478  	data := make([]byte, StdEncoding.EncodedLen(8192))
   479  	StdEncoding.Encode(data, make([]byte, 8192))
   480  	buf := make([]byte, 8192)
   481  	b.SetBytes(int64(len(data)))
   482  	for i := 0; i < b.N; i++ {
   483  		StdEncoding.Decode(buf, data)
   484  	}
   485  }
   486  func BenchmarkDecodeString(b *testing.B) {
   487  	data := StdEncoding.EncodeToString(make([]byte, 8192))
   488  	b.SetBytes(int64(len(data)))
   489  	for i := 0; i < b.N; i++ {
   490  		StdEncoding.DecodeString(data)
   491  	}
   492  }
   493  
   494  func TestWithCustomPadding(t *testing.T) {
   495  	for _, testcase := range pairs {
   496  		defaultPadding := StdEncoding.EncodeToString([]byte(testcase.decoded))
   497  		customPadding := StdEncoding.WithPadding('@').EncodeToString([]byte(testcase.decoded))
   498  		expected := strings.ReplaceAll(defaultPadding, "=", "@")
   499  
   500  		if expected != customPadding {
   501  			t.Errorf("Expected custom %s, got %s", expected, customPadding)
   502  		}
   503  		if testcase.encoded != defaultPadding {
   504  			t.Errorf("Expected %s, got %s", testcase.encoded, defaultPadding)
   505  		}
   506  	}
   507  }
   508  
   509  func TestWithoutPadding(t *testing.T) {
   510  	for _, testcase := range pairs {
   511  		defaultPadding := StdEncoding.EncodeToString([]byte(testcase.decoded))
   512  		customPadding := StdEncoding.WithPadding(NoPadding).EncodeToString([]byte(testcase.decoded))
   513  		expected := strings.TrimRight(defaultPadding, "=")
   514  
   515  		if expected != customPadding {
   516  			t.Errorf("Expected custom %s, got %s", expected, customPadding)
   517  		}
   518  		if testcase.encoded != defaultPadding {
   519  			t.Errorf("Expected %s, got %s", testcase.encoded, defaultPadding)
   520  		}
   521  	}
   522  }
   523  
   524  func TestDecodeWithPadding(t *testing.T) {
   525  	encodings := []*Encoding{
   526  		StdEncoding,
   527  		StdEncoding.WithPadding('-'),
   528  		StdEncoding.WithPadding(NoPadding),
   529  	}
   530  
   531  	for i, enc := range encodings {
   532  		for _, pair := range pairs {
   533  
   534  			input := pair.decoded
   535  			encoded := enc.EncodeToString([]byte(input))
   536  
   537  			decoded, err := enc.DecodeString(encoded)
   538  			if err != nil {
   539  				t.Errorf("DecodeString Error for encoding %d (%q): %v", i, input, err)
   540  			}
   541  
   542  			if input != string(decoded) {
   543  				t.Errorf("Unexpected result for encoding %d: got %q; want %q", i, decoded, input)
   544  			}
   545  		}
   546  	}
   547  }
   548  
   549  func TestDecodeWithWrongPadding(t *testing.T) {
   550  	encoded := StdEncoding.EncodeToString([]byte("foobar"))
   551  
   552  	_, err := StdEncoding.WithPadding('-').DecodeString(encoded)
   553  	if err == nil {
   554  		t.Error("expected error")
   555  	}
   556  
   557  	_, err = StdEncoding.WithPadding(NoPadding).DecodeString(encoded)
   558  	if err == nil {
   559  		t.Error("expected error")
   560  	}
   561  }
   562  
   563  func TestBufferedDecodingSameError(t *testing.T) {
   564  	testcases := []struct {
   565  		prefix            string
   566  		chunkCombinations [][]string
   567  		expected          error
   568  	}{
   569  		// NBSWY3DPO5XXE3DE == helloworld
   570  		// Test with "ZZ" as extra input
   571  		{"helloworld", [][]string{
   572  			{"NBSW", "Y3DP", "O5XX", "E3DE", "ZZ"},
   573  			{"NBSWY3DPO5XXE3DE", "ZZ"},
   574  			{"NBSWY3DPO5XXE3DEZZ"},
   575  			{"NBS", "WY3", "DPO", "5XX", "E3D", "EZZ"},
   576  			{"NBSWY3DPO5XXE3", "DEZZ"},
   577  		}, io.ErrUnexpectedEOF},
   578  
   579  		// Test with "ZZY" as extra input
   580  		{"helloworld", [][]string{
   581  			{"NBSW", "Y3DP", "O5XX", "E3DE", "ZZY"},
   582  			{"NBSWY3DPO5XXE3DE", "ZZY"},
   583  			{"NBSWY3DPO5XXE3DEZZY"},
   584  			{"NBS", "WY3", "DPO", "5XX", "E3D", "EZZY"},
   585  			{"NBSWY3DPO5XXE3", "DEZZY"},
   586  		}, io.ErrUnexpectedEOF},
   587  
   588  		// Normal case, this is valid input
   589  		{"helloworld", [][]string{
   590  			{"NBSW", "Y3DP", "O5XX", "E3DE"},
   591  			{"NBSWY3DPO5XXE3DE"},
   592  			{"NBS", "WY3", "DPO", "5XX", "E3D", "E"},
   593  			{"NBSWY3DPO5XXE3", "DE"},
   594  		}, nil},
   595  
   596  		// MZXW6YTB = fooba
   597  		{"fooba", [][]string{
   598  			{"MZXW6YTBZZ"},
   599  			{"MZXW6YTBZ", "Z"},
   600  			{"MZXW6YTB", "ZZ"},
   601  			{"MZXW6YT", "BZZ"},
   602  			{"MZXW6Y", "TBZZ"},
   603  			{"MZXW6Y", "TB", "ZZ"},
   604  			{"MZXW6", "YTBZZ"},
   605  			{"MZXW6", "YTB", "ZZ"},
   606  			{"MZXW6", "YT", "BZZ"},
   607  		}, io.ErrUnexpectedEOF},
   608  
   609  		// Normal case, this is valid input
   610  		{"fooba", [][]string{
   611  			{"MZXW6YTB"},
   612  			{"MZXW6YT", "B"},
   613  			{"MZXW6Y", "TB"},
   614  			{"MZXW6", "YTB"},
   615  			{"MZXW6", "YT", "B"},
   616  			{"MZXW", "6YTB"},
   617  			{"MZXW", "6Y", "TB"},
   618  		}, nil},
   619  	}
   620  
   621  	for _, testcase := range testcases {
   622  		for _, chunks := range testcase.chunkCombinations {
   623  			pr, pw := io.Pipe()
   624  
   625  			// Write the encoded chunks into the pipe
   626  			go func() {
   627  				for _, chunk := range chunks {
   628  					pw.Write([]byte(chunk))
   629  				}
   630  				pw.Close()
   631  			}()
   632  
   633  			decoder := NewDecoder(StdEncoding, pr)
   634  			_, err := io.ReadAll(decoder)
   635  
   636  			if err != testcase.expected {
   637  				t.Errorf("Expected %v, got %v; case %s %+v", testcase.expected, err, testcase.prefix, chunks)
   638  			}
   639  		}
   640  	}
   641  }
   642  
   643  func TestBufferedDecodingPadding(t *testing.T) {
   644  	testcases := []struct {
   645  		chunks        []string
   646  		expectedError string
   647  	}{
   648  		{[]string{
   649  			"I4======",
   650  			"==",
   651  		}, "unexpected EOF"},
   652  
   653  		{[]string{
   654  			"I4======N4======",
   655  		}, "illegal base32 data at input byte 2"},
   656  
   657  		{[]string{
   658  			"I4======",
   659  			"N4======",
   660  		}, "illegal base32 data at input byte 0"},
   661  
   662  		{[]string{
   663  			"I4======",
   664  			"========",
   665  		}, "illegal base32 data at input byte 0"},
   666  
   667  		{[]string{
   668  			"I4I4I4I4",
   669  			"I4======",
   670  			"I4======",
   671  		}, "illegal base32 data at input byte 0"},
   672  	}
   673  
   674  	for _, testcase := range testcases {
   675  		testcase := testcase
   676  		pr, pw := io.Pipe()
   677  		go func() {
   678  			for _, chunk := range testcase.chunks {
   679  				_, _ = pw.Write([]byte(chunk))
   680  			}
   681  			_ = pw.Close()
   682  		}()
   683  
   684  		decoder := NewDecoder(StdEncoding, pr)
   685  		_, err := io.ReadAll(decoder)
   686  
   687  		if err == nil && len(testcase.expectedError) != 0 {
   688  			t.Errorf("case %q: got nil error, want %v", testcase.chunks, testcase.expectedError)
   689  		} else if err.Error() != testcase.expectedError {
   690  			t.Errorf("case %q: got %v, want %v", testcase.chunks, err, testcase.expectedError)
   691  		}
   692  	}
   693  }
   694  
   695  func TestEncodedLen(t *testing.T) {
   696  	var rawStdEncoding = StdEncoding.WithPadding(NoPadding)
   697  	type test struct {
   698  		enc  *Encoding
   699  		n    int
   700  		want int64
   701  	}
   702  	tests := []test{
   703  		{StdEncoding, 0, 0},
   704  		{StdEncoding, 1, 8},
   705  		{StdEncoding, 2, 8},
   706  		{StdEncoding, 3, 8},
   707  		{StdEncoding, 4, 8},
   708  		{StdEncoding, 5, 8},
   709  		{StdEncoding, 6, 16},
   710  		{StdEncoding, 10, 16},
   711  		{StdEncoding, 11, 24},
   712  		{rawStdEncoding, 0, 0},
   713  		{rawStdEncoding, 1, 2},
   714  		{rawStdEncoding, 2, 4},
   715  		{rawStdEncoding, 3, 5},
   716  		{rawStdEncoding, 4, 7},
   717  		{rawStdEncoding, 5, 8},
   718  		{rawStdEncoding, 6, 10},
   719  		{rawStdEncoding, 7, 12},
   720  		{rawStdEncoding, 10, 16},
   721  		{rawStdEncoding, 11, 18},
   722  	}
   723  	// check overflow
   724  	switch strconv.IntSize {
   725  	case 32:
   726  		tests = append(tests, test{rawStdEncoding, (math.MaxInt-4)/8 + 1, 429496730})
   727  		tests = append(tests, test{rawStdEncoding, math.MaxInt/8*5 + 4, math.MaxInt})
   728  	case 64:
   729  		tests = append(tests, test{rawStdEncoding, (math.MaxInt-4)/8 + 1, 1844674407370955162})
   730  		tests = append(tests, test{rawStdEncoding, math.MaxInt/8*5 + 4, math.MaxInt})
   731  	}
   732  	for _, tt := range tests {
   733  		if got := tt.enc.EncodedLen(tt.n); int64(got) != tt.want {
   734  			t.Errorf("EncodedLen(%d): got %d, want %d", tt.n, got, tt.want)
   735  		}
   736  	}
   737  }
   738  
   739  func TestDecodedLen(t *testing.T) {
   740  	var rawStdEncoding = StdEncoding.WithPadding(NoPadding)
   741  	type test struct {
   742  		enc  *Encoding
   743  		n    int
   744  		want int64
   745  	}
   746  	tests := []test{
   747  		{StdEncoding, 0, 0},
   748  		{StdEncoding, 8, 5},
   749  		{StdEncoding, 16, 10},
   750  		{StdEncoding, 24, 15},
   751  		{rawStdEncoding, 0, 0},
   752  		{rawStdEncoding, 2, 1},
   753  		{rawStdEncoding, 4, 2},
   754  		{rawStdEncoding, 5, 3},
   755  		{rawStdEncoding, 7, 4},
   756  		{rawStdEncoding, 8, 5},
   757  		{rawStdEncoding, 10, 6},
   758  		{rawStdEncoding, 12, 7},
   759  		{rawStdEncoding, 16, 10},
   760  		{rawStdEncoding, 18, 11},
   761  	}
   762  	// check overflow
   763  	switch strconv.IntSize {
   764  	case 32:
   765  		tests = append(tests, test{rawStdEncoding, math.MaxInt/5 + 1, 268435456})
   766  		tests = append(tests, test{rawStdEncoding, math.MaxInt, 1342177279})
   767  	case 64:
   768  		tests = append(tests, test{rawStdEncoding, math.MaxInt/5 + 1, 1152921504606846976})
   769  		tests = append(tests, test{rawStdEncoding, math.MaxInt, 5764607523034234879})
   770  	}
   771  	for _, tt := range tests {
   772  		if got := tt.enc.DecodedLen(tt.n); int64(got) != tt.want {
   773  			t.Errorf("DecodedLen(%d): got %d, want %d", tt.n, got, tt.want)
   774  		}
   775  	}
   776  }
   777  
   778  func TestWithoutPaddingClose(t *testing.T) {
   779  	encodings := []*Encoding{
   780  		StdEncoding,
   781  		StdEncoding.WithPadding(NoPadding),
   782  	}
   783  
   784  	for _, encoding := range encodings {
   785  		for _, testpair := range pairs {
   786  
   787  			var buf strings.Builder
   788  			encoder := NewEncoder(encoding, &buf)
   789  			encoder.Write([]byte(testpair.decoded))
   790  			encoder.Close()
   791  
   792  			expected := testpair.encoded
   793  			if encoding.padChar == NoPadding {
   794  				expected = strings.ReplaceAll(expected, "=", "")
   795  			}
   796  
   797  			res := buf.String()
   798  
   799  			if res != expected {
   800  				t.Errorf("Expected %s got %s; padChar=%d", expected, res, encoding.padChar)
   801  			}
   802  		}
   803  	}
   804  }
   805  
   806  func TestDecodeReadAll(t *testing.T) {
   807  	encodings := []*Encoding{
   808  		StdEncoding,
   809  		StdEncoding.WithPadding(NoPadding),
   810  	}
   811  
   812  	for _, pair := range pairs {
   813  		for encIndex, encoding := range encodings {
   814  			encoded := pair.encoded
   815  			if encoding.padChar == NoPadding {
   816  				encoded = strings.ReplaceAll(encoded, "=", "")
   817  			}
   818  
   819  			decReader, err := io.ReadAll(NewDecoder(encoding, strings.NewReader(encoded)))
   820  			if err != nil {
   821  				t.Errorf("NewDecoder error: %v", err)
   822  			}
   823  
   824  			if pair.decoded != string(decReader) {
   825  				t.Errorf("Expected %s got %s; Encoding %d", pair.decoded, decReader, encIndex)
   826  			}
   827  		}
   828  	}
   829  }
   830  
   831  func TestDecodeSmallBuffer(t *testing.T) {
   832  	encodings := []*Encoding{
   833  		StdEncoding,
   834  		StdEncoding.WithPadding(NoPadding),
   835  	}
   836  
   837  	for bufferSize := 1; bufferSize < 200; bufferSize++ {
   838  		for _, pair := range pairs {
   839  			for encIndex, encoding := range encodings {
   840  				encoded := pair.encoded
   841  				if encoding.padChar == NoPadding {
   842  					encoded = strings.ReplaceAll(encoded, "=", "")
   843  				}
   844  
   845  				decoder := NewDecoder(encoding, strings.NewReader(encoded))
   846  
   847  				var allRead []byte
   848  
   849  				for {
   850  					buf := make([]byte, bufferSize)
   851  					n, err := decoder.Read(buf)
   852  					allRead = append(allRead, buf[0:n]...)
   853  					if err == io.EOF {
   854  						break
   855  					}
   856  					if err != nil {
   857  						t.Error(err)
   858  					}
   859  				}
   860  
   861  				if pair.decoded != string(allRead) {
   862  					t.Errorf("Expected %s got %s; Encoding %d; bufferSize %d", pair.decoded, allRead, encIndex, bufferSize)
   863  				}
   864  			}
   865  		}
   866  	}
   867  }
   868  

View as plain text