// Copyright (c) 2003 Dustin Sallings <dustin@spy.net>
package net.spy.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Base64 test. Derived from the python base64 tests.
*/
public class Base64Test extends TestCase {
private static final String CHARSET="UTF-8";
private Map<String, String> cases=null;
/**
* Get an instance of Base64Test.
*/
public Base64Test(String name) {
super(name);
}
/**
* Get the test suite.
*/
public static Test suite() {
return new TestSuite(Base64Test.class);
}
@Override
protected void setUp() {
cases=new HashMap<String, String>();
cases.put("d3d3LnB5dGhvbi5vcmc=", "www.python.org");
cases.put("YQ==", "a");
cases.put("YWI=", "ab");
cases.put("YWJj", "abc");
cases.put("", "");
cases.put("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQ"
+ "kNERUZHSElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0\r\n"
+ "NTY3ODkhQCMwXiYqKCk7Ojw+LC4gW117fQ==",
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789!@#0^&*();:<>,. []{}");
}
/**
* Test the singleton semantics.
*/
public void testSingleton() {
assertSame(Base64.getInstance(), Base64.getInstance());
}
private String encode(String s) throws Exception {
Base64 b64=Base64.getInstance();
String rv=b64.encode(s.getBytes(CHARSET));
return(rv);
}
/**
* Test base64 encoding of strings.
*/
@SuppressWarnings("unchecked")
public void testEncode() throws Exception {
for(Iterator i=cases.entrySet().iterator(); i.hasNext();) {
Map.Entry me=(Map.Entry)i.next();
assertEquals("Encode " + me.getValue(), me.getKey(),
encode((String)me.getValue()));
}
}
private String decode(String s) throws Exception {
Base64 b64=Base64.getInstance();
return(new String(b64.decode(s), CHARSET));
}
/**
* Test base64 decodes.
*/
@SuppressWarnings("unchecked")
public void testDecode() throws Exception {
for(Iterator i=cases.entrySet().iterator(); i.hasNext();) {
Map.Entry me=(Map.Entry)i.next();
assertEquals("Decode " + me.getKey(), me.getValue(),
decode((String)me.getKey()));
}
}
/**
* Test the isValidBase64Char implementation.
*/
@SuppressWarnings("unchecked")
public void testAlphabet() {
Base64 b64=Base64.getInstance();
char[] CHARMAP={
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
Map<Character, Boolean> allChars=new HashMap<Character, Boolean>();
for(int i=0; i<65535; i++) {
allChars.put( new Character((char)i), Boolean.FALSE);
}
for(int i=0; i<CHARMAP.length; i++) {
allChars.put(new Character(CHARMAP[i]), Boolean.TRUE);
}
for(Iterator i=allChars.entrySet().iterator(); i.hasNext();) {
Map.Entry me=(Map.Entry)i.next();
assertEquals(((Boolean)me.getValue()).booleanValue(),
b64.isValidBase64Char(((Character)me.getKey()).charValue()));
}
}
/**
* Test output stream implementation.
*/
@SuppressWarnings("unchecked")
public void testOutputStream() throws Exception {
ByteArrayOutputStream bos=new ByteArrayOutputStream();
for(Iterator i=cases.entrySet().iterator(); i.hasNext();) {
Map.Entry me=(Map.Entry)i.next();
bos.reset();
Base64OutputStream b64os=new Base64OutputStream(bos);
b64os.write(((String)me.getValue()).getBytes(CHARSET));
b64os.close();
String result=new String(bos.toByteArray(), CHARSET);
// The stream adds a newline to everything that doesn't end in a
// newline.
String expected=me.getKey() + "\r\n";
if(((String)me.getKey()).length() % 76 == 0) {
expected=(String)me.getKey();
}
assertEquals("Stream Encode ``" + expected + "'' got ``"
+ result + "''", expected, result);
}
bos.close();
}
/**
* Test input stream implementation.
*/
@SuppressWarnings("unchecked")
public void testInputStream() throws Exception {
byte[] buffer=new byte[1024];
for(Iterator i=cases.entrySet().iterator(); i.hasNext();) {
Map.Entry me=(Map.Entry)i.next();
byte[] input=((String)me.getKey()).getBytes(CHARSET);
ByteArrayInputStream bis=new ByteArrayInputStream(input);
Base64InputStream b64is=new Base64InputStream(bis);
assertFalse(b64is.markSupported());
int expectedAvailable=input.length * 3 / 4;
assertEquals("available() failed for ``" + me.getKey() + "''",
expectedAvailable, b64is.available());
int bytesread=b64is.read(buffer, 0, buffer.length);
b64is.close();
String result=new String(buffer, 0, bytesread);
String expected=(String)me.getValue();
assertEquals("Stream decode ``" + expected + "'' got ``"
+ result + "''", expected, result);
}
}
/**
* Test that streaming base64 yields the same result as whole chunk
* encoding.
*/
@SuppressWarnings("unchecked")
public void testBlockOutput() throws Exception {
HashMap<String, Comparable> hm=new HashMap<String, Comparable>();
hm.put("Some Key", new Integer(13));
hm.put("Some Other Key", "Another value");
ByteArrayOutputStream bos1=new ByteArrayOutputStream();
Base64OutputStream b64os=new Base64OutputStream(bos1);
ObjectOutputStream oos1=new ObjectOutputStream(b64os);
oos1.writeObject(hm);
oos1.close();
b64os.close();
bos1.close();
String encoded1=new String(bos1.toByteArray());
ByteArrayOutputStream bos2=new ByteArrayOutputStream();
ObjectOutputStream oos2=new ObjectOutputStream(bos2);
oos2.writeObject(hm);
oos2.close();
bos2.close();
String encoded2=Base64.getInstance().encode(bos2.toByteArray());
assertEquals(encoded2.trim(), encoded1.trim());
}
/**
* Test that streaming base64 in yields the same result as whole chunk
* decoding.
*/
@SuppressWarnings("unchecked")
public void testBlockInput() throws Exception {
HashMap<String, Comparable> hm=new HashMap<String, Comparable>();
hm.put("Some Key", new Integer(13));
hm.put("Some Other Key", "Another value");
// This will produce our seed data.
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(hm);
String src=Base64.getInstance().encode(bos.toByteArray());
byte[] b1=Base64.getInstance().decode(src);
ByteArrayInputStream bis=new ByteArrayInputStream(
src.getBytes(CHARSET));
Base64InputStream b64is=new Base64InputStream(bis);
byte[] b2=new byte[b1.length];
int bytesRead=b64is.read(b2);
assertEquals(b1.length, bytesRead);
for(int i=0; i<bytesRead; i++) {
assertEquals("Differs at " + i, b1[i], b2[i]);
}
}
/**
* Test object serialization and compression and all that into base64.
* This particular case failed in the field.
*/
@SuppressWarnings("unchecked")
public void testSerializingStream() throws Exception {
ByteArrayOutputStream bos=new ByteArrayOutputStream();
Base64OutputStream b64os=new Base64OutputStream(bos);
GZIPOutputStream gzos=new GZIPOutputStream(b64os);
ObjectOutputStream oos=new ObjectOutputStream(gzos);
HashMap<String, Comparable> hm=new HashMap<String, Comparable>();
hm.put("Some Key", new Integer(13));
hm.put("Some Other Key", "Another value");
oos.writeObject(hm);
oos.close();
gzos.close();
b64os.close();
bos.close();
String encoded=new String(bos.toByteArray());
// Now try to pull them back
ByteArrayInputStream bis=new ByteArrayInputStream(
encoded.getBytes(CHARSET));
Base64InputStream b64is=new Base64InputStream(bis);
GZIPInputStream gzis=new GZIPInputStream(b64is);
ObjectInputStream ois=new ObjectInputStream(gzis);
HashMap readMap=(HashMap)ois.readObject();
ois.close();
gzis.close();
b64is.close();
bis.close();
assertEquals(hm, readMap);
}
}