From 893744262b1a5a291b3cba08f864b18ad8fa7c04 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Tue, 12 Sep 2006 00:37:13 +0000
Subject: [PATCH] Update the test cases for the ASN.1 octet string, sequence, set, reader, and writer classes to provide better coverage.

---
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/SocketReadThread.java        |  156 +++
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Sequence.java        |  714 ++++++++++---
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Set.java             |  624 ++++++++---
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/SocketWriteThread.java       |  103 ++
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1OctetString.java     |  852 +++++++++++----
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1ReaderAndWriter.java |  557 +++++-----
 6 files changed, 2,145 insertions(+), 861 deletions(-)

diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/SocketReadThread.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/SocketReadThread.java
new file mode 100644
index 0000000..cf7fdfc
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/SocketReadThread.java
@@ -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) {}
+  }
+}
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/SocketWriteThread.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/SocketWriteThread.java
new file mode 100644
index 0000000..f63696e
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/SocketWriteThread.java
@@ -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) {}
+  }
+}
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1OctetString.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1OctetString.java
index e8fb993..0f3cbc7 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1OctetString.java
+++ b/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());
   }
 }
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1ReaderAndWriter.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1ReaderAndWriter.java
index eb3e3a6..8096257 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1ReaderAndWriter.java
+++ b/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();
   }
 }
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Sequence.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Sequence.java
index ed11a87..fd3738c 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Sequence.java
+++ b/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);
   }
 }
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Set.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Set.java
index 88c8f7b..a06ea6c 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/protocols/asn1/TestASN1Set.java
+++ b/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);
   }
 }
+

--
Gitblit v1.10.0