10888a09821a98ac0680fad765217302858e70fa4Paul Duffin/*
20888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Copyright (C) 2012 The Guava Authors
30888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
40888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
50888a09821a98ac0680fad765217302858e70fa4Paul Duffin * in compliance with the License. You may obtain a copy of the License at
60888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
70888a09821a98ac0680fad765217302858e70fa4Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
80888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
90888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Unless required by applicable law or agreed to in writing, software distributed under the License
100888a09821a98ac0680fad765217302858e70fa4Paul Duffin * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
110888a09821a98ac0680fad765217302858e70fa4Paul Duffin * or implied. See the License for the specific language governing permissions and limitations under
120888a09821a98ac0680fad765217302858e70fa4Paul Duffin * the License.
130888a09821a98ac0680fad765217302858e70fa4Paul Duffin */
140888a09821a98ac0680fad765217302858e70fa4Paul Duffin
150888a09821a98ac0680fad765217302858e70fa4Paul Duffinpackage com.google.common.io;
160888a09821a98ac0680fad765217302858e70fa4Paul Duffin
170888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.io.BaseEncoding.base16;
180888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.io.BaseEncoding.base32;
190888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.io.BaseEncoding.base32Hex;
200888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport static com.google.common.io.BaseEncoding.base64;
210888a09821a98ac0680fad765217302858e70fa4Paul Duffin
220888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.annotations.GwtCompatible;
230888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.base.Ascii;
240888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.base.Joiner;
250888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.base.Splitter;
260888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.collect.ImmutableList;
270888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.common.io.BaseEncoding.DecodingException;
280888a09821a98ac0680fad765217302858e70fa4Paul Duffin
290888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport junit.framework.TestCase;
300888a09821a98ac0680fad765217302858e70fa4Paul Duffin
310888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport java.io.UnsupportedEncodingException;
320888a09821a98ac0680fad765217302858e70fa4Paul Duffin
330888a09821a98ac0680fad765217302858e70fa4Paul Duffin/**
340888a09821a98ac0680fad765217302858e70fa4Paul Duffin * Tests for {@code BaseEncoding}.
350888a09821a98ac0680fad765217302858e70fa4Paul Duffin *
360888a09821a98ac0680fad765217302858e70fa4Paul Duffin * @author Louis Wasserman
370888a09821a98ac0680fad765217302858e70fa4Paul Duffin */
380888a09821a98ac0680fad765217302858e70fa4Paul Duffin@GwtCompatible(emulated = true)
390888a09821a98ac0680fad765217302858e70fa4Paul Duffinpublic class BaseEncodingTest extends TestCase {
400888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public static void assertEquals(byte[] expected, byte[] actual) {
410888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(expected.length, actual.length);
420888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int i = 0; i < expected.length; i++) {
430888a09821a98ac0680fad765217302858e70fa4Paul Duffin      assertEquals(expected[i], actual[i]);
440888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
450888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
460888a09821a98ac0680fad765217302858e70fa4Paul Duffin
470888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testSeparatorsExplicitly() {
480888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodes(base64().withSeparator("\n", 3), "foobar", "Zm9\nvYm\nFy");
490888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodes(base64().withSeparator("$", 4), "foobar", "Zm9v$YmFy");
500888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodes(base32().withSeparator("*", 4), "foobar", "MZXW*6YTB*OI==*====");
510888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
520888a09821a98ac0680fad765217302858e70fa4Paul Duffin
530888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings("ReturnValueIgnored")
540888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testSeparatorSameAsPadChar() {
550888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
560888a09821a98ac0680fad765217302858e70fa4Paul Duffin      base64().withSeparator("=", 3);
570888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("Expected IllegalArgumentException");
580888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (IllegalArgumentException expected) {}
590888a09821a98ac0680fad765217302858e70fa4Paul Duffin
600888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
610888a09821a98ac0680fad765217302858e70fa4Paul Duffin      base64().withPadChar('#').withSeparator("!#!", 3);
620888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("Expected IllegalArgumentException");
630888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (IllegalArgumentException expected) {}
640888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
650888a09821a98ac0680fad765217302858e70fa4Paul Duffin
660888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings("ReturnValueIgnored")
670888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testAtMostOneSeparator() {
680888a09821a98ac0680fad765217302858e70fa4Paul Duffin    BaseEncoding separated = base64().withSeparator("\n", 3);
690888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
700888a09821a98ac0680fad765217302858e70fa4Paul Duffin      separated.withSeparator("$", 4);
710888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("Expected UnsupportedOperationException");
720888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (UnsupportedOperationException expected) {}
730888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
740888a09821a98ac0680fad765217302858e70fa4Paul Duffin
750888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase64() {
760888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // The following test vectors are specified in RFC 4648 itself
770888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(base64(), "", "");
780888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(base64(), "f", "Zg==");
790888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(base64(), "fo", "Zm8=");
800888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(base64(), "foo", "Zm9v");
810888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(base64(), "foob", "Zm9vYg==");
820888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(base64(), "fooba", "Zm9vYmE=");
830888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(base64(), "foobar", "Zm9vYmFy");
840888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
850888a09821a98ac0680fad765217302858e70fa4Paul Duffin
860888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase64LenientPadding() {
870888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base64(), "Zg", "f");
880888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base64(), "Zg=", "f");
890888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base64(), "Zg==", "f"); // proper padding length
900888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base64(), "Zg===", "f");
910888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base64(), "Zg====", "f");
920888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
930888a09821a98ac0680fad765217302858e70fa4Paul Duffin
940888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase64InvalidDecodings() {
950888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // These contain bytes not in the decodabet.
960888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base64(), "\u007f");
970888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base64(), "Wf2!");
980888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // This sentence just isn't base64() encoded.
990888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base64(), "let's not talk of love or chains!");
1000888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // A 4n+1 length string is never legal base64().
1010888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base64(), "12345");
1020888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1030888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1040888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings("ReturnValueIgnored")
1050888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase64CannotUpperCase() {
1060888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
1070888a09821a98ac0680fad765217302858e70fa4Paul Duffin      base64().upperCase();
1080888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail();
1090888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (IllegalStateException expected) {
1100888a09821a98ac0680fad765217302858e70fa4Paul Duffin      // success
1110888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1120888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1130888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1140888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @SuppressWarnings("ReturnValueIgnored")
1150888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase64CannotLowerCase() {
1160888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
1170888a09821a98ac0680fad765217302858e70fa4Paul Duffin      base64().lowerCase();
1180888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail();
1190888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (IllegalStateException expected) {
1200888a09821a98ac0680fad765217302858e70fa4Paul Duffin      // success
1210888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
1220888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1230888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1240888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase64AlternatePadding() {
1250888a09821a98ac0680fad765217302858e70fa4Paul Duffin    BaseEncoding enc = base64().withPadChar('~');
1260888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "", "");
1270888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "f", "Zg~~");
1280888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "fo", "Zm8~");
1290888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "foo", "Zm9v");
1300888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "foob", "Zm9vYg~~");
1310888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "fooba", "Zm9vYmE~");
1320888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "foobar", "Zm9vYmFy");
1330888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1340888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1350888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase64OmitPadding() {
1360888a09821a98ac0680fad765217302858e70fa4Paul Duffin    BaseEncoding enc = base64().omitPadding();
1370888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "", "");
1380888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "f", "Zg");
1390888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "fo", "Zm8");
1400888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "foo", "Zm9v");
1410888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "foob", "Zm9vYg");
1420888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "fooba", "Zm9vYmE");
1430888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(enc, "foobar", "Zm9vYmFy");
1440888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1450888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1460888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase32() {
1470888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // The following test vectors are specified in RFC 4648 itself
1480888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32(), "", "");
1490888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32(), "f", "MY======");
1500888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32(), "fo", "MZXQ====");
1510888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32(), "foo", "MZXW6===");
1520888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32(), "foob", "MZXW6YQ=");
1530888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32(), "fooba", "MZXW6YTB");
1540888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32(), "foobar", "MZXW6YTBOI======");
1550888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1560888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1570888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase32LenientPadding() {
1580888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base32(), "MZXW6", "foo");
1590888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base32(), "MZXW6=", "foo");
1600888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base32(), "MZXW6==", "foo");
1610888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base32(), "MZXW6===", "foo"); // proper padding length
1620888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base32(), "MZXW6====", "foo");
1630888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base32(), "MZXW6=====", "foo");
1640888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1650888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1660888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase32AlternatePadding() {
1670888a09821a98ac0680fad765217302858e70fa4Paul Duffin    BaseEncoding enc = base32().withPadChar('~');
1680888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(enc, "", "");
1690888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(enc, "f", "MY~~~~~~");
1700888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(enc, "fo", "MZXQ~~~~");
1710888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(enc, "foo", "MZXW6~~~");
1720888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(enc, "foob", "MZXW6YQ~");
1730888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(enc, "fooba", "MZXW6YTB");
1740888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(enc, "foobar", "MZXW6YTBOI~~~~~~");
1750888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1760888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1770888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase32InvalidDecodings() {
1780888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // These contain bytes not in the decodabet.
1790888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base32(), "\u007f");
1800888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base32(), "Wf2!");
1810888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // This sentence just isn't base32() encoded.
1820888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base32(), "let's not talk of love or chains!");
1830888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // An 8n+{1,3,6} length string is never legal base32.
1840888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base32(), "A");
1850888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base32(), "ABC");
1860888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base32(), "ABCDEF");
1870888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1880888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1890888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase32UpperCaseIsNoOp() {
1900888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertSame(base32(), base32().upperCase());
1910888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
1920888a09821a98ac0680fad765217302858e70fa4Paul Duffin
1930888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase32Hex() {
1940888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // The following test vectors are specified in RFC 4648 itself
1950888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32Hex(), "", "");
1960888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32Hex(), "f", "CO======");
1970888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32Hex(), "fo", "CPNG====");
1980888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32Hex(), "foo", "CPNMU===");
1990888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32Hex(), "foob", "CPNMUOG=");
2000888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32Hex(), "fooba", "CPNMUOJ1");
2010888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base32Hex(), "foobar", "CPNMUOJ1E8======");
2020888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2030888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2040888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase32HexLenientPadding() {
2050888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base32Hex(), "CPNMU", "foo");
2060888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base32Hex(), "CPNMU=", "foo");
2070888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base32Hex(), "CPNMU==", "foo");
2080888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base32Hex(), "CPNMU===", "foo"); // proper padding length
2090888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base32Hex(), "CPNMU====", "foo");
2100888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(base32Hex(), "CPNMU=====", "foo");
2110888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2120888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2130888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase32HexInvalidDecodings() {
2140888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // These contain bytes not in the decodabet.
2150888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base32Hex(), "\u007f");
2160888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base32Hex(), "Wf2!");
2170888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // This sentence just isn't base32 encoded.
2180888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base32Hex(), "let's not talk of love or chains!");
2190888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // An 8n+{1,3,6} length string is never legal base32.
2200888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base32Hex(), "A");
2210888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base32Hex(), "ABC");
2220888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertFailsToDecode(base32Hex(), "ABCDEF");
2230888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2240888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2250888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase32HexUpperCaseIsNoOp() {
2260888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertSame(base32Hex(), base32Hex().upperCase());
2270888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2280888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2290888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase16() {
2300888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base16(), "", "");
2310888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base16(), "f", "66");
2320888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base16(), "fo", "666F");
2330888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base16(), "foo", "666F6F");
2340888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base16(), "foob", "666F6F62");
2350888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base16(), "fooba", "666F6F6261");
2360888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithCasing(base16(), "foobar", "666F6F626172");
2370888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2380888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2390888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testBase16UpperCaseIsNoOp() {
2400888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertSame(base16(), base16().upperCase());
2410888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2420888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2430888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void testEncodingWithCasing(
2440888a09821a98ac0680fad765217302858e70fa4Paul Duffin      BaseEncoding encoding, String decoded, String encoded) {
2450888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(encoding, decoded, encoded);
2460888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(encoding.upperCase(), decoded, Ascii.toUpperCase(encoded));
2470888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodingWithSeparators(encoding.lowerCase(), decoded, Ascii.toLowerCase(encoded));
2480888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2490888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2500888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void testEncodingWithSeparators(
2510888a09821a98ac0680fad765217302858e70fa4Paul Duffin      BaseEncoding encoding, String decoded, String encoded) {
2520888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncoding(encoding, decoded, encoded);
2530888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2540888a09821a98ac0680fad765217302858e70fa4Paul Duffin    // test separators work
2550888a09821a98ac0680fad765217302858e70fa4Paul Duffin    for (int sepLength = 3; sepLength <= 5; sepLength++) {
2560888a09821a98ac0680fad765217302858e70fa4Paul Duffin      for (String separator : ImmutableList.of(",", "\n", ";;", "")) {
2570888a09821a98ac0680fad765217302858e70fa4Paul Duffin        testEncoding(encoding.withSeparator(separator, sepLength), decoded,
2580888a09821a98ac0680fad765217302858e70fa4Paul Duffin            Joiner.on(separator).join(Splitter.fixedLength(sepLength).split(encoded)));
2590888a09821a98ac0680fad765217302858e70fa4Paul Duffin      }
2600888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2610888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2620888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2630888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void testEncoding(BaseEncoding encoding, String decoded, String encoded) {
2640888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testEncodes(encoding, decoded, encoded);
2650888a09821a98ac0680fad765217302858e70fa4Paul Duffin    testDecodes(encoding, encoded, decoded);
2660888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2670888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2680888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void testEncodes(BaseEncoding encoding, String decoded, String encoded) {
2690888a09821a98ac0680fad765217302858e70fa4Paul Duffin    byte[] bytes;
2700888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
2710888a09821a98ac0680fad765217302858e70fa4Paul Duffin      // GWT does not support String.getBytes(Charset)
2720888a09821a98ac0680fad765217302858e70fa4Paul Duffin      bytes = decoded.getBytes("UTF-8");
2730888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (UnsupportedEncodingException e) {
2740888a09821a98ac0680fad765217302858e70fa4Paul Duffin      throw new AssertionError();
2750888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2760888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(encoded, encoding.encode(bytes));
2770888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2780888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2790888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void testDecodes(BaseEncoding encoding, String encoded, String decoded) {
2800888a09821a98ac0680fad765217302858e70fa4Paul Duffin    byte[] bytes;
2810888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
2820888a09821a98ac0680fad765217302858e70fa4Paul Duffin      // GWT does not support String.getBytes(Charset)
2830888a09821a98ac0680fad765217302858e70fa4Paul Duffin      bytes = decoded.getBytes("UTF-8");
2840888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (UnsupportedEncodingException e) {
2850888a09821a98ac0680fad765217302858e70fa4Paul Duffin      throw new AssertionError();
2860888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2870888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals(bytes, encoding.decode(encoded));
2880888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
2890888a09821a98ac0680fad765217302858e70fa4Paul Duffin
2900888a09821a98ac0680fad765217302858e70fa4Paul Duffin  private static void assertFailsToDecode(BaseEncoding encoding, String cannotDecode) {
2910888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
2920888a09821a98ac0680fad765217302858e70fa4Paul Duffin      encoding.decode(cannotDecode);
2930888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("Expected IllegalArgumentException");
2940888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (IllegalArgumentException expected) {
2950888a09821a98ac0680fad765217302858e70fa4Paul Duffin      // success
2960888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
2970888a09821a98ac0680fad765217302858e70fa4Paul Duffin    try {
2980888a09821a98ac0680fad765217302858e70fa4Paul Duffin      encoding.decodeChecked(cannotDecode);
2990888a09821a98ac0680fad765217302858e70fa4Paul Duffin      fail("Expected DecodingException");
3000888a09821a98ac0680fad765217302858e70fa4Paul Duffin    } catch (DecodingException expected) {
3010888a09821a98ac0680fad765217302858e70fa4Paul Duffin      // success
3020888a09821a98ac0680fad765217302858e70fa4Paul Duffin    }
3030888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3040888a09821a98ac0680fad765217302858e70fa4Paul Duffin
3050888a09821a98ac0680fad765217302858e70fa4Paul Duffin  public void testToString() {
3060888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals("BaseEncoding.base64().withPadChar(=)", BaseEncoding.base64().toString());
3070888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals("BaseEncoding.base32Hex().omitPadding()",
3080888a09821a98ac0680fad765217302858e70fa4Paul Duffin        BaseEncoding.base32Hex().omitPadding().toString());
3090888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals("BaseEncoding.base32().lowerCase().withPadChar($)",
3100888a09821a98ac0680fad765217302858e70fa4Paul Duffin        BaseEncoding.base32().lowerCase().withPadChar('$').toString());
3110888a09821a98ac0680fad765217302858e70fa4Paul Duffin    assertEquals("BaseEncoding.base16().withSeparator(\"\n\", 10)",
3120888a09821a98ac0680fad765217302858e70fa4Paul Duffin        BaseEncoding.base16().withSeparator("\n", 10).toString());
3130888a09821a98ac0680fad765217302858e70fa4Paul Duffin  }
3140888a09821a98ac0680fad765217302858e70fa4Paul Duffin}
3150888a09821a98ac0680fad765217302858e70fa4Paul Duffin
316