1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package com.google.common.io;
16
17 import static com.google.common.io.BaseEncoding.base16;
18 import static com.google.common.io.BaseEncoding.base32;
19 import static com.google.common.io.BaseEncoding.base32Hex;
20 import static com.google.common.io.BaseEncoding.base64;
21
22 import com.google.common.annotations.GwtCompatible;
23 import com.google.common.base.Ascii;
24 import com.google.common.base.Joiner;
25 import com.google.common.base.Splitter;
26 import com.google.common.collect.ImmutableList;
27 import com.google.common.io.BaseEncoding.DecodingException;
28
29 import junit.framework.TestCase;
30
31 import java.io.UnsupportedEncodingException;
32
33
34
35
36
37
38 @GwtCompatible(emulated = true)
39 public class BaseEncodingTest extends TestCase {
40 public static void assertEquals(byte[] expected, byte[] actual) {
41 assertEquals(expected.length, actual.length);
42 for (int i = 0; i < expected.length; i++) {
43 assertEquals(expected[i], actual[i]);
44 }
45 }
46
47 public void testSeparatorsExplicitly() {
48 testEncodes(base64().withSeparator("\n", 3), "foobar", "Zm9\nvYm\nFy");
49 testEncodes(base64().withSeparator("$", 4), "foobar", "Zm9v$YmFy");
50 testEncodes(base32().withSeparator("*", 4), "foobar", "MZXW*6YTB*OI==*====");
51 }
52
53 @SuppressWarnings("ReturnValueIgnored")
54 public void testSeparatorSameAsPadChar() {
55 try {
56 base64().withSeparator("=", 3);
57 fail("Expected IllegalArgumentException");
58 } catch (IllegalArgumentException expected) {}
59
60 try {
61 base64().withPadChar('#').withSeparator("!#!", 3);
62 fail("Expected IllegalArgumentException");
63 } catch (IllegalArgumentException expected) {}
64 }
65
66 @SuppressWarnings("ReturnValueIgnored")
67 public void testAtMostOneSeparator() {
68 BaseEncoding separated = base64().withSeparator("\n", 3);
69 try {
70 separated.withSeparator("$", 4);
71 fail("Expected UnsupportedOperationException");
72 } catch (UnsupportedOperationException expected) {}
73 }
74
75 public void testBase64() {
76
77 testEncodingWithSeparators(base64(), "", "");
78 testEncodingWithSeparators(base64(), "f", "Zg==");
79 testEncodingWithSeparators(base64(), "fo", "Zm8=");
80 testEncodingWithSeparators(base64(), "foo", "Zm9v");
81 testEncodingWithSeparators(base64(), "foob", "Zm9vYg==");
82 testEncodingWithSeparators(base64(), "fooba", "Zm9vYmE=");
83 testEncodingWithSeparators(base64(), "foobar", "Zm9vYmFy");
84 }
85
86 public void testBase64LenientPadding() {
87 testDecodes(base64(), "Zg", "f");
88 testDecodes(base64(), "Zg=", "f");
89 testDecodes(base64(), "Zg==", "f");
90 testDecodes(base64(), "Zg===", "f");
91 testDecodes(base64(), "Zg====", "f");
92 }
93
94 public void testBase64InvalidDecodings() {
95
96 assertFailsToDecode(base64(), "\u007f");
97 assertFailsToDecode(base64(), "Wf2!");
98
99 assertFailsToDecode(base64(), "let's not talk of love or chains!");
100
101 assertFailsToDecode(base64(), "12345");
102 }
103
104 @SuppressWarnings("ReturnValueIgnored")
105 public void testBase64CannotUpperCase() {
106 try {
107 base64().upperCase();
108 fail();
109 } catch (IllegalStateException expected) {
110
111 }
112 }
113
114 @SuppressWarnings("ReturnValueIgnored")
115 public void testBase64CannotLowerCase() {
116 try {
117 base64().lowerCase();
118 fail();
119 } catch (IllegalStateException expected) {
120
121 }
122 }
123
124 public void testBase64AlternatePadding() {
125 BaseEncoding enc = base64().withPadChar('~');
126 testEncodingWithSeparators(enc, "", "");
127 testEncodingWithSeparators(enc, "f", "Zg~~");
128 testEncodingWithSeparators(enc, "fo", "Zm8~");
129 testEncodingWithSeparators(enc, "foo", "Zm9v");
130 testEncodingWithSeparators(enc, "foob", "Zm9vYg~~");
131 testEncodingWithSeparators(enc, "fooba", "Zm9vYmE~");
132 testEncodingWithSeparators(enc, "foobar", "Zm9vYmFy");
133 }
134
135 public void testBase64OmitPadding() {
136 BaseEncoding enc = base64().omitPadding();
137 testEncodingWithSeparators(enc, "", "");
138 testEncodingWithSeparators(enc, "f", "Zg");
139 testEncodingWithSeparators(enc, "fo", "Zm8");
140 testEncodingWithSeparators(enc, "foo", "Zm9v");
141 testEncodingWithSeparators(enc, "foob", "Zm9vYg");
142 testEncodingWithSeparators(enc, "fooba", "Zm9vYmE");
143 testEncodingWithSeparators(enc, "foobar", "Zm9vYmFy");
144 }
145
146 public void testBase32() {
147
148 testEncodingWithCasing(base32(), "", "");
149 testEncodingWithCasing(base32(), "f", "MY======");
150 testEncodingWithCasing(base32(), "fo", "MZXQ====");
151 testEncodingWithCasing(base32(), "foo", "MZXW6===");
152 testEncodingWithCasing(base32(), "foob", "MZXW6YQ=");
153 testEncodingWithCasing(base32(), "fooba", "MZXW6YTB");
154 testEncodingWithCasing(base32(), "foobar", "MZXW6YTBOI======");
155 }
156
157 public void testBase32LenientPadding() {
158 testDecodes(base32(), "MZXW6", "foo");
159 testDecodes(base32(), "MZXW6=", "foo");
160 testDecodes(base32(), "MZXW6==", "foo");
161 testDecodes(base32(), "MZXW6===", "foo");
162 testDecodes(base32(), "MZXW6====", "foo");
163 testDecodes(base32(), "MZXW6=====", "foo");
164 }
165
166 public void testBase32AlternatePadding() {
167 BaseEncoding enc = base32().withPadChar('~');
168 testEncodingWithCasing(enc, "", "");
169 testEncodingWithCasing(enc, "f", "MY~~~~~~");
170 testEncodingWithCasing(enc, "fo", "MZXQ~~~~");
171 testEncodingWithCasing(enc, "foo", "MZXW6~~~");
172 testEncodingWithCasing(enc, "foob", "MZXW6YQ~");
173 testEncodingWithCasing(enc, "fooba", "MZXW6YTB");
174 testEncodingWithCasing(enc, "foobar", "MZXW6YTBOI~~~~~~");
175 }
176
177 public void testBase32InvalidDecodings() {
178
179 assertFailsToDecode(base32(), "\u007f");
180 assertFailsToDecode(base32(), "Wf2!");
181
182 assertFailsToDecode(base32(), "let's not talk of love or chains!");
183
184 assertFailsToDecode(base32(), "A");
185 assertFailsToDecode(base32(), "ABC");
186 assertFailsToDecode(base32(), "ABCDEF");
187 }
188
189 public void testBase32UpperCaseIsNoOp() {
190 assertSame(base32(), base32().upperCase());
191 }
192
193 public void testBase32Hex() {
194
195 testEncodingWithCasing(base32Hex(), "", "");
196 testEncodingWithCasing(base32Hex(), "f", "CO======");
197 testEncodingWithCasing(base32Hex(), "fo", "CPNG====");
198 testEncodingWithCasing(base32Hex(), "foo", "CPNMU===");
199 testEncodingWithCasing(base32Hex(), "foob", "CPNMUOG=");
200 testEncodingWithCasing(base32Hex(), "fooba", "CPNMUOJ1");
201 testEncodingWithCasing(base32Hex(), "foobar", "CPNMUOJ1E8======");
202 }
203
204 public void testBase32HexLenientPadding() {
205 testDecodes(base32Hex(), "CPNMU", "foo");
206 testDecodes(base32Hex(), "CPNMU=", "foo");
207 testDecodes(base32Hex(), "CPNMU==", "foo");
208 testDecodes(base32Hex(), "CPNMU===", "foo");
209 testDecodes(base32Hex(), "CPNMU====", "foo");
210 testDecodes(base32Hex(), "CPNMU=====", "foo");
211 }
212
213 public void testBase32HexInvalidDecodings() {
214
215 assertFailsToDecode(base32Hex(), "\u007f");
216 assertFailsToDecode(base32Hex(), "Wf2!");
217
218 assertFailsToDecode(base32Hex(), "let's not talk of love or chains!");
219
220 assertFailsToDecode(base32Hex(), "A");
221 assertFailsToDecode(base32Hex(), "ABC");
222 assertFailsToDecode(base32Hex(), "ABCDEF");
223 }
224
225 public void testBase32HexUpperCaseIsNoOp() {
226 assertSame(base32Hex(), base32Hex().upperCase());
227 }
228
229 public void testBase16() {
230 testEncodingWithCasing(base16(), "", "");
231 testEncodingWithCasing(base16(), "f", "66");
232 testEncodingWithCasing(base16(), "fo", "666F");
233 testEncodingWithCasing(base16(), "foo", "666F6F");
234 testEncodingWithCasing(base16(), "foob", "666F6F62");
235 testEncodingWithCasing(base16(), "fooba", "666F6F6261");
236 testEncodingWithCasing(base16(), "foobar", "666F6F626172");
237 }
238
239 public void testBase16UpperCaseIsNoOp() {
240 assertSame(base16(), base16().upperCase());
241 }
242
243 private static void testEncodingWithCasing(
244 BaseEncoding encoding, String decoded, String encoded) {
245 testEncodingWithSeparators(encoding, decoded, encoded);
246 testEncodingWithSeparators(encoding.upperCase(), decoded, Ascii.toUpperCase(encoded));
247 testEncodingWithSeparators(encoding.lowerCase(), decoded, Ascii.toLowerCase(encoded));
248 }
249
250 private static void testEncodingWithSeparators(
251 BaseEncoding encoding, String decoded, String encoded) {
252 testEncoding(encoding, decoded, encoded);
253
254
255 for (int sepLength = 3; sepLength <= 5; sepLength++) {
256 for (String separator : ImmutableList.of(",", "\n", ";;", "")) {
257 testEncoding(encoding.withSeparator(separator, sepLength), decoded,
258 Joiner.on(separator).join(Splitter.fixedLength(sepLength).split(encoded)));
259 }
260 }
261 }
262
263 private static void testEncoding(BaseEncoding encoding, String decoded, String encoded) {
264 testEncodes(encoding, decoded, encoded);
265 testDecodes(encoding, encoded, decoded);
266 }
267
268 private static void testEncodes(BaseEncoding encoding, String decoded, String encoded) {
269 byte[] bytes;
270 try {
271
272 bytes = decoded.getBytes("UTF-8");
273 } catch (UnsupportedEncodingException e) {
274 throw new AssertionError();
275 }
276 assertEquals(encoded, encoding.encode(bytes));
277 }
278
279 private static void testDecodes(BaseEncoding encoding, String encoded, String decoded) {
280 byte[] bytes;
281 try {
282
283 bytes = decoded.getBytes("UTF-8");
284 } catch (UnsupportedEncodingException e) {
285 throw new AssertionError();
286 }
287 assertEquals(bytes, encoding.decode(encoded));
288 }
289
290 private static void assertFailsToDecode(BaseEncoding encoding, String cannotDecode) {
291 try {
292 encoding.decode(cannotDecode);
293 fail("Expected IllegalArgumentException");
294 } catch (IllegalArgumentException expected) {
295
296 }
297 try {
298 encoding.decodeChecked(cannotDecode);
299 fail("Expected DecodingException");
300 } catch (DecodingException expected) {
301
302 }
303 }
304
305 public void testToString() {
306 assertEquals("BaseEncoding.base64().withPadChar(=)", BaseEncoding.base64().toString());
307 assertEquals("BaseEncoding.base32Hex().omitPadding()",
308 BaseEncoding.base32Hex().omitPadding().toString());
309 assertEquals("BaseEncoding.base32().lowerCase().withPadChar($)",
310 BaseEncoding.base32().lowerCase().withPadChar('$').toString());
311 assertEquals("BaseEncoding.base16().withSeparator(\"\n\", 10)",
312 BaseEncoding.base16().withSeparator("\n", 10).toString());
313 }
314 }
315