mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

neil_a_wilson
11.30.2006 ad8f9f880dcf39969fe4752c883b6396a41ebd17
Rewrite the unit tests for the ASN1Element class to work better within the
testng framework and to provide more complete coverage.
1 files modified
1784 ■■■■■ changed files
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Element.java 1784 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Element.java
@@ -26,745 +26,1361 @@
 */
package org.opends.server.protocols.asn1;
import static org.opends.server.util.StaticUtils.listsAreEqual;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeClass;
import org.opends.server.types.ByteString;
import static org.testng.Assert.*;
import static org.opends.server.messages.ProtocolMessages.*;
/**
 * This class defines a set of tests for the
 * org.opends.server.protocols.asn1.ASN1Element class.
 */
public class TestASN1Element extends ASN1TestCase {
  // The sets of pre-encoded ASN.1 elements that will be included in the
  // test
  // case.
  private ArrayList<ArrayList<ASN1Element>> testElementSets;
  // The set of pre-encoded element sets that will be used in the test
  // cases.
  private ArrayList<byte[]> testEncodedElementSets;
  // The set of pre-encoded integer values that will be included in the
  // test
  // cases.
  private ArrayList<byte[]> testEncodedIntegers;
  // The set of pre-encoded lengths that will be included in the test
  // cases.
  private ArrayList<byte[]> testEncodedLengths;
  // The set of BER types that will be included in the test cases.
  private ArrayList<Byte> testTypes;
  // The set of element values that will be included in the test cases.
  private ArrayList<byte[]> testValues;
  // The set of integer values that will be included in the test cases.
  private ArrayList<Integer> testIntegers;
  // The set of lengths that will be included in the test cases.
  private ArrayList<Integer> testLengths;
public class TestASN1Element
       extends ASN1TestCase
{
  /**
   * Performs any necessary initialization for this test case.
   * Create the values that can be used for testing BER types.
   *
   * @return  The values that can be used for testing BER types.
   */
  @BeforeClass
  public void setUp() {
    // Initialize the set of types. It will encapsulate the entire range
    // of
    // possible byte values.
    testTypes = new ArrayList<Byte>();
    for (int i = 0; i < 0xFF; i++) {
      testTypes.add((byte) (i & 0xFF));
  @DataProvider(name = "testTypes")
  public Object[][] getTestTypes()
  {
    // Create an array with all of the valid single-byte types.  We don't
    // support multi-byte types, so this should be a comprehensive data set.
    Object[][] testTypes = new Object[0xFF][1];
    for (int i=0x00; i < 0xFF; i++)
    {
      testTypes[i] = new Object[] { (byte) (i & 0xFF) };
    }
    // Initialize the set of values. Don't make these too big since they
    // consume memory.
    testValues = new ArrayList<byte[]>();
    testValues.add(null); // The null value.
    testValues.add(new byte[0x00]); // The zero-byte value.
    testValues.add(new byte[0x01]); // The single-byte value.
    testValues.add(new byte[0x7F]); // The largest 1-byte length
    // encoding.
    testValues.add(new byte[0x80]);
    testValues.add(new byte[0xFF]); // The largest 2-byte length
    // encoding.
    testValues.add(new byte[0x0100]);
    testValues.add(new byte[0xFFFF]); // The largest 3-byte length
    // encoding.
    testValues.add(new byte[0x010000]);
    // Initialize the set of element lengths and their pre-encoded
    // representations. Don't make these too big since we will create
    // arrays
    // with these lengths during testing.
    testLengths = new ArrayList<Integer>();
    testEncodedLengths = new ArrayList<byte[]>();
    testLengths.add(0x00); // The zero-byte length.
    testEncodedLengths.add(new byte[] { (byte) 0x00 });
    testLengths.add(0x01); // A common 1-byte length.
    testEncodedLengths.add(new byte[] { (byte) 0x01 });
    testLengths.add(0x7F); // The largest 1-byte length encoding.
    testEncodedLengths.add(new byte[] { (byte) 0x7F });
    testLengths.add(0x80); // The smallest length that must use 2
    // bytes.
    testEncodedLengths.add(new byte[] { (byte) 0x81, (byte) 0x80 });
    testLengths.add(0xFF); // The largest length that may use 2 bytes.
    testEncodedLengths.add(new byte[] { (byte) 0x81, (byte) 0xFF });
    testLengths.add(0x0100); // The smallest length that must use 3
    // bytes.
    testEncodedLengths.add(new byte[] { (byte) 0x82, (byte) 0x01,
        (byte) 0x00 });
    testLengths.add(0xFFFF); // The largest length that may use 3
    // bytes.
    testEncodedLengths.add(new byte[] { (byte) 0x82, (byte) 0xFF,
        (byte) 0xFF });
    testLengths.add(0x010000); // The smallest length that must use 4
    // bytes.
    testEncodedLengths.add(new byte[] { (byte) 0x83, (byte) 0x01,
        (byte) 0x00, (byte) 0x00 });
    // Initialize the set of integer values and their pre-encoded
    // representations. These can get big since they will not be used to
    // create
    // arrays. Also, there is no need to test negative values since LDAP
    // doesn't make use of them.
    testIntegers = new ArrayList<Integer>();
    testEncodedIntegers = new ArrayList<byte[]>();
    testIntegers.add(0x00); // A common 1-byte encoding.
    testEncodedIntegers.add(new byte[] { (byte) 0x00 });
    testIntegers.add(0x7F); // The largest 1-byte encoding.
    testEncodedIntegers.add(new byte[] { (byte) 0x7F });
    testIntegers.add(0x80); // The smallest 2-byte encoding.
    testEncodedIntegers.add(new byte[] { (byte) 0x00, (byte) 0x80 });
    testIntegers.add(0xFF); // A boundary case for 2-byte encoding.
    testEncodedIntegers.add(new byte[] { (byte) 0x00, (byte) 0xFF });
    testIntegers.add(0x0100); // A boundary case for 2-byte encoding.
    testEncodedIntegers.add(new byte[] { (byte) 0x01, (byte) 0x00 });
    testIntegers.add(0x7FFF); // The largest 2-byte encoding.
    testEncodedIntegers.add(new byte[] { (byte) 0x7F, (byte) 0xFF });
    testIntegers.add(0x8000); // The smallest 3-byte encoding.
    testEncodedIntegers.add(new byte[] { (byte) 0x00, (byte) 0x80,
        (byte) 0x00 });
    testIntegers.add(0xFFFF); // A boundary case for 3-byte encoding.
    testEncodedIntegers.add(new byte[] { (byte) 0x00, (byte) 0xFF,
        (byte) 0xFF });
    testIntegers.add(0x010000); // A boundary case for 3-byte encoding.
    testEncodedIntegers.add(new byte[] { (byte) 0x01, (byte) 0x00,
        (byte) 0x00 });
    testIntegers.add(0x7FFFFF); // The largest 3-byte encoding.
    testEncodedIntegers.add(new byte[] { (byte) 0x7F, (byte) 0xFF,
        (byte) 0xFF });
    testIntegers.add(0x800000); // The smallest 4-byte encoding.
    testEncodedIntegers.add(new byte[] { (byte) 0x00, (byte) 0x80,
        (byte) 0x00, (byte) 0x00 });
    testIntegers.add(0xFFFFFF); // A boundary case for 4-byte encoding.
    testEncodedIntegers.add(new byte[] { (byte) 0x00, (byte) 0xFF,
        (byte) 0xFF, (byte) 0xFF });
    testIntegers.add(0x01000000); // A boundary case for 4-byte
    // encoding.
    testEncodedIntegers.add(new byte[] { (byte) 0x01, (byte) 0x00,
        (byte) 0x00, (byte) 0x00 });
    testIntegers.add(0x7FFFFFFF); // The largest value we will allow.
    testEncodedIntegers.add(new byte[] { (byte) 0x7F, (byte) 0xFF,
        (byte) 0xFF, (byte) 0xFF });
    // Initialize the sets of ASN.1 elements that will be used in
    // testing the
    // group encode/decode operations.
    testElementSets = new ArrayList<ArrayList<ASN1Element>>();
    testEncodedElementSets = new ArrayList<byte[]>();
    testElementSets.add(null); // The null set.
    testEncodedElementSets.add(new byte[0]);
    testElementSets.add(new ArrayList<ASN1Element>(0)); // The empty
    // set.
    testEncodedElementSets.add(new byte[0]);
    // Sets containing from 1 to 10 elements.
    for (int i = 1; i <= 10; i++) {
      ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(i);
      for (int j = 0; j < i; j++) {
        elements.add(new ASN1Element((byte) 0x00));
      }
      testElementSets.add(elements);
      testEncodedElementSets.add(new byte[i * 2]);
    }
    return testTypes;
  }
  /**
   * Tests the <CODE>getType</CODE> method.
   */
  @Test()
  public void testGetType() {
    for (byte type : testTypes) {
      ASN1Element element = new ASN1Element(type);
      assertEquals(type, element.getType());
      for (byte[] value : testValues) {
        element = new ASN1Element(type, value);
        assertEquals(type, element.getType());
      }
    }
  }
  /**
   * Tests the <CODE>setType</CODE> method.
   * Tests the <CODE>getType</CODE> and <CODE>setType</CODE> methods.
   *
   * @param  type  The BER type to use in the test.
   */
  @Test()
  public void testSetType() {
    ASN1Element element = new ASN1Element((byte) 0x00);
    for (byte type : testTypes) {
      element.setType(type);
      assertEquals(type, element.getType());
    }
  @Test(dataProvider = "testTypes")
  public void testGetAndSetType(byte type)
  {
    ASN1Element e = new ASN1Element((byte) 0x00);
    e.setType(type);
    assertEquals(type, e.getType());
  }
  /**
   * Tests the <CODE>isUniversal</CODE> method.
   *
   * @param  type  The BER type to use in the test.
   */
  @Test()
  public void testIsUniversal() {
    ASN1Element element = new ASN1Element((byte) 0x00);
    for (byte type : testTypes) {
      element.setType(type);
      boolean isUniversal = (((byte) (type & 0xC0)) == ((byte) 0x00));
      assertEquals(isUniversal, element.isUniversal());
    }
  @Test(dataProvider = "testTypes")
  public void testIsUniversal(byte type)
  {
    boolean isUniversal = (((type & 0xFF) >> 6) == 0x00);
    assertEquals(isUniversal, new ASN1Element(type).isUniversal());
  }
  /**
   * Tests the <CODE>isApplicationSpecific</CODE> method.
   *
   * @param  type  The BER type to use in the test.
   */
  @Test()
  public void testIsApplicationSpecific() {
    ASN1Element element = new ASN1Element((byte) 0x00);
    for (byte type : testTypes) {
      element.setType(type);
      boolean isApplicationSpecific = (((byte) (type & 0xC0)) == ((byte) 0x40));
      assertEquals(isApplicationSpecific, element.isApplicationSpecific());
    }
  @Test(dataProvider = "testTypes")
  public void testIsApplicationSpecific(byte type)
  {
    boolean isApplicationSpecific = (((type & 0xFF) >> 6) == 0x01);
    assertEquals(isApplicationSpecific,
                 new ASN1Element(type).isApplicationSpecific());
  }
  /**
   * Tests the <CODE>isContextSpecific</CODE> method.
   *
   * @param  type  The BER type to use in the test.
   */
  @Test()
  public void testIsContextSpecific() {
    ASN1Element element = new ASN1Element((byte) 0x00);
    for (byte type : testTypes) {
      element.setType(type);
      boolean isContextSpecific = (((byte) (type & 0xC0)) == ((byte) 0x80));
      assertEquals(isContextSpecific, element.isContextSpecific());
    }
  @Test(dataProvider = "testTypes")
  public void testIsContextSpecific(byte type)
  {
    boolean isContextSpecific = (((type & 0xFF) >> 6) == 0x02);
    assertEquals(isContextSpecific, new ASN1Element(type).isContextSpecific());
  }
  /**
   * Tests the <CODE>isPrivate</CODE> method.
   *
   * @param  type  The BER type to use in the test.
   */
  @Test()
  public void testIsPrivate() {
    ASN1Element element = new ASN1Element((byte) 0x00);
    for (byte type : testTypes) {
      element.setType(type);
      boolean isPrivate = (((byte) (type & 0xC0)) == ((byte) 0xC0));
      assertEquals(isPrivate, element.isPrivate());
    }
  @Test(dataProvider = "testTypes")
  public void testIsPrivate(byte type)
  {
    boolean isPrivate = (((type & 0xFF) >> 6) == 0x03);
    assertEquals(isPrivate, new ASN1Element(type).isPrivate());
  }
  /**
   * Tests the <CODE>isPrimitive</CODE> method.
   *
   * @param  type  The BER type to use in the test.
   */
  @Test()
  public void testIsPrimitive() {
    ASN1Element element = new ASN1Element((byte) 0x00);
    for (byte type : testTypes) {
      element.setType(type);
      boolean isPrimitive = (((byte) (type & 0x20)) == ((byte) 0x00));
      assertEquals(isPrimitive, element.isPrimitive());
    }
  @Test(dataProvider = "testTypes")
  public void testIsPrimitive(byte type)
  {
    boolean isPrimitive = ((type & 0xDF) == (type & 0xFF));
    assertEquals(isPrimitive, new ASN1Element(type).isPrimitive());
  }
  /**
   * Tests the <CODE>isConstructed</CODE> method.
   */
  @Test()
  public void testIsConstructed() {
    ASN1Element element = new ASN1Element((byte) 0x00);
    for (byte type : testTypes) {
      element.setType(type);
      boolean isConstructed = (((byte) (type & 0x20)) == ((byte) 0x20));
      assertEquals(isConstructed, element.isConstructed());
    }
  }
  /**
   * Tests the <CODE>getValue</CODE> method.
   */
  @Test()
  public void testGetValue() {
    for (byte type : testTypes) {
      ASN1Element element = new ASN1Element(type);
      assertTrue(Arrays.equals(new byte[0], element.value()));
      for (byte[] value : testValues) {
        element = new ASN1Element(type, value);
        if (value == null) {
          assertTrue(Arrays.equals(new byte[0], element.value()));
        } else {
          assertTrue(Arrays.equals(value, element.value()));
        }
      }
    }
  }
  /**
   * Tests the <CODE>setValue</CODE> method.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @param  type  The BER type to use in the test.
   */
  @Test()
  public void testSetValue() throws Exception {
    ASN1Element element = new ASN1Element((byte) 0x00);
  @Test(dataProvider = "testTypes")
  public void testIsConstructed(byte type)
  {
    boolean isConstructed = ((type & 0xDF) != (type & 0xFF));
    assertEquals(isConstructed, new ASN1Element(type).isConstructed());
  }
    for (byte[] value : testValues) {
      element.setValue(value);
      if (value == null) {
        assertTrue(Arrays.equals(new byte[0], element.value()));
      } else {
        assertTrue(Arrays.equals(value, element.value()));
      }
  /**
   * Create byte arrays to use for element values.
   *
   * @return  A list of byte arrays that can be used as element values.
   */
  @DataProvider(name = "testValues")
  public Object[][] getTestValues()
  {
    // NOTE -- Don't make these arrays too big since they consume memory.
    return new Object[][]
    {
      new Object[] { null },              // The null value
      new Object[] { new byte[0x00] },    // The zero-byte value
      new Object[] { new byte[0x01] },    // The single-byte value
      new Object[] { new byte[0x7F] },    // The largest 1-byte length encoding
      new Object[] { new byte[0x80] },    // The smallest 2-byte length encoding
      new Object[] { new byte[0xFF] },    // The largest 2-byte length encoding
      new Object[] { new byte[0x0100] },  // The smallest 3-byte length encoding
      new Object[] { new byte[0xFFFF] },  // The largest 3-byte length encoding
      new Object[] { new byte[0x010000] } // The smallest 4-byte length encoding
    };
  }
  /**
   * Tests the <CODE>getValue</CODE> and <CODE>setValue</CODE> methods.
   *
   * @param  value  The value to use in the test.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(dataProvider = "testValues")
  public void testGetAndSetValue(byte[] value)
         throws Exception
  {
    ASN1Element e = new ASN1Element((byte) 0x00);
    e.setValue(value);
    if (value == null)
    {
      assertEquals(new byte[0], e.value());
    }
    else
    {
      assertEquals(value, e.value());
    }
  }
  /**
   * Create decoded and encoded lengths.
   *
   * @return  A list of decoded and encoded lengths.
   */
  @DataProvider(name = "testLengths")
  public Object[][] getTestLengths()
  {
    return new Object[][]
    {
      new Object[] { 0x00, new byte[] { 0x00 } },
      new Object[] { 0x01, new byte[] { 0x01 } },
      new Object[] { 0x7F, new byte[] { 0x7F } },
      new Object[] { 0x80, new byte[] { (byte) 0x81, (byte) 0x80 } },
      new Object[] { 0xFF, new byte[] { (byte) 0x81, (byte) 0xFF } },
      new Object[] { 0x0100, new byte[] { (byte) 0x82, 0x01, 0x00 } },
      new Object[] { 0xFFFF,
                     new byte[] { (byte) 0x82, (byte) 0xFF, (byte) 0xFF } },
      new Object[] { 0x010000, new byte[] { (byte) 0x83, 0x01, 0x00, 0x00 } },
      new Object[] { 0xFFFFFF,
                     new byte[] { (byte) 0x83, (byte) 0xFF, (byte) 0xFF,
                                  (byte) 0xFF } },
      new Object[] { 0x01000000,
                     new byte[] { (byte) 0x84, 0x01, 0x00, 0x00, 0x00 } },
      new Object[] { 0x7FFFFFFF,
                     new byte[] { (byte) 0x84, (byte) 0x7F, (byte) 0xFF,
                                  (byte) 0xFF, (byte) 0xFF } },
    };
  }
  /**
   * Tests the <CODE>encodeLength</CODE> method.
   *
   * @param  decodedLength  The decoded length to encode.
   * @param  encodedLength  The encoded representation of the length.
   */
  @Test()
  public void testEncodeLength() {
    int numLengths = testLengths.size();
    for (int i = 0; i < numLengths; i++) {
      int length = testLengths.get(i);
      byte[] encodedLength = testEncodedLengths.get(i);
      assertTrue(Arrays.equals(encodedLength, ASN1Element
          .encodeLength(length)));
    }
  @Test(dataProvider = "testLengths")
  public void testEncodeLength(int decodedLength, byte[] encodedLength)
  {
    assertEquals(encodedLength, ASN1Element.encodeLength(decodedLength));
  }
  /**
   * Tests the <CODE>encode</CODE> and <CODE>decode</CODE> methods.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   */
  @Test()
  public void testEncodeAndDecode() throws Exception {
    for (byte type : testTypes) {
      for (byte[] value : testValues) {
        int length;
        byte[] encodedLength;
        if (value == null) {
          length = 0;
          encodedLength = new byte[] { (byte) 0x00 };
        } else {
          length = value.length;
          encodedLength = ASN1Element.encodeLength(length);
        }
        byte[] encodedElement = new byte[1 + length + encodedLength.length];
        encodedElement[0] = type;
        System.arraycopy(encodedLength, 0, encodedElement, 1,
            encodedLength.length);
        if (value != null) {
          System.arraycopy(value, 0, encodedElement,
              1 + encodedLength.length, length);
        }
        ASN1Element element = new ASN1Element(type, value);
        assertTrue(Arrays.equals(encodedElement, element.encode()));
        assertTrue(element.equals(ASN1Element.decode(encodedElement)));
      }
      int numLengths = testLengths.size();
      for (int i = 0; i < numLengths; i++) {
        int length = testLengths.get(i);
        byte[] encodedLength = testEncodedLengths.get(i);
        byte[] value = new byte[length];
        byte[] encodedElement = new byte[1 + length + encodedLength.length];
        encodedElement[0] = type;
        System.arraycopy(encodedLength, 0, encodedElement, 1,
            encodedLength.length);
        ASN1Element element = new ASN1Element(type, value);
        assertTrue(Arrays.equals(encodedElement, element.encode()));
        assertTrue(element.equals(ASN1Element.decode(encodedElement)));
      }
    }
  }
  /**
   * Tests the <CODE>encodeValue</CODE> method with a single boolean
   * argument.
   */
  @Test()
  public void testEncodeBooleanValue() {
    byte[] encodedFalse = new byte[] { (byte) 0x00 };
    byte[] encodedTrue = new byte[] { (byte) 0xFF };
    assertTrue(Arrays.equals(encodedFalse, ASN1Element.encodeValue(false)));
    assertTrue(Arrays.equals(encodedTrue, ASN1Element.encodeValue(true)));
  }
  /**
   * Tests the <CODE>encodeValue</CODE> method with a single int
   * argument.
   */
  @Test()
  public void testEncodeIntValue() {
    int numIntValues = testIntegers.size();
    for (int i = 0; i < numIntValues; i++) {
      int intValue = testIntegers.get(i);
      byte[] encodedInt = testEncodedIntegers.get(i);
      assertTrue(Arrays.equals(encodedInt, ASN1Element
          .encodeValue(intValue)));
    }
  }
  /**
   * Tests the <CODE>encodeValue</CODE> method with a set of ASN.1
   * elements.
   * @param  value  The value to use in the test.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test()
  public void testEncodeAndDecodeElements() throws Exception {
    int numElementSets = testElementSets.size();
    for (int i = 0; i < numElementSets; i++) {
      ArrayList<ASN1Element> elementSet = testElementSets.get(i);
      byte[] encodedElementSet = testEncodedElementSets.get(i);
  @Test(dataProvider = "testValues")
  public void testEncodeAndDecode(byte[] value)
         throws Exception
  {
    for (int i=0x00; i < 0xFF; i++)
    {
      byte type = (byte) i;
      ASN1Element e = new ASN1Element(type, value);
      byte[] encodedElement = e.encode();
      assertTrue(Arrays.equals(encodedElementSet, ASN1Element
          .encodeValue(elementSet)));
      ASN1Element d = ASN1Element.decode(encodedElement);
      assertEquals(d, e);
      assertEquals(type, d.getType());
      assertTrue(e.equalsElement(d));
      ArrayList<ASN1Element> decodedElementSet;
      decodedElementSet = ASN1Element.decodeElements(encodedElementSet);
      ArrayList<ASN1Element> compareSet;
      if (elementSet == null) {
        compareSet = new ArrayList<ASN1Element>(0);
      } else {
        compareSet = elementSet;
      if (value == null)
      {
        assertEquals(new byte[0], d.value());
      }
      else
      {
        assertEquals(value, d.value());
      }
      assertTrue(listsAreEqual(compareSet, decodedElementSet));
      d = ASN1Element.decode(encodedElement, 0, encodedElement.length);
      assertEquals(d, e);
      assertEquals(type, d.getType());
      assertTrue(e.equalsElement(d));
      if (value == null)
      {
        assertEquals(new byte[0], d.value());
      }
      else
      {
        assertEquals(value, d.value());
      }
    }
  }
  /**
   * Tests to ensure that there is a failure when trying to decode a null as an
   * element.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeFailureNull()
         throws Exception
  {
    ASN1Element.decode(null);
  }
  /**
   * Tests the <CODE>decodeAsBoolean</CODE> method.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test()
  public void testDecodeAsBoolean() throws Exception {
    for (int i = 0; i < 256; i++) {
      byte[] valueByte = new byte[] { (byte) i };
      ASN1Element element = new ASN1Element((byte) 0x00, valueByte);
      boolean booleanValue = (i != 0);
  public void testDecodeAsBoolean()
         throws Exception
  {
    // First, make sure that we can decode actual Boolean elements as Boolean
    // elements, using both the standard type as well as a nonstandard type.
    boolean[] booleanValues = new boolean[] { true, false };
    for (boolean b : booleanValues)
    {
      ASN1Element e = new ASN1Boolean(b);
      ASN1Boolean booleanElement = e.decodeAsBoolean();
      assertEquals(b, booleanElement.booleanValue());
      assertEquals(booleanValue, element.decodeAsBoolean().booleanValue());
      e = new ASN1Boolean((byte) 0x50, b);
      booleanElement = e.decodeAsBoolean();
      assertEquals(b, booleanElement.booleanValue());
    }
      element = new ASN1Element((byte) 0x01, valueByte);
      assertEquals(booleanValue, element.decodeAsBoolean().booleanValue());
    // Next, make sure we can decode generic ASN.1 elements with a single-byte
    // value as a Boolean element.
    for (int i=0; i < 256; i++)
    {
      ASN1Element e = new ASN1Element(ASN1Constants.UNIVERSAL_BOOLEAN_TYPE,
                                      new byte[] { (byte) i });
      ASN1Boolean b = e.decodeAsBoolean();
      assertEquals((i != 0), b.booleanValue());
      e = new ASN1Element((byte) 0x50, new byte[] { (byte) i });
      b = e.decodeAsBoolean();
      assertEquals((i != 0), b.booleanValue());
    }
  }
  /**
   * Tests the <CODE>decodeAsEnumerated</CODE> method.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test()
  public void testDecodeAsEnumerated() throws Exception {
    int numIntValues = testIntegers.size();
    for (int i = 0; i < numIntValues; i++) {
      int intValue = testIntegers.get(i);
      byte[] encodedInt = testEncodedIntegers.get(i);
  public void testDecodeAsEnumerated()
         throws Exception
  {
    int[] intValues =
    {
      0x00000000,
      0x00000001,
      0x0000000F,
      0x00000010,
      0x0000007F,
      0x00000080,
      0x000000FF,
      0x00000100,
      0x00000FFF,
      0x00001000,
      0x0000FFFF,
      0x00010000,
      0x000FFFFF,
      0x00100000,
      0x00FFFFFF,
      0x01000000,
      0x0FFFFFFF,
      0x10000000,
      0x7FFFFFFF
    };
      ASN1Element element = new ASN1Element((byte) 0x00, encodedInt);
    // First, make sure that we can decode actual enumerated elements as
    // enumerated elements, using both the standard type as well as a
    // nonstandard type.
    for (int i : intValues)
    {
      ASN1Element e = new ASN1Enumerated(i);
      ASN1Enumerated enumeratedElement = e.decodeAsEnumerated();
      assertEquals(i, enumeratedElement.intValue());
      assertEquals(intValue, element.decodeAsEnumerated().intValue());
      e = new ASN1Enumerated((byte) 0x50, i);
      enumeratedElement = e.decodeAsEnumerated();
      assertEquals(i, enumeratedElement.intValue());
    }
      element = new ASN1Element((byte) 0x0A, encodedInt);
      assertEquals(intValue, element.decodeAsEnumerated().intValue());
    // Next, make sure we can decode generic ASN.1 elements as enumerated
    // elements.
    for (int i : intValues)
    {
      byte[] encoding;
      if ((i & 0xFF) == i)
      {
        encoding = new byte[1];
        encoding[0] = (byte) (i & 0xFF);
      }
      else if ((i & 0xFFFF) == i)
      {
        encoding = new byte[2];
        encoding[0] = (byte) ((i >> 8) & 0xFF);
        encoding[1] = (byte) (i & 0xFF);
      }
      else if ((i & 0xFFFFFF) == i)
      {
        encoding = new byte[3];
        encoding[0] = (byte) ((i >> 16) & 0xFF);
        encoding[1] = (byte) ((i >> 8) & 0xFF);
        encoding[2] = (byte) (i & 0xFF);
      }
      else
      {
        encoding = new byte[4];
        encoding[0] = (byte) ((i >> 24) & 0xFF);
        encoding[1] = (byte) ((i >> 16) & 0xFF);
        encoding[2] = (byte) ((i >> 8) & 0xFF);
        encoding[3] = (byte) (i & 0xFF);
      }
      ASN1Element e = new ASN1Element(ASN1Constants.UNIVERSAL_ENUMERATED_TYPE,
                                      encoding);
      ASN1Enumerated enumeratedElement = e.decodeAsEnumerated();
      assertEquals(i, enumeratedElement.intValue());
      e = new ASN1Element((byte) 0x50, encoding);
      enumeratedElement = e.decodeAsEnumerated();
      assertEquals(i, enumeratedElement.intValue());
    }
  }
  /**
   * Tests the <CODE>decodeAsInteger</CODE> method.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test()
  public void testDecodeAsInteger() throws Exception {
    int numIntValues = testIntegers.size();
    for (int i = 0; i < numIntValues; i++) {
      int intValue = testIntegers.get(i);
      byte[] encodedInt = testEncodedIntegers.get(i);
  public void testDecodeAsInteger()
         throws Exception
  {
    int[] intValues =
    {
      0x00000000,
      0x00000001,
      0x0000000F,
      0x00000010,
      0x0000007F,
      0x00000080,
      0x000000FF,
      0x00000100,
      0x00000FFF,
      0x00001000,
      0x0000FFFF,
      0x00010000,
      0x000FFFFF,
      0x00100000,
      0x00FFFFFF,
      0x01000000,
      0x0FFFFFFF,
      0x10000000,
      0x7FFFFFFF,
      -0x00000001,
      -0x0000000F,
      -0x00000010,
      -0x0000007F,
      -0x00000080,
      -0x000000FF,
      -0x00000100,
      -0x00000FFF,
      -0x00001000,
      -0x0000FFFF,
      -0x00010000,
      -0x000FFFFF,
      -0x00100000,
      -0x00FFFFFF,
      -0x01000000,
      -0x0FFFFFFF,
      -0x10000000,
      -0x7FFFFFFF,
      0x80000000
    };
      ASN1Element element = new ASN1Element((byte) 0x00, encodedInt);
    // First, make sure that we can decode actual integer elements as integer
    // elements, using both the standard type as well as a nonstandard type.
    for (int i : intValues)
    {
      ASN1Element e = new ASN1Integer(i);
      ASN1Integer integerElement = e.decodeAsInteger();
      assertEquals(i, integerElement.intValue());
      assertEquals(intValue, element.decodeAsInteger().intValue());
      e = new ASN1Integer((byte) 0x50, i);
      integerElement = e.decodeAsInteger();
      assertEquals(i, integerElement.intValue());
    }
      element = new ASN1Element((byte) 0x02, encodedInt);
      assertEquals(intValue, element.decodeAsInteger().intValue());
    // Next, make sure we can decode generic ASN.1 elements as integer elements.
    for (int i : intValues)
    {
      byte[] encoding;
      if ((i & 0x7F) == i)
      {
        encoding = new byte[1];
        encoding[0] = (byte) (i & 0xFF);
      }
      else if ((i & 0x7FFF) == i)
      {
        encoding = new byte[2];
        encoding[0] = (byte) ((i >> 8) & 0xFF);
        encoding[1] = (byte) (i & 0xFF);
      }
      else if ((i & 0x7FFFFF) == i)
      {
        encoding = new byte[3];
        encoding[0] = (byte) ((i >> 16) & 0xFF);
        encoding[1] = (byte) ((i >> 8) & 0xFF);
        encoding[2] = (byte) (i & 0xFF);
      }
      else
      {
        encoding = new byte[4];
        encoding[0] = (byte) ((i >> 24) & 0xFF);
        encoding[1] = (byte) ((i >> 16) & 0xFF);
        encoding[2] = (byte) ((i >> 8) & 0xFF);
        encoding[3] = (byte) (i & 0xFF);
      }
      ASN1Element e = new ASN1Element(ASN1Constants.UNIVERSAL_INTEGER_TYPE,
                                      encoding);
      ASN1Integer integerElement = e.decodeAsInteger();
      assertEquals(i, integerElement.intValue());
      e = new ASN1Element((byte) 0x50, encoding);
      integerElement = e.decodeAsInteger();
      assertEquals(i, integerElement.intValue());
    }
  }
  /**
   * Tests the <CODE>decodeAsLong</CODE> method.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test()
  public void testDecodeAsLong()
         throws Exception
  {
    long[] longValues =
    {
      0x0000000000000000L,
      0x0000000000000001L,
      0x000000000000007FL,
      0x0000000000000080L,
      0x00000000000000FFL,
      0x0000000000000100L,
      0x000000000000FFFFL,
      0x0000000000010000L,
      0x0000000000FFFFFFL,
      0x0000000001000000L,
      0x00000000FFFFFFFFL,
      0x0000000100000000L,
      0x000000FFFFFFFFFFL,
      0x0000010000000000L,
      0x0000FFFFFFFFFFFFL,
      0x0001000000000000L,
      0x00FFFFFFFFFFFFFFL,
      0x0100000000000000L,
      0x7FFFFFFFFFFFFFFFL,
      -0x0000000000000001L,
      -0x000000000000007FL,
      -0x0000000000000080L,
      -0x00000000000000FFL,
      -0x0000000000000100L,
      -0x000000000000FFFFL,
      -0x0000000000010000L,
      -0x0000000000FFFFFFL,
      -0x0000000001000000L,
      -0x00000000FFFFFFFFL,
      -0x0000000100000000L,
      -0x000000FFFFFFFFFFL,
      -0x0000010000000000L,
      -0x0000FFFFFFFFFFFFL,
      -0x0001000000000000L,
      -0x00FFFFFFFFFFFFFFL,
      -0x0100000000000000L,
      -0x7FFFFFFFFFFFFFFFL,
      0x8000000000000000L
    };
    // First, make sure that we can decode actual long elements as long
    // elements, using both the standard type as well as a nonstandard type.
    for (long l : longValues)
    {
      ASN1Element e = new ASN1Long(l);
      ASN1Long longElement = e.decodeAsLong();
      assertEquals(l, longElement.longValue());
      e = new ASN1Long((byte) 0x50, l);
      longElement = e.decodeAsLong();
      assertEquals(l, longElement.longValue());
    }
    // Next, make sure we can decode generic ASN.1 elements as long elements.
    for (long l : longValues)
    {
      byte[] encoding;
      if ((l & 0x7FL) == l)
      {
        encoding = new byte[1];
        encoding[0] = (byte) (l & 0xFF);
      }
      else if ((l & 0x7FFFL) == l)
      {
        encoding = new byte[2];
        encoding[0] = (byte) ((l >> 8) & 0xFF);
        encoding[1] = (byte) (l & 0xFF);
      }
      else if ((l & 0x7FFFFFL) == l)
      {
        encoding = new byte[3];
        encoding[0] = (byte) ((l >> 16) & 0xFF);
        encoding[1] = (byte) ((l >> 8) & 0xFF);
        encoding[2] = (byte) (l & 0xFF);
      }
      else if ((l & 0x7FFFFFFFL) == l)
      {
        encoding = new byte[4];
        encoding[0] = (byte) ((l >> 24) & 0xFF);
        encoding[1] = (byte) ((l >> 16) & 0xFF);
        encoding[2] = (byte) ((l >> 8) & 0xFF);
        encoding[3] = (byte) (l & 0xFF);
      }
      else if ((l & 0x7FFFFFFFFFL) == l)
      {
        encoding = new byte[5];
        encoding[0] = (byte) ((l >> 32) & 0xFF);
        encoding[1] = (byte) ((l >> 24) & 0xFF);
        encoding[2] = (byte) ((l >> 16) & 0xFF);
        encoding[3] = (byte) ((l >> 8) & 0xFF);
        encoding[4] = (byte) (l & 0xFF);
      }
      else if ((l & 0x7FFFFFFFFFFFL) == l)
      {
        encoding = new byte[6];
        encoding[0] = (byte) ((l >> 40) & 0xFF);
        encoding[1] = (byte) ((l >> 32) & 0xFF);
        encoding[2] = (byte) ((l >> 24) & 0xFF);
        encoding[3] = (byte) ((l >> 16) & 0xFF);
        encoding[4] = (byte) ((l >> 8) & 0xFF);
        encoding[5] = (byte) (l & 0xFF);
      }
      else if ((l & 0x7FFFFFFFFFFFFFL) == l)
      {
        encoding = new byte[7];
        encoding[0] = (byte) ((l >> 48) & 0xFF);
        encoding[1] = (byte) ((l >> 40) & 0xFF);
        encoding[2] = (byte) ((l >> 32) & 0xFF);
        encoding[3] = (byte) ((l >> 24) & 0xFF);
        encoding[4] = (byte) ((l >> 16) & 0xFF);
        encoding[5] = (byte) ((l >> 8) & 0xFF);
        encoding[6] = (byte) (l & 0xFF);
      }
      else
      {
        encoding = new byte[8];
        encoding[0] = (byte) ((l >> 56) & 0xFF);
        encoding[1] = (byte) ((l >> 48) & 0xFF);
        encoding[2] = (byte) ((l >> 40) & 0xFF);
        encoding[3] = (byte) ((l >> 32) & 0xFF);
        encoding[4] = (byte) ((l >> 24) & 0xFF);
        encoding[5] = (byte) ((l >> 16) & 0xFF);
        encoding[6] = (byte) ((l >> 8) & 0xFF);
        encoding[7] = (byte) (l & 0xFF);
      }
      ASN1Element e = new ASN1Element(ASN1Constants.UNIVERSAL_INTEGER_TYPE,
                                      encoding);
      ASN1Long longElement = e.decodeAsLong();
      assertEquals(l, longElement.longValue());
      e = new ASN1Element((byte) 0x50, encoding);
      longElement = e.decodeAsLong();
      assertEquals(l, longElement.longValue());
    }
  }
  /**
   * Tests the <CODE>decodeAsNull</CODE> method.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test()
  public void testDecodeAsNull() throws Exception {
    for (byte type : testTypes) {
      ASN1Element element = new ASN1Element(type);
      ASN1Null nullElement = new ASN1Null(type);
  public void testDecodeAsNull()
         throws Exception
  {
    // First, make sure that we can decode actual null elements as null
    // elements, using both the standard type as well as a nonstandard type.
    ASN1Element e = new ASN1Null();
    e.decodeAsNull();
      assertEquals(nullElement, element.decodeAsNull());
    }
    e = new ASN1Null((byte) 0x50);
    e.decodeAsNull();
    // Next, make sure we can decode generic ASN.1 elements with a zero-byte
    // value as a null element.
    e = new ASN1Element(ASN1Constants.UNIVERSAL_NULL_TYPE);
    e.decodeAsNull();
    e = new ASN1Element(ASN1Constants.UNIVERSAL_NULL_TYPE, null);
    e.decodeAsNull();
    e = new ASN1Element(ASN1Constants.UNIVERSAL_NULL_TYPE, new byte[0]);
    e.decodeAsNull();
    e = new ASN1Element((byte) 0x50);
    e.decodeAsNull();
    e = new ASN1Element((byte) 0x50, null);
    e.decodeAsNull();
    e = new ASN1Element((byte) 0x50, new byte[0]);
    e.decodeAsNull();
  }
  /**
   * Tests the <CODE>decodeAsOctetString</CODE> method.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @param  value  The value to use for the octet string element.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test()
  public void testDecodeAsOctetString() throws Exception {
    for (byte[] value : testValues) {
      ASN1Element element = new ASN1Element((byte) 0x00, value);
  @Test(dataProvider = "testValues")
  public void testDecodeAsOctetString(byte[] value)
         throws Exception
  {
    // First, make sure that we can decode actual octet string elements as octet
    // string elements, using both the standard type as well as a nonstandard
    // type.
    ASN1Element e = new ASN1OctetString(value);
    ASN1OctetString octetStringElement = e.decodeAsOctetString();
    if (value == null)
    {
      assertEquals(new byte[0], octetStringElement.value());
    }
    else
    {
      assertEquals(value, octetStringElement.value());
    }
      byte[] compareValue;
      if (value == null) {
        compareValue = new byte[0];
      } else {
        compareValue = value;
      }
    e = new ASN1OctetString((byte) 0x50, value);
    octetStringElement = e.decodeAsOctetString();
    if (value == null)
    {
      assertEquals(new byte[0], octetStringElement.value());
    }
    else
    {
      assertEquals(value, octetStringElement.value());
    }
      assertTrue(Arrays.equals(compareValue, element.decodeAsOctetString()
          .value()));
      element = new ASN1Element((byte) 0x04, value);
    // Next, make sure that we can decode a generic ASN.1 element as an octet
    // string element.
    e = new ASN1Element(ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE, value);
    octetStringElement = e.decodeAsOctetString();
    if (value == null)
    {
      assertEquals(new byte[0], octetStringElement.value());
    }
    else
    {
      assertEquals(value, octetStringElement.value());
    }
      assertTrue(Arrays.equals(compareValue, element.decodeAsOctetString()
          .value()));
    e = new ASN1Element((byte) 0x50, value);
    octetStringElement = e.decodeAsOctetString();
    if (value == null)
    {
      assertEquals(new byte[0], octetStringElement.value());
    }
    else
    {
      assertEquals(value, octetStringElement.value());
    }
  }
  /**
   * Retrieves arrays of ASN.1 elements for use in testing with sequences and
   * sets.
   *
   * @return  Arrays of ASN.1 elements for use in testing with sequences and
   *          sets.
   */
  @DataProvider(name = "elementArrays")
  public Object[][] getElementArrays()
  {
    ArrayList<ASN1Element[]> arrays = new ArrayList<ASN1Element[]>();
    arrays.add(null);
    arrays.add(new ASN1Element[0]);
    arrays.add(new ASN1Element[] { new ASN1Element((byte) 0x50) });
    arrays.add(new ASN1Element[] { new ASN1Element((byte) 0x50, null) });
    arrays.add(new ASN1Element[] { new ASN1Element((byte) 0x50, new byte[0]) });
    arrays.add(new ASN1Element[] { new ASN1Element((byte) 0x50, new byte[1]) });
    arrays.add(new ASN1Element[] { new ASN1Boolean(true) });
    arrays.add(new ASN1Element[] { new ASN1Enumerated(0) });
    arrays.add(new ASN1Element[] { new ASN1Integer(0) });
    arrays.add(new ASN1Element[] { new ASN1Long(0) });
    arrays.add(new ASN1Element[] { new ASN1OctetString() });
    arrays.add(new ASN1Element[] { new ASN1OctetString(),
                                   new ASN1OctetString() });
    arrays.add(new ASN1Element[] { new ASN1OctetString(),
                                   new ASN1OctetString(),
                                   new ASN1OctetString() });
    arrays.add(new ASN1Element[] { new ASN1OctetString(),
                                   new ASN1OctetString(),
                                   new ASN1OctetString(),
                                   new ASN1OctetString() });
    arrays.add(new ASN1Element[] { new ASN1OctetString(),
                                   new ASN1OctetString(),
                                   new ASN1OctetString(),
                                   new ASN1OctetString(),
                                   new ASN1OctetString() });
    arrays.add(new ASN1Element[] { new ASN1Integer(1),
                                   new ASN1Null((byte) 0x42) });
    Object[][] objects = new Object[arrays.size()][];
    for (int i=0; i < arrays.size(); i++)
    {
      objects[i] = new Object[] { arrays.get(i) };
    }
    return objects;
  }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @param  elements  The set of ASN.1 elements to use in the tests.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test()
  public void testDecodeAsSequence() throws Exception {
    int numElementSets = testElementSets.size();
    for (int i = 0; i < numElementSets; i++) {
      ArrayList<ASN1Element> elementSet = testElementSets.get(i);
      byte[] encodedElementSet = testEncodedElementSets.get(i);
      ArrayList<ASN1Element> compareList;
      if (elementSet == null) {
        compareList = new ArrayList<ASN1Element>(0);
      } else {
        compareList = elementSet;
  @Test(dataProvider = "elementArrays")
  public void testDecodeAsSequence(ASN1Element[] elements)
         throws Exception
  {
    ArrayList<ASN1Element> elementList = new ArrayList<ASN1Element>();
    if (elements == null)
    {
      elementList = null;
    }
    else
    {
      for (ASN1Element e : elements)
      {
        elementList.add(e);
      }
    }
      ASN1Element element = new ASN1Element((byte) 0x00, encodedElementSet);
      assertTrue(listsAreEqual(compareList, element.decodeAsSequence()
          .elements()));
    // First, make sure that we can decode actual sequence elements as sequence
    // elements, using both the standard type as well as a nonstandard type.
    ASN1Element e = new ASN1Sequence(elementList);
    ASN1Sequence sequenceElement = e.decodeAsSequence();
    if (elements == null)
    {
      assertEquals(new ArrayList<ASN1Element>(), sequenceElement.elements());
    }
    else
    {
      assertEquals(elementList, sequenceElement.elements());
    }
      element = new ASN1Element((byte) 0x30, encodedElementSet);
    e = new ASN1Sequence((byte) 0x50, elementList);
    sequenceElement = e.decodeAsSequence();
    if (elements == null)
    {
      assertEquals(new ArrayList<ASN1Element>(), sequenceElement.elements());
    }
    else
    {
      assertEquals(elementList, sequenceElement.elements());
    }
      assertTrue(listsAreEqual(compareList, element.decodeAsSequence()
          .elements()));
    // Next, make sure that we can decode a generic ASN.1 element as an octet
    // string element.
    e = new ASN1Element(ASN1Constants.UNIVERSAL_SEQUENCE_TYPE,
                        ASN1Element.encodeValue(elementList));
    sequenceElement = e.decodeAsSequence();
    if (elements == null)
    {
      assertEquals(new ArrayList<ASN1Element>(), sequenceElement.elements());
    }
    else
    {
      assertEquals(elementList, sequenceElement.elements());
    }
    e = new ASN1Element((byte) 0x50, ASN1Element.encodeValue(elementList));
    sequenceElement = e.decodeAsSequence();
    if (elements == null)
    {
      assertEquals(new ArrayList<ASN1Element>(), sequenceElement.elements());
    }
    else
    {
      assertEquals(elementList, sequenceElement.elements());
    }
  }
  /**
   * Tests the <CODE>decodeAsSet</CODE> method.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @param  elements  The set of ASN.1 elements to use in the tests.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test()
  public void testDecodeAsSet() throws Exception {
    int numElementSets = testElementSets.size();
    for (int i = 0; i < numElementSets; i++) {
      ArrayList<ASN1Element> elementSet = testElementSets.get(i);
      byte[] encodedElementSet = testEncodedElementSets.get(i);
      ArrayList<ASN1Element> compareList;
      if (elementSet == null) {
        compareList = new ArrayList<ASN1Element>(0);
      } else {
        compareList = elementSet;
  @Test(dataProvider = "elementArrays")
  public void testDecodeAsSet(ASN1Element[] elements)
         throws Exception
  {
    ArrayList<ASN1Element> elementList = new ArrayList<ASN1Element>();
    if (elements == null)
    {
      elementList = null;
    }
    else
    {
      for (ASN1Element e : elements)
      {
        elementList.add(e);
      }
    }
      ASN1Element element = new ASN1Element((byte) 0x00, encodedElementSet);
      assertTrue(listsAreEqual(compareList, element.decodeAsSet()
          .elements()));
    // First, make sure that we can decode actual set elements as set elements,
    // using both the standard type as well as a nonstandard type.
    ASN1Element e = new ASN1Set(elementList);
    ASN1Set setElement = e.decodeAsSet();
    if (elements == null)
    {
      assertEquals(new ArrayList<ASN1Element>(), setElement.elements());
    }
    else
    {
      assertEquals(elementList, setElement.elements());
    }
      element = new ASN1Element((byte) 0x31, encodedElementSet);
    e = new ASN1Set((byte) 0x50, elementList);
    setElement = e.decodeAsSet();
    if (elements == null)
    {
      assertEquals(new ArrayList<ASN1Element>(), setElement.elements());
    }
    else
    {
      assertEquals(elementList, setElement.elements());
    }
      assertTrue(listsAreEqual(compareList, element.decodeAsSet()
          .elements()));
    // Next, make sure that we can decode a generic ASN.1 element as an octet
    // string element.
    e = new ASN1Element(ASN1Constants.UNIVERSAL_SET_TYPE,
                        ASN1Element.encodeValue(elementList));
    setElement = e.decodeAsSet();
    if (elements == null)
    {
      assertEquals(new ArrayList<ASN1Element>(), setElement.elements());
    }
    else
    {
      assertEquals(elementList, setElement.elements());
    }
    e = new ASN1Element((byte) 0x50, ASN1Element.encodeValue(elementList));
    setElement = e.decodeAsSet();
    if (elements == null)
    {
      assertEquals(new ArrayList<ASN1Element>(), setElement.elements());
    }
    else
    {
      assertEquals(elementList, setElement.elements());
    }
  }
  /**
   * Tests the <CODE>equals</CODE> and <CODE>hashCode</CODE>
   * methods.
   * Tests the <CODE>equals</CODE>, <CODE>equalsElement</CODE>, and
   * <CODE>equalsIgnoreType</CODE> methods.
   *
   * @param  value  The value to use in the test.
   */
  @Test(dataProvider = "testValues")
  public void testEquals(byte[] value)
  {
    ASN1Element controlElement = new ASN1Element((byte) 0x00, value);
    for (int i=0x00; i < 0xFF; i++)
    {
      ASN1Element e = new ASN1Element((byte) i, value);
      if (i == 0x00)
      {
        assertTrue(controlElement.equals(e));
        assertTrue(e.equals(controlElement));
        assertTrue(controlElement.equalsElement(e));
        assertTrue(e.equalsElement(controlElement));
      }
      else
      {
        assertFalse(controlElement.equals(e));
        assertFalse(e.equals(controlElement));
        assertFalse(controlElement.equalsElement(e));
        assertFalse(e.equalsElement(controlElement));
      }
      assertTrue(e.equals(e));
      assertTrue(e.equalsElement(e));
      assertTrue(e.equalsIgnoreType(e));
      assertTrue(e.equalsIgnoreType((ByteString) new ASN1OctetString(value)));
      assertTrue(controlElement.equalsIgnoreType(e));
      assertTrue(e.equalsIgnoreType(controlElement));
      assertFalse(e.equals(null));
      assertFalse(e.equals("notanelement"));
    }
  }
  /**
   * Tests the <CODE>decode</CODE> method taking an array argument with an
   * invalid element that is too short to be valid.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeShortElement1()
         throws Exception
  {
    ASN1Element.decode(new byte[1]);
  }
  /**
   * Tests the <CODE>decode</CODE> method taking an array and two integer
   * arguments with an invalid element that is too short to be valid.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeShortElement2()
         throws Exception
  {
    ASN1Element.decode(new byte[1], 0, 1);
  }
  /**
   * Tests the <CODE>decode</CODE> method taking an array argument with a null
   * element.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeNull1()
         throws Exception
  {
    ASN1Element.decode(null);
  }
  /**
   * Tests the <CODE>decode</CODE> method taking an array and two integer
   * arguments with a null element.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeNull2()
         throws Exception
  {
    ASN1Element.decode(null, 0, 0);
  }
  /**
   * Tests the <CODE>decode</CODE> method taking an array argument with an
   * element indicating that it takes more than four bytes to describe the
   * length.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeLongLength1()
         throws Exception
  {
    byte[] elementBytes =
    {
      0x04,
      (byte) 0x85,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00
    };
    ASN1Element.decode(elementBytes);
  }
  /**
   * Tests the <CODE>decode</CODE> method taking an array and two integer
   * arguments with an indicating that it takes more than four bytes to describe
   * the length.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeLongLength2()
         throws Exception
  {
    byte[] elementBytes =
    {
      0x04,
      (byte) 0x85,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00
    };
    ASN1Element.decode(elementBytes, 0, elementBytes.length);
  }
  /**
   * Tests the <CODE>decode</CODE> method taking an array argument with an
   * element that isn't long enough to fully decode the length.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeTruncatedLength1()
         throws Exception
  {
    byte[] elementBytes =
    {
      0x04,
      (byte) 0x82,
      0x00
   };
    ASN1Element.decode(elementBytes);
  }
  /**
   * Tests the <CODE>decode</CODE> method taking an array and two integer
   * arguments with an element that isn't long enough to fully decode the
   * length.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeTruncatedLength2()
         throws Exception
  {
    byte[] elementBytes =
    {
      0x04,
      (byte) 0x82,
      0x00
   };
    ASN1Element.decode(elementBytes, 0, elementBytes.length);
  }
  /**
   * Tests the <CODE>decode</CODE> method taking an array argument with an
   * element whose decoded length doesn't match the number of bytes remaining.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeLengthMismatch1()
         throws Exception
  {
    byte[] elementBytes =
    {
      0x04,
      0x01,
      0x00,
      0x00
   };
    ASN1Element.decode(elementBytes);
  }
  /**
   * Tests the <CODE>decode</CODE> method taking an array and two integer
   * arguments with an element whose decoded length doesn't match the number of
   * bytes remaining.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeLengthMismatch2()
         throws Exception
  {
    byte[] elementBytes =
    {
      0x04,
      0x01,
      0x00,
      0x00
   };
    ASN1Element.decode(elementBytes, 0, elementBytes.length);
  }
  /**
   * Tests the <CODE>decodeElements</CODE> method taking an array with a null
   * array.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeElementsNull()
         throws Exception
  {
    ASN1Element.decodeElements(null);
  }
  /**
   * Tests the <CODE>decodeElements</CODE> method taking an array with an array
   * containing an element with too many bytes used to describe the length.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeElementsLongLength()
         throws Exception
  {
    byte[] elementBytes =
    {
      0x04,
      (byte) 0x85,
      0x00,
      0x00,
      0x00,
      0x00,
      0x00
    };
    ASN1Element.decodeElements(elementBytes);
  }
  /**
   * Tests the <CODE>decodeElements</CODE> method taking an array with an array
   * containing an element without enough bytes to fully decode the length.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeElementsTruncatedLength()
         throws Exception
  {
    byte[] elementBytes =
    {
      0x04,
      (byte) 0x82,
      0x00,
    };
    ASN1Element.decodeElements(elementBytes);
  }
  /**
   * Tests the <CODE>equalsElement</CODE> method taking an array with a null
   * array.
   *
   * @throws  Exception  If the test failed unexpectedly.
   */
  @Test()
  public void testEqualsAndHashCode() {
    // Perform simple tests for two basic elements that should be the
    // same, one
    // that should differ in type, one that should differ in value, and
    // one that
    // should differ in both.
    ASN1Element e1 = new ASN1Element((byte) 0x00);
    ASN1Element e2 = new ASN1Element((byte) 0x00, new byte[0]);
    ASN1Element e3 = new ASN1Element((byte) 0x01);
    ASN1Element e4 = new ASN1Element((byte) 0x00,
        new byte[] { (byte) 0x00 });
    ASN1Element e5 = new ASN1Element((byte) 0x01,
        new byte[] { (byte) 0x00 });
    ASN1Element e6 = new ASN1Element((byte) 0x00,
        new byte[] { (byte) 0x01 });
  public void testEqualsElementNull()
         throws Exception
  {
    ASN1Element e = new ASN1OctetString();
    assertFalse(e.equalsElement(null));
  }
    assertTrue(e1.equals(e2)); // Basic equality test.
    assertTrue(e2.equals(e1)); // Reflexive equality test.
    assertFalse(e1.equals(e3)); // Difference in type.
    assertFalse(e1.equals(e4)); // Difference in value.
    assertFalse(e1.equals(e5)); // Differences in type and value.
    assertFalse(e4.equals(e6)); // Difference in values with the same
    // length.
    // Make sure that equal elements have equal hash codes.
    assertEquals(e1.hashCode(), e2.hashCode()); // Hash code equality
    // test.
    // Test equals against a null element.
    assertFalse(e1.equals(null));
    // Test boolean elements against equivalent generic elements.
    ASN1Element trueElement = new ASN1Element((byte) 0x01,
        new byte[] { (byte) 0xFF });
    ASN1Element falseElement = new ASN1Element((byte) 0x01,
        new byte[] { (byte) 0x00 });
    ASN1Boolean trueBoolean = new ASN1Boolean(true);
    ASN1Boolean falseBoolean = new ASN1Boolean(false);
    assertTrue(trueElement.equals(trueBoolean));
    assertTrue(trueBoolean.equals(trueElement));
    assertEquals(trueElement.hashCode(), trueBoolean.hashCode());
    assertTrue(falseElement.equals(falseBoolean));
    assertTrue(falseBoolean.equals(falseElement));
    assertEquals(falseElement.hashCode(), falseBoolean.hashCode());
    // Test integer elements against equivalent generic elements.
    int numIntegers = testIntegers.size();
    for (int i = 0; i < numIntegers; i++) {
      int intValue = testIntegers.get(i);
      byte[] encodedIntValue = testEncodedIntegers.get(i);
      ASN1Element genericElement = new ASN1Element((byte) 0x02,
          encodedIntValue);
      ASN1Integer integerElement = new ASN1Integer(intValue);
      assertTrue(genericElement.equals(integerElement));
      assertTrue(integerElement.equals(genericElement)); // Reflexive
      // test.
      // Test for matching hash codes.
      assertEquals(genericElement.hashCode(), integerElement.hashCode());
  /**
   * Tests miscellaneous methods, including <CODE>toString</CODE> and
   * <CODE>getProtocolElementName</CODE> that don't fit in anywhere else.
   *
   * @param  value  The value to use in the test.
   */
  @Test(dataProvider = "testValues")
  public void testMiscellaneous(byte[] value)
  {
    for (int i=0x00; i < 0xFF; i++)
    {
      byte type = (byte) i;
      ASN1Element e = new ASN1Element(type, value);
      e.toString();
      e.toString(new StringBuilder());
      e.toString(new StringBuilder(), 1);
      assertEquals("ASN.1", e.getProtocolElementName());
    }
  }
}