blob: 6b9b34badbfff476f2a52195c1bf07eb20930bbf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Stepan M. Mishura
*/
package org.apache.harmony.security.tests.asn1.der;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
import junit.framework.TestCase;
import org.apache.harmony.security.asn1.ASN1Constants;
import org.apache.harmony.security.asn1.ASN1Exception;
import org.apache.harmony.security.asn1.BerInputStream;
/**
* Tests BerInputStream implementation
*
* @see http://asn1.elibel.tm.fr/en/standards/index.htm
*/
public class BerInputStreamTest extends TestCase {
/**
* @tests org.apache.harmony.security.asn1.BerInputStream#BerInputStream(
*java.io.ByteArrayInputStream)
*/
public void test_CtorLjava_io_ByteArrayInputStream() throws IOException {
//
// tests for decoding initial length of encodings
//
Object[][] testcase = {
// length = 0x01
{ new byte[] { 0x30, (byte) 0x81, 0x01 }, BigInteger.valueOf(1) },
// length = 0xFF
{ new byte[] { 0x30, (byte) 0x81, (byte) 0xFF },
BigInteger.valueOf(0xFF) },
// length = 0x0101
{ new byte[] { 0x30, (byte) 0x82, 0x01, 0x01 },
BigInteger.valueOf(0x0101) },
// length = 0xFFFF
{ new byte[] { 0x30, (byte) 0x82, (byte) 0xFF, (byte) 0xFF },
BigInteger.valueOf(0xFFFF) },
// length = 0x0FFFFF
{
new byte[] { 0x30, (byte) 0x83, 0x0F, (byte) 0xFF,
(byte) 0xFF }, BigInteger.valueOf(0x0FFFFF) },
// length = 0xFFFFFF
{
new byte[] { 0x30, (byte) 0x83, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF },
BigInteger.valueOf(0xFFFFFF) },
// length = 0xFFFFFF (encoded length has extra byte)
{
new byte[] { 0x30, (byte) 0x84, 0x00, (byte) 0xFF,
(byte) 0xFF, (byte) 0xFF },
BigInteger.valueOf(0xFFFFFF) }, };
// positive testcases
for (int i = 0; i < testcase.length; i++) {
try {
BerInputStream in = new BerInputStream(
new ByteArrayInputStream((byte[]) testcase[i][0]));
int expected = ((BigInteger) testcase[i][1]).intValue();
assertEquals(expected, in.getLength());
} catch (IOException e) {
e.printStackTrace();
fail("Testcase: " + i + "\nUnexpected exception." + e);
}
}
// negative testcase
try {
new BerInputStream(new ByteArrayInputStream(new byte[] { 0x30,
(byte) 0x84, 0x01, 0x01, 0x01, 0x01 }));
fail("No expected ASN1Exception");
} catch (ASN1Exception e) {
assertTrue(e.getMessage().startsWith("Too long"));
}
//
// Test for correct internal array reallocation
// Regression for HARMONY-5054
//
// must be greater then buffer initial size (16K)
int arrayLength = 17000;
// 1 byte for tag and 3 for length
byte[] encoding = new byte[arrayLength + 4];
// fill tag and length bytes
encoding[0] = ASN1Constants.TAG_OCTETSTRING;
encoding[1] = (byte) 0x82; // length is encoded in two bytes
encoding[2] = (byte) (arrayLength >> 8);
encoding[3] = (byte) (arrayLength & 0xFF);
BerInputStream in = new BerInputStream(new ByteArrayInputStream(
encoding));
assertEquals(encoding.length, in.getBuffer().length);
}
/**
* @tests org.apache.harmony.security.asn1.BerInputStream#BerInputStream(byte[],
*int, int)
*/
public void test_Ctor$LbyteLintLint() throws IOException {
//
// tests for 'expectedLength' parameter
//
byte[] encoded = new byte[] { 0x01, 0x01, 0x03, // boolean bytes
0x06, 0x02, 0x01, 0x03, // oid bytes
0x01, 0x00 // just random bytes
};
// pass boolean encoding
BerInputStream in = new BerInputStream(encoded, 0, 3);
assertEquals("boolean", 1, in.getLength());
// pass oid encoding
in = new BerInputStream(encoded, 3, 4);
assertEquals("boolean", 2, in.getLength());
// pass random encoding (equals to ANY)
in = new BerInputStream(encoded, 7, 2);
assertEquals("any", 0, in.getLength());
// extra bytes for oid
try {
new BerInputStream(encoded, 3, 5);
fail("No expected ASN1Exception");
} catch (ASN1Exception e) {
assertEquals("Wrong content length", e.getMessage());
}
// less bytes for oid
try {
new BerInputStream(encoded, 3, 3);
fail("No expected ASN1Exception");
} catch (ASN1Exception e) {
assertEquals("Wrong content length", e.getMessage());
}
}
/**
* @tests org.apache.harmony.security.asn1.BerInputStream#readContent()
*/
public void test_readContent() throws IOException {
byte[] encoding = { ASN1Constants.TAG_OCTETSTRING, 0x0F, 0x01, 0x02,
0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
0x0D, 0x0E, 0x0F };
// a custom input stream that doesn't return all data at once
ByteArrayInputStream in = new ByteArrayInputStream(encoding) {
public int read(byte[] b, int off, int len) {
if (len < 2) {
return super.read(b, off, len);
} else {
return super.read(b, off, 4);
}
}
};
BerInputStream berIn = new BerInputStream(in);
berIn.readContent();
assertTrue(Arrays.equals(encoding, berIn.getEncoded()));
//
// negative test case: the stream returns only 4 bytes of content
//
in = new ByteArrayInputStream(encoding) {
int i = 0;
public int read(byte[] b, int off, int len) {
if (i == 0) {
i++;
return super.read(b, off, 4);
} else {
return 0;
}
}
};
berIn = new BerInputStream(in);
try {
berIn.readContent();
fail("No expected ASN1Exception");
} catch (ASN1Exception e) {
}
}
}