001: package org.bouncycastle.util.encoders.test;
002:
003: import java.io.ByteArrayOutputStream;
004: import java.io.IOException;
005: import java.util.Arrays;
006: import java.util.Random;
007:
008: import junit.framework.TestCase;
009:
010: import org.bouncycastle.util.encoders.Encoder;
011:
012: public abstract class AbstractCoderTest extends TestCase {
013:
014: private static final int[] SIZES_TO_CHECK = { 64, 128, 1024, 1025,
015: 1026, 2048, 2049, 2050, 4096, 4097, 4098, 8192, 8193, 8194 };
016:
017: protected Encoder enc;
018: private Random r;
019:
020: AbstractCoderTest(String name) {
021: super (name);
022: }
023:
024: protected void setUp() {
025: r = new Random();
026: }
027:
028: private void checkArrayOfSize(int size) throws IOException {
029: byte[] original = new byte[size];
030: r.nextBytes(original);
031:
032: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
033: enc.encode(original, 0, original.length, bOut);
034:
035: byte[] encoded = bOut.toByteArray();
036:
037: assertTrue(encoded.length > original.length);
038: assertTrue(encoded.length <= (original.length * 2));
039: checkEncoding(encoded);
040: checkSimpleDecode(original, encoded);
041: checkStringDecode(original, encoded);
042: checkOutputStreamDecode(original, encoded);
043:
044: int offset = r.nextInt(20);
045: byte[] offsetEncoded = new byte[offset + encoded.length];
046: System.arraycopy(encoded, 0, offsetEncoded, offset,
047: encoded.length);
048: checkOffsetDecode(original, offsetEncoded, offset,
049: encoded.length);
050:
051: offset = r.nextInt(20);
052: byte[] offsetOriginal = new byte[offset + original.length];
053: System.arraycopy(original, 0, offsetOriginal, offset,
054: original.length);
055: checkOffsetEncode(original, offsetOriginal, offset,
056: original.length);
057:
058: byte[] encodedWithSpace = addWhitespace(encoded);
059: checkSimpleDecode(original, encodedWithSpace);
060: checkStringDecode(original, encodedWithSpace);
061: checkOutputStreamDecode(original, encodedWithSpace);
062: }
063:
064: public void testEncode() throws IOException {
065: for (int i = 0; i < SIZES_TO_CHECK.length; i++) {
066: checkArrayOfSize(SIZES_TO_CHECK[i]);
067: }
068: }
069:
070: private void checkEncoding(byte[] encoded) {
071: String encString = convertBytesToString(encoded);
072: for (int i = 0; i < encString.length(); i++) {
073: char c = encString.charAt(i);
074: if (c == paddingChar()) {
075: // should only be padding at end of string
076: assertTrue(i > encString.length() - 3);
077: continue;
078: } else if (isEncodedChar(c)) {
079: continue;
080: }
081: fail("Unexpected encoded character " + c);
082: }
083: }
084:
085: private void checkOutputStreamDecode(byte[] original, byte[] encoded) {
086: String encString = convertBytesToString(encoded);
087: ByteArrayOutputStream out = new ByteArrayOutputStream();
088: try {
089: assertEquals(original.length, enc.decode(encString, out));
090: assertTrue(Arrays.equals(original, out.toByteArray()));
091: } catch (IOException e) {
092: fail("This shouldn't happen");
093: }
094: }
095:
096: private void checkSimpleDecode(byte[] original, byte[] encoded)
097: throws IOException {
098: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
099: enc.decode(encoded, 0, encoded.length, bOut);
100:
101: assertTrue(Arrays.equals(original, bOut.toByteArray()));
102: }
103:
104: private void checkOffsetEncode(byte[] original,
105: byte[] offsetOriginal, int off, int length)
106: throws IOException {
107: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
108:
109: enc.encode(offsetOriginal, off, length, bOut);
110:
111: byte[] encoded = bOut.toByteArray();
112:
113: bOut.reset();
114:
115: enc.decode(encoded, 0, encoded.length, bOut);
116:
117: assertTrue(Arrays.equals(original, bOut.toByteArray()));
118: }
119:
120: private void checkOffsetDecode(byte[] original, byte[] encoded,
121: int off, int length) throws IOException {
122: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
123: enc.decode(encoded, off, length, bOut);
124:
125: assertTrue(Arrays.equals(original, bOut.toByteArray()));
126: }
127:
128: private void checkStringDecode(byte[] original, byte[] encoded)
129: throws IOException {
130: String encString = convertBytesToString(encoded);
131: ByteArrayOutputStream bOut = new ByteArrayOutputStream();
132: enc.decode(encString, bOut);
133: assertTrue(Arrays.equals(original, bOut.toByteArray()));
134: }
135:
136: private byte[] addWhitespace(byte[] encoded) {
137: ByteArrayOutputStream out = new ByteArrayOutputStream();
138: addSpace(out);
139: for (int i = 0; i < encoded.length - 5; i++) {
140: out.write(encoded, i, 1);
141: if (r.nextInt(100) < 5) {
142: addSpace(out);
143: }
144: }
145: for (int i = encoded.length - 5; i < encoded.length; i++) {
146: out.write(encoded, i, 1);
147: }
148: addSpace(out);
149: return out.toByteArray();
150: }
151:
152: private void addSpace(ByteArrayOutputStream out) {
153: do {
154: switch (r.nextInt(3)) {
155: case 0:
156: out.write((int) '\n');
157: break;
158: case 1:
159: out.write((int) '\r');
160: break;
161: case 2:
162: out.write((int) '\t');
163: break;
164: case 3:
165: out.write((int) ' ');
166: break;
167: }
168: } while (r.nextBoolean());
169: }
170:
171: private String convertBytesToString(byte[] encoded) {
172: StringBuffer b = new StringBuffer();
173:
174: for (int i = 0; i != encoded.length; i++) {
175: b.append((char) (encoded[i] & 0xff));
176: }
177:
178: return b.toString();
179: }
180:
181: abstract protected char paddingChar();
182:
183: abstract protected boolean isEncodedChar(char c);
184:
185: }
|