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

neil_a_wilson
12.37.2006 893744262b1a5a291b3cba08f864b18ad8fa7c04
Update the test cases for the ASN.1 octet string, sequence, set, reader, and
writer classes to provide better coverage.
2 files added
4 files modified
3006 ■■■■ changed files
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/SocketReadThread.java 156 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/SocketWriteThread.java 103 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1OctetString.java 852 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1ReaderAndWriter.java 557 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Sequence.java 714 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Set.java 624 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/SocketReadThread.java
New file
@@ -0,0 +1,156 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying * information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 */
package org.opends.server.protocols.asn1;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
/**
 * This class defines a thread that will create a server socket, read data from
 * it, and make that data available in a byte array.
 */
public class SocketReadThread
       extends Thread
{
  // The server socket that we will use to accept the connection.
  private ServerSocket serverSocket;
  // The client socket accepted by this thread.
  private Socket clientSocket;
  /**
   * Creates a new server socket on an arbitrarily-selected available port.
   *
   * @param  testCaseName  The name of the test case with which this thread is
   *                       associated.
   *
   * @throws  Exception  If a problem occurs while creating the server socket.
   */
  public SocketReadThread(String testCaseName)
         throws Exception
  {
    setName("Socket Read Thread -- " + testCaseName);
    setDaemon(true);
    serverSocket = new ServerSocket();
    serverSocket.setReuseAddress(true);
    serverSocket.bind(new InetSocketAddress("127.0.0.1", 0));
  }
  /**
   * Retrieves the port on which the server socket is listening.
   *
   * @return  The port on which the server socket is listening.
   */
  public int getListenPort()
  {
    return serverSocket.getLocalPort();
  }
  /**
   * Accepts a single connection and consumes anything written on that
   * connection.
   */
  public void run()
  {
    try
    {
      clientSocket = serverSocket.accept();
    }
    catch (Exception e)
    {
      // FIXME -- What to do here?
    }
  }
  /**
   * Retrieves the data read from the socket and clears the output stream.
   *
   * @param  length  The number of bytes to read.
   *
   * @return  The data read from the socket.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  public byte[] getDataRead(int length)
         throws Exception
  {
    while (clientSocket == null)
    {
      Thread.sleep(1);
    }
    byte[] buffer = new byte[length];
    int pos = 0;
    while (pos < length)
    {
      int bytesRead = clientSocket.getInputStream().read(buffer, pos,
                                                         length-pos);
      if (bytesRead < 0)
      {
        throw new Exception("Hit the end of the stream");
      }
      pos += bytesRead;
    }
    return buffer;
  }
  /**
   * Closes the client and server sockets.
   */
  public void close()
  {
    try
    {
      clientSocket.close();
    } catch (Exception e) {}
    try
    {
      serverSocket.close();
    } catch (Exception e) {}
  }
}
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/SocketWriteThread.java
New file
@@ -0,0 +1,103 @@
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at
 * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
 * add the following below this CDDL HEADER, with the fields enclosed
 * by brackets "[]" replaced with your own identifying * information:
 *      Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006 Sun Microsystems, Inc.
 */
package org.opends.server.protocols.asn1;
import java.net.Socket;
/**
 * This class defines a thread that will establish a connection to a server and
 * send it a specified data set.
 */
public class SocketWriteThread
       extends Thread
{
  // The data to write to the server.
  private byte[] data;
  // The port to use to connect to the server.
  private int serverPort;
  // The socket to use to communicate with the server.
  private Socket socket;
  /**
   * Creates a new instance of this write thread that will send data to the
   * specified server port.
   *
   * @param  testCaseName  The name of the test case with which this thread is
   *                       associated.
   * @param  serverPort    The port to use to connect to the server.
   * @param  data          The data to write.
   */
  public SocketWriteThread(String testCaseName, int serverPort, byte[] data)
  {
    setName("Socket Write Thread -- " + testCaseName);
    setDaemon(true);
    this.serverPort = serverPort;
    this.data       = data;
  }
  /**
   * Accepts a single connection and consumes anything written on that
   * connection.
   */
  public void run()
  {
    try
    {
      socket = new Socket("127.0.0.1", serverPort);
      socket.getOutputStream().write(data);
    }
    catch (Exception e)
    {
      // FIXME -- What to do here?
    }
  }
  /**
   * Closes the connection to the server.
   */
  public void close()
  {
    try
    {
      socket.close();
    } catch (Exception e) {}
  }
}
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1OctetString.java
@@ -26,302 +26,646 @@
 */
package org.opends.server.protocols.asn1;
import static org.opends.server.util.StaticUtils.getBytes;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeClass;
import static org.testng.Assert.*;
/**
 * This class defines a set of tests for the
 * org.opends.server.protocols.asn1.ASN1OctetString class.
 */
public class TestASN1OctetString extends ASN1TestCase {
  // The set of binary values that should be used in test cases.
  private ArrayList<byte[]> testByteValues;
  // The set of encoded versions of the provided string values.
  private ArrayList<byte[]> testEncodedStrings;
  // The set of string values that should be used in test cases.
  private ArrayList<String> testStrings;
public class TestASN1OctetString
       extends ASN1TestCase
{
  /**
   * Performs any necessary initialization for this test case.
   */
  @BeforeClass
  public void setUp() {
    // Initialize the set of binary values. Don't make these too big
    // since they
    // consume memory.
    testByteValues = new ArrayList<byte[]>();
    testByteValues.add(null); // The null value.
    testByteValues.add(new byte[0x00]); // The zero-byte value.
    testByteValues.add(new byte[0x01]); // The single-byte value.
    testByteValues.add(new byte[0x7F]); // The largest 1-byte length
    // encoding.
    testByteValues.add(new byte[0x80]);
    testByteValues.add(new byte[0xFF]); // The largest 2-byte length
    // encoding.
    testByteValues.add(new byte[0x0100]);
    testByteValues.add(new byte[0xFFFF]); // The largest 3-byte length
    // encoding.
    testByteValues.add(new byte[0x010000]);
    // Initialize the set of string values.
    testStrings = new ArrayList<String>();
    testEncodedStrings = new ArrayList<byte[]>();
    testStrings.add(null);
    testEncodedStrings.add(new byte[0]);
    testStrings.add("");
    testEncodedStrings.add(new byte[0]);
    String lastString = "";
    for (int i = 0; i <= 256; i++) {
      String newString = lastString + "a";
      testStrings.add(newString);
      testEncodedStrings.add(getBytes(newString));
      lastString = newString;
    }
  }
  /**
   * Tests the <CODE>stringValue</CODE> method.
   * Tests the first constructor, which doesn't take any arguments.
   */
  @Test()
  public void testStringValue() {
    for (String s : testStrings) {
      if (s == null) {
        assertEquals("", new ASN1OctetString(s).stringValue());
      } else {
        assertEquals(s, new ASN1OctetString(s).stringValue());
      }
    }
  public void testConstructor1()
  {
    new ASN1OctetString();
  }
  /**
   * Tests the <CODE>setValue</CODE> method that takes a string
   * argument.
   */
  @Test()
  public void testSetStringValue() {
    ASN1OctetString element = new ASN1OctetString();
    int numStrings = testStrings.size();
    for (int i = 0; i < numStrings; i++) {
      String s = testStrings.get(i);
      byte[] b = testEncodedStrings.get(i);
      String compareValue;
      if (s == null) {
        compareValue = "";
      } else {
        compareValue = s;
      }
      element.setValue(s);
      assertEquals(compareValue, element.stringValue());
      assertTrue(Arrays.equals(b, element.value()));
    }
  }
  /**
   * Tests the <CODE>setValue</CODE> method that takes a byte array
   * argument.
   */
  @Test()
  public void testSetByteValue() {
    ASN1OctetString element = new ASN1OctetString();
    // Test the binary representations.
    for (byte[] value : testByteValues) {
      byte[] compareValue;
      if (value == null) {
        compareValue = new byte[0];
      } else {
        compareValue = value;
      }
      element.setValue(value);
      assertTrue(Arrays.equals(compareValue, element.value()));
    }
    // Test the string representations.
    int numStrings = testStrings.size();
    for (int i = 0; i < numStrings; i++) {
      String s = testStrings.get(i);
      byte[] b = testEncodedStrings.get(i);
      String compareString;
      if (s == null) {
        compareString = "";
      } else {
        compareString = s;
      }
      element.setValue(b);
      assertEquals(compareString, element.stringValue());
      assertTrue(Arrays.equals(b, element.value()));
    }
  }
  /**
   * Tests the <CODE>decodeAsOctetString</CODE> method that takes an
   * ASN.1 element argument.
   * Create the values that can be used for testing BER types.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @return  The values that can be used for testing BER types.
   */
  @Test()
  public void testDecodeElementAsOctetString() throws Exception {
    // Run tests with the binary values.
    for (byte[] value : testByteValues) {
      ASN1Element element = new ASN1Element((byte) 0x00, value);
      byte[] compareValue;
      if (value == null) {
        compareValue = new byte[0];
      } else {
        compareValue = value;
      }
      assertTrue(Arrays.equals(compareValue, ASN1OctetString
          .decodeAsOctetString(element).value()));
  @DataProvider(name = "types")
  public Object[][] getTypes()
  {
    // 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) };
    }
    // Run tests with the string values.
    int numStrings = testStrings.size();
    for (int i = 0; i < numStrings; i++) {
      String s = testStrings.get(i);
      byte[] b = testEncodedStrings.get(i);
      String compareString;
      if (s == null) {
        compareString = "";
      } else {
        compareString = s;
      }
      ASN1Element element = new ASN1Element((byte) 0x00, b);
      assertEquals(compareString, ASN1OctetString.decodeAsOctetString(
          element).stringValue());
    }
    return testTypes;
  }
  /**
   * Tests the <CODE>decodeAsOctetString</CODE> method that takes a
   * byte array argument.
   * Tests the second constructor, which takes a byte argument.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @param  type  The BER type to use for the test.
   */
  @Test()
  public void testDecodeBytesAsOctetString() throws Exception {
    // Run tests with the binary values.
    for (byte[] value : testByteValues) {
      byte[] encodedLength;
      byte[] encodedElement;
      if (value == null) {
        encodedLength = ASN1Element.encodeLength(0);
        encodedElement = new byte[1 + encodedLength.length];
      } else {
        encodedLength = ASN1Element.encodeLength(value.length);
        encodedElement = new byte[1 + encodedLength.length + value.length];
      }
  @Test(dataProvider = "types")
  public void testConstructor2(byte type)
  {
    ASN1OctetString os = new ASN1OctetString(type);
    assertEquals(type, os.getType());
  }
      encodedElement[0] = (byte) 0x00;
      System.arraycopy(encodedLength, 0, encodedElement, 1,
          encodedLength.length);
      if (value != null) {
        System.arraycopy(value, 0, encodedElement,
            1 + encodedLength.length, value.length);
      }
      byte[] compareValue;
      if (value == null) {
        compareValue = new byte[0];
      } else {
        compareValue = value;
      }
  /**
   * Create byte arrays to use for element values.
   *
   * @return  A list of byte arrays that can be used as element values.
   */
  @DataProvider(name = "binaryValues")
  public Object[][] getBinaryValues()
  {
    // 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
    };
  }
      assertTrue(Arrays.equals(compareValue, ASN1OctetString
          .decodeAsOctetString(encodedElement).value()));
  /**
   * Tests the third constructor, which takes a byte array argument.
   *
   * @param  value  The value to use for the test.
   */
  @Test(dataProvider = "binaryValues")
  public void testConstructor3(byte[] value)
  {
    ASN1OctetString os = new ASN1OctetString(value);
    if (value == null)
    {
      assertEquals(new byte[0], os.value());
    }
    // Run tests with the string values.
    int numStrings = testStrings.size();
    for (int i = 0; i < numStrings; i++) {
      String s = testStrings.get(i);
      byte[] b = testEncodedStrings.get(i);
      String compareString;
      if (s == null) {
        compareString = "";
      } else {
        compareString = s;
      }
      byte[] encodedLength = ASN1Element.encodeLength(b.length);
      byte[] encodedElement = new byte[1 + encodedLength.length + b.length];
      encodedElement[0] = (byte) 0x00;
      System.arraycopy(encodedLength, 0, encodedElement, 1,
          encodedLength.length);
      System.arraycopy(b, 0, encodedElement, 1 + encodedLength.length,
          b.length);
      assertEquals(compareString, ASN1OctetString.decodeAsOctetString(
          encodedElement).stringValue());
    else
    {
      assertEquals(value, os.value());
    }
  }
  /**
   * Create strings to use for element values.
   *
   * @return  A list of strings that can be used as element values.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @DataProvider(name = "stringValues")
  public Object[][] getStringValues()
         throws Exception
  {
    return new Object[][]
    {
      new Object[] { null },
      new Object[] { "" },
      new Object[] { "\u0000" },
      new Object[] { "\t" },
      new Object[] { "\n" },
      new Object[] { "\r\n" },
      new Object[] { " " },
      new Object[] { "a" },
      new Object[] { "Test1\tTest2\tTest3" },
      new Object[] { "Test1\nTest2\nTest3" },
      new Object[] { "Test1\r\nTest2\r\nTest3" },
      new Object[] { "The Quick Brown Fox Jumps Over The Lazy Dog" },
      new Object[] { "\u00BFD\u00F3nde est\u00E1 el ba\u00F1o?" }
    };
  }
  /**
   * Tests the fourth constructor, which takes a string argument.
   *
   * @param  value  The value to use for the test.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "stringValues")
  public void testConstructor4(String value)
         throws Exception
  {
    ASN1OctetString os = new ASN1OctetString(value);
    if (value == null)
    {
      assertEquals("", os.stringValue());
      assertEquals(new byte[0], os.value());
    }
    else
    {
      assertEquals(value, os.stringValue());
      assertEquals(value.getBytes("UTF-8"), os.value());
    }
  }
  /**
   * Tests the fifth constructor, which takes byte and byte array arguments.
   *
   * @param  value  The value to use for the test.
   */
  @Test(dataProvider = "binaryValues")
  public void testConstructor5(byte[] value)
  {
    for (int i=0; i < 255; i++)
    {
      ASN1OctetString os = new ASN1OctetString((byte) (i & 0xFF), value);
      if (value == null)
      {
        assertEquals(new byte[0], os.value());
      }
      else
      {
        assertEquals(value, os.value());
      }
    }
  }
  /**
   * Tests the sixth constructor, which takes byte and string arguments.
   *
   * @param  value  The value to use for the test.
   */
  @Test(dataProvider = "stringValues")
  public void testConstructor6(String value)
  {
    for (int i=0; i < 255; i++)
    {
      ASN1OctetString os = new ASN1OctetString((byte) (i & 0xFF), value);
      if (value == null)
      {
        assertEquals("", os.stringValue());
      }
      else
      {
        assertEquals(value, os.stringValue());
      }
    }
  }
  /**
   * Tests the <CODE>stringValue</CODE> methods for the case in which the octet
   * string was created using a string representation.
   *
   * @param  value  The value to use for the test.
   */
  @Test(dataProvider = "stringValues")
  public void testStringValueFromStrings(String value)
  {
    ASN1OctetString os = new ASN1OctetString(value);
    if (value == null)
    {
      assertEquals("", os.stringValue());
    }
    else
    {
      assertEquals(value, os.stringValue());
    }
    os = new ASN1OctetString(value);
    StringBuilder valueBuffer = new StringBuilder();
    os.stringValue(valueBuffer);
    if (value == null)
    {
      assertEquals("", valueBuffer.toString());
    }
    else
    {
      assertEquals(value, valueBuffer.toString());
    }
  }
  /**
   * Tests the <CODE>stringValue</CODE> methods for the case in which the octet
   * string was created using a binary representation.
   *
   * @param  value  The value to use for the test.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "stringValues")
  public void testStringValueFromBytes(String value)
         throws Exception
  {
    byte[] valueBytes;
    if (value == null)
    {
      valueBytes = null;
    }
    else
    {
      valueBytes = value.getBytes("UTF-8");
    }
    ASN1OctetString os = new ASN1OctetString(valueBytes);
    if (value == null)
    {
      assertEquals("", os.stringValue());
    }
    else
    {
      assertEquals(value, os.stringValue());
    }
    os = new ASN1OctetString(valueBytes);
    StringBuilder valueBuffer = new StringBuilder();
    os.stringValue(valueBuffer);
    if (value == null)
    {
      assertEquals("", valueBuffer.toString());
    }
    else
    {
      assertEquals(value, valueBuffer.toString());
    }
  }
  /**
   * Tests the <CODE>setValue</CODE> method that takes a string argument.
   *
   * @param  value  The value to use for the test.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "stringValues")
  public void testSetStringValue(String value)
         throws Exception
  {
    ASN1OctetString os = new ASN1OctetString();
    os.setValue(value);
    if (value == null)
    {
      assertEquals("", os.stringValue());
      assertEquals(new byte[0], os.value());
    }
    else
    {
      assertEquals(value, os.stringValue());
      assertEquals(value.getBytes("UTF-8"), os.value());
    }
  }
  /**
   * Tests the <CODE>setValue</CODE> method that takes a byte array argument.
   *
   * @param  value  The value to use for the test.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "binaryValues")
  public void testSetBinaryValue(byte[] value)
         throws Exception
  {
    ASN1OctetString os = new ASN1OctetString();
    os.setValue(value);
    if (value == null)
    {
      assertEquals("", os.stringValue());
      assertEquals(new byte[0], os.value());
    }
    else
    {
      assertEquals(new String(value, "UTF-8"), os.stringValue());
      assertEquals(value, os.value());
    }
  }
  /**
   * Create ASN.1 elements to test decoding them as octet strings.
   *
   * @return  A list of ASN.1 elements that can be decoded as octet strings.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @DataProvider(name = "elements")
  public Object[][] getElements()
  {
    return new Object[][]
    {
      new Object[] { new ASN1OctetString() },
      new Object[] { new ASN1OctetString((byte) 0x50) },
      new Object[] { new ASN1OctetString(new byte[50]) },
      new Object[] { new ASN1OctetString("Hello") },
      new Object[] { new ASN1Element((byte) 0x50) },
      new Object[] { new ASN1Element((byte) 0x50, new byte[50]) },
      new Object[] { new ASN1Boolean(false) },
      new Object[] { new ASN1Boolean(true) },
      new Object[] { new ASN1Enumerated(0) },
      new Object[] { new ASN1Enumerated(1) },
      new Object[] { new ASN1Enumerated(127) },
      new Object[] { new ASN1Enumerated(128) },
      new Object[] { new ASN1Enumerated(255) },
      new Object[] { new ASN1Enumerated(256) },
      new Object[] { new ASN1Integer(0) },
      new Object[] { new ASN1Integer(1) },
      new Object[] { new ASN1Integer(127) },
      new Object[] { new ASN1Integer(128) },
      new Object[] { new ASN1Integer(255) },
      new Object[] { new ASN1Integer(256) },
      new Object[] { new ASN1Long(0) },
      new Object[] { new ASN1Long(1) },
      new Object[] { new ASN1Long(127) },
      new Object[] { new ASN1Long(128) },
      new Object[] { new ASN1Long(255) },
      new Object[] { new ASN1Long(256) },
      new Object[] { new ASN1Null() },
      new Object[] { new ASN1Sequence() },
      new Object[] { new ASN1Set() }
    };
  }
  /**
   * Test the <CODE>decodeAsOctetString</CODE> method that takes an ASN.1
   * element using valid elements.
   *
   * @param  element  The element to decode.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elements")
  public void testDecodeValidElementAsOctetString(ASN1Element element)
         throws Exception
  {
    ASN1OctetString.decodeAsOctetString(element);
  }
  /**
   * Test the <CODE>decodeAsOctetString</CODE> method that takes an ASN.1
   * element using a null element.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeNullElementAsOctetString()
         throws Exception
  {
    ASN1Element e = null;
    ASN1OctetString.decodeAsOctetString(e);
  }
  /**
   * Create byte arrays with encoded ASN.1 elements to test decoding them as
   * octet strings.
   *
   * @return  A list of byte arrays with encoded ASN.1 elements that can be
   *          decoded as octet strings.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @DataProvider(name = "elementArrays")
  public Object[][] getElementArrays()
  {
    return new Object[][]
    {
      new Object[] { new byte[] { 0x04, 0x00 } },
      new Object[] { new byte[] { (byte) 0x50, 0x00 } },
      new Object[] { new byte[] { 0x04, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F } },
      new Object[] { new byte[] { 0x01, 0x01, 0x00 } },
      new Object[] { new byte[] { 0x01, 0x01, (byte) 0xFF } },
      new Object[] { new byte[] { 0x0A, 0x01, 0x00 } },
      new Object[] { new byte[] { 0x0A, 0x01, 0x01 } },
      new Object[] { new byte[] { 0x0A, 0x01, 0x7F } },
      new Object[] { new byte[] { 0x0A, 0x01, (byte) 0x80 } },
      new Object[] { new byte[] { 0x0A, 0x01, (byte) 0xFF } },
      new Object[] { new byte[] { 0x0A, 0x02, 0x01, 0x00 } },
      new Object[] { new byte[] { 0x02, 0x01, 0x00 } },
      new Object[] { new byte[] { 0x02, 0x01, 0x01 } },
      new Object[] { new byte[] { 0x02, 0x01, 0x7F } },
      new Object[] { new byte[] { 0x02, 0x02, 0x00, (byte) 0x80 } },
      new Object[] { new byte[] { 0x02, 0x02, 0x00, (byte) 0xFF } },
      new Object[] { new byte[] { 0x02, 0x02, 0x01, 0x00 } },
      new Object[] { new byte[] { 0x05, 0x00 } },
      new Object[] { new byte[] { 0x30, 0x00 } },
      new Object[] { new byte[] { 0x31, 0x00 } },
      new Object[] { new byte[] { 0x05, (byte) 0x81, 0x00 } },
      new Object[] { new byte[] { 0x05, (byte) 0x82, 0x00, 0x00 } },
      new Object[] { new byte[] { 0x05, (byte) 0x83, 0x00, 0x00, 0x00 } },
      new Object[] { new byte[] { 0x05, (byte) 0x84, 0x00, 0x00, 0x00, 0x00 } },
    };
  }
  /**
   * Tests the <CODE>decodeAsOctetString</CODE> method that takes a byte array
   * using a valid array.
   *
   * @param  b  The byte array to decode.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elementArrays")
  public void testDecodeValidArrayAsOctetString(byte[] b)
         throws Exception
  {
    ASN1OctetString.decodeAsOctetString(b);
  }
  /**
   * Tests the <CODE>decodeAsOctetString</CODE> method that takes a byte array
   * using a null array.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions  = { ASN1Exception.class })
  public void testDecodeNullArrayAsOctetString()
         throws Exception
  {
    byte[] b = null;
    ASN1OctetString.decodeAsOctetString(b);
  }
  /**
   * Tests the <CODE>decodeAsOctetString</CODE> method that takes a byte array
   * using a short array.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions  = { ASN1Exception.class })
  public void testDecodeShortArrayAsOctetString()
         throws Exception
  {
    byte[] b = new byte[1];
    ASN1OctetString.decodeAsOctetString(b);
  }
  /**
   * Tests the <CODE>decodeAsOctetString</CODE> method that takes a byte array
   * using an array that indicates it takes more than four bytes to encode the
   * length.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions  = { ASN1Exception.class })
  public void testDecodeLongLengthArrayAsOctetString()
         throws Exception
  {
    byte[] b = { 0x04, (byte) 0x85, 0x00, 0x00, 0x00, 0x00, 0x00 };
    ASN1OctetString.decodeAsOctetString(b);
  }
  /**
   * Tests the <CODE>decodeAsOctetString</CODE> method that takes a byte array
   * using an array that doesn't fully contain the length.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions  = { ASN1Exception.class })
  public void testDecodeTruncatedLengthArrayAsOctetString()
         throws Exception
  {
    byte[] b = { 0x04, (byte) 0x82, 0x00 };
    ASN1OctetString.decodeAsOctetString(b);
  }
  /**
   * Tests the <CODE>decodeAsOctetString</CODE> method that takes a byte array
   * using an array whose actual length doesn't match with the decoded length.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions  = { ASN1Exception.class })
  public void testDecodeLengthMismatchArrayAsOctetString()
         throws Exception
  {
    byte[] b = { 0x04, 0x00, 0x00 };
    ASN1OctetString.decodeAsOctetString(b);
  }
  /**
   * Tests the <CODE>duplicate</CODE> method.
   *
   * @param  b  The byte array to decode as an octet string.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testDuplicate() {
    // Run tests with the binary values.
    for (byte[] value : testByteValues) {
      ASN1OctetString os1 = new ASN1OctetString(value);
      ASN1OctetString os2 = os1.duplicate();
      assertEquals(os1, os2);
  @Test(dataProvider = "elementArrays")
  public void testDuplicate(byte[] b)
         throws Exception
  {
    ASN1OctetString os1 = ASN1OctetString.decodeAsOctetString(b);
    ASN1OctetString os2 = os1.duplicate();
    assertTrue(os1.equals(os2));
    assertNotSame(os1, os2);
      assertEquals(os1.hashCode(), os2.hashCode());
    }
    os1.setValue(new byte[50]);
    assertFalse(os1.equals(os2));
  }
    // Run tests with the string values.
    int numStrings = testStrings.size();
    for (int i = 0; i < numStrings; i++) {
      String s = testStrings.get(i);
      String compareString;
      if (s == null) {
        compareString = "";
      } else {
        compareString = s;
      }
      ASN1OctetString os1 = new ASN1OctetString(s);
      ASN1OctetString os2 = os1.duplicate();
  /**
   * Tests the <CODE>toString</CODE> method that takes a string builder
   * argument.
   *
   * @param  b  The byte array to decode as an octet string.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elementArrays")
  public void testToString1(byte[] b)
         throws Exception
  {
    ASN1OctetString os = ASN1OctetString.decodeAsOctetString(b);
    os.toString(new StringBuilder());
  }
      assertEquals(os1, os2);
      assertEquals(compareString, os2.stringValue());
      assertEquals(os1.hashCode(), os2.hashCode());
    }
  /**
   * Tests the <CODE>toString</CODE> method that takes a string builder and
   * integer arguments.
   *
   * @param  b  The byte array to decode as an octet string.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elementArrays")
  public void testToString2(byte[] b)
         throws Exception
  {
    ASN1OctetString os = ASN1OctetString.decodeAsOctetString(b);
    os.toString(new StringBuilder(), 1);
  }
  /**
   * Tests the <CODE>toASN1OctetString</CODE> method.
   *
   * @param  b  The byte array to decode as an octet string.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elementArrays")
  public void testToASN1OctetString(byte[] b)
         throws Exception
  {
    ASN1OctetString os1 = ASN1OctetString.decodeAsOctetString(b);
    ASN1OctetString os2 = os1.toASN1OctetString();
    assertEquals(os1.value(), os2.value());
  }
}
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1ReaderAndWriter.java
@@ -26,305 +26,342 @@
 */
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.assertTrue;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.AfterClass;
import static org.testng.Assert.*;
/**
 * This class defines a set of tests for the
 * org.opends.server.protocols.asn1.ASN1Reader and
 * org.opends.server.protocols.asn1.ASN1Writer classes.
 */
public class TestASN1ReaderAndWriter extends ASN1TestCase {
  // The set of ASN.1 Boolean elements that will be written and read.
  private ArrayList<ASN1Boolean> booleanElements;
  // The set of ASN.1 enumerated elements that will be written and read.
  private ArrayList<ASN1Enumerated> enumeratedElements;
  // The set of generic ASN.1 elements that will be written and read.
  private ArrayList<ASN1Element> genericElements;
  // The set of ASN.1 integer elements that will be written and read.
  private ArrayList<ASN1Integer> integerElements;
  // The set of ASN.1 null elements that will be written and read.
  private ArrayList<ASN1Null> nullElements;
  // The set of ASN.1 octet string elements that will be written and
  // read.
  private ArrayList<ASN1OctetString> octetStringElements;
  // The set of ASN.1 sequence elements that will be written and read.
  private ArrayList<ASN1Sequence> sequenceElements;
  // The set of ASN.1 enumerated elements that will be written and read.
  private ArrayList<ASN1Set> setElements;
  // The data file to which data will be written and read back.
  private File dataFile;
public class TestASN1ReaderAndWriter
       extends ASN1TestCase
{
  /**
   * Performs any necessary initialization for this test case.
   * Create byte arrays with encoded ASN.1 elements to test decoding them as
   * octet strings.
   *
   * @throws Exception
   *           If a problem occurs during initialization.
   * @return  A list of byte arrays with encoded ASN.1 elements that can be
   *          decoded as octet strings.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @BeforeClass
  public void setUp() throws Exception {
    // Create the temporary file that we will write to and read from.
    dataFile = File.createTempFile("TestASN1ReaderAndWriter-", ".data");
    // Create the set of generic elements that will be written and read.
    genericElements = new ArrayList<ASN1Element>();
    genericElements.add(new ASN1Element((byte) 0x00));
    genericElements.add(new ASN1Element((byte) 0x00, null));
    genericElements.add(new ASN1Element((byte) 0x00, new byte[0]));
    genericElements.add(new ASN1Element((byte) 0x00, new byte[1]));
    genericElements.add(new ASN1Element((byte) 0x00, new byte[127]));
    genericElements.add(new ASN1Element((byte) 0x00, new byte[128]));
    genericElements.add(new ASN1Element((byte) 0x00, new byte[255]));
    genericElements.add(new ASN1Element((byte) 0x00, new byte[256]));
    genericElements.add(new ASN1Element((byte) 0x00, new byte[32767]));
    genericElements.add(new ASN1Element((byte) 0x00, new byte[32768]));
    genericElements.add(new ASN1Element((byte) 0x00, new byte[65535]));
    genericElements.add(new ASN1Element((byte) 0x00, new byte[65536]));
    // Create the set of Boolean elements that will be written and read.
    booleanElements = new ArrayList<ASN1Boolean>();
    booleanElements.add(new ASN1Boolean(false));
    booleanElements.add(new ASN1Boolean(true));
    booleanElements.add(new ASN1Boolean((byte) 0x00, false));
    booleanElements.add(new ASN1Boolean((byte) 0x00, true));
    // Create the set of enumerated elements that will be written and
    // read.
    enumeratedElements = new ArrayList<ASN1Enumerated>();
    enumeratedElements.add(new ASN1Enumerated(0));
    enumeratedElements.add(new ASN1Enumerated(1));
    enumeratedElements.add(new ASN1Enumerated(127));
    enumeratedElements.add(new ASN1Enumerated(128));
    enumeratedElements.add(new ASN1Enumerated(255));
    enumeratedElements.add(new ASN1Enumerated(256));
    enumeratedElements.add(new ASN1Enumerated(32767));
    enumeratedElements.add(new ASN1Enumerated(32768));
    enumeratedElements.add(new ASN1Enumerated(65535));
    enumeratedElements.add(new ASN1Enumerated(65536));
    // Create the set of integer elements that will be written and read.
    integerElements = new ArrayList<ASN1Integer>();
    integerElements.add(new ASN1Integer(0));
    integerElements.add(new ASN1Integer(1));
    integerElements.add(new ASN1Integer(127));
    integerElements.add(new ASN1Integer(128));
    integerElements.add(new ASN1Integer(255));
    integerElements.add(new ASN1Integer(256));
    integerElements.add(new ASN1Integer(32767));
    integerElements.add(new ASN1Integer(32768));
    integerElements.add(new ASN1Integer(65535));
    integerElements.add(new ASN1Integer(65536));
    // Create the set of null elements that will be written and read.
    nullElements = new ArrayList<ASN1Null>();
    nullElements.add(new ASN1Null());
    for (int i = 0; i < 256; i++) {
      byte type = (byte) (i & 0xFF);
      nullElements.add(new ASN1Null(type));
    }
    // Create the set of octet string elements that will be written and
    // read.
    octetStringElements = new ArrayList<ASN1OctetString>();
    octetStringElements.add(new ASN1OctetString());
    octetStringElements.add(new ASN1OctetString((byte[]) null));
    octetStringElements.add(new ASN1OctetString((String) null));
    octetStringElements.add(new ASN1OctetString(new byte[0]));
    octetStringElements.add(new ASN1OctetString(new byte[1]));
    octetStringElements.add(new ASN1OctetString(new byte[127]));
    octetStringElements.add(new ASN1OctetString(new byte[128]));
    octetStringElements.add(new ASN1OctetString(new byte[255]));
    octetStringElements.add(new ASN1OctetString(new byte[256]));
    octetStringElements.add(new ASN1OctetString(new byte[32767]));
    octetStringElements.add(new ASN1OctetString(new byte[32768]));
    octetStringElements.add(new ASN1OctetString(new byte[65535]));
    octetStringElements.add(new ASN1OctetString(new byte[65536]));
    octetStringElements.add(new ASN1OctetString(""));
    octetStringElements.add(new ASN1OctetString("a"));
    char[] chars127 = new char[127];
    Arrays.fill(chars127, 'a');
    octetStringElements.add(new ASN1OctetString(new String(chars127)));
    char[] chars128 = new char[128];
    Arrays.fill(chars128, 'a');
    octetStringElements.add(new ASN1OctetString(new String(chars128)));
    // Create the set of sequence elements that will be written and
    // read.
    sequenceElements = new ArrayList<ASN1Sequence>();
    sequenceElements.add(new ASN1Sequence());
    sequenceElements.add(new ASN1Sequence(null));
    sequenceElements.add(new ASN1Sequence(new ArrayList<ASN1Element>(0)));
    sequenceElements.add(new ASN1Sequence(genericElements));
    sequenceElements.add(new ASN1Sequence(new ArrayList<ASN1Element>(
        booleanElements)));
    sequenceElements.add(new ASN1Sequence(new ArrayList<ASN1Element>(
        enumeratedElements)));
    sequenceElements.add(new ASN1Sequence(new ArrayList<ASN1Element>(
        integerElements)));
    sequenceElements.add(new ASN1Sequence(new ArrayList<ASN1Element>(
        nullElements)));
    sequenceElements.add(new ASN1Sequence(new ArrayList<ASN1Element>(
        octetStringElements)));
    // Create the set of set elements that will be written and read.
    setElements = new ArrayList<ASN1Set>();
    setElements.add(new ASN1Set());
    setElements.add(new ASN1Set(null));
    setElements.add(new ASN1Set(new ArrayList<ASN1Element>(0)));
    setElements.add(new ASN1Set(genericElements));
    setElements
        .add(new ASN1Set(new ArrayList<ASN1Element>(booleanElements)));
    setElements.add(new ASN1Set(new ArrayList<ASN1Element>(
        enumeratedElements)));
    setElements
        .add(new ASN1Set(new ArrayList<ASN1Element>(integerElements)));
    setElements.add(new ASN1Set(new ArrayList<ASN1Element>(nullElements)));
    setElements.add(new ASN1Set(new ArrayList<ASN1Element>(
        octetStringElements)));
    setElements.add(new ASN1Set(
        new ArrayList<ASN1Element>(sequenceElements)));
  @DataProvider(name = "elementArrays")
  public Object[][] getElementArrays()
  {
    return new Object[][]
    {
      new Object[] { new byte[] { 0x04, 0x00 } },
      new Object[] { new byte[] { (byte) 0x50, 0x00 } },
      new Object[] { new byte[] { 0x04, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F } },
      new Object[] { new byte[] { 0x01, 0x01, 0x00 } },
      new Object[] { new byte[] { 0x01, 0x01, (byte) 0xFF } },
      new Object[] { new byte[] { 0x0A, 0x01, 0x00 } },
      new Object[] { new byte[] { 0x0A, 0x01, 0x01 } },
      new Object[] { new byte[] { 0x0A, 0x01, 0x7F } },
      new Object[] { new byte[] { 0x0A, 0x01, (byte) 0x80 } },
      new Object[] { new byte[] { 0x0A, 0x01, (byte) 0xFF } },
      new Object[] { new byte[] { 0x0A, 0x02, 0x01, 0x00 } },
      new Object[] { new byte[] { 0x02, 0x01, 0x00 } },
      new Object[] { new byte[] { 0x02, 0x01, 0x01 } },
      new Object[] { new byte[] { 0x02, 0x01, 0x7F } },
      new Object[] { new byte[] { 0x02, 0x02, 0x00, (byte) 0x80 } },
      new Object[] { new byte[] { 0x02, 0x02, 0x00, (byte) 0xFF } },
      new Object[] { new byte[] { 0x02, 0x02, 0x01, 0x00 } },
      new Object[] { new byte[] { 0x05, 0x00 } },
      new Object[] { new byte[] { 0x30, 0x00 } },
      new Object[] { new byte[] { 0x31, 0x00 } },
    };
  }
  /**
   * Performs any necessary cleanup for this test case.
   * Tests writing elements to an output stream.
   *
   * @throws Exception
   *           If a problem occurs during cleanup.
   * @param  elementBytes  The byte array that makes up an encoded element.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @AfterClass
  public void tearDown() throws Exception {
    // Delete the temporary data file.
    dataFile.delete();
  @Test(dataProvider = "elementArrays")
  public void testWriteToStream(byte[] elementBytes)
         throws Exception
  {
    ASN1Element e = ASN1Element.decode(elementBytes);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ASN1Writer writer = new ASN1Writer(baos);
    writer.writeElement(e);
    assertEquals(elementBytes, baos.toByteArray());
    writer.close();
  }
  /**
   * Tests the <CODE>ASN1Writer.writeElement</CODE> and the
   * <CODE>ASN1Reader.readElement</CODE> methods.
   * Tests writing elements to a socket.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @param  elementBytes  The byte array that makes up an encoded element.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testWriteAndRead() throws Exception {
    // Create the ASN.1 writer that will be used to write the elements.
    ASN1Writer asn1Writer;
    asn1Writer = new ASN1Writer(new FileOutputStream(dataFile, false));
  @Test(dataProvider = "elementArrays")
  public void testWriteToSocket(byte[] elementBytes)
         throws Exception
  {
    ASN1Element e = ASN1Element.decode(elementBytes);
    // Write the set of generic elements.
    for (ASN1Element element : genericElements) {
      asn1Writer.writeElement(element);
    SocketReadThread readThread = new SocketReadThread("testWriteToSocket");
    readThread.start();
    Socket s = new Socket("127.0.0.1", readThread.getListenPort());
    ASN1Writer writer = new ASN1Writer(s);
    int bytesWritten = writer.writeElement(e);
    assertEquals(elementBytes, readThread.getDataRead(bytesWritten));
    writer.close();
    readThread.close();
  }
  /**
   * Tests reading elements from an input stream.
   *
   * @param  elementBytes  The byte array that makes up an encoded element.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elementArrays")
  public void testReadFromStream(byte[] elementBytes)
         throws Exception
  {
    ByteArrayInputStream bais = new ByteArrayInputStream(elementBytes);
    ASN1Reader reader = new ASN1Reader(bais);
    reader.setIOTimeout(30000);
    assertEquals(-1, reader.getIOTimeout());
    ASN1Element e = reader.readElement();
    assertEquals(elementBytes, e.encode());
    assertEquals(e, ASN1Element.decode(elementBytes));
    assertNull(reader.readElement());
    reader.close();
  }
  /**
   * Tests reading elements from a socket.
   *
   * @param  elementBytes  The byte array that makes up an encoded element.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elementArrays")
  public void testReadFromSocket(byte[] elementBytes)
         throws Exception
  {
    SocketWriteThread writeThread  = null;
    Socket            socket       = null;
    ServerSocket      serverSocket = null;
    try
    {
      ASN1Element element = ASN1Element.decode(elementBytes);
      serverSocket = new ServerSocket();
      serverSocket.setReuseAddress(true);
      serverSocket.bind(new InetSocketAddress("127.0.0.1", 0));
      writeThread = new SocketWriteThread("testReadFromSocket",
                                          serverSocket.getLocalPort(),
                                          elementBytes);
      writeThread.start();
      socket = serverSocket.accept();
      ASN1Reader reader = new ASN1Reader(socket);
      reader.setIOTimeout(30000);
      assertEquals(30000, reader.getIOTimeout());
      ASN1Element element2 = reader.readElement();
      assertEquals(element, element2);
      assertEquals(elementBytes, element2.encode());
    }
    finally
    {
      try
      {
        writeThread.close();
      } catch (Exception e) {}
    // Write the set of Boolean elements.
    for (ASN1Boolean element : booleanElements) {
      asn1Writer.writeElement(element);
      try
      {
        socket.close();
      } catch (Exception e) {}
      try
      {
        serverSocket.close();
      } catch (Exception e) {}
    }
  }
    // Write the set of enumerated elements.
    for (ASN1Enumerated element : enumeratedElements) {
      asn1Writer.writeElement(element);
  /**
   * Tests reading elements from an input stream with all elements falling below
   * the maximum element size.
   *
   * @param  elementBytes  The byte array that makes up an encoded element.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elementArrays")
  public void testReadSuccessWithMaxElementSize(byte[] elementBytes)
         throws Exception
  {
    ByteArrayInputStream bais = new ByteArrayInputStream(elementBytes);
    ASN1Reader reader = new ASN1Reader(bais);
    reader.setMaxElementSize(elementBytes.length);
    assertEquals(elementBytes.length, reader.getMaxElementSize());
    ASN1Element e = reader.readElement();
    assertEquals(elementBytes, e.encode());
    assertEquals(e, ASN1Element.decode(elementBytes));
    assertNull(reader.readElement());
    reader.close();
  }
  /**
   * Tests reading elements from an input stream with all elements falling above
   * the maximum element size.
   *
   * @param  elementBytes  The byte array that makes up an encoded element.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elementArrays",
        expectedExceptions = { ASN1Exception.class, IOException.class })
  public void testReadFailureWithMaxElementSize(byte[] elementBytes)
         throws Exception
  {
    ByteArrayInputStream bais = new ByteArrayInputStream(elementBytes);
    ASN1Reader reader = new ASN1Reader(bais);
    reader.setMaxElementSize(1);
    assertEquals(1, reader.getMaxElementSize());
    try
    {
      ASN1Element e = reader.readElement();
      if (e.value().length <= 1)
      {
        throw new ASN1Exception(-1, "Too small to trip the max element size");
      }
    }
    // Write the set of integer elements.
    for (ASN1Integer element : integerElements) {
      asn1Writer.writeElement(element);
    finally
    {
      reader.close();
    }
  }
    // Write the set of null elements.
    for (ASN1Null element : nullElements) {
      asn1Writer.writeElement(element);
  /**
   * Tests to ensure that attempting to read an element with a length encoded in
   * too many bytes will fail.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class, IOException.class })
  public void testReadFailureLongLength()
         throws Exception
  {
    byte[] elementBytes = { 0x04, (byte) 0x85, 0x00, 0x00, 0x00, 0x00, 0x00 };
    ByteArrayInputStream bais = new ByteArrayInputStream(elementBytes);
    ASN1Reader reader = new ASN1Reader(bais);
    try
    {
      ASN1Element e = reader.readElement();
    }
    // Write the set of octet string elements.
    for (ASN1OctetString element : octetStringElements) {
      asn1Writer.writeElement(element);
    finally
    {
      reader.close();
    }
  }
    // Write the set of sequence elements.
    for (ASN1Sequence element : sequenceElements) {
      asn1Writer.writeElement(element);
  /**
   * Tests to ensure that attempting to read an element with a truncated length
   * will fail.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class, IOException.class })
  public void testReadFailureTruncatedLength()
         throws Exception
  {
    byte[] elementBytes = { 0x04, (byte) 0x82, 0x00 };
    ByteArrayInputStream bais = new ByteArrayInputStream(elementBytes);
    ASN1Reader reader = new ASN1Reader(bais);
    try
    {
      ASN1Element e = reader.readElement();
    }
    // Write the set of set elements.
    for (ASN1Set element : setElements) {
      asn1Writer.writeElement(element);
    finally
    {
      reader.close();
    }
  }
    // Always remember to close the output file.
    asn1Writer.close();
    // Create the ASN.1 reader that will be used to read the elements
    // back.
    ASN1Reader asn1Reader;
    asn1Reader = new ASN1Reader(new FileInputStream(dataFile));
    // Read back the set of generic elements.
    for (ASN1Element element : genericElements) {
      assertEquals(element, asn1Reader.readElement());
  /**
   * Tests to ensure that attempting to read an element with a truncated value
   * will fail.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class, IOException.class })
  public void testReadFailureTruncatedValue()
         throws Exception
  {
    byte[] elementBytes = { 0x04, 0x02, 0x00 };
    ByteArrayInputStream bais = new ByteArrayInputStream(elementBytes);
    ASN1Reader reader = new ASN1Reader(bais);
    try
    {
      ASN1Element e = reader.readElement();
    }
    // Read back the set of Boolean elements.
    for (ASN1Boolean element : booleanElements) {
      assertEquals(element.booleanValue(), asn1Reader.readElement()
          .decodeAsBoolean().booleanValue());
    finally
    {
      reader.close();
    }
    // Read back the set of enumerated elements.
    for (ASN1Enumerated element : enumeratedElements) {
      assertEquals(element.intValue(), asn1Reader.readElement()
          .decodeAsEnumerated().intValue());
    }
    // Read back the set of integer elements.
    for (ASN1Integer element : integerElements) {
      assertEquals(element.intValue(), asn1Reader.readElement()
          .decodeAsInteger().intValue());
    }
    // Read back the set of null elements.
    for (ASN1Null element : nullElements) {
      assertEquals(element, asn1Reader.readElement().decodeAsNull());
    }
    // Read back the set of octet string elements.
    for (ASN1OctetString element : octetStringElements) {
      assertEquals(element, asn1Reader.readElement().decodeAsOctetString());
    }
    // Read back the set of sequence elements.
    for (ASN1Sequence element : sequenceElements) {
      assertTrue(listsAreEqual(element.elements(), asn1Reader.readElement()
          .decodeAsSequence().elements()));
    }
    // Read back the set of set elements.
    for (ASN1Set element : setElements) {
      assertTrue(listsAreEqual(element.elements(), asn1Reader.readElement()
          .decodeAsSet().elements()));
    }
    // Always remember to close the input file.
    asn1Reader.close();
  }
}
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Sequence.java
@@ -26,237 +26,613 @@
 */
package org.opends.server.protocols.asn1;
import static org.opends.server.util.StaticUtils.listsAreEqual;
import static org.testng.AssertJUnit.assertTrue;
import java.util.ArrayList;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeMethod;
import static org.testng.Assert.*;
/**
 * This class defines a set of tests for the
 * org.opends.server.protocols.asn1.ASN1Sequence class.
 */
public class TestASN1Sequence extends ASN1TestCase {
  // The sets of pre-encoded ASN.1 elements that will be included in the
  // test
  // case.
  private ArrayList<ArrayList<ASN1Element>> testElementSets;
public class TestASN1Sequence
       extends ASN1TestCase
{
  // The array of element arrays to use for the testing.  Each element is a
  // single-element array containing a byte[] with the encoded elements.
  private Object[][] elementArrays;
  // The set of pre-encoded element sets that will be used in the test
  // cases.
  private ArrayList<byte[]> testEncodedElementSets;
  // The array of elements to use for the testing.  Each element is a
  // single-element array containing an ArrayList<ASN1Element>.
  private Object[][] elementLists;
  /**
   * Performs any necessary initialization for this test case.
   * Constructs the element lists that will be used to perform the testing.
   */
  @BeforeMethod
  public void setUp() {
    // 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[]>();
  @BeforeClass()
  public void populateElementLists()
  {
    ArrayList<ArrayList<ASN1Element>> lists =
         new ArrayList<ArrayList<ASN1Element>>();
    testElementSets.add(null); // The null set.
    testEncodedElementSets.add(new byte[0]);
    // Add a null element.
    lists.add(null);
    testElementSets.add(new ArrayList<ASN1Element>(0)); // The empty
    // set.
    testEncodedElementSets.add(new byte[0]);
    // Add an empty list.
    lists.add(new ArrayList<ASN1Element>());
    // Sets containing from 1 to 10 zero-length elements.
    for (int i = 1; i <= 10; i++) {
      ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(i);
    // Create an array of single elements, and add each of them in their own
    // lists.
    ASN1Element[] elementArray =
    {
      new ASN1OctetString(),
      new ASN1OctetString((byte) 0x50),
      new ASN1OctetString(new byte[50]),
      new ASN1OctetString("Hello"),
      new ASN1Element((byte) 0x50),
      new ASN1Element((byte) 0x50, new byte[50]),
      new ASN1Boolean(false),
      new ASN1Boolean(true),
      new ASN1Enumerated(0),
      new ASN1Enumerated(1),
      new ASN1Enumerated(127),
      new ASN1Enumerated(128),
      new ASN1Enumerated(255),
      new ASN1Enumerated(256),
      new ASN1Integer(0),
      new ASN1Integer(1),
      new ASN1Integer(127),
      new ASN1Integer(128),
      new ASN1Integer(255),
      new ASN1Integer(256),
      new ASN1Long(0),
      new ASN1Long(1),
      new ASN1Long(127),
      new ASN1Long(128),
      new ASN1Long(255),
      new ASN1Long(256),
      new ASN1Null(),
      new ASN1Sequence(),
      new ASN1Set()
    };
      for (int j = 0; j < i; j++) {
        elements.add(new ASN1Element((byte) 0x00));
      }
      testElementSets.add(elements);
      testEncodedElementSets.add(new byte[i * 2]);
    // Add lists of single elements.
    for (ASN1Element e : elementArray)
    {
      ArrayList<ASN1Element> list = new ArrayList<ASN1Element>(1);
      list.add(e);
      lists.add(list);
    }
    // Sets containing from 1 to 10 1-byte-length elements.
    for (int i = 1; i <= 10; i++) {
      ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(i);
      byte[] encodedElements = new byte[i * 3];
      for (int j = 0; j < i; j++) {
        elements.add(new ASN1Element((byte) 0x00, new byte[1]));
        encodedElements[(j * 3) + 1] = (byte) 0x01;
    // Create multi-element lists based on the single-element lists.
    for (int i=0; i < elementArray.length; i++)
    {
      ArrayList<ASN1Element> list = new ArrayList<ASN1Element>(i+1);
      for (int j=0; j <=i; j++)
      {
        list.add(elementArray[j]);
      }
      testElementSets.add(elements);
      testEncodedElementSets.add(encodedElements);
      lists.add(list);
    }
    // Sets containing from 1 to 10 127-byte-length elements.
    for (int i = 1; i <= 10; i++) {
      ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(i);
      byte[] encodedElements = new byte[i * 129];
      for (int j = 0; j < i; j++) {
        elements.add(new ASN1Element((byte) 0x00, new byte[127]));
        encodedElements[(j * 129) + 1] = (byte) 0x7F;
      }
      testElementSets.add(elements);
      testEncodedElementSets.add(encodedElements);
    // Convert the lists into object arrays.
    elementLists = new Object[lists.size()][1];
    for (int i=0; i < elementLists.length; i++)
    {
      elementLists[i] = new Object[] { lists.get(i) };
    }
    // Sets containing from 1 to 10 128-byte-length elements.
    for (int i = 1; i <= 10; i++) {
      ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(i);
      byte[] encodedElements = new byte[i * 131];
      for (int j = 0; j < i; j++) {
        elements.add(new ASN1Element((byte) 0x00, new byte[128]));
        encodedElements[(j * 131) + 1] = (byte) 0x81;
        encodedElements[(j * 131) + 2] = (byte) 0x80;
      }
      testElementSets.add(elements);
      testEncodedElementSets.add(encodedElements);
    lists.remove(null);
    elementArrays = new Object[lists.size()][1];
    for (int i=0; i < elementArrays.length; i++)
    {
      elementArrays[i] = new Object[] { ASN1Element.encodeValue(lists.get(i)) };
    }
  }
  /**
   * Retrieves lists of byte arrays that can be used to construct sequences.
   *
   * @return  Lists of byte arrays that can be used to construct sequences.
   */
  @DataProvider(name = "elementArrays")
  public Object[][] getElementArrays()
  {
    return elementArrays;
  }
  /**
   * Retrieves lists of ASN.1 elements that can be used to construct sequences.
   *
   * @return  Lists of ASN.1 elements that can be used to construct sequences.
   */
  @DataProvider(name = "elementLists")
  public Object[][] getElementLists()
  {
    return elementLists;
  }
  /**
   * Tests the first constructor, which doesn't take any arguments.
   */
  @Test()
  public void testConstructor1()
  {
    new ASN1Sequence();
  }
  /**
   * Create the values that can be used for testing BER types.
   *
   * @return  The values that can be used for testing BER types.
   */
  @DataProvider(name = "types")
  public Object[][] getTypes()
  {
    // 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) };
    }
    return testTypes;
  }
  /**
   * Tests the second constructor, which takes a byte argument.
   *
   * @param  b  The BER type to use for the sequence.
   */
  @Test(dataProvider = "types")
  public void testConstructor2(byte b)
  {
    new ASN1Sequence(b);
  }
  /**
   * Tests the third constructor, which takes a list of elements.
   *
   * @param  elements  The list of elements to use to create the sequence.
   */
  @Test(dataProvider = "elementLists")
  public void testConstructor3(ArrayList<ASN1Element> elements)
  {
    new ASN1Sequence(elements);
  }
  /**
   * Tests the third constructor, which takes a byte and a list of elements.
   *
   * @param  elements  The list of elements to use to create the sequence.
   */
  @Test(dataProvider = "elementLists")
  public void testConstructor4(ArrayList<ASN1Element> elements)
  {
    for (int i=0; i < 255; i++)
    {
      new ASN1Sequence((byte) (i & 0xFF), elements);
    }
  }
  /**
   * Tests the <CODE>elements</CODE> method.
   *
   * @param  elements  The list of elements to use to create the sequence.
   */
  @Test()
  public void testElements() {
    int numElementSets = testElementSets.size();
    for (int i = 0; i < numElementSets; i++) {
      ArrayList<ASN1Element> elementSet = testElementSets.get(i);
      ArrayList<ASN1Element> compareList;
      if (elementSet == null) {
        compareList = new ArrayList<ASN1Element>(0);
      } else {
        compareList = elementSet;
      }
      ASN1Sequence element = new ASN1Sequence(elementSet);
      assertTrue(listsAreEqual(compareList, element.elements()));
  @Test(dataProvider = "elementLists")
  public void testGetElements(ArrayList<ASN1Element> elements)
  {
    ASN1Sequence s = new ASN1Sequence(elements);
    if (elements == null)
    {
      assertEquals(new ArrayList<ASN1Element>(), s.elements());
    }
    else
    {
      assertEquals(elements, s.elements());
    }
  }
  /**
   * Tests the <CODE>setElements</CODE> method.
   *
   * @param  elements  The list of elements to use to create the sequence.
   */
  @Test()
  public void testSetElements() {
    ASN1Sequence element = new ASN1Sequence();
    int numElementSets = testElementSets.size();
    for (int i = 0; i < numElementSets; i++) {
      ArrayList<ASN1Element> elementSet = testElementSets.get(i);
      ArrayList<ASN1Element> compareList;
      if (elementSet == null) {
        compareList = new ArrayList<ASN1Element>(0);
      } else {
        compareList = elementSet;
      }
      element.setElements(elementSet);
      assertTrue(listsAreEqual(compareList, element.elements()));
  @Test(dataProvider = "elementLists")
  public void testSetElements(ArrayList<ASN1Element> elements)
  {
    ASN1Sequence s = new ASN1Sequence();
    s.setElements(elements);
    if (elements == null)
    {
      assertEquals(new ArrayList<ASN1Element>(), s.elements());
    }
    else
    {
      assertEquals(elements, s.elements());
    }
  }
  /**
   * Tests the <CODE>setValue</CODE> method.
   * Tests the <CODE>setValue</CODE> method with valid values.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @param  encodedElements  The byte array containing the encoded elements to
   *                          use in the value.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testSetValue() throws Exception {
    ASN1Sequence element = new ASN1Sequence();
  @Test(dataProvider = "elementArrays")
  public void testSetValueValid(byte[] encodedElements)
         throws Exception
  {
    ASN1Sequence s = new ASN1Sequence();
    s.setValue(encodedElements);
  }
    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;
      }
      element.setValue(encodedElementSet);
  /**
   * Tests the <CODE>setValue</CODE> method with a null array.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testSetValueNull()
         throws Exception
  {
    ASN1Sequence s = new ASN1Sequence();
    s.setValue(null);
  }
      assertTrue(listsAreEqual(compareList, element.elements()));
  /**
   * Retrieves a set of byte arrays containing invalid element value encodings.
   *
   * @return  A set of byte arrays containing invalid element value encodings.
   */
  @DataProvider(name = "invalidElementArrays")
  public Object[][] getInvalidArrays()
  {
    return new Object[][]
    {
      new Object[] { new byte[] { 0x05 } },
      new Object[] { new byte[] { 0x05, 0x01 } },
      new Object[] { new byte[] { 0x05, (byte) 0x85, 0x00, 0x00, 0x00, 0x00,
                                  0x00 } },
      new Object[] { new byte[] { 0x05, (byte) 0x82, 0x00 } },
      new Object[] { new byte[] { 0x05, 0x00, 0x05 } },
      new Object[] { new byte[] { 0x05, 0x00, 0x05, 0x01 } },
    };
  }
  /**
   * Tests the <CODE>setValue</CODE> method with valid values.
   *
   * @param  encodedElements  The byte array containing the encoded elements to
   *                          use in the value.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "invalidElementArrays",
        expectedExceptions = { ASN1Exception.class })
  public void testSetValueInvalid(byte[] invalidElements)
         throws Exception
  {
    ASN1Sequence s = new ASN1Sequence();
    s.setValue(invalidElements);
  }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes an ASN1Element
   * argument with valid elements.
   *
   * @param  encodedElements  Byte arrays that may be used as valid values for
   *                          encoded elements.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elementArrays")
  public void testDecodeValidElementAsSequence(byte[] encodedElements)
         throws Exception
  {
    ASN1Element e = new ASN1Element(ASN1Constants.UNIVERSAL_SEQUENCE_TYPE,
                                    encodedElements);
    ASN1Sequence.decodeAsSequence(e);
  }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes an ASN1Element
   * argument with valid elements.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeNullElementAsSequence()
         throws Exception
  {
    ASN1Element e = null;
    ASN1Sequence.decodeAsSequence(e);
  }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
   * argument with valid arrays.
   *
   * @param  encodedElements  Byte arrays that may be used as valid values for
   *                          encoded elements.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elementArrays")
  public void testDecodeValidArrayAsSequence(byte[] encodedElements)
         throws Exception
  {
    byte[] encodedLength = ASN1Element.encodeLength(encodedElements.length);
    byte[] elementBytes  =
         new byte[1 + encodedLength.length + encodedElements.length];
    elementBytes[0] = ASN1Constants.UNIVERSAL_SEQUENCE_TYPE;
    System.arraycopy(encodedLength, 0, elementBytes, 1, encodedLength.length);
    System.arraycopy(encodedElements, 0, elementBytes, 1+encodedLength.length,
                     encodedElements.length);
    ASN1Sequence.decodeAsSequence(elementBytes);
  }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
   * argument with a null array.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeNullArrayAsSequence()
         throws Exception
  {
    byte[] b = null;
    ASN1Sequence.decodeAsSequence(b);
  }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
   * argument with a short array.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeShortArrayAsSequence()
         throws Exception
  {
    byte[] b = new byte[1];
    ASN1Sequence.decodeAsSequence(b);
  }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
   * argument with an array that takes too many bytes to encode the length.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeLongLengthArrayAsSequence()
         throws Exception
  {
    byte[] b = { 0x30, (byte) 0x85, 0x00, 0x00, 0x00, 0x00, 0x00 };
    ASN1Sequence.decodeAsSequence(b);
  }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
   * argument with an array that doesn't fully describe the length.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeTruncatedLengthArrayAsSequence()
         throws Exception
  {
    byte[] b = { 0x30, (byte) 0x82, 0x00 };
    ASN1Sequence.decodeAsSequence(b);
  }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
   * argument with an array whose decoded length doesn't match the real length.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeLengthMismatchArrayAsSequence()
         throws Exception
  {
    byte[] b = { 0x30, 0x01 };
    ASN1Sequence.decodeAsSequence(b);
  }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
   * argument with valid arrays.
   *
   * @param  encodedElements  Byte arrays that may be used as valid values for
   *                          encoded elements.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elementArrays")
  public void testDecodeTypeAndValidArrayAsSequence(byte[] encodedElements)
         throws Exception
  {
    for (int i=0; i < 255; i++)
    {
      byte[] encodedLength = ASN1Element.encodeLength(encodedElements.length);
      byte[] elementBytes  =
           new byte[1 + encodedLength.length + encodedElements.length];
      elementBytes[0] = ASN1Constants.UNIVERSAL_SEQUENCE_TYPE;
      System.arraycopy(encodedLength, 0, elementBytes, 1, encodedLength.length);
      System.arraycopy(encodedElements, 0, elementBytes, 1+encodedLength.length,
                       encodedElements.length);
      ASN1Sequence.decodeAsSequence((byte) (i & 0xFF), elementBytes);
    }
  }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes an
   * ASN.1 element argument.
   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
   * argument with a null array.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testDecodeElementAsSequence() 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;
      }
      ASN1Element element = new ASN1Element((byte) 0x00, encodedElementSet);
      assertTrue(listsAreEqual(compareList, ASN1Sequence.decodeAsSequence(
          element).elements()));
    }
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeTypeAndNullArrayAsSequence()
         throws Exception
  {
    byte[] b = null;
    ASN1Sequence.decodeAsSequence((byte) 0x50, b);
  }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte
   * array argument.
   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
   * argument with a short array.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testDecodeBytesAsSequence() 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(expectedExceptions = { ASN1Exception.class })
  public void testDecodeTypeAndShortArrayAsSequence()
         throws Exception
  {
    byte[] b = new byte[1];
    ASN1Sequence.decodeAsSequence((byte) 0x50, b);
  }
      ArrayList<ASN1Element> compareList;
      if (elementSet == null) {
        compareList = new ArrayList<ASN1Element>(0);
      } else {
        compareList = elementSet;
      }
      byte[] encodedLength = ASN1Element
          .encodeLength(encodedElementSet.length);
      byte[] encodedElement = new byte[1 + encodedLength.length
          + encodedElementSet.length];
      encodedElement[0] = 0x00;
      System.arraycopy(encodedLength, 0, encodedElement, 1,
          encodedLength.length);
      System.arraycopy(encodedElementSet, 0, encodedElement,
          1 + encodedLength.length, encodedElementSet.length);
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
   * argument with an array that takes too many bytes to encode the length.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeTypeAndLongLengthArrayAsSequence()
         throws Exception
  {
    byte[] b = { 0x30, (byte) 0x85, 0x00, 0x00, 0x00, 0x00, 0x00 };
    ASN1Sequence.decodeAsSequence((byte) 0x50, b);
  }
      assertTrue(listsAreEqual(compareList, ASN1Sequence.decodeAsSequence(
          encodedElement).elements()));
    }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
   * argument with an array that doesn't fully describe the length.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeTypeAndTruncatedLengthArrayAsSequence()
         throws Exception
  {
    byte[] b = { 0x30, (byte) 0x82, 0x00 };
    ASN1Sequence.decodeAsSequence((byte) 0x50, b);
  }
  /**
   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
   * argument with an array whose decoded length doesn't match the real length.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeTypeAndLengthMismatchArrayAsSequence()
         throws Exception
  {
    byte[] b = { 0x30, 0x01 };
    ASN1Sequence.decodeAsSequence((byte) 0x50, b);
  }
  /**
   * Tests the <CODE>toString</CODE> method that takes a string builder
   * argument.
   *
   * @param  elements  The list of elements to use to create the sequence.
   */
  @Test(dataProvider = "elementLists")
  public void testToString1(ArrayList<ASN1Element> elements)
  {
    new ASN1Sequence(elements).toString(new StringBuilder());
  }
  /**
   * Tests the <CODE>toString</CODE> method that takes string builder and
   * integer arguments.
   *
   * @param  elements  The list of elements to use to create the sequence.
   */
  @Test(dataProvider = "elementLists")
  public void testToString2(ArrayList<ASN1Element> elements)
  {
    new ASN1Sequence(elements).toString(new StringBuilder(), 1);
  }
}
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Set.java
@@ -26,237 +26,505 @@
 */
package org.opends.server.protocols.asn1;
import static org.opends.server.util.StaticUtils.listsAreEqual;
import static org.testng.AssertJUnit.assertTrue;
import java.util.ArrayList;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
/**
 * This class defines a set of tests for the
 * org.opends.server.protocols.asn1.ASN1Set class.
 */
public class TestASN1Set extends ASN1TestCase {
  // The sets of pre-encoded ASN.1 elements that will be included in the
  // test
  // case.
  private ArrayList<ArrayList<ASN1Element>> testElementSets;
public class TestASN1Set
       extends ASN1TestCase
{
  // The array of element arrays to use for the testing.  Each element is a
  // single-element array containing a byte[] with the encoded elements.
  private Object[][] elementArrays;
  // The set of pre-encoded element sets that will be used in the test
  // cases.
  private ArrayList<byte[]> testEncodedElementSets;
  // The array of elements to use for the testing.  Each element is a
  // single-element array containing an ArrayList<ASN1Element>.
  private Object[][] elementLists;
  /**
   * Performs any necessary initialization for this test case.
   * Constructs the element lists that will be used to perform the testing.
   */
  @BeforeClass
  public void setUp() {
    // 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[]>();
  @BeforeClass()
  public void populateElementLists()
  {
    ArrayList<ArrayList<ASN1Element>> lists =
         new ArrayList<ArrayList<ASN1Element>>();
    testElementSets.add(null); // The null set.
    testEncodedElementSets.add(new byte[0]);
    // Add a null element.
    lists.add(null);
    testElementSets.add(new ArrayList<ASN1Element>(0)); // The empty
    // set.
    testEncodedElementSets.add(new byte[0]);
    // Add an empty list.
    lists.add(new ArrayList<ASN1Element>());
    // Sets containing from 1 to 10 zero-length elements.
    for (int i = 1; i <= 10; i++) {
      ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(i);
    // Create an array of single elements, and add each of them in their own
    // lists.
    ASN1Element[] elementArray =
    {
      new ASN1OctetString(),
      new ASN1OctetString((byte) 0x50),
      new ASN1OctetString(new byte[50]),
      new ASN1OctetString("Hello"),
      new ASN1Element((byte) 0x50),
      new ASN1Element((byte) 0x50, new byte[50]),
      new ASN1Boolean(false),
      new ASN1Boolean(true),
      new ASN1Enumerated(0),
      new ASN1Enumerated(1),
      new ASN1Enumerated(127),
      new ASN1Enumerated(128),
      new ASN1Enumerated(255),
      new ASN1Enumerated(256),
      new ASN1Integer(0),
      new ASN1Integer(1),
      new ASN1Integer(127),
      new ASN1Integer(128),
      new ASN1Integer(255),
      new ASN1Integer(256),
      new ASN1Long(0),
      new ASN1Long(1),
      new ASN1Long(127),
      new ASN1Long(128),
      new ASN1Long(255),
      new ASN1Long(256),
      new ASN1Null(),
      new ASN1Sequence(),
      new ASN1Set()
    };
      for (int j = 0; j < i; j++) {
        elements.add(new ASN1Element((byte) 0x00));
      }
      testElementSets.add(elements);
      testEncodedElementSets.add(new byte[i * 2]);
    // Add lists of single elements.
    for (ASN1Element e : elementArray)
    {
      ArrayList<ASN1Element> list = new ArrayList<ASN1Element>(1);
      list.add(e);
      lists.add(list);
    }
    // Sets containing from 1 to 10 1-byte-length elements.
    for (int i = 1; i <= 10; i++) {
      ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(i);
      byte[] encodedElements = new byte[i * 3];
      for (int j = 0; j < i; j++) {
        elements.add(new ASN1Element((byte) 0x00, new byte[1]));
        encodedElements[(j * 3) + 1] = (byte) 0x01;
    // Create multi-element lists based on the single-element lists.
    for (int i=0; i < elementArray.length; i++)
    {
      ArrayList<ASN1Element> list = new ArrayList<ASN1Element>(i+1);
      for (int j=0; j <=i; j++)
      {
        list.add(elementArray[j]);
      }
      testElementSets.add(elements);
      testEncodedElementSets.add(encodedElements);
      lists.add(list);
    }
    // Sets containing from 1 to 10 127-byte-length elements.
    for (int i = 1; i <= 10; i++) {
      ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(i);
      byte[] encodedElements = new byte[i * 129];
      for (int j = 0; j < i; j++) {
        elements.add(new ASN1Element((byte) 0x00, new byte[127]));
        encodedElements[(j * 129) + 1] = (byte) 0x7F;
      }
      testElementSets.add(elements);
      testEncodedElementSets.add(encodedElements);
    // Convert the lists into object arrays.
    elementLists = new Object[lists.size()][1];
    for (int i=0; i < elementLists.length; i++)
    {
      elementLists[i] = new Object[] { lists.get(i) };
    }
    // Sets containing from 1 to 10 128-byte-length elements.
    for (int i = 1; i <= 10; i++) {
      ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(i);
      byte[] encodedElements = new byte[i * 131];
      for (int j = 0; j < i; j++) {
        elements.add(new ASN1Element((byte) 0x00, new byte[128]));
        encodedElements[(j * 131) + 1] = (byte) 0x81;
        encodedElements[(j * 131) + 2] = (byte) 0x80;
      }
      testElementSets.add(elements);
      testEncodedElementSets.add(encodedElements);
    lists.remove(null);
    elementArrays = new Object[lists.size()][1];
    for (int i=0; i < elementArrays.length; i++)
    {
      elementArrays[i] = new Object[] { ASN1Element.encodeValue(lists.get(i)) };
    }
  }
  /**
   * Retrieves lists of byte arrays that can be used to construct sets.
   *
   * @return  Lists of byte arrays that can be used to construct sets.
   */
  @DataProvider(name = "elementArrays")
  public Object[][] getElementArrays()
  {
    return elementArrays;
  }
  /**
   * Retrieves lists of ASN.1 elements that can be used to construct sets.
   *
   * @return  Lists of ASN.1 elements that can be used to construct sets.
   */
  @DataProvider(name = "elementLists")
  public Object[][] getElementLists()
  {
    return elementLists;
  }
  /**
   * Tests the first constructor, which doesn't take any arguments.
   */
  @Test()
  public void testConstructor1()
  {
    new ASN1Set();
  }
  /**
   * Create the values that can be used for testing BER types.
   *
   * @return  The values that can be used for testing BER types.
   */
  @DataProvider(name = "types")
  public Object[][] getTypes()
  {
    // 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) };
    }
    return testTypes;
  }
  /**
   * Tests the second constructor, which takes a byte argument.
   *
   * @param  b  The BER type to use for the set.
   */
  @Test(dataProvider = "types")
  public void testConstructor2(byte b)
  {
    new ASN1Set(b);
  }
  /**
   * Tests the third constructor, which takes a list of elements.
   *
   * @param  elements  The list of elements to use to create the set.
   */
  @Test(dataProvider = "elementLists")
  public void testConstructor3(ArrayList<ASN1Element> elements)
  {
    new ASN1Set(elements);
  }
  /**
   * Tests the third constructor, which takes a byte and a list of elements.
   *
   * @param  elements  The list of elements to use to create the set.
   */
  @Test(dataProvider = "elementLists")
  public void testConstructor4(ArrayList<ASN1Element> elements)
  {
    for (int i=0; i < 255; i++)
    {
      new ASN1Set((byte) (i & 0xFF), elements);
    }
  }
  /**
   * Tests the <CODE>elements</CODE> method.
   *
   * @param  elements  The list of elements to use to create the set.
   */
  @Test()
  public void testElements() {
    int numElementSets = testElementSets.size();
    for (int i = 0; i < numElementSets; i++) {
      ArrayList<ASN1Element> elementSet = testElementSets.get(i);
      ArrayList<ASN1Element> compareList;
      if (elementSet == null) {
        compareList = new ArrayList<ASN1Element>(0);
      } else {
        compareList = elementSet;
      }
      ASN1Set element = new ASN1Set(elementSet);
      assertTrue(listsAreEqual(compareList, element.elements()));
  @Test(dataProvider = "elementLists")
  public void testGetElements(ArrayList<ASN1Element> elements)
  {
    ASN1Set s = new ASN1Set(elements);
    if (elements == null)
    {
      assertEquals(new ArrayList<ASN1Element>(), s.elements());
    }
    else
    {
      assertEquals(elements, s.elements());
    }
  }
  /**
   * Tests the <CODE>setElements</CODE> method.
   */
  @Test()
  public void testSetElements() {
    ASN1Set element = new ASN1Set();
    int numElementSets = testElementSets.size();
    for (int i = 0; i < numElementSets; i++) {
      ArrayList<ASN1Element> elementSet = testElementSets.get(i);
      ArrayList<ASN1Element> compareList;
      if (elementSet == null) {
        compareList = new ArrayList<ASN1Element>(0);
      } else {
        compareList = elementSet;
      }
      element.setElements(elementSet);
      assertTrue(listsAreEqual(compareList, element.elements()));
    }
  }
  /**
   * Tests the <CODE>setValue</CODE> method.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @param  elements  The list of elements to use to create the set.
   */
  @Test()
  public void testSetValue() throws Exception {
    ASN1Set element = new ASN1Set();
    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;
      }
      element.setValue(encodedElementSet);
      assertTrue(listsAreEqual(compareList, element.elements()));
  @Test(dataProvider = "elementLists")
  public void testSetElements(ArrayList<ASN1Element> elements)
  {
    ASN1Set s = new ASN1Set();
    s.setElements(elements);
    if (elements == null)
    {
      assertEquals(new ArrayList<ASN1Element>(), s.elements());
    }
    else
    {
      assertEquals(elements, s.elements());
    }
  }
  /**
   * Tests the <CODE>decodeAsSet</CODE> method that takes an ASN.1
   * element argument.
   * Tests the <CODE>setValue</CODE> method with valid values.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @param  encodedElements  The byte array containing the encoded elements to
   *                          use in the value.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testDecodeElementAsSet() 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;
      }
      ASN1Element element = new ASN1Element((byte) 0x00, encodedElementSet);
      assertTrue(listsAreEqual(compareList, ASN1Set.decodeAsSet(element)
          .elements()));
    }
  @Test(dataProvider = "elementArrays")
  public void testSetValueValid(byte[] encodedElements)
         throws Exception
  {
    ASN1Set s = new ASN1Set();
    s.setValue(encodedElements);
  }
  /**
   * Tests the <CODE>decodeAsSet</CODE> method that takes a byte array
   * Tests the <CODE>setValue</CODE> method with a null array.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testSetValueNull()
         throws Exception
  {
    ASN1Set s = new ASN1Set();
    s.setValue(null);
  }
  /**
   * Retrieves a set of byte arrays containing invalid element value encodings.
   *
   * @return  A set of byte arrays containing invalid element value encodings.
   */
  @DataProvider(name = "invalidElementArrays")
  public Object[][] getInvalidArrays()
  {
    return new Object[][]
    {
      new Object[] { new byte[] { 0x05 } },
      new Object[] { new byte[] { 0x05, 0x01 } },
      new Object[] { new byte[] { 0x05, (byte) 0x85, 0x00, 0x00, 0x00, 0x00,
                                  0x00 } },
      new Object[] { new byte[] { 0x05, (byte) 0x82, 0x00 } },
      new Object[] { new byte[] { 0x05, 0x00, 0x05 } },
      new Object[] { new byte[] { 0x05, 0x00, 0x05, 0x01 } },
    };
  }
  /**
   * Tests the <CODE>setValue</CODE> method with valid values.
   *
   * @param  encodedElements  The byte array containing the encoded elements to
   *                          use in the value.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "invalidElementArrays",
        expectedExceptions = { ASN1Exception.class })
  public void testSetValueInvalid(byte[] invalidElements)
         throws Exception
  {
    ASN1Set s = new ASN1Set();
    s.setValue(invalidElements);
  }
  /**
   * Tests the <CODE>decodeAsSet</CODE> method that takes an ASN1Element
   * argument with valid elements.
   *
   * @param  encodedElements  Byte arrays that may be used as valid values for
   *                          encoded elements.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elementArrays")
  public void testDecodeValidElementAsSet(byte[] encodedElements)
         throws Exception
  {
    ASN1Element e = new ASN1Element(ASN1Constants.UNIVERSAL_SET_TYPE,
                                    encodedElements);
    ASN1Set.decodeAsSet(e);
  }
  /**
   * Tests the <CODE>decodeAsSet</CODE> method that takes an ASN1Element
   * argument with valid elements.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeNullElementAsSet()
         throws Exception
  {
    ASN1Element e = null;
    ASN1Set.decodeAsSet(e);
  }
  /**
   * Tests the <CODE>decodeAsSet</CODE> method that takes a byte array argument
   * with valid arrays.
   *
   * @param  encodedElements  Byte arrays that may be used as valid values for
   *                          encoded elements.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(dataProvider = "elementArrays")
  public void testDecodeValidArrayAsSet(byte[] encodedElements)
         throws Exception
  {
    byte[] encodedLength = ASN1Element.encodeLength(encodedElements.length);
    byte[] elementBytes  =
         new byte[1 + encodedLength.length + encodedElements.length];
    elementBytes[0] = ASN1Constants.UNIVERSAL_SET_TYPE;
    System.arraycopy(encodedLength, 0, elementBytes, 1, encodedLength.length);
    System.arraycopy(encodedElements, 0, elementBytes, 1+encodedLength.length,
                     encodedElements.length);
    ASN1Set.decodeAsSet(elementBytes);
  }
  /**
   * Tests the <CODE>decodeAsSet</CODE> method that takes a byte array argument
   * with a null array.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeNullArrayAsSet()
         throws Exception
  {
    byte[] b = null;
    ASN1Set.decodeAsSet(b);
  }
  /**
   * Tests the <CODE>decodeAsSet</CODE> method that takes a byte array argument
   * with a short array.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeShortArrayAsSet()
         throws Exception
  {
    byte[] b = new byte[1];
    ASN1Set.decodeAsSet(b);
  }
  /**
   * Tests the <CODE>decodeAsSet</CODE> method that takes a byte array argument
   * with an array that takes too many bytes to encode the length.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeLongLengthArrayAsSet()
         throws Exception
  {
    byte[] b = { 0x30, (byte) 0x85, 0x00, 0x00, 0x00, 0x00, 0x00 };
    ASN1Set.decodeAsSet(b);
  }
  /**
   * Tests the <CODE>decodeAsSet</CODE> method that takes a byte array argument
   * with an array that doesn't fully describe the length.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeTruncatedLengthArrayAsSet()
         throws Exception
  {
    byte[] b = { 0x30, (byte) 0x82, 0x00 };
    ASN1Set.decodeAsSet(b);
  }
  /**
   * Tests the <CODE>decodeAsSet</CODE> method that takes a byte array argument
   * with an array whose decoded length doesn't match the real length.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test(expectedExceptions = { ASN1Exception.class })
  public void testDecodeLengthMismatchArrayAsSet()
         throws Exception
  {
    byte[] b = { 0x30, 0x01 };
    ASN1Set.decodeAsSet(b);
  }
  /**
   * Tests the <CODE>toString</CODE> method that takes a string builder
   * argument.
   *
   * @throws Exception
   *           If the test failed unexpectedly.
   * @param  elements  The list of elements to use to create the set.
   */
  @Test()
  public void testDecodeBytesAsSet() 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 = "elementLists")
  public void testToString1(ArrayList<ASN1Element> elements)
  {
    new ASN1Set(elements).toString(new StringBuilder());
  }
      ArrayList<ASN1Element> compareList;
      if (elementSet == null) {
        compareList = new ArrayList<ASN1Element>(0);
      } else {
        compareList = elementSet;
      }
      byte[] encodedLength = ASN1Element
          .encodeLength(encodedElementSet.length);
      byte[] encodedElement = new byte[1 + encodedLength.length
          + encodedElementSet.length];
      encodedElement[0] = 0x00;
      System.arraycopy(encodedLength, 0, encodedElement, 1,
          encodedLength.length);
      System.arraycopy(encodedElementSet, 0, encodedElement,
          1 + encodedLength.length, encodedElementSet.length);
      assertTrue(listsAreEqual(compareList, ASN1Set.decodeAsSet(
          encodedElement).elements()));
    }
  /**
   * Tests the <CODE>toString</CODE> method that takes string builder and
   * integer arguments.
   *
   * @param  elements  The list of elements to use to create the set.
   */
  @Test(dataProvider = "elementLists")
  public void testToString2(ArrayList<ASN1Element> elements)
  {
    new ASN1Set(elements).toString(new StringBuilder(), 1);
  }
}