/** Tests the <CODE>write/readOctetString</CODE> methods. */
  @Test(dataProvider = "binaryValues")
  public void testEncodeDecodeOctetStringType(final byte[] b) throws Exception {
    final ByteString bs = ByteString.wrap(b);
    final ByteStringBuilder bsb = new ByteStringBuilder();

    for (final byte type : testTypes) {
      bsb.clear();
      getWriter().writeOctetString(type, bs);

      ASN1Reader r = getReader(getEncodedBytes());
      assertEquals(r.peekLength(), b.length);
      assertEquals(r.peekType(), type);
      r.readOctetString(bsb);
      assertTrue(bs.equals(bsb));

      bsb.clear();
      getWriter().writeOctetString(type, b, 0, b.length);

      r = getReader(getEncodedBytes());
      assertEquals(r.peekLength(), b.length);
      assertEquals(r.peekType(), type);
      r.readOctetString(bsb);
      assertTrue(bs.equals(bsb));
    }
  }
  @Test
  public void testEncodeDecodeSequence() throws Exception {
    final ASN1Writer writer = getWriter();

    writer.writeStartSequence();

    writer.writeBoolean(true);
    writer.writeBoolean(false);
    writer.writeInteger(0);
    writer.writeInteger(10L);
    writer.writeNull();
    writer.writeOctetString("test value");
    writer.writeOctetString("skip value");

    writer.writeStartSequence();
    writer.writeOctetString("nested sequence");
    writer.writeEndSequence();

    writer.writeStartSet();
    writer.writeOctetString("nested set");
    writer.writeEndSet();

    writer.writeEndSequence();

    final ASN1Reader reader = getReader(getEncodedBytes());
    assertEquals(reader.peekType(), ASN1.UNIVERSAL_SEQUENCE_TYPE);
    assertEquals(reader.peekLength(), 71);

    assertTrue(reader.hasNextElement());
    reader.readStartSequence();
    assertTrue(reader.hasNextElement());

    assertEquals(true, reader.readBoolean());
    assertEquals(false, reader.readBoolean());
    assertEquals(0, reader.readInteger());
    assertEquals(10, reader.readInteger());
    reader.readNull();
    assertEquals("test value", reader.readOctetStringAsString());
    reader.skipElement();

    assertEquals(reader.peekLength(), 17);
    assertEquals(reader.peekType(), ASN1.UNIVERSAL_SEQUENCE_TYPE);
    reader.readStartSequence();
    assertEquals("nested sequence", reader.readOctetStringAsString());
    reader.readEndSequence();

    assertEquals(reader.peekLength(), 12);
    assertEquals(reader.peekType(), ASN1.UNIVERSAL_SET_TYPE);
    reader.readStartSequence();
    assertEquals("nested set", reader.readOctetStringAsString());
    reader.readEndSequence();

    assertFalse(reader.hasNextElement());
    reader.readEndSequence();
    assertFalse(reader.elementAvailable());
  }
  /** Tests the <CODE>write/readOctetString</CODE> methods. */
  @Test(dataProvider = "binaryValues")
  public void testEncodeDecodeOctetString(final byte[] b) throws Exception {
    final ByteString bs = ByteString.wrap(b);

    getWriter().writeOctetString(bs);

    ASN1Reader r = getReader(getEncodedBytes());
    assertEquals(r.peekLength(), b.length);
    assertEquals(r.peekType(), ASN1.UNIVERSAL_OCTET_STRING_TYPE);
    assertTrue(bs.equals(r.readOctetString()));

    getWriter().writeOctetString(b, 0, b.length);

    r = getReader(getEncodedBytes());
    assertEquals(r.peekLength(), b.length);
    assertEquals(r.peekType(), ASN1.UNIVERSAL_OCTET_STRING_TYPE);
    assertTrue(bs.equals(r.readOctetString()));
  }
  /** Tests the <CODE>write/readNull</CODE> methods. */
  @Test
  public void testEncodeDecodeNull() throws Exception {
    getWriter().writeNull();

    final ASN1Reader r = getReader(getEncodedBytes());
    assertEquals(r.peekLength(), 0);
    assertEquals(r.peekType(), ASN1.UNIVERSAL_NULL_TYPE);
    r.readNull();
  }
  /**
   * Tests the <CODE>write/readInteger</CODE> methods with Java longs.
   *
   * @param l The long value to use for the test.
   */
  @Test(dataProvider = "longValues")
  public void testEncodeDecodeInteger(final long l, final int length) throws Exception {
    getWriter().writeInteger(l);

    final ASN1Reader r = getReader(getEncodedBytes());
    assertEquals(r.peekLength(), length);
    assertEquals(r.peekType(), ASN1.UNIVERSAL_INTEGER_TYPE);
    assertEquals(r.readInteger(), l);
  }
  /**
   * Tests the <CODE>write/readInteger</CODE> methods with Java ints.
   *
   * @param i The integer value to use for the test.
   */
  @Test(dataProvider = "intValues")
  public void testEncodeDecodeEnuerated(final int i, final int length) throws Exception {
    getWriter().writeEnumerated(i);

    final ASN1Reader r = getReader(getEncodedBytes());
    assertEquals(r.peekLength(), length);
    assertEquals(r.peekType(), ASN1.UNIVERSAL_ENUMERATED_TYPE);
    assertEquals(r.readInteger(), i);
  }
  /**
   * Tests the <CODE>write/readBoolean</CODE> methods.
   *
   * @param b The boolean value to use in the test.
   */
  @Test(dataProvider = "booleanValues")
  public void testEncodeDecodeBoolean(final boolean b) throws Exception {
    getWriter().writeBoolean(b);

    final ASN1Reader r = getReader(getEncodedBytes());
    assertEquals(r.peekLength(), 1);
    assertEquals(r.peekType(), ASN1.UNIVERSAL_BOOLEAN_TYPE);
    assertEquals(r.readBoolean(), b);
  }
  /** Tests the <CODE>write/readOctetString</CODE> methods. */
  @Test(dataProvider = "stringValues")
  public void testEncodeDecodeOctetString(final String s) throws Exception {
    getWriter().writeOctetString(s);

    final String expected = s != null ? s : "";
    final ASN1Reader r = getReader(getEncodedBytes());
    assertEquals(r.peekLength(), StaticUtils.getBytes(expected).length);
    assertEquals(r.peekType(), ASN1.UNIVERSAL_OCTET_STRING_TYPE);
    assertEquals(r.readOctetStringAsString(), expected);
  }
  /** Tests the <CODE>write/readNull</CODE> methods. */
  @Test
  public void testEncodeDecodeNullType() throws Exception {
    for (final byte type : testTypes) {
      getWriter().writeNull(type);

      final ASN1Reader r = getReader(getEncodedBytes());
      assertEquals(r.peekLength(), 0);
      assertEquals(r.peekType(), type);
      r.readNull();
    }
  }
  /**
   * Tests the <CODE>write/readInteger</CODE> methods wiht JavaLongs.
   *
   * @param l The long value to use for the test.
   */
  @Test(dataProvider = "longValues")
  public void testEncodeDecodeIntegerType(final long l, final int length) throws Exception {
    for (final byte type : testTypes) {
      getWriter().writeInteger(type, l);

      final ASN1Reader r = getReader(getEncodedBytes());
      assertEquals(r.peekLength(), length);
      assertEquals(r.peekType(), type);
      assertEquals(r.readInteger(), l);
    }
  }
  /**
   * Tests the <CODE>write/readBoolean</CODE> methods.
   *
   * @param b The boolean value to use in the test.
   */
  @Test(dataProvider = "booleanValues")
  public void testEncodeDecodeBooleanType(final boolean b) throws Exception {
    for (final byte type : testTypes) {
      getWriter().writeBoolean(type, b);

      final ASN1Reader r = getReader(getEncodedBytes());
      assertEquals(r.peekLength(), 1);
      assertEquals(r.peekType(), type);
      assertEquals(r.readBoolean(), b);
    }
  }
  /** Tests the <CODE>write/readOctetString</CODE> methods. */
  @Test(dataProvider = "stringValues")
  public void testEncodeDecodeOctetStringType(final String s) throws Exception {
    for (final byte type : testTypes) {
      getWriter().writeOctetString(type, s);

      final String expected = s != null ? s : "";
      final ASN1Reader r = getReader(getEncodedBytes());
      assertEquals(r.peekLength(), StaticUtils.getBytes(expected).length);
      assertEquals(r.peekType(), type);
      assertEquals(r.readOctetStringAsString(), expected);
    }
  }
  /** Tests the <CODE>write/readOctetString</CODE> methods. */
  @Test
  public void testEncodeDecodeOctetStringOffLen() throws Exception {
    final byte[] b = new byte[] {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

    for (int i = 0; i < 5; i += 2) {
      final byte[] bsb = new byte[3];
      System.arraycopy(b, i, bsb, 0, 3);
      final ByteString bs = ByteString.wrap(bsb);
      getWriter().writeOctetString(b, i, 3);

      final ASN1Reader r = getReader(getEncodedBytes());
      assertEquals(r.peekLength(), 3);
      assertEquals(r.peekType(), ASN1.UNIVERSAL_OCTET_STRING_TYPE);
      assertTrue(bs.equals(r.readOctetString()));
    }
  }