From 3e488672c6ba793a818dabf6df3b376459323613 Mon Sep 17 00:00:00 2001
From: Violette Roche-Montane <violette.roche-montane@forgerock.com>
Date: Tue, 17 Dec 2013 15:07:12 +0000
Subject: [PATCH] Added unit tests to requests

---
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/SimpleBindRequestTestCase.java             |   70 +
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ModifyDNRequestTestCase.java               |   98 ++
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AbandonRequestTestCase.java                |   53 +
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/SearchRequestTestCase.java                 |  133 +++
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DeleteRequestTestCase.java                 |   62 +
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/WhoAmIExtendedRequestTestCase.java         |  106 ++
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/UnbindRequestTestCase.java                 |   30 
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestTestCase.java          |   80 +
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/RequestsTestCase.java                      |  199 +++++
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AnonymousSASLBindRequestTestCase.java      |   56 +
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GenericExtendedRequestTestCase.java        |  114 ++
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestTestCase.java      |  131 +++
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/PasswordModifyExtendedRequestTestCase.java |  153 +++
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AddRequestTestCase.java                    |  125 ++
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestTestCase.java         |  131 +++
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CompareRequestTestCase.java                |   85 +
 /dev/null                                                                                               |  111 --
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestTestCase.java        |   76 +
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ModifyRequestTestCase.java                 |   83 +
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestTestCase.java       |   47 +
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ExtendedRequestTestCase.java               |    5 
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GenericBindRequestTestCase.java            |   73 +
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/StartTLSExtendedRequestTestCase.java       |  135 +++
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CancelExtendedRequestTestCase.java         |  112 ++
 opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/BindRequestTestCase.java                   |   23 
 25 files changed, 2,056 insertions(+), 235 deletions(-)

diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AbandonRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AbandonRequestTestCase.java
index efbe56c..b498fa2 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AbandonRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AbandonRequestTestCase.java
@@ -27,24 +27,61 @@
 
 package org.forgerock.opendj.ldap.requests;
 
+import static org.fest.assertions.Assertions.assertThat;
+
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 /**
  * Tests Abandon requests.
  */
 @SuppressWarnings("javadoc")
-public class AbandonRequestTestCase extends RequestTestCase {
+public class AbandonRequestTestCase extends RequestsTestCase {
+    private static final AbandonRequest NEW_ABANDON_REQUEST = Requests.newAbandonRequest(-1);
+    private static final AbandonRequest NEW_ABANDON_REQUEST2 = Requests.newAbandonRequest(0);
+    private static final AbandonRequest NEW_ABANDON_REQUEST3 = Requests.newAbandonRequest(1);
+
     @DataProvider(name = "abandonRequests")
-    public Object[][] getAbandonRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getAbandonRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected AbandonRequest[] createTestRequests() throws Exception {
+    protected AbandonRequest[] newInstance() {
         return new AbandonRequest[] {
-                Requests.newAbandonRequest(-1),
-                Requests.newAbandonRequest(0),
-                Requests.newAbandonRequest(1)
-        };
+            NEW_ABANDON_REQUEST,
+            NEW_ABANDON_REQUEST2,
+            NEW_ABANDON_REQUEST3 };
+    }
+
+    @Override
+    protected Request copyOf(final Request original) {
+        return Requests.copyOfAbandonRequest((AbandonRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(final Request original) {
+        return Requests.unmodifiableAbandonRequest((AbandonRequest) original);
+    }
+
+    @Test(dataProvider = "abandonRequests")
+    public void testModifiableRequest(final AbandonRequest original) {
+        final int newReqId = 9999;
+        final AbandonRequest copy = (AbandonRequest) copyOf(original);
+        copy.setRequestID(newReqId);
+        assertThat(copy.getRequestID()).isEqualTo(newReqId);
+        assertThat(original.getRequestID()).isNotEqualTo(newReqId);
+    }
+
+    @Test(dataProvider = "abandonRequests")
+    public void testUnmodifiableRequest(final AbandonRequest original) {
+        final AbandonRequest unmodifiable = (AbandonRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getRequestID()).isEqualTo(original.getRequestID());
+    }
+
+    @Test(dataProvider = "abandonRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetters(final AbandonRequest original) {
+        final AbandonRequest unmodifiable = (AbandonRequest) unmodifiableOf(original);
+        unmodifiable.setRequestID(0);
     }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AddRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AddRequestTestCase.java
index 9af360d..a4d0853 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AddRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AddRequestTestCase.java
@@ -27,26 +27,131 @@
 
 package org.forgerock.opendj.ldap.requests;
 
+import static org.fest.assertions.Assertions.assertThat;
+
+import org.forgerock.opendj.ldap.AttributeDescription;
 import org.forgerock.opendj.ldap.DN;
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 /**
  * Tests ADD requests.
  */
 @SuppressWarnings("javadoc")
-public class AddRequestTestCase extends RequestTestCase {
+public class AddRequestTestCase extends RequestsTestCase {
+    private static final AddRequest NEW_ADD_REQUEST = Requests.newAddRequest(DN.valueOf("uid=addrequest1"));
+    private static final AddRequest NEW_ADD_REQUEST2 = Requests.newAddRequest("cn=addrequesttestcase");
+    private static final AddRequest NEW_ADD_REQUEST3 = Requests.newAddRequest("dn: ou=People,o=test",
+            "objectClass: top", "objectClass: organizationalUnit", "ou: People");
+
     @DataProvider(name = "addRequests")
-    public Object[][] getAddRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getAddRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected AddRequest[] createTestRequests() throws Exception {
-        return new AddRequest[] {
-                    Requests.newAddRequest(DN.valueOf("uid=addrequest1")),
-                    Requests.newAddRequest("cn=addrequesttestcase"),
-                    Requests.newAddRequest("dn: ou=People,o=test", "objectClass: top",
-                            "objectClass: organizationalUnit", "ou: People")
-        };
+    protected AddRequest[] newInstance() {
+        return new AddRequest[] { NEW_ADD_REQUEST, NEW_ADD_REQUEST2, NEW_ADD_REQUEST3 };
+    }
+
+    @Override
+    protected Request copyOf(final Request original) {
+        return Requests.copyOfAddRequest((AddRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(final Request original) {
+        return Requests.unmodifiableAddRequest((AddRequest) original);
+    }
+
+    @Test(dataProvider = "addRequests")
+    public void testModifiableRequest(final AddRequest original) {
+        final String newValue = "uid=newName";
+        final AddRequest copy = (AddRequest) copyOf(original);
+
+        copy.setName(newValue);
+        assertThat(copy.getName().toString()).isEqualTo(newValue);
+        assertThat(original.getName().toString()).isNotEqualTo(newValue);
+
+        copy.addAttribute("cn", "Bob");
+        assertThat(copy.getAttribute("cn")).isNotEmpty();
+        assertThat(original.getAttribute("cn")).isNull();
+
+        copy.clearAttributes();
+        assertThat(copy.getAttribute("cn")).isNull();
+        assertThat(copy.getAttributeCount()).isEqualTo(0);
+
+        copy.addAttribute("sn", "Bobby");
+        assertThat(original.getAttribute("sn")).isNull();
+        assertThat(copy.containsAttribute("sn", "Bobby")).isTrue();
+
+        copy.removeAttribute("sn");
+        assertThat(copy.containsAttribute("sn", "Bobby")).isFalse();
+    }
+
+    @Test(dataProvider = "addRequests")
+    public void testUnmodifiableRequest(final AddRequest original) {
+        final AddRequest unmodifiable = (AddRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getName().toString()).isEqualTo(original.getName().toString());
+    }
+
+    @Test(dataProvider = "addRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetName(final AddRequest original) {
+        final AddRequest unmodifiable = (AddRequest) unmodifiableOf(original);
+        unmodifiable.setName("cn=myexample");
+    }
+
+    @Test(dataProvider = "addRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetDNName(final AddRequest original) {
+        final AddRequest unmodifiable = (AddRequest) unmodifiableOf(original);
+        unmodifiable.setName(DN.valueOf("cn=mynewexample"));
+    }
+
+    @Test(dataProvider = "addRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableAddAttribute(final AddRequest original) {
+        final AddRequest unmodifiable = (AddRequest) unmodifiableOf(original);
+        unmodifiable.addAttribute("sn", "Bobby");
+    }
+
+    @Test(dataProvider = "addRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableAddAttribute2(final AddRequest original) {
+        final AddRequest unmodifiable = (AddRequest) unmodifiableOf(original);
+        unmodifiable.addAttribute(org.forgerock.opendj.ldap.Attributes.emptyAttribute("description"));
+    }
+
+    @Test(dataProvider = "addRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableRemoveAttribute(final AddRequest original) {
+        final AddRequest unmodifiable = (AddRequest) unmodifiableOf(original);
+        unmodifiable.removeAttribute("sn", "Bobby");
+    }
+
+    @Test(dataProvider = "addRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableRemoveAttribute2(final AddRequest original) {
+        final AddRequest unmodifiable = (AddRequest) unmodifiableOf(original);
+        unmodifiable.removeAttribute(AttributeDescription.valueOf("description"));
+    }
+
+    @Test(dataProvider = "addRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableReplaceAttribute(final AddRequest original) {
+        final AddRequest unmodifiable = (AddRequest) unmodifiableOf(original);
+        unmodifiable.replaceAttribute("sn", "cn");
+    }
+
+    @Test(dataProvider = "addRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableReplaceAttribute2(final AddRequest original) {
+        final AddRequest unmodifiable = (AddRequest) unmodifiableOf(original);
+        unmodifiable.replaceAttribute("sn");
+    }
+
+    @Test(dataProvider = "addRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableReplaceAttribute3(final AddRequest original) {
+        final AddRequest unmodifiable = (AddRequest) unmodifiableOf(original);
+        unmodifiable.replaceAttribute(org.forgerock.opendj.ldap.Attributes.emptyAttribute("description"));
+    }
+
+    @Test(dataProvider = "addRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableClearAttribute(final AddRequest original) {
+        final AddRequest unmodifiable = (AddRequest) unmodifiableOf(original);
+        unmodifiable.clearAttributes();
     }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AnonymousSASLBindRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AnonymousSASLBindRequestTestCase.java
index 28514a4..39f0ced 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AnonymousSASLBindRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AnonymousSASLBindRequestTestCase.java
@@ -27,23 +27,65 @@
 
 package org.forgerock.opendj.ldap.requests;
 
+import static org.fest.assertions.Assertions.assertThat;
+
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 /**
  * Tests anonymous SASL bind requests.
  */
 @SuppressWarnings("javadoc")
 public class AnonymousSASLBindRequestTestCase extends BindRequestTestCase {
+    private static final AnonymousSASLBindRequest NEW_ANONYMOUS_SASL_BIND_REQUEST2 = Requests
+            .newAnonymousSASLBindRequest("test");
+    private static final AnonymousSASLBindRequest NEW_ANONYMOUS_SASL_BIND_REQUEST = Requests
+            .newAnonymousSASLBindRequest("");
+
     @DataProvider(name = "anonymousSASLBindRequests")
-    public Object[][] getAnonymousSASLBindRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getAnonymousSASLBindRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected AnonymousSASLBindRequest[] createTestRequests() throws Exception {
-        return new AnonymousSASLBindRequest[] {
-                Requests.newAnonymousSASLBindRequest(""),
-                Requests.newAnonymousSASLBindRequest("test")
-        };
+    protected AnonymousSASLBindRequest[] newInstance() {
+        return new AnonymousSASLBindRequest[] { NEW_ANONYMOUS_SASL_BIND_REQUEST, NEW_ANONYMOUS_SASL_BIND_REQUEST2 };
+    }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfAnonymousSASLBindRequest((AnonymousSASLBindRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableAnonymousSASLBindRequest((AnonymousSASLBindRequest) original);
+    }
+
+    @Test(dataProvider = "anonymousSASLBindRequests")
+    public void testModifiableRequest(final AnonymousSASLBindRequest original) {
+        final String newValue = "MyNewValue";
+        final AnonymousSASLBindRequest copy = (AnonymousSASLBindRequest) copyOf(original);
+        copy.setTraceString(newValue);
+        assertThat(copy.getTraceString()).isEqualTo(newValue);
+        assertThat(copy.getAuthenticationType()).isEqualTo(original.getAuthenticationType());
+        assertThat(copy.getName()).isEqualTo(original.getName());
+        assertThat(copy.getSASLMechanism()).isEqualTo(original.getSASLMechanism());
+        assertThat(copy.getTraceString()).isNotEqualTo(original.getTraceString());
+    }
+
+    @Test(dataProvider = "anonymousSASLBindRequests")
+    public void testUnmodifiableRequest(final AnonymousSASLBindRequest original) {
+        final AnonymousSASLBindRequest unmodifiable = (AnonymousSASLBindRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getAuthenticationType()).isEqualTo(original.getAuthenticationType());
+        assertThat(unmodifiable.getName()).isEqualTo(original.getName());
+        assertThat(unmodifiable.getSASLMechanism()).isEqualTo(original.getSASLMechanism());
+        assertThat(unmodifiable.getTraceString()).isEqualTo(original.getTraceString());
+    }
+
+    @Test(dataProvider = "anonymousSASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableRequestSetter(final AnonymousSASLBindRequest original) {
+        final AnonymousSASLBindRequest unmodifiable = (AnonymousSASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setTraceString("the_new_trace_string");
     }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/BindRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/BindRequestTestCase.java
index 5e53b96..78644c0 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/BindRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/BindRequestTestCase.java
@@ -26,6 +26,7 @@
 
 package org.forgerock.opendj.ldap.requests;
 
+import static org.fest.assertions.Assertions.assertThat;
 import static org.testng.Assert.assertNotNull;
 
 import org.forgerock.opendj.io.LDAP;
@@ -36,8 +37,8 @@
  * Tests the BIND requests.
  */
 @SuppressWarnings("javadoc")
-public abstract class BindRequestTestCase extends RequestTestCase {
-    @Test(dataProvider = "testRequests")
+public abstract class BindRequestTestCase extends RequestsTestCase {
+    @Test(dataProvider = "createModifiableInstance")
     public void testAuthType(final BindRequest request) throws Exception {
         final byte b = request.getAuthenticationType();
         if (!(b == LDAP.TYPE_AUTHENTICATION_SASL || b == LDAP.TYPE_AUTHENTICATION_SIMPLE)) {
@@ -45,14 +46,28 @@
         }
     }
 
-    @Test(dataProvider = "testRequests")
+    @Test(dataProvider = "createModifiableInstance")
     public void testBindClient(final BindRequest request) throws Exception {
         final BindClient client = request.createBindClient("localhost");
         assertNotNull(client);
     }
 
-    @Test(dataProvider = "testRequests")
+    @Test(dataProvider = "createModifiableInstance")
     public void testName(final BindRequest request) throws Exception {
         assertNotNull(request.getName());
     }
+
+    @Test(dataProvider = "createModifiableInstance")
+    public void testModifiableRequest(final BindRequest original) {
+        final BindRequest copy = (BindRequest) copyOf(original);
+        assertThat(copy.getAuthenticationType()).isEqualTo(original.getAuthenticationType());
+        assertThat(copy.getName()).isEqualTo(original.getName());
+    }
+
+    @Test(dataProvider = "createModifiableInstance")
+    public void testUnmodifiableRequest(final BindRequest original) {
+        final BindRequest unmodifiable = (BindRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getAuthenticationType()).isEqualTo(original.getAuthenticationType());
+        assertThat(unmodifiable.getName()).isEqualTo(original.getName());
+    }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestTestCase.java
index 547789b..41690c6 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestTestCase.java
@@ -29,24 +29,90 @@
 
 import static com.forgerock.opendj.util.StaticUtils.EMPTY_BYTES;
 import static com.forgerock.opendj.util.StaticUtils.getBytes;
+import static org.fest.assertions.Assertions.assertThat;
 
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 /**
  * Tests CRAM MD5 SASL bind requests.
  */
 @SuppressWarnings("javadoc")
 public class CRAMMD5SASLBindRequestTestCase extends BindRequestTestCase {
+
+    private static final CRAMMD5SASLBindRequest NEW_CRAMMD5SASL_BIND_REQUEST = Requests.newCRAMMD5SASLBindRequest(
+            "id1", EMPTY_BYTES);
+    private static final CRAMMD5SASLBindRequest NEW_CRAMMD5SASL_BIND_REQUEST2 = Requests.newCRAMMD5SASLBindRequest(
+            "id2", getBytes("test"));
+
     @DataProvider(name = "CRAMMD5SASLBindRequests")
-    public Object[][] getCRAMMD5SASLBindRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getCRAMMD5SASLBindRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected CRAMMD5SASLBindRequest[] createTestRequests() throws Exception {
+    protected CRAMMD5SASLBindRequest[] newInstance() {
         return new CRAMMD5SASLBindRequest[] {
-                Requests.newCRAMMD5SASLBindRequest("id1", EMPTY_BYTES),
-                Requests.newCRAMMD5SASLBindRequest("id2", getBytes("test"))
+            NEW_CRAMMD5SASL_BIND_REQUEST,
+            NEW_CRAMMD5SASL_BIND_REQUEST2
         };
     }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfCRAMMD5SASLBindRequest((CRAMMD5SASLBindRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableCRAMMD5SASLBindRequest((CRAMMD5SASLBindRequest) original);
+    }
+
+    @Test(dataProvider = "CRAMMD5SASLBindRequests")
+    public void testModifiableRequest(final CRAMMD5SASLBindRequest original) {
+        final String authId = "newAuthId";
+        final String pwd = "pass";
+        final String pwd2 = "pass2";
+
+        final CRAMMD5SASLBindRequest copy = (CRAMMD5SASLBindRequest) copyOf(original);
+        copy.setAuthenticationID(authId);
+        assertThat(copy.getAuthenticationID()).isEqualTo(authId);
+        assertThat(original.getAuthenticationID()).isNotEqualTo(authId);
+
+        copy.setPassword(pwd.toCharArray());
+        assertThat(copy.getPassword()).isEqualTo(pwd.getBytes());
+        assertThat(original.getPassword()).isNotEqualTo(pwd.getBytes());
+
+        copy.setPassword(pwd2.getBytes());
+        assertThat(copy.getPassword()).isEqualTo(pwd2.getBytes());
+        assertThat(original.getPassword()).isNotEqualTo(pwd2.getBytes());
+    }
+
+    @Test(dataProvider = "CRAMMD5SASLBindRequests")
+    public void testUnmodifiableRequest(final CRAMMD5SASLBindRequest original) {
+        final CRAMMD5SASLBindRequest unmodifiable = (CRAMMD5SASLBindRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getAuthenticationID()).isEqualTo(original.getAuthenticationID());
+        assertThat(unmodifiable.getAuthenticationType()).isEqualTo(original.getAuthenticationType());
+        assertThat(unmodifiable.getName()).isEqualTo(original.getName());
+        assertThat(unmodifiable.getPassword()).isEqualTo(original.getPassword());
+        assertThat(unmodifiable.getSASLMechanism()).isEqualTo(original.getSASLMechanism());
+    }
+
+    @Test(dataProvider = "CRAMMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAuthenticationId(final CRAMMD5SASLBindRequest original) {
+        final CRAMMD5SASLBindRequest unmodifiable = (CRAMMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setAuthenticationID("dn: uid=scarter,ou=people,dc=example,dc=com");
+    }
+
+    @Test(dataProvider = "CRAMMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetPassword(final CRAMMD5SASLBindRequest original) {
+        final CRAMMD5SASLBindRequest unmodifiable = (CRAMMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setPassword("password".getBytes());
+    }
+
+    @Test(dataProvider = "CRAMMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetPassword2(final CRAMMD5SASLBindRequest original) {
+        final CRAMMD5SASLBindRequest unmodifiable = (CRAMMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setPassword("password".toCharArray());
+    }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CancelExtendedRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CancelExtendedRequestTestCase.java
new file mode 100644
index 0000000..ddcffd3
--- /dev/null
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CancelExtendedRequestTestCase.java
@@ -0,0 +1,112 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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
+ *
+ *
+ *      Copyright 2013 ForgeRock AS.
+ */
+
+package org.forgerock.opendj.ldap.requests;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.DecodeOptions;
+import org.forgerock.opendj.ldap.controls.GenericControl;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Tests CANCELEXTENDED requests.
+ */
+@SuppressWarnings("javadoc")
+public class CancelExtendedRequestTestCase extends RequestsTestCase {
+    private static final CancelExtendedRequest NEW_CANCELEXTENDED_REQUEST = Requests.newCancelExtendedRequest(-1);
+    private static final CancelExtendedRequest NEW_CANCELEXTENDED_REQUEST2 = Requests.newCancelExtendedRequest(0);
+    private static final CancelExtendedRequest NEW_CANCELEXTENDED_REQUEST3 = Requests.newCancelExtendedRequest(1);
+
+    @DataProvider(name = "cancelExtendedRequests")
+    private Object[][] getCancelExtendedRequests() throws Exception {
+        return createModifiableInstance();
+    }
+
+    @Override
+    protected CancelExtendedRequest[] newInstance() {
+        return new CancelExtendedRequest[] {
+            NEW_CANCELEXTENDED_REQUEST,
+            NEW_CANCELEXTENDED_REQUEST2,
+            NEW_CANCELEXTENDED_REQUEST3 };
+    }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfCancelExtendedRequest((CancelExtendedRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableCancelExtendedRequest((CancelExtendedRequest) original);
+    }
+
+
+    @Test(dataProvider = "cancelExtendedRequests")
+    public void testModifiableRequest(final CancelExtendedRequest original) {
+        final int newReqId = 9999;
+        final CancelExtendedRequest copy = (CancelExtendedRequest) copyOf(original);
+        copy.setRequestID(newReqId);
+        assertThat(copy.getRequestID()).isEqualTo(newReqId);
+        assertThat(copy.getOID()).isEqualTo(original.getOID());
+        assertThat(original.getRequestID()).isNotEqualTo(newReqId);
+    }
+
+    @Test(dataProvider = "cancelExtendedRequests")
+    public void testUnmodifiableRequest(final CancelExtendedRequest original) {
+        final CancelExtendedRequest unmodifiable = (CancelExtendedRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getRequestID()).isEqualTo(original.getRequestID());
+        assertThat(unmodifiable.getOID()).isEqualTo(original.getOID());
+        assertThat(unmodifiable.getResultDecoder()).isEqualTo(original.getResultDecoder());
+        assertThat(unmodifiable.getValue()).isEqualTo(original.getValue());
+    }
+
+    @Test(dataProvider = "cancelExtendedRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetRequestId(final CancelExtendedRequest original) {
+        final CancelExtendedRequest unmodifiable = (CancelExtendedRequest) unmodifiableOf(original);
+        unmodifiable.setRequestID(99);
+    }
+
+    @Test(dataProvider = "cancelExtendedRequests")
+    public void testModifiableRequestDecode(final CancelExtendedRequest original) throws DecodeException {
+        final GenericControl control = GenericControl.newControl("1.2.3".intern());
+
+        final CancelExtendedRequest copy = (CancelExtendedRequest) copyOf(original);
+        copy.setRequestID(99);
+        copy.addControl(control);
+        assertThat(original.getControls().contains(control)).isFalse();
+
+        try {
+            final CancelExtendedRequest decoded = CancelExtendedRequest.DECODER.decodeExtendedRequest(copy,
+                    new DecodeOptions());
+            assertThat(decoded.getControls().contains(control)).isTrue();
+        } catch (DecodeException e) {
+            throw e;
+        }
+    }
+}
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CompareRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CompareRequestTestCase.java
index bfdfb1e..be929ad 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CompareRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CompareRequestTestCase.java
@@ -27,24 +27,93 @@
 
 package org.forgerock.opendj.ldap.requests;
 
+import static org.fest.assertions.Assertions.assertThat;
+
+import org.forgerock.opendj.ldap.AttributeDescription;
+import org.forgerock.opendj.ldap.DN;
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 /**
  * Tests compare requests.
  */
 @SuppressWarnings("javadoc")
-public class CompareRequestTestCase extends RequestTestCase {
-    @DataProvider(name = "CompareRequests")
-    public Object[][] getCompareRequests() throws Exception {
-        return getTestRequests();
+public class CompareRequestTestCase extends RequestsTestCase {
+    private static final CompareRequest NEW_COMPARE_REQUEST2 = Requests.newCompareRequest(
+            "uid=user.0,ou=people,o=test", "uid", "user.0");
+    private static final CompareRequest NEW_COMPARE_REQUEST = Requests.newCompareRequest("uid=user.0,ou=people,o=test",
+            "cn", "user.0");
+
+    @DataProvider(name = "compareRequests")
+    private Object[][] getCompareRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected CompareRequest[] createTestRequests() throws Exception {
+    protected CompareRequest[] newInstance() {
         return new CompareRequest[] {
-                Requests.newCompareRequest("uid=user.0,ou=people,o=test", "cn", "user.0"),
-                Requests.newCompareRequest("uid=user.0,ou=people,o=test", "uid", "user.0")
-        };
+            NEW_COMPARE_REQUEST,
+            NEW_COMPARE_REQUEST2 };
     }
 
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfCompareRequest((CompareRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableCompareRequest((CompareRequest) original);
+    }
+
+    @Test(dataProvider = "compareRequests")
+    public void testModifiableRequest(final CompareRequest original) {
+        final String newValue = "uid=user.0";
+        final String attrDescription = "newattributedescription";
+        final CompareRequest copy = (CompareRequest) copyOf(original);
+        copy.setName(newValue);
+        copy.setAttributeDescription(attrDescription);
+        assertThat(copy.getName().toString()).isEqualTo(newValue);
+        assertThat(original.getName().toString()).isNotEqualTo(newValue);
+        assertThat(copy.getAttributeDescription().toString()).isEqualTo(attrDescription);
+        assertThat(original.getAttributeDescription()).isNotEqualTo(attrDescription);
+    }
+
+    @Test(dataProvider = "compareRequests")
+    public void testUnmodifiableRequest(final CompareRequest original) {
+        final CompareRequest unmodifiable = (CompareRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getAssertionValue()).isEqualTo(original.getAssertionValue());
+        assertThat(unmodifiable.getAttributeDescription()).isEqualTo(original.getAttributeDescription());
+        assertThat(unmodifiable.getName().toString()).isEqualTo(original.getName().toString());
+    }
+
+    @Test(dataProvider = "compareRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAssertionValue(final CompareRequest original) {
+        final CompareRequest unmodifiable = (CompareRequest) unmodifiableOf(original);
+        unmodifiable.setAssertionValue("newValue");
+    }
+
+    @Test(dataProvider = "compareRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAttributeDescription(final CompareRequest original) {
+        final CompareRequest unmodifiable = (CompareRequest) unmodifiableOf(original);
+        unmodifiable.setAttributeDescription(AttributeDescription.valueOf("sn"));
+    }
+
+    @Test(dataProvider = "compareRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAttributeDescription2(final CompareRequest original) {
+        final CompareRequest unmodifiable = (CompareRequest) unmodifiableOf(original);
+        unmodifiable.setAttributeDescription("sn");
+    }
+
+    @Test(dataProvider = "compareRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetName(final CompareRequest original) {
+        final CompareRequest unmodifiable = (CompareRequest) unmodifiableOf(original);
+        unmodifiable.setName("uid=user.0");
+    }
+
+    @Test(dataProvider = "compareRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetName2(final CompareRequest original) {
+        final CompareRequest unmodifiable = (CompareRequest) unmodifiableOf(original);
+        unmodifiable.setName(DN.valueOf("uid=user.0"));
+    }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DeleteRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DeleteRequestTestCase.java
index 13877d3..c951572 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DeleteRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DeleteRequestTestCase.java
@@ -27,25 +27,71 @@
 
 package org.forgerock.opendj.ldap.requests;
 
+import static org.fest.assertions.Assertions.assertThat;
+
 import org.forgerock.opendj.ldap.DN;
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 /**
  * Tests the delete request.
  */
 @SuppressWarnings("javadoc")
-public class DeleteRequestTestCase extends RequestTestCase {
-    @DataProvider(name = "DeleteRequests")
-    public Object[][] getDeleteRequests() throws Exception {
-        return getTestRequests();
+public class DeleteRequestTestCase extends RequestsTestCase {
+
+    private static final DeleteRequest NEW_DELETE_REQUEST = Requests.newDeleteRequest(DN.valueOf("uid=Deleterequest1"));
+    private static final DeleteRequest NEW_DELETE_REQUEST2 = Requests.newDeleteRequest("cn=Deleterequesttestcase");
+    private static final DeleteRequest NEW_DELETE_REQUEST3 = Requests.newDeleteRequest("uid=user.999,ou=people,o=test");
+
+    @DataProvider(name = "deleteRequests")
+    private Object[][] getDeleteRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected DeleteRequest[] createTestRequests() throws Exception {
+    protected DeleteRequest[] newInstance() {
         return new DeleteRequest[] {
-                Requests.newDeleteRequest(DN.valueOf("uid=Deleterequest1")),
-                Requests.newDeleteRequest("cn=Deleterequesttestcase"),
-                Requests.newDeleteRequest("uid=user.999,ou=people,o=test")
+            NEW_DELETE_REQUEST,
+            NEW_DELETE_REQUEST2,
+            NEW_DELETE_REQUEST3
         };
     }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfDeleteRequest((DeleteRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableDeleteRequest((DeleteRequest) original);
+    }
+
+    @Test(dataProvider = "deleteRequests")
+    public void testModifiableRequest(final DeleteRequest original) {
+        final String newValue = "uid=newName";
+        final DeleteRequest copy = (DeleteRequest) copyOf(original);
+
+        copy.setName(newValue);
+        assertThat(copy.getName().toString()).isEqualTo(newValue);
+        assertThat(original.getName().toString()).isNotEqualTo(newValue);
+    }
+
+    @Test(dataProvider = "deleteRequests")
+    public void testUnmodifiableRequest(final DeleteRequest original) {
+        final DeleteRequest unmodifiable = (DeleteRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getName().toString()).isEqualTo(original.getName().toString());
+    }
+
+    @Test(dataProvider = "deleteRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetName(final DeleteRequest original) {
+        final DeleteRequest unmodifiable = (DeleteRequest) unmodifiableOf(original);
+        unmodifiable.setName("uid=scarter,ou=people,dc=example,dc=com");
+    }
+
+    @Test(dataProvider = "deleteRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetName2(final DeleteRequest original) {
+        final DeleteRequest unmodifiable = (DeleteRequest) unmodifiableOf(original);
+        unmodifiable.setName(DN.valueOf("uid=scarter,ou=people,dc=example,dc=com"));
+    }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestTestCase.java
index f0c41a2..f5d5679 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestTestCase.java
@@ -29,6 +29,7 @@
 
 import static com.forgerock.opendj.util.StaticUtils.EMPTY_BYTES;
 import static com.forgerock.opendj.util.StaticUtils.getBytes;
+import static org.fest.assertions.Assertions.assertThat;
 import static org.testng.Assert.assertEquals;
 
 import java.util.Arrays;
@@ -41,16 +42,21 @@
  */
 @SuppressWarnings("javadoc")
 public class DigestMD5SASLBindRequestTestCase extends BindRequestTestCase {
+    private static final DigestMD5SASLBindRequest NEW_DIGEST_MD5SASL_BIND_REQUEST = Requests
+            .newDigestMD5SASLBindRequest("id1", EMPTY_BYTES);
+    private static final DigestMD5SASLBindRequest NEW_DIGEST_MD5SASL_BIND_REQUEST2 = Requests
+            .newDigestMD5SASLBindRequest("id2", getBytes("password"));
+
     @DataProvider(name = "DigestMD5SASLBindRequests")
-    public Object[][] getDigestMD5SASLBindRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getDigestMD5SASLBindRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected DigestMD5SASLBindRequest[] createTestRequests() throws Exception {
+    protected DigestMD5SASLBindRequest[] newInstance() {
         return new DigestMD5SASLBindRequest[] {
-                Requests.newDigestMD5SASLBindRequest("id1", EMPTY_BYTES),
-                Requests.newDigestMD5SASLBindRequest("id2", getBytes("password"))
+            NEW_DIGEST_MD5SASL_BIND_REQUEST,
+            NEW_DIGEST_MD5SASL_BIND_REQUEST2
         };
     }
 
@@ -89,4 +95,119 @@
         request.setMaxReceiveBufferSize(1024);
         assertEquals(request.getMaxReceiveBufferSize(), 1024);
     }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfDigestMD5SASLBindRequest((DigestMD5SASLBindRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableDigestMD5SASLBindRequest((DigestMD5SASLBindRequest) original);
+    }
+
+    @Test(dataProvider = "DigestMD5SASLBindRequests")
+    public void testModifiableRequest(final DigestMD5SASLBindRequest original) {
+        final String authID = "u:user.0";
+        final String azID = "dn:user.0,dc=com";
+        final String cipher = DigestMD5SASLBindRequest.CIPHER_LOW;
+        final String password = "pass";
+        final int maxRBufferSize = 1024;
+        final int maxSBufferSize = 2048;
+        final String realm = "my.domain.com";
+
+        final DigestMD5SASLBindRequest copy = (DigestMD5SASLBindRequest) copyOf(original);
+        copy.setAuthenticationID(authID);
+        copy.setAuthorizationID(azID);
+        copy.setCipher(cipher);
+        copy.setPassword(password.toCharArray());
+        copy.setMaxReceiveBufferSize(maxRBufferSize);
+        copy.setMaxSendBufferSize(maxSBufferSize);
+        copy.setRealm(realm);
+        copy.setServerAuth(true);
+
+        assertThat(copy.getAuthenticationID()).isEqualTo(authID);
+        assertThat(copy.getAuthorizationID()).isEqualTo(azID);
+        assertThat(copy.getCipher()).isEqualTo(cipher);
+        assertThat(copy.getMaxReceiveBufferSize()).isEqualTo(maxRBufferSize);
+        assertThat(copy.getMaxSendBufferSize()).isEqualTo(maxSBufferSize);
+        assertThat(copy.getRealm()).isEqualTo(realm);
+        assertThat(original.getRealm()).isNotEqualTo(realm);
+    }
+
+    @Test(dataProvider = "DigestMD5SASLBindRequests")
+    public void testUnmodifiableRequest(final DigestMD5SASLBindRequest original) {
+        final DigestMD5SASLBindRequest unmodifiable = (DigestMD5SASLBindRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getAuthorizationID()).isEqualTo(original.getAuthorizationID());
+        assertThat(unmodifiable.getCipher()).isEqualTo(original.getCipher());
+        assertThat(unmodifiable.getMaxReceiveBufferSize()).isEqualTo(original.getMaxReceiveBufferSize());
+        assertThat(unmodifiable.getMaxSendBufferSize()).isEqualTo(original.getMaxSendBufferSize());
+        assertThat(unmodifiable.getRealm()).isEqualTo(original.getRealm());
+    }
+
+    @Test(dataProvider = "DigestMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableAddAdditionalAuthParam(final DigestMD5SASLBindRequest original) {
+        final DigestMD5SASLBindRequest unmodifiable = (DigestMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.addAdditionalAuthParam("id2", "value");
+    }
+
+    @Test(dataProvider = "DigestMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableAddQOP(final DigestMD5SASLBindRequest original) {
+        final DigestMD5SASLBindRequest unmodifiable = (DigestMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.addQOP(DigestMD5SASLBindRequest.QOP_AUTH, DigestMD5SASLBindRequest.QOP_AUTH_CONF);
+    }
+
+    @Test(dataProvider = "DigestMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAuthenticationID(final DigestMD5SASLBindRequest original) {
+        final DigestMD5SASLBindRequest unmodifiable = (DigestMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setAuthenticationID("dn: uid=scarter,ou=people,dc=example,dc=com");
+    }
+
+    @Test(dataProvider = "DigestMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAuthorizationID(final DigestMD5SASLBindRequest original) {
+        final DigestMD5SASLBindRequest unmodifiable = (DigestMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setAuthorizationID("dn: uid=scarter,ou=people,dc=example,dc=com");
+    }
+
+    @Test(dataProvider = "DigestMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetCipher(final DigestMD5SASLBindRequest original) {
+        final DigestMD5SASLBindRequest unmodifiable = (DigestMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setCipher(DigestMD5SASLBindRequest.CIPHER_LOW);
+    }
+
+    @Test(dataProvider = "DigestMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetMaxReceiveBufferSize(final DigestMD5SASLBindRequest original) {
+        final DigestMD5SASLBindRequest unmodifiable = (DigestMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setMaxReceiveBufferSize(1048);
+    }
+
+    @Test(dataProvider = "DigestMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetMaxSendBufferSize(final DigestMD5SASLBindRequest original) {
+        final DigestMD5SASLBindRequest unmodifiable = (DigestMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setMaxSendBufferSize(1048);
+    }
+
+    @Test(dataProvider = "DigestMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetPassword(final DigestMD5SASLBindRequest original) {
+        final DigestMD5SASLBindRequest unmodifiable = (DigestMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setPassword("password".getBytes());
+    }
+
+    @Test(dataProvider = "DigestMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetPassword2(final DigestMD5SASLBindRequest original) {
+        final DigestMD5SASLBindRequest unmodifiable = (DigestMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setPassword("passworda".toCharArray());
+    }
+
+    @Test(dataProvider = "DigestMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetRealm(final DigestMD5SASLBindRequest original) {
+        final DigestMD5SASLBindRequest unmodifiable = (DigestMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setRealm("my.domain");
+    }
+
+    @Test(dataProvider = "DigestMD5SASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetServerAuth(final DigestMD5SASLBindRequest original) {
+        final DigestMD5SASLBindRequest unmodifiable = (DigestMD5SASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setServerAuth(true);
+    }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ExtendedRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ExtendedRequestTestCase.java
index d40e4b5..49593db 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ExtendedRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ExtendedRequestTestCase.java
@@ -35,8 +35,9 @@
  * Tests various extended requests.
  */
 @SuppressWarnings("javadoc")
-public abstract class ExtendedRequestTestCase extends RequestTestCase {
-    @Test(dataProvider = "testRequests")
+public abstract class ExtendedRequestTestCase extends RequestsTestCase {
+
+    @Test(dataProvider = "ExtendedRequests")
     public void testDecoder(final ExtendedRequest<?> request) throws Exception {
         final ExtendedResultDecoder<?> decoder = request.getResultDecoder();
         assertNotNull(decoder);
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestTestCase.java
index 7b27ca9..4b5eb5e 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestTestCase.java
@@ -27,20 +27,59 @@
 
 package org.forgerock.opendj.ldap.requests;
 
+import static org.fest.assertions.Assertions.assertThat;
+
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 /**
  * Tests the external SASL Bind requests.
  */
 @SuppressWarnings("javadoc")
 public class ExternalSASLBindRequestTestCase extends BindRequestTestCase {
+    private static final ExternalSASLBindRequest NEW_EXTERNAL_SASL_BIND_REQUEST = Requests.newExternalSASLBindRequest();
+
     @DataProvider(name = "ExternalSASLBindRequests")
-    public Object[][] getExternalSASLBindRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getExternalSASLBindRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected ExternalSASLBindRequest[] createTestRequests() throws Exception {
-        return new ExternalSASLBindRequest[] { Requests.newExternalSASLBindRequest() };
+    protected ExternalSASLBindRequest[] newInstance() {
+        return new ExternalSASLBindRequest[] {
+            NEW_EXTERNAL_SASL_BIND_REQUEST };
+    }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfExternalSASLBindRequest((ExternalSASLBindRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableExternalSASLBindRequest((ExternalSASLBindRequest) original);
+    }
+
+    @Test(dataProvider = "ExternalSASLBindRequests")
+    public void testModifiableRequest(final ExternalSASLBindRequest original) {
+        final String authID = "u:user.0";
+        final ExternalSASLBindRequest copy = (ExternalSASLBindRequest) copyOf(original);
+        copy.setAuthorizationID(authID);
+        assertThat(copy.getAuthorizationID()).isEqualTo(authID);
+        assertThat(copy.getSASLMechanism()).isEqualTo(original.getSASLMechanism());
+    }
+
+    @Test(dataProvider = "ExternalSASLBindRequests")
+    public void testUnmodifiableRequest(final ExternalSASLBindRequest original) {
+        final ExternalSASLBindRequest unmodifiable = (ExternalSASLBindRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getAuthorizationID()).isEqualTo(original.getAuthorizationID());
+        assertThat(unmodifiable.getAuthenticationType()).isEqualTo(original.getAuthenticationType());
+        assertThat(unmodifiable.getSASLMechanism()).isEqualTo(original.getSASLMechanism());
+    }
+
+    @Test(dataProvider = "ExternalSASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAuthorizationID(final ExternalSASLBindRequest original) {
+        final ExternalSASLBindRequest unmodifiable = (ExternalSASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setAuthorizationID("dn: uid=scarter,ou=people,dc=example,dc=com");
     }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestTestCase.java
index bcace9e..e4f272d 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestTestCase.java
@@ -29,10 +29,13 @@
 
 import static com.forgerock.opendj.util.StaticUtils.EMPTY_BYTES;
 import static com.forgerock.opendj.util.StaticUtils.getBytes;
+import static org.fest.assertions.Assertions.assertThat;
 import static org.testng.Assert.assertEquals;
 
 import java.util.Arrays;
 
+import javax.security.auth.Subject;
+
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
@@ -41,16 +44,22 @@
  */
 @SuppressWarnings("javadoc")
 public class GSSAPISASLBindRequestTestCase extends BindRequestTestCase {
+
+    private static final GSSAPISASLBindRequest NEW_GSSAPISASL_BIND_REQUEST = Requests.newGSSAPISASLBindRequest("id1",
+            EMPTY_BYTES);
+    private static final GSSAPISASLBindRequest NEW_GSSAPISASL_BIND_REQUEST2 = Requests.newGSSAPISASLBindRequest("id2",
+            getBytes("password"));
+
     @DataProvider(name = "GSSAPISASLBindRequests")
-    public Object[][] getGSSAPISASLBindRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getGSSAPISASLBindRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected GSSAPISASLBindRequest[] createTestRequests() throws Exception {
+    protected GSSAPISASLBindRequest[] newInstance() {
         return new GSSAPISASLBindRequest[] {
-                Requests.newGSSAPISASLBindRequest("id1", EMPTY_BYTES),
-                Requests.newGSSAPISASLBindRequest("id2", getBytes("password"))
+            NEW_GSSAPISASL_BIND_REQUEST,
+            NEW_GSSAPISASL_BIND_REQUEST2
         };
     }
 
@@ -86,4 +95,116 @@
         request.setMaxReceiveBufferSize(512);
         assertEquals(request.getMaxReceiveBufferSize(), 512);
     }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfGSSAPISASLBindRequest((GSSAPISASLBindRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableGSSAPISASLBindRequest((GSSAPISASLBindRequest) original);
+    }
+
+    @Test(dataProvider = "GSSAPISASLBindRequests")
+    public void testModifiableRequest(final GSSAPISASLBindRequest original) {
+        final String authID = "u:user.0";
+        final String azID = "dn:user.0,dc=com";
+        final String password = "pass";
+        final int maxRBufferSize = 1024;
+        final int maxSBufferSize = 2048;
+        final String realm = "my.domain.com";
+        final Subject subject = new Subject();
+        subject.setReadOnly();
+
+        final GSSAPISASLBindRequest copy = (GSSAPISASLBindRequest) copyOf(original);
+        copy.setAuthenticationID(authID);
+        copy.setAuthorizationID(azID);
+        copy.setPassword(password.toCharArray());
+        copy.setMaxReceiveBufferSize(maxRBufferSize);
+        copy.setMaxSendBufferSize(maxSBufferSize);
+        copy.setRealm(realm);
+        copy.setServerAuth(true);
+        copy.setSubject(subject);
+
+        assertThat(copy.getAuthenticationID()).isEqualTo(authID);
+        assertThat(copy.getAuthorizationID()).isEqualTo(azID);
+        assertThat(copy.getMaxReceiveBufferSize()).isEqualTo(maxRBufferSize);
+        assertThat(copy.getMaxSendBufferSize()).isEqualTo(maxSBufferSize);
+        assertThat(copy.getRealm()).isEqualTo(realm);
+        assertThat(original.getRealm()).isNotEqualTo(realm);
+        assertThat(copy.getSubject()).isEqualTo(subject);
+        assertThat(original.getSubject()).isNotEqualTo(subject);
+    }
+
+    @Test(dataProvider = "GSSAPISASLBindRequests")
+    public void testUnmodifiableRequest(final GSSAPISASLBindRequest original) {
+        final GSSAPISASLBindRequest unmodifiable = (GSSAPISASLBindRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getAuthorizationID()).isEqualTo(original.getAuthorizationID());
+        assertThat(unmodifiable.getMaxReceiveBufferSize()).isEqualTo(original.getMaxReceiveBufferSize());
+        assertThat(unmodifiable.getMaxSendBufferSize()).isEqualTo(original.getMaxSendBufferSize());
+        assertThat(unmodifiable.getRealm()).isEqualTo(original.getRealm());
+        assertThat(unmodifiable.getSubject()).isEqualTo(original.getSubject());
+        assertThat(unmodifiable.getSASLMechanism()).isEqualTo(original.getSASLMechanism());
+    }
+
+    @Test(dataProvider = "GSSAPISASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableAddAdditionalAuthParam(final GSSAPISASLBindRequest original) {
+        final GSSAPISASLBindRequest unmodifiable = (GSSAPISASLBindRequest) unmodifiableOf(original);
+        unmodifiable.addAdditionalAuthParam("id2", "value");
+    }
+
+    @Test(dataProvider = "GSSAPISASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableAddQOP(final GSSAPISASLBindRequest original) {
+        final GSSAPISASLBindRequest unmodifiable = (GSSAPISASLBindRequest) unmodifiableOf(original);
+        unmodifiable.addQOP(GSSAPISASLBindRequest.QOP_AUTH, GSSAPISASLBindRequest.QOP_AUTH_CONF);
+    }
+
+    @Test(dataProvider = "GSSAPISASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAuthenticationID(final GSSAPISASLBindRequest original) {
+        final GSSAPISASLBindRequest unmodifiable = (GSSAPISASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setAuthenticationID("dn: uid=scarter,ou=people,dc=example,dc=com");
+    }
+
+    @Test(dataProvider = "GSSAPISASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAuthorizationID(final GSSAPISASLBindRequest original) {
+        final GSSAPISASLBindRequest unmodifiable = (GSSAPISASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setAuthorizationID("dn: uid=scarter,ou=people,dc=example,dc=com");
+    }
+
+    @Test(dataProvider = "GSSAPISASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetMaxReceiveBufferSize(final GSSAPISASLBindRequest original) {
+        final GSSAPISASLBindRequest unmodifiable = (GSSAPISASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setMaxReceiveBufferSize(1048);
+    }
+
+    @Test(dataProvider = "GSSAPISASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetMaxSendBufferSize(final GSSAPISASLBindRequest original) {
+        final GSSAPISASLBindRequest unmodifiable = (GSSAPISASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setMaxSendBufferSize(1048);
+    }
+
+    @Test(dataProvider = "GSSAPISASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetPassword(final GSSAPISASLBindRequest original) {
+        final GSSAPISASLBindRequest unmodifiable = (GSSAPISASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setPassword("password".getBytes());
+    }
+
+    @Test(dataProvider = "GSSAPISASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetPassword2(final GSSAPISASLBindRequest original) {
+        final GSSAPISASLBindRequest unmodifiable = (GSSAPISASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setPassword("password".toCharArray());
+    }
+
+    @Test(dataProvider = "GSSAPISASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetRealm(final GSSAPISASLBindRequest original) {
+        final GSSAPISASLBindRequest unmodifiable = (GSSAPISASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setRealm("my.domain");
+    }
+
+    @Test(dataProvider = "GSSAPISASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetServerAuth(final GSSAPISASLBindRequest original) {
+        final GSSAPISASLBindRequest unmodifiable = (GSSAPISASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setServerAuth(true);
+    }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GenericBindRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GenericBindRequestTestCase.java
index 2d662a6..e7eeaa2 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GenericBindRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GenericBindRequestTestCase.java
@@ -29,9 +29,11 @@
 
 import static com.forgerock.opendj.util.StaticUtils.EMPTY_BYTES;
 import static com.forgerock.opendj.util.StaticUtils.getBytes;
+import static org.fest.assertions.Assertions.assertThat;
 
 import org.forgerock.opendj.io.LDAP;
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 
 /**
@@ -39,18 +41,75 @@
  */
 @SuppressWarnings("javadoc")
 public class GenericBindRequestTestCase extends BindRequestTestCase {
+
+    private static final GenericBindRequest NEW_GENERIC_BIND_REQUEST = Requests.newGenericBindRequest(
+            LDAP.TYPE_AUTHENTICATION_SASL, EMPTY_BYTES);
+    private static final GenericBindRequest NEW_GENERIC_BIND_REQUEST2 = Requests.newGenericBindRequest(
+            LDAP.TYPE_AUTHENTICATION_SIMPLE, getBytes("password"));
+    private static final GenericBindRequest NEW_GENERIC_BIND_REQUEST3 = Requests.newGenericBindRequest("username",
+            LDAP.TYPE_AUTHENTICATION_SIMPLE, getBytes("password"));
+
     @DataProvider(name = "GenericBindRequests")
-    public Object[][] getGenericBindRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getGenericBindRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected GenericBindRequest[] createTestRequests() throws Exception {
+    protected GenericBindRequest[] newInstance() {
         return new GenericBindRequest[] {
-                Requests.newGenericBindRequest(LDAP.TYPE_AUTHENTICATION_SASL, EMPTY_BYTES),
-                Requests.newGenericBindRequest(LDAP.TYPE_AUTHENTICATION_SIMPLE, getBytes("password")),
-                Requests.newGenericBindRequest("username", LDAP.TYPE_AUTHENTICATION_SIMPLE,
-                        getBytes("password"))
+            NEW_GENERIC_BIND_REQUEST,
+            NEW_GENERIC_BIND_REQUEST2,
+            NEW_GENERIC_BIND_REQUEST3
         };
     }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfGenericBindRequest((GenericBindRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableGenericBindRequest((GenericBindRequest) original);
+    }
+
+    @Test(dataProvider = "GenericBindRequests")
+    public void testModifiableRequest(final GenericBindRequest original) {
+        final String password = "pass";
+        final String newName = "uid:user.0";
+
+        final GenericBindRequest copy = (GenericBindRequest) copyOf(original);
+        copy.setAuthenticationType((byte) 0);
+        copy.setAuthenticationValue(password.getBytes());
+        copy.setName(newName);
+
+        assertThat(copy.getAuthenticationType()).isEqualTo((byte) 0);
+        assertThat(original.getAuthenticationType()).isNotEqualTo((byte) 0);
+        assertThat(copy.getAuthenticationValue()).isEqualTo(password.getBytes());
+    }
+
+    @Test(dataProvider = "GenericBindRequests")
+    public void testUnmodifiableRequest(final GenericBindRequest original) {
+        final GenericBindRequest unmodifiable = (GenericBindRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getAuthenticationType()).isEqualTo(original.getAuthenticationType());
+        assertThat(unmodifiable.getAuthenticationValue()).isEqualTo(original.getAuthenticationValue());
+    }
+
+    @Test(dataProvider = "GenericBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetName(final GenericBindRequest original) {
+        final GenericBindRequest unmodifiable = (GenericBindRequest) unmodifiableOf(original);
+        unmodifiable.setName("");
+    }
+
+    @Test(dataProvider = "GenericBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAuthenticationType(final GenericBindRequest original) {
+        final GenericBindRequest unmodifiable = (GenericBindRequest) unmodifiableOf(original);
+        unmodifiable.setAuthenticationType((byte) 0xA3);
+    }
+
+    @Test(dataProvider = "GenericBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAuthenticationValue(final GenericBindRequest original) {
+        final GenericBindRequest unmodifiable = (GenericBindRequest) unmodifiableOf(original);
+        unmodifiable.setAuthenticationValue(null);
+    }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GenericExtendedRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GenericExtendedRequestTestCase.java
new file mode 100644
index 0000000..2ba97dc
--- /dev/null
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GenericExtendedRequestTestCase.java
@@ -0,0 +1,114 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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
+ *
+ *
+ *      Copyright 2013 ForgeRock AS
+ */
+
+package org.forgerock.opendj.ldap.requests;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.DecodeOptions;
+import org.forgerock.opendj.ldap.controls.GenericControl;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Tests GENERICEXTENDED requests.
+ */
+@SuppressWarnings("javadoc")
+public class GenericExtendedRequestTestCase extends RequestsTestCase {
+    private static final GenericExtendedRequest NEW_GENERICEXTENDED_REQUEST = Requests
+            .newGenericExtendedRequest("Generic1");
+    private static final GenericExtendedRequest NEW_GENERICEXTENDED_REQUEST2 = Requests
+            .newGenericExtendedRequest("Generic2");
+    private static final GenericExtendedRequest NEW_GENERICEXTENDED_REQUEST3 = Requests
+            .newGenericExtendedRequest("Generic3");
+
+    @DataProvider(name = "GenericExtendedRequests")
+    private Object[][] getGenericExtendedRequests() throws Exception {
+        return createModifiableInstance();
+    }
+
+    @Override
+    protected GenericExtendedRequest[] newInstance() {
+        return new GenericExtendedRequest[] {
+            NEW_GENERICEXTENDED_REQUEST,
+            NEW_GENERICEXTENDED_REQUEST2,
+            NEW_GENERICEXTENDED_REQUEST3 };
+    }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfGenericExtendedRequest((GenericExtendedRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableGenericExtendedRequest((GenericExtendedRequest) original);
+    }
+
+    @Test(dataProvider = "GenericExtendedRequests")
+    public void testModifiableRequest(final GenericExtendedRequest original) {
+        final String newOID = "1.2.3.99";
+        final String newValue = "newValue";
+
+        final GenericExtendedRequest copy = (GenericExtendedRequest) copyOf(original);
+        copy.setOID(newOID);
+        copy.setValue(newValue);
+        assertThat(copy.getOID()).isEqualTo(newOID);
+        assertThat(original.getOID()).isNotEqualTo(newOID);
+    }
+
+    @Test(dataProvider = "GenericExtendedRequests")
+    public void testUnmodifiableRequest(final GenericExtendedRequest original) {
+        final GenericExtendedRequest unmodifiable = (GenericExtendedRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getOID()).isEqualTo(original.getOID());
+        assertThat(unmodifiable.getValue()).isEqualTo(original.getValue());
+        assertThat(unmodifiable.getResultDecoder()).isEqualTo(original.getResultDecoder());
+    }
+
+    @Test(dataProvider = "GenericExtendedRequests")
+    public void testModifiableRequestDecode(final GenericExtendedRequest original) throws DecodeException {
+        final String oid = "1.2.3.4";
+        final String value = "myValue";
+        final GenericControl control = GenericControl.newControl("1.2.3".intern());
+
+        final GenericExtendedRequest copy = (GenericExtendedRequest) copyOf(original);
+        copy.setOID(oid);
+        copy.setValue(value);
+        copy.addControl(control);
+
+        try {
+            GenericExtendedRequest decoded = GenericExtendedRequest.DECODER.decodeExtendedRequest(copy,
+                    new DecodeOptions());
+            assertThat(decoded.getOID()).isEqualTo(oid);
+            assertThat(decoded.getValue()).isEqualTo(ByteString.valueOf(value));
+            assertThat(decoded.getControls().contains(control)).isTrue();
+        } catch (DecodeException e) {
+            throw e;
+        }
+    }
+}
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ModifyDNRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ModifyDNRequestTestCase.java
index 8a60ff6..b130159 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ModifyDNRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ModifyDNRequestTestCase.java
@@ -27,23 +27,109 @@
 
 package org.forgerock.opendj.ldap.requests;
 
+import static org.fest.assertions.Assertions.assertThat;
+
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.RDN;
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 /**
  * Tests the Modify DN requests.
  */
 @SuppressWarnings("javadoc")
-public class ModifyDNRequestTestCase extends RequestTestCase {
+public class ModifyDNRequestTestCase extends RequestsTestCase {
+
+    private static final ModifyDNRequest NEW_MODIFY_DN_REQUEST = Requests.newModifyDNRequest(
+            "uid=user.100,ou=people,o=test", "uid=100.user,ou=people,o=testl");
+    private static final ModifyDNRequest NEW_MODIFY_DN_REQUEST2 = Requests.newModifyDNRequest(
+            "cn=ModifyDNrequesttestcase", "cn=xyz");
+
     @DataProvider(name = "ModifyDNRequests")
-    public Object[][] getModifyDNRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getModifyDNRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected ModifyDNRequest[] createTestRequests() throws Exception {
+    protected ModifyDNRequest[] newInstance() {
         return new ModifyDNRequest[] {
-                Requests.newModifyDNRequest("uid=user.100,ou=people,o=test", "uid=100.user,ou=people,o=testl"),
-                Requests.newModifyDNRequest("cn=ModifyDNrequesttestcase", "cn=xyz"),
+            NEW_MODIFY_DN_REQUEST,
+            NEW_MODIFY_DN_REQUEST2,
         };
     }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfModifyDNRequest((ModifyDNRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableModifyDNRequest((ModifyDNRequest) original);
+    }
+
+    @Test(dataProvider = "ModifyDNRequests")
+    public void testModifiableRequest(final ModifyDNRequest original) {
+        final String newDN = "cn=Ted,ou=People,dc=example,dc=com";
+        final String superior = "ou=People,dc=example,dc=org";
+
+        final ModifyDNRequest copy = (ModifyDNRequest) copyOf(original);
+        copy.setName(DN.valueOf(newDN));
+        copy.setDeleteOldRDN(true);
+        copy.setNewSuperior(superior);
+        assertThat(copy.getName().toString()).isEqualTo(newDN);
+        assertThat(copy.getNewSuperior().toString()).isEqualTo(superior);
+        assertThat(original.getNewSuperior()).isNull();
+        assertThat(copy.toString()).contains("deleteOldRDN=true");
+    }
+
+    @Test(dataProvider = "ModifyDNRequests")
+    public void testUnmodifiableRequest(final ModifyDNRequest original) {
+        final ModifyDNRequest unmodifiable = (ModifyDNRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getName().toString()).isEqualTo(original.getName().toString());
+        assertThat(original.getNewSuperior()).isNull();
+        assertThat(unmodifiable.getNewSuperior()).isNull();
+    }
+
+    @Test(dataProvider = "ModifyDNRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetDeleteOldRDN(final ModifyDNRequest original) {
+        final ModifyDNRequest unmodifiable = (ModifyDNRequest) unmodifiableOf(original);
+        unmodifiable.setDeleteOldRDN(true);
+    }
+
+    @Test(dataProvider = "ModifyDNRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetName(final ModifyDNRequest original) {
+        final ModifyDNRequest unmodifiable = (ModifyDNRequest) unmodifiableOf(original);
+        unmodifiable.setName(DN.valueOf("uid=scarter,ou=people,dc=example,dc=com"));
+    }
+
+    @Test(dataProvider = "ModifyDNRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetName2(final ModifyDNRequest original) {
+        final ModifyDNRequest unmodifiable = (ModifyDNRequest) unmodifiableOf(original);
+        unmodifiable.setName("uid=scarter,ou=people,dc=example,dc=com");
+    }
+
+    @Test(dataProvider = "ModifyDNRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetNewRDN(final ModifyDNRequest original) {
+        final ModifyDNRequest unmodifiable = (ModifyDNRequest) unmodifiableOf(original);
+        unmodifiable.setNewRDN("dc=example,dc=org");
+    }
+
+    @Test(dataProvider = "ModifyDNRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetNewRDN2(final ModifyDNRequest original) {
+        final ModifyDNRequest unmodifiable = (ModifyDNRequest) unmodifiableOf(original);
+        unmodifiable.setNewRDN(RDN.valueOf("dc=example,dc=org"));
+    }
+
+    @Test(dataProvider = "ModifyDNRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetNewSuperior(final ModifyDNRequest original) {
+        final ModifyDNRequest unmodifiable = (ModifyDNRequest) unmodifiableOf(original);
+        unmodifiable.setNewSuperior("ou=people2,dc=example,dc=com");
+    }
+
+    @Test(dataProvider = "ModifyDNRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetNewSuperior2(final ModifyDNRequest original) {
+        final ModifyDNRequest unmodifiable = (ModifyDNRequest) unmodifiableOf(original);
+        unmodifiable.setNewSuperior(DN.valueOf("ou=people2,dc=example,dc=com"));
+    }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ModifyRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ModifyRequestTestCase.java
index b4aeda4..fdcdf76 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ModifyRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ModifyRequestTestCase.java
@@ -27,30 +27,93 @@
 
 package org.forgerock.opendj.ldap.requests;
 
+import static org.fest.assertions.Assertions.assertThat;
+
 import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.LinkedAttribute;
+import org.forgerock.opendj.ldap.Modification;
 import org.forgerock.opendj.ldap.ModificationType;
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 /**
  * Tests the modify request.
  */
 @SuppressWarnings("javadoc")
-public class ModifyRequestTestCase extends RequestTestCase {
+public class ModifyRequestTestCase extends RequestsTestCase {
+
+    private static final ModifyRequest ADD_MODIFICATION = Requests.newModifyRequest(DN.valueOf("uid=Modifyrequest1"))
+            .addModification(ModificationType.ADD, "userpassword", "password");
+    private static final ModifyRequest ADD_MODIFICATION2 = Requests.newModifyRequest("cn=Modifyrequesttestcase")
+            .addModification(ModificationType.ADD, "userpassword", "password");
+    private static final ModifyRequest NEW_MODIFY_REQUEST = Requests.newModifyRequest("dn: ou=People,o=test",
+            "changetype: modify", "add: userpassword", "userpassword: password");
+
     @DataProvider(name = "ModifyRequests")
-    public Object[][] getModifyRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getModifyRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected ModifyRequest[] createTestRequests() throws Exception {
+    protected ModifyRequest[] newInstance() {
         return new ModifyRequest[] {
-                Requests.newModifyRequest(DN.valueOf("uid=Modifyrequest1")).addModification(
-                        ModificationType.ADD, "userpassword", "password"),
-                Requests.newModifyRequest("cn=Modifyrequesttestcase").addModification(
-                        ModificationType.ADD, "userpassword", "password"),
-                Requests.newModifyRequest("dn: ou=People,o=test", "changetype: modify",
-                        "add: userpassword", "userpassword: password")
+            ADD_MODIFICATION,
+            ADD_MODIFICATION2,
+            NEW_MODIFY_REQUEST
         };
     }
 
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfModifyRequest((ModifyRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableModifyRequest((ModifyRequest) original);
+    }
+
+    @Test(dataProvider = "ModifyRequests")
+    public void testModifiableRequest(final ModifyRequest original) {
+        final String newDN = "cn=Ted,ou=People,dc=example,dc=com";
+
+        final ModifyRequest copy = (ModifyRequest) copyOf(original);
+        copy.setName(DN.valueOf(newDN));
+        assertThat(copy.getName().toString()).isEqualTo(newDN);
+        assertThat(copy.toString()).contains("dn=" + newDN);
+    }
+
+    @Test(dataProvider = "ModifyRequests")
+    public void testUnmodifiableRequest(final ModifyRequest original) {
+        final ModifyRequest unmodifiable = (ModifyRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getName().toString()).isEqualTo(original.getName().toString());
+        assertThat(unmodifiable.getModifications().size()).isEqualTo(original.getModifications().size());
+
+    }
+
+    @Test(dataProvider = "ModifyRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableAddModification(final ModifyRequest original) {
+        final ModifyRequest unmodifiable = (ModifyRequest) unmodifiableOf(original);
+        unmodifiable.addModification(ModificationType.ADD, "member",
+                DN.valueOf("uid=scarter,ou=people,dc=example,dc=com"));
+    }
+
+    @Test(dataProvider = "ModifyRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableAddModification2(final ModifyRequest original) {
+        final ModifyRequest unmodifiable = (ModifyRequest) unmodifiableOf(original);
+        unmodifiable.addModification(new Modification(ModificationType.ADD,
+                new LinkedAttribute("description", "value1")));
+    }
+
+    @Test(dataProvider = "ModifyRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetName(final ModifyRequest original) {
+        final ModifyRequest unmodifiable = (ModifyRequest) unmodifiableOf(original);
+        unmodifiable.setName(DN.valueOf("uid=scarter,ou=people,dc=example,dc=com"));
+    }
+
+    @Test(dataProvider = "ModifyRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetName2(final ModifyRequest original) {
+        final ModifyRequest unmodifiable = (ModifyRequest) unmodifiableOf(original);
+        unmodifiable.setName("uid=scarter,ou=people,dc=example,dc=com");
+    }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/PasswordModifyExtendedRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/PasswordModifyExtendedRequestTestCase.java
new file mode 100644
index 0000000..93f7005
--- /dev/null
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/PasswordModifyExtendedRequestTestCase.java
@@ -0,0 +1,153 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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
+ *
+ *
+ *      Copyright 2013 ForgeRock AS.
+ */
+
+package org.forgerock.opendj.ldap.requests;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.DecodeOptions;
+import org.forgerock.opendj.ldap.controls.GenericControl;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Tests PASSWORDMODIFYEXTENDED requests.
+ */
+@SuppressWarnings("javadoc")
+public class PasswordModifyExtendedRequestTestCase extends RequestsTestCase {
+    private static final PasswordModifyExtendedRequest NEW_PASSWORDMODIFYEXTENDED_REQUEST = Requests
+            .newPasswordModifyExtendedRequest();
+
+    @DataProvider(name = "passwordModifyExtendedRequests")
+    private Object[][] getPasswordModifyExtendedRequests() throws Exception {
+        return createModifiableInstance();
+    }
+
+    @Override
+    protected PasswordModifyExtendedRequest[] newInstance() {
+        return new PasswordModifyExtendedRequest[] {
+            NEW_PASSWORDMODIFYEXTENDED_REQUEST
+        };
+    }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfPasswordModifyExtendedRequest((PasswordModifyExtendedRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiablePasswordModifyExtendedRequest((PasswordModifyExtendedRequest) original);
+    }
+
+    @Test(dataProvider = "passwordModifyExtendedRequests")
+    public void testModifiableRequest(final PasswordModifyExtendedRequest original) {
+        final String password = "password";
+        final String oldPassword = "oldPassword";
+        final String userIdentity = "user.0";
+
+        final PasswordModifyExtendedRequest copy = (PasswordModifyExtendedRequest) copyOf(original);
+        copy.setNewPassword(password.toCharArray());
+        copy.setOldPassword(oldPassword.toCharArray());
+        copy.setUserIdentity(ByteString.valueOf(userIdentity));
+
+        assertThat(copy.getNewPassword()).isEqualTo(password.getBytes());
+        assertThat(original.getNewPassword()).isNull();
+        assertThat(copy.getOldPassword()).isEqualTo(oldPassword.getBytes());
+        assertThat(copy.getOID()).isEqualTo(original.getOID());
+    }
+
+    @Test(dataProvider = "passwordModifyExtendedRequests")
+    public void testModifiableRequestDecode(final PasswordModifyExtendedRequest original) throws DecodeException {
+        final String password = "";
+        final String oldPassword = "old";
+        final String userIdentity = "uid=scarter,ou=people,dc=example,dc=com";
+        final GenericControl control = GenericControl.newControl("1.2.3".intern());
+
+        final PasswordModifyExtendedRequest copy = (PasswordModifyExtendedRequest) copyOf(original);
+        copy.setNewPassword(password.toCharArray());
+        copy.setUserIdentity(userIdentity);
+        copy.setOldPassword(oldPassword.getBytes());
+        copy.addControl(control);
+
+        try {
+            PasswordModifyExtendedRequest decoded = PasswordModifyExtendedRequest.DECODER.decodeExtendedRequest(copy,
+                    new DecodeOptions());
+            assertThat(decoded.getNewPassword()).isEqualTo(password.getBytes());
+            assertThat(decoded.getOldPassword()).isEqualTo(oldPassword.getBytes());
+            assertThat(decoded.getUserIdentity()).isEqualTo(ByteString.valueOf(userIdentity));
+            assertThat(decoded.getControls().contains(control)).isTrue();
+        } catch (DecodeException e) {
+            throw e;
+        }
+    }
+
+    @Test(dataProvider = "passwordModifyExtendedRequests")
+    public void testUnmodifiableRequest(final PasswordModifyExtendedRequest original) {
+        final PasswordModifyExtendedRequest unmodifiable = (PasswordModifyExtendedRequest) unmodifiableOf(original);
+        original.setUserIdentity("uid=scarter,ou=people,dc=example,dc=com");
+        original.setOldPassword("old".getBytes());
+        assertThat(unmodifiable.getOID()).isEqualTo(original.getOID());
+        assertThat(unmodifiable.getUserIdentity()).isEqualTo(original.getUserIdentity());
+        assertThat(unmodifiable.getUserIdentityAsString()).isEqualTo(original.getUserIdentityAsString());
+        original.setNewPassword("carter".getBytes());
+        assertThat(unmodifiable.getNewPassword()).isEqualTo(original.getNewPassword());
+        assertThat(unmodifiable.getOldPassword()).isEqualTo(original.getOldPassword());
+
+    }
+
+    @Test(dataProvider = "passwordModifyExtendedRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetNewPassword(final PasswordModifyExtendedRequest original) {
+        final PasswordModifyExtendedRequest unmodifiable = (PasswordModifyExtendedRequest) unmodifiableOf(original);
+        unmodifiable.setNewPassword("password".toCharArray());
+    }
+
+    @Test(dataProvider = "passwordModifyExtendedRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetNewPassword2(final PasswordModifyExtendedRequest original) {
+        final PasswordModifyExtendedRequest unmodifiable = (PasswordModifyExtendedRequest) unmodifiableOf(original);
+        unmodifiable.setNewPassword("password".getBytes());
+    }
+
+    @Test(dataProvider = "passwordModifyExtendedRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetOldPassword(final PasswordModifyExtendedRequest original) {
+        final PasswordModifyExtendedRequest unmodifiable = (PasswordModifyExtendedRequest) unmodifiableOf(original);
+        unmodifiable.setOldPassword("password".toCharArray());
+    }
+
+    @Test(dataProvider = "passwordModifyExtendedRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetOldPassword2(final PasswordModifyExtendedRequest original) {
+        final PasswordModifyExtendedRequest unmodifiable = (PasswordModifyExtendedRequest) unmodifiableOf(original);
+        unmodifiable.setOldPassword("password".getBytes());
+    }
+
+    @Test(dataProvider = "passwordModifyExtendedRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetUserIdentity(final PasswordModifyExtendedRequest original) {
+        final PasswordModifyExtendedRequest unmodifiable = (PasswordModifyExtendedRequest) unmodifiableOf(original);
+        unmodifiable.setUserIdentity("uid=scarter,ou=people,dc=example,dc=com");
+    }
+}
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestTestCase.java
index bd53a0f..bc71c0f 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestTestCase.java
@@ -29,24 +29,92 @@
 
 import static com.forgerock.opendj.util.StaticUtils.EMPTY_BYTES;
 import static com.forgerock.opendj.util.StaticUtils.getBytes;
+import static org.fest.assertions.Assertions.assertThat;
 
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 /**
  * Tests Plain SASL Bind requests.
  */
 @SuppressWarnings("javadoc")
-public class PlainSASLBindRequestTestCase extends BindRequestTestCase {
+public class PlainSASLBindRequestTestCase extends RequestsTestCase {
+
+    private static final PlainSASLBindRequest NEW_PLAIN_SASL_BIND_REQUEST = Requests.newPlainSASLBindRequest("id1",
+            EMPTY_BYTES);
+    private static final PlainSASLBindRequest NEW_PLAIN_SASL_BIND_REQUEST2 = Requests.newPlainSASLBindRequest("id2",
+            getBytes("password"));
+
     @DataProvider(name = "plainSASLBindRequests")
-    public Object[][] getPlainSASLBindRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getPlainSASLBindRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected PlainSASLBindRequest[] createTestRequests() throws Exception {
+    protected PlainSASLBindRequest[] newInstance() {
         return new PlainSASLBindRequest[] {
-                Requests.newPlainSASLBindRequest("id1", EMPTY_BYTES),
-                Requests.newPlainSASLBindRequest("id2", getBytes("password"))
+            NEW_PLAIN_SASL_BIND_REQUEST,
+            NEW_PLAIN_SASL_BIND_REQUEST2
         };
     }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfPlainSASLBindRequest((PlainSASLBindRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiablePlainSASLBindRequest((PlainSASLBindRequest) original);
+    }
+
+    @Test(dataProvider = "plainSASLBindRequests")
+    public void testModifiableRequest(final PlainSASLBindRequest original) {
+        final String authID = "u:user.0";
+        final String azID = "dn:user.0,dc=com";
+        final String password = "pass";
+
+        final PlainSASLBindRequest copy = (PlainSASLBindRequest) copyOf(original);
+        copy.setAuthenticationID(authID);
+        copy.setAuthorizationID(azID);
+        copy.setPassword(password.toCharArray());
+
+        assertThat(copy.getAuthenticationID()).isEqualTo(authID);
+        assertThat(copy.getAuthorizationID()).isEqualTo(azID);
+        assertThat(original.getAuthenticationID()).isNotEqualTo(copy.getAuthenticationID());
+        assertThat(original.getAuthorizationID()).isNotEqualTo(copy.getAuthorizationID());
+    }
+
+    @Test(dataProvider = "plainSASLBindRequests")
+    public void testUnmodifiableRequest(final PlainSASLBindRequest original) {
+        final PlainSASLBindRequest unmodifiable = (PlainSASLBindRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getName()).isEqualTo(original.getName());
+        assertThat(unmodifiable.getAuthorizationID()).isEqualTo(original.getAuthorizationID());
+        assertThat(unmodifiable.getAuthenticationID()).isEqualTo(original.getAuthenticationID());
+        assertThat(unmodifiable.getSASLMechanism()).isEqualTo(original.getSASLMechanism());
+    }
+
+    @Test(dataProvider = "plainSASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAuthenticationID(final PlainSASLBindRequest original) {
+        final PlainSASLBindRequest unmodifiable = (PlainSASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setAuthenticationID("dn: uid=scarter,ou=people,dc=example,dc=com");
+    }
+
+    @Test(dataProvider = "plainSASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAuthorizationID(final PlainSASLBindRequest original) {
+        final PlainSASLBindRequest unmodifiable = (PlainSASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setAuthorizationID("dn: uid=scarter,ou=people,dc=example,dc=com");
+    }
+
+    @Test(dataProvider = "plainSASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetPassword(final PlainSASLBindRequest original) {
+        final PlainSASLBindRequest unmodifiable = (PlainSASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setPassword("password".toCharArray());
+    }
+
+    @Test(dataProvider = "plainSASLBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetPassword2(final PlainSASLBindRequest original) {
+        final PlainSASLBindRequest unmodifiable = (PlainSASLBindRequest) unmodifiableOf(original);
+        unmodifiable.setPassword("password".getBytes());
+    }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/RequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/RequestTestCase.java
deleted file mode 100644
index 4800186..0000000
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/RequestTestCase.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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 legal-notices/CDDLv1_0.txt
- * or http://forgerock.org/license/CDDLv1.0.html.
- * 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 legal-notices/CDDLv1_0.txt.
- * 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
- *
- *
- *      Copyright 2010 Sun Microsystems, Inc.
- */
-
-package org.forgerock.opendj.ldap.requests;
-
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import org.forgerock.opendj.ldap.Connection;
-import org.forgerock.opendj.ldap.DecodeException;
-import org.forgerock.opendj.ldap.DecodeOptions;
-import org.forgerock.opendj.ldap.TestCaseUtils;
-import org.forgerock.opendj.ldap.controls.Control;
-import org.forgerock.opendj.ldap.controls.ControlDecoder;
-import org.forgerock.opendj.ldap.controls.GenericControl;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-/**
- * Tests the Request class.
- */
-@SuppressWarnings("javadoc")
-public abstract class RequestTestCase extends RequestsTestCase {
-    // Dummy decoder which does nothing.
-    private static class MyDecoder implements ControlDecoder<Control> {
-        public Control decodeControl(final Control control, final DecodeOptions options)
-                throws DecodeException {
-            // do nothing.
-            return control;
-        }
-
-        public String getOID() {
-            return "1.2.3".intern();
-        }
-    }
-
-    // Connection used for sending requests.
-    protected Connection con;
-
-    /**
-     * Request data to be validated.
-     *
-     * @return An array of requests.
-     * @throws Exception
-     */
-    @DataProvider(name = "testRequests")
-    public Object[][] getTestRequests() throws Exception {
-        final Request[] requestArray = createTestRequests();
-        final Object[][] objectArray = new Object[requestArray.length][1];
-
-        for (int i = 0; i < requestArray.length; i++) {
-            objectArray[i][0] = requestArray[i];
-        }
-        return objectArray;
-    }
-
-    /**
-     * Ensures that the LDAP Server is running.
-     *
-     * @throws Exception
-     *             If an unexpected problem occurs.
-     */
-    @BeforeClass()
-    public void startServer() throws Exception {
-        TestCaseUtils.startServer();
-        con = TestCaseUtils.getInternalConnection();
-    }
-
-    @Test(dataProvider = "testRequests")
-    public void testControls(final Request request) throws Exception {
-        // Add an arbitrary control and see if it is present.
-        Control control = GenericControl.newControl("1.2.3".intern());
-        request.addControl(control);
-        assertTrue(request.getControls().size() > 0);
-        final MyDecoder decoder = new MyDecoder();
-        control = request.getControl(decoder, new DecodeOptions());
-        assertNotNull(control);
-    }
-
-    /**
-     * Creates the test requests.
-     *
-     * @return
-     * @throws Exception
-     */
-    protected abstract Request[] createTestRequests() throws Exception;
-}
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/RequestsTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/RequestsTestCase.java
index 05e33bf..cd74dba 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/RequestsTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/RequestsTestCase.java
@@ -27,15 +27,208 @@
 
 package org.forgerock.opendj.ldap.requests;
 
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.fest.assertions.Assertions.assertThat;
+
+import org.forgerock.opendj.ldap.Connection;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.DecodeOptions;
+import org.forgerock.opendj.ldap.TestCaseUtils;
+import org.forgerock.opendj.ldap.controls.Control;
+import org.forgerock.opendj.ldap.controls.ControlDecoder;
+import org.forgerock.opendj.ldap.controls.GenericControl;
 import org.forgerock.testng.ForgeRockTestCase;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 /**
- * An abstract class that all requests unit tests should extend. Requests
- * represents the classes found directly under the package
- * org.forgerock.opendj.ldap.requests.
+ * An abstract class that all requests unit tests should extend. Requests represents the classes found directly under
+ * the package org.forgerock.opendj.ldap.requests.
  */
 
 @Test(groups = { "precommit", "requests", "sdk" })
 public abstract class RequestsTestCase extends ForgeRockTestCase {
+
+    private static final GenericControl NEW_CONTROL = GenericControl.newControl("1.2.3".intern());
+    private static final GenericControl NEW_CONTROL2 = GenericControl.newControl("3.4.5".intern());
+    private static final GenericControl NEW_CONTROL3 = GenericControl.newControl("6.7.8".intern());
+    private static final GenericControl NEW_CONTROL4 = GenericControl.newControl("8.9.0".intern());
+
+    // Dummy decoder which does nothing.
+    private static class MyDecoder implements ControlDecoder<Control> {
+        public Control decodeControl(final Control control, final DecodeOptions options) throws DecodeException {
+            // do nothing.
+            return control;
+        }
+
+        public String getOID() {
+            return "1.2.3".intern();
+        }
+    }
+
+    /**
+     * Ensures that the LDAP Server is running.
+     *
+     * @throws Exception
+     *             If an unexpected problem occurs.
+     */
+    @BeforeClass()
+    public void startServer() throws Exception {
+        TestCaseUtils.startServer();
+        con = TestCaseUtils.getInternalConnection();
+    }
+
+    /**
+     * Creates the requests.
+     *
+     * @return An array of requests.
+     */
+    protected abstract Request[] newInstance();
+
+    /**
+     * Creates a copy of the request.
+     *
+     * @param original
+     *            The original request to copy.
+     * @return A copy of the request.
+     */
+    protected abstract Request copyOf(final Request original);
+
+    /**
+     * Creates an unmodifiable request.
+     *
+     * @param original
+     *            The original request.
+     * @return A unmodifiable request from the original.
+     */
+    protected abstract Request unmodifiableOf(final Request original);
+
+    // Connection used for sending requests.
+    protected Connection con;
+
+    /**
+     * Request data to be validated.
+     *
+     * @return An array of requests.
+     * @throws Exception
+     */
+    @DataProvider(name = "createModifiableInstance")
+    Object[][] createModifiableInstance() throws Exception {
+        final Request[] requestArray = newInstance();
+        final Object[][] objectArray = new Object[requestArray.length][1];
+
+        for (int i = 0; i < requestArray.length; i++) {
+            objectArray[i][0] = requestArray[i];
+        }
+        return objectArray;
+    }
+
+    @DataProvider(name = "createCopyOfInstance")
+    final Object[][] createCopyOfInstance() throws Exception {
+        final Request[] requestArray = newInstance();
+        final Object[][] objectArray = new Object[requestArray.length][2];
+
+        for (int i = 0; i < requestArray.length; i++) {
+            objectArray[i][0] = requestArray[i];
+            objectArray[i][1] = copyOf(requestArray[i]);
+        }
+        return objectArray;
+    }
+
+    @DataProvider(name = "createUnmodifiableInstance")
+    final Object[][] createUnmodifiableInstance() throws Exception {
+        final Request[] requestArray = newInstance();
+        final Object[][] objectArray = new Object[requestArray.length][2];
+
+        for (int i = 0; i < requestArray.length; i++) {
+            objectArray[i][0] = requestArray[i];
+            objectArray[i][1] = unmodifiableOf(requestArray[i]);
+        }
+        return objectArray;
+    }
+
+
+    /**
+     * Adds a control to a request and make sure it is present.
+     *
+     * @param request
+     *            The request to test.
+     * @throws DecodeException
+     *             If the control cannot be decode.
+     */
+    @Test(dataProvider = "createModifiableInstance")
+    public void testAddControl(final Request request) throws DecodeException {
+        assertThat(request.containsControl(NEW_CONTROL.getOID())).isFalse();
+        request.addControl(NEW_CONTROL);
+        assertThat(request.containsControl(NEW_CONTROL.getOID())).isTrue();
+        assertTrue(request.getControls().size() > 0);
+        final MyDecoder decoder = new MyDecoder();
+        Control control = request.getControl(decoder, new DecodeOptions());
+        assertNotNull(control);
+    }
+
+    /**
+     * Adds a control to the original request and make sure the unmodifiable request is affected. Adding a control to
+     * the unmodifiable throws an exception.
+     *
+     * @param original
+     *            The original request.
+     * @param unmodifiable
+     *            The unmodifiable 'view' request.
+     */
+    @Test(dataProvider = "createUnmodifiableInstance", expectedExceptions = UnsupportedOperationException.class)
+    public void testAddControlUnmodifiable(final Request original, final Request unmodifiable) {
+
+        assertThat(unmodifiable.containsControl(NEW_CONTROL2.getOID())).isFalse();
+        assertThat(original.containsControl(NEW_CONTROL2.getOID())).isFalse();
+        original.addControl(NEW_CONTROL2);
+
+        // Unmodifiable is a view of the original request.
+        assertThat(original.containsControl(NEW_CONTROL2.getOID())).isTrue();
+        assertThat(unmodifiable.containsControl(NEW_CONTROL2.getOID())).isTrue();
+
+        unmodifiable.addControl(NEW_CONTROL3);
+    }
+
+    /**
+     * Tests adding a control to the original request. The Copy should not be affected by the modification.
+     *
+     * @param original
+     *            The original request.
+     * @param copy
+     *            Copy of the original request.
+     */
+    @Test(dataProvider = "createCopyOfInstance")
+    public void testAddControlToCopy(final Request original, final Request copy) {
+        assertThat(original.containsControl(NEW_CONTROL3.getOID())).isFalse();
+        assertThat(copy.containsControl(NEW_CONTROL3.getOID())).isFalse();
+
+        original.addControl(NEW_CONTROL3);
+        assertThat(original.containsControl(NEW_CONTROL3.getOID())).isTrue();
+        assertTrue(original.getControls().size() > 0);
+        assertThat(copy.containsControl(NEW_CONTROL3.getOID())).isFalse();
+
+        copy.addControl(NEW_CONTROL4);
+        assertThat(original.containsControl(NEW_CONTROL4.getOID())).isFalse();
+        assertThat(copy.containsControl(NEW_CONTROL4.getOID())).isTrue();
+    }
+
+    /**
+     * The toString function from the copy should always starts with the class name.
+     * <p>
+     * eg. AbandonRequest(requestID=-1...)
+     *
+     * @param original
+     *            The original request.
+     * @param copy
+     *            The copy request.
+     */
+    @Test(dataProvider = "createCopyOfInstance")
+    public void testCopyToStringShouldContainClassName(final Request original, final Request copy) {
+        final String className = copy.getClass().getSimpleName().replace("Impl", "");
+        assertThat(copy.toString().startsWith(className)).isTrue();
+    }
+
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/SearchRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/SearchRequestTestCase.java
index 2d92da6..2042b58 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/SearchRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/SearchRequestTestCase.java
@@ -28,33 +28,36 @@
 import static org.fest.assertions.Assertions.*;
 
 import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.DereferenceAliasesPolicy;
 import org.forgerock.opendj.ldap.Filter;
 import org.forgerock.opendj.ldap.SearchScope;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
 @SuppressWarnings("javadoc")
-public class SearchRequestTestCase extends RequestTestCase {
+public class SearchRequestTestCase extends RequestsTestCase {
+
+    private static final SearchRequest NEW_SEARCH_REQUEST = Requests.newSearchRequest("uid=user.0,ou=people,o=test",
+            SearchScope.BASE_OBJECT, "(uid=user)", "uid", "ou");
+
+    private static final SearchRequest NEW_SEARCH_REQUEST2 = Requests.newSearchRequest("uid=user.0,ou=people,o=test",
+            SearchScope.SINGLE_LEVEL, "(uid=user)", "uid", "ou");
 
     @DataProvider(name = "SearchRequests")
-    public Object[][] getSearchRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getSearchRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected SearchRequest[] createTestRequests() throws Exception {
+    protected SearchRequest[] newInstance() {
         return new SearchRequest[] {
-                Requests.newSearchRequest(
-                        "uid=user.0,ou=people,o=test",
-                        SearchScope.BASE_OBJECT, "(uid=user)", "uid", "ou"),
-                Requests.newSearchRequest("uid=user.0,ou=people,o=test",
-                        SearchScope.SINGLE_LEVEL, "(uid=user)", "uid", "ou") };
+            NEW_SEARCH_REQUEST,
+            NEW_SEARCH_REQUEST2 };
     }
 
     @Test
     public void createRequestForSingleEntrySearch() throws Exception {
-        SearchRequest request = Requests.newSingleEntrySearchRequest(
-                DN.valueOf("uid=user.0,ou=people,o=test"),
+        SearchRequest request = Requests.newSingleEntrySearchRequest(DN.valueOf("uid=user.0,ou=people,o=test"),
                 SearchScope.BASE_OBJECT, Filter.equality("uid", "user"), "uid");
 
         assertThat(request.getSizeLimit()).isEqualTo(1);
@@ -63,8 +66,7 @@
 
     @Test
     public void createRequestForSingleEntrySearchWithStrings() throws Exception {
-        SearchRequest request = Requests.newSingleEntrySearchRequest(
-                "uid=user.0,ou=people,o=test",
+        SearchRequest request = Requests.newSingleEntrySearchRequest("uid=user.0,ou=people,o=test",
                 SearchScope.BASE_OBJECT, "(uid=user)", "uid");
 
         assertThat(request.getSizeLimit()).isEqualTo(1);
@@ -73,10 +75,111 @@
 
     @Test
     public void createRequestWithBaseObjectScope() throws Exception {
-        SearchRequest request = Requests.newSearchRequest(
-                DN.valueOf("uid=user.0,ou=people,o=test"),
+        SearchRequest request = Requests.newSearchRequest(DN.valueOf("uid=user.0,ou=people,o=test"),
                 SearchScope.BASE_OBJECT, Filter.equality("uid", "user"), "uid");
 
         assertThat(request.isSingleEntrySearch()).isTrue();
     }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfSearchRequest((SearchRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableSearchRequest((SearchRequest) original);
+    }
+
+    @Test(dataProvider = "SearchRequests")
+    public void testModifiableRequest(final SearchRequest original) {
+        final String name = "uid=bjensen";
+        final Filter filter = Filter.format("(&(uid=%s)(age>=%s))", "bjensen", 21);
+        final SearchScope scope = SearchScope.BASE_OBJECT;
+        final DereferenceAliasesPolicy policy = DereferenceAliasesPolicy.ALWAYS;
+        final int timeLimit = 10;
+        final int sizeLimit = 15;
+
+        final SearchRequest copy = (SearchRequest) copyOf(original);
+        copy.setName(name);
+        copy.setFilter(filter);
+        copy.setScope(scope);
+        copy.setDereferenceAliasesPolicy(policy);
+        copy.setSizeLimit(sizeLimit);
+        copy.setTimeLimit(timeLimit);
+        copy.setTypesOnly(true);
+
+        assertThat(copy.getName().toString()).isEqualTo(name);
+        assertThat(copy.getFilter()).isEqualTo(filter);
+        assertThat(copy.getScope()).isEqualTo(scope);
+        assertThat(copy.getDereferenceAliasesPolicy()).isEqualTo(policy);
+        assertThat(copy.getTimeLimit()).isEqualTo(timeLimit);
+        assertThat(copy.getSizeLimit()).isEqualTo(sizeLimit);
+        assertThat(copy.isTypesOnly()).isTrue();
+    }
+
+    @Test(dataProvider = "SearchRequests")
+    public void testUnmodifiableRequest(final SearchRequest original) {
+        final SearchRequest unmodifiable = (SearchRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getName().toString()).isEqualTo(original.getName().toString());
+        assertThat(unmodifiable.getFilter()).isEqualTo(original.getFilter());
+        assertThat(unmodifiable.getScope()).isEqualTo(original.getScope());
+        assertThat(unmodifiable.getDereferenceAliasesPolicy()).isEqualTo(original.getDereferenceAliasesPolicy());
+        assertThat(unmodifiable.getTimeLimit()).isEqualTo(original.getTimeLimit());
+        assertThat(unmodifiable.getSizeLimit()).isEqualTo(original.getSizeLimit());
+    }
+
+    @Test(dataProvider = "SearchRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetDereferenceAliasesPolicy(final SearchRequest original) {
+        final SearchRequest unmodifiable = (SearchRequest) unmodifiableOf(original);
+        unmodifiable.setDereferenceAliasesPolicy(DereferenceAliasesPolicy.ALWAYS);
+    }
+
+    @Test(dataProvider = "SearchRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetFilter(final SearchRequest original) {
+        final SearchRequest unmodifiable = (SearchRequest) unmodifiableOf(original);
+        unmodifiable.setFilter(Filter.format("(&(cn=%s)(age>=%s))", "bjensen", 21));
+    }
+
+    @Test(dataProvider = "SearchRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetFilter2(final SearchRequest original) {
+        final SearchRequest unmodifiable = (SearchRequest) unmodifiableOf(original);
+        unmodifiable.setFilter("(&(cn=bjensen)(age>=21))");
+    }
+
+    @Test(dataProvider = "SearchRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetName(final SearchRequest original) {
+        final SearchRequest unmodifiable = (SearchRequest) unmodifiableOf(original);
+        unmodifiable.setName("uid=scarter,ou=people,dc=example,dc=com");
+    }
+
+    @Test(dataProvider = "SearchRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetName2(final SearchRequest original) {
+        final SearchRequest unmodifiable = (SearchRequest) unmodifiableOf(original);
+        unmodifiable.setName(DN.valueOf("uid=scarter,ou=people,dc=example,dc=com"));
+    }
+
+    @Test(dataProvider = "SearchRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetScope(final SearchRequest original) {
+        final SearchRequest unmodifiable = (SearchRequest) unmodifiableOf(original);
+        unmodifiable.setScope(SearchScope.BASE_OBJECT);
+    }
+
+    @Test(dataProvider = "SearchRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetSizeLimit(final SearchRequest original) {
+        final SearchRequest unmodifiable = (SearchRequest) unmodifiableOf(original);
+        unmodifiable.setSizeLimit(10);
+    }
+
+    @Test(dataProvider = "SearchRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetTimeLimit(final SearchRequest original) {
+        final SearchRequest unmodifiable = (SearchRequest) unmodifiableOf(original);
+        unmodifiable.setTimeLimit(200);
+    }
+
+    @Test(dataProvider = "SearchRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetTypesOnly(final SearchRequest original) {
+        final SearchRequest unmodifiable = (SearchRequest) unmodifiableOf(original);
+        unmodifiable.setTypesOnly(false);
+    }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/SimpleBindRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/SimpleBindRequestTestCase.java
index eaa2619..6589483 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/SimpleBindRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/SimpleBindRequestTestCase.java
@@ -27,24 +27,82 @@
 
 package org.forgerock.opendj.ldap.requests;
 
+import static org.fest.assertions.Assertions.assertThat;
+
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 /**
  * Tests Simple Bind requests.
  */
 @SuppressWarnings("javadoc")
 public class SimpleBindRequestTestCase extends BindRequestTestCase {
+    private static final SimpleBindRequest NEW_SIMPLE_BIND_REQUEST = Requests.newSimpleBindRequest();
+    private static final SimpleBindRequest NEW_SIMPLE_BIND_REQUEST2 = Requests.newSimpleBindRequest("username",
+            "password".toCharArray());
+
     @DataProvider(name = "simpleBindRequests")
-    public Object[][] getSimpleBindRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getSimpleBindRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected SimpleBindRequest[] createTestRequests() throws Exception {
+    protected SimpleBindRequest[] newInstance() {
         return new SimpleBindRequest[] {
-            Requests.newSimpleBindRequest(), // anonymous;
-            Requests.newSimpleBindRequest("username", "password".toCharArray())
-        };
+            NEW_SIMPLE_BIND_REQUEST, // anonymous;
+            NEW_SIMPLE_BIND_REQUEST2 };
     }
 
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfSimpleBindRequest((SimpleBindRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableSimpleBindRequest((SimpleBindRequest) original);
+    }
+
+    @Test(dataProvider = "simpleBindRequests")
+    public void testModifiableRequest(final SimpleBindRequest original) {
+        final String name = "user.0";
+        final String password = "pass99";
+
+        final SimpleBindRequest copy = (SimpleBindRequest) copyOf(original);
+
+        copy.setName(name);
+        copy.setPassword(password.getBytes());
+
+        assertThat(copy.getName()).isEqualTo(name);
+        assertThat(copy.getPassword()).isEqualTo(password.getBytes());
+        assertThat(copy.getAuthenticationType()).isEqualTo(original.getAuthenticationType());
+        assertThat(original.getName()).isNotEqualTo(copy.getName());
+        assertThat(original.getPassword()).isNotEqualTo(copy.getPassword());
+    }
+
+    @Test(dataProvider = "simpleBindRequests")
+    public void testUnmodifiableRequest(final SimpleBindRequest original) {
+        final SimpleBindRequest unmodifiable = (SimpleBindRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getAuthenticationType()).isEqualTo(original.getAuthenticationType());
+        assertThat(unmodifiable.getName()).isEqualTo(original.getName());
+        assertThat(unmodifiable.getPassword()).isEqualTo(original.getPassword());
+    }
+
+    @Test(dataProvider = "simpleBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetName2(final SimpleBindRequest original) {
+        final SimpleBindRequest unmodifiable = (SimpleBindRequest) unmodifiableOf(original);
+        unmodifiable.setName("uid=scarter,ou=people,dc=example,dc=com");
+    }
+
+    @Test(dataProvider = "simpleBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetPassword(final SimpleBindRequest original) {
+        final SimpleBindRequest unmodifiable = (SimpleBindRequest) unmodifiableOf(original);
+        unmodifiable.setPassword("password".toCharArray());
+    }
+
+    @Test(dataProvider = "simpleBindRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetPassword2(final SimpleBindRequest original) {
+        final SimpleBindRequest unmodifiable = (SimpleBindRequest) unmodifiableOf(original);
+        unmodifiable.setPassword("password".getBytes());
+    }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/StartTLSExtendedRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/StartTLSExtendedRequestTestCase.java
new file mode 100644
index 0000000..e1c4c3d
--- /dev/null
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/StartTLSExtendedRequestTestCase.java
@@ -0,0 +1,135 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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
+ *
+ *
+ *      Copyright 2013 ForgeRock AS
+ */
+
+package org.forgerock.opendj.ldap.requests;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+import java.security.NoSuchAlgorithmException;
+
+import javax.net.ssl.SSLContext;
+
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.DecodeOptions;
+import org.forgerock.opendj.ldap.controls.GenericControl;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Tests Start TLS Extended Requests.
+ */
+@SuppressWarnings("javadoc")
+public class StartTLSExtendedRequestTestCase extends RequestsTestCase {
+
+    @DataProvider(name = "StartTLSExtendedRequests")
+    private Object[][] getPlainSASLBindRequests() throws Exception {
+        return createModifiableInstance();
+    }
+
+    @Override
+    protected StartTLSExtendedRequest[] newInstance() {
+        try {
+            return new StartTLSExtendedRequest[] { Requests.newStartTLSExtendedRequest(SSLContext.getDefault()) };
+        } catch (NoSuchAlgorithmException e) {
+            // nothing to do;
+        }
+        return null;
+    }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfStartTLSExtendedRequest((StartTLSExtendedRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableStartTLSExtendedRequest((StartTLSExtendedRequest) original);
+    }
+
+    @Test(dataProvider = "StartTLSExtendedRequests")
+    public void testModifiableRequest(final StartTLSExtendedRequest original) throws NoSuchAlgorithmException {
+
+        final StartTLSExtendedRequest copy = (StartTLSExtendedRequest) copyOf(original);
+        copy.setSSLContext(SSLContext.getInstance("TLS"));
+
+        assertThat(copy.getSSLContext().getProtocol()).isEqualTo("TLS");
+        assertThat(original.getSSLContext().getProtocol()).isEqualTo("Default");
+    }
+
+    @Test(dataProvider = "StartTLSExtendedRequests")
+    public void testUnmodifiableRequest(final StartTLSExtendedRequest original) {
+        final StartTLSExtendedRequest unmodifiable = (StartTLSExtendedRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getSSLContext()).isEqualTo(original.getSSLContext());
+        assertThat(original.getSSLContext().getProtocol()).isEqualTo("Default");
+        assertThat(unmodifiable.getOID()).isEqualTo(original.getOID());
+    }
+
+    @Test(dataProvider = "StartTLSExtendedRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableAddEnabledCipherSuite(final StartTLSExtendedRequest original)
+            throws NoSuchAlgorithmException {
+        final StartTLSExtendedRequest unmodifiable = (StartTLSExtendedRequest) unmodifiableOf(original);
+        unmodifiable.addEnabledCipherSuite("suite");
+    }
+
+    @Test(dataProvider = "StartTLSExtendedRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableAddEnabledProtocol(final StartTLSExtendedRequest original)
+            throws NoSuchAlgorithmException {
+        final StartTLSExtendedRequest unmodifiable = (StartTLSExtendedRequest) unmodifiableOf(original);
+        unmodifiable.addEnabledProtocol("SSL", "TLS");
+    }
+
+    @Test(dataProvider = "StartTLSExtendedRequests", expectedExceptions = UnsupportedOperationException.class)
+    public void testUnmodifiableSetAuthenticationID(final StartTLSExtendedRequest original)
+            throws NoSuchAlgorithmException {
+        final StartTLSExtendedRequest unmodifiable = (StartTLSExtendedRequest) unmodifiableOf(original);
+        unmodifiable.setSSLContext(SSLContext.getInstance("SSL"));
+    }
+
+    @Test(dataProvider = "StartTLSExtendedRequests")
+    public void testModifiableRequestDecode(final StartTLSExtendedRequest original) throws DecodeException,
+            NoSuchAlgorithmException {
+        final GenericControl control = GenericControl.newControl("1.2.3".intern());
+
+        final StartTLSExtendedRequest copy = (StartTLSExtendedRequest) copyOf(original);
+        copy.addControl(control);
+        copy.addEnabledCipherSuite("TLSv1");
+        copy.addEnabledProtocol("TLS");
+        copy.setSSLContext(SSLContext.getInstance("TLS"));
+        assertThat(original.getControls().contains(control)).isFalse();
+        assertThat(original.getEnabledCipherSuites().contains("TLSv1")).isFalse();
+        assertThat(original.getSSLContext().getProtocol()).isNotEqualTo("TLS");
+        assertThat(copy.getEnabledCipherSuites().contains("TLSv1")).isTrue();
+        assertThat(copy.getSSLContext().getProtocol()).isEqualTo("TLS");
+
+        try {
+            final StartTLSExtendedRequest decoded = StartTLSExtendedRequest.DECODER.decodeExtendedRequest(copy,
+                    new DecodeOptions());
+            assertThat(decoded.getControls().contains(control)).isTrue();
+        } catch (DecodeException e) {
+            throw e;
+        }
+    }
+}
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/UnbindRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/UnbindRequestTestCase.java
index 08fbb4c..7624bc2 100644
--- a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/UnbindRequestTestCase.java
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/UnbindRequestTestCase.java
@@ -27,20 +27,40 @@
 
 package org.forgerock.opendj.ldap.requests;
 
+import static org.fest.assertions.Assertions.assertThat;
+
 import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
 
 /**
  * Tests the unbind requests.
  */
 @SuppressWarnings("javadoc")
-public class UnbindRequestTestCase extends RequestTestCase {
+public class UnbindRequestTestCase extends RequestsTestCase {
+    private static final UnbindRequest NEW_UNBIND_REQUEST = Requests.newUnbindRequest();
+
     @DataProvider(name = "UnbindRequests")
-    public Object[][] getUnbindRequests() throws Exception {
-        return getTestRequests();
+    private Object[][] getUnbindRequests() throws Exception {
+        return createModifiableInstance();
     }
 
     @Override
-    protected UnbindRequest[] createTestRequests() throws Exception {
-        return new UnbindRequest[] { Requests.newUnbindRequest(), };
+    protected UnbindRequest[] newInstance() {
+        return new UnbindRequest[] { NEW_UNBIND_REQUEST };
+    }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfUnbindRequest((UnbindRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableUnbindRequest((UnbindRequest) original);
+    }
+    @Test()
+    public void testModifiableRequest() {
+        final UnbindRequest copy = (UnbindRequest) copyOf(Requests.newUnbindRequest());
+        assertThat(copy.toString()).isEqualTo("UnbindRequest(controls=[])");
     }
 }
diff --git a/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/WhoAmIExtendedRequestTestCase.java b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/WhoAmIExtendedRequestTestCase.java
new file mode 100644
index 0000000..8e44e0f
--- /dev/null
+++ b/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/WhoAmIExtendedRequestTestCase.java
@@ -0,0 +1,106 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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
+ *
+ *
+ *      Copyright 2013 ForgeRock AS.
+ */
+
+package org.forgerock.opendj.ldap.requests;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.DecodeOptions;
+import org.forgerock.opendj.ldap.controls.GenericControl;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Tests WHOAMIEXTENDED requests.
+ */
+@SuppressWarnings("javadoc")
+public class WhoAmIExtendedRequestTestCase extends RequestsTestCase {
+    private static final WhoAmIExtendedRequest NEW_WHOAMIEXTENDED_REQUEST = Requests
+            .newWhoAmIExtendedRequest();
+
+    @DataProvider(name = "whoAmIExtendedRequests")
+    private Object[][] getWhoAmIExtendedRequests() throws Exception {
+        return createModifiableInstance();
+    }
+
+    @Override
+    protected WhoAmIExtendedRequest[] newInstance() {
+        return new WhoAmIExtendedRequest[] {
+            NEW_WHOAMIEXTENDED_REQUEST
+        };
+    }
+
+    @Override
+    protected Request copyOf(Request original) {
+        return Requests.copyOfWhoAmIExtendedRequest((WhoAmIExtendedRequest) original);
+    }
+
+    @Override
+    protected Request unmodifiableOf(Request original) {
+        return Requests.unmodifiableWhoAmIExtendedRequest((WhoAmIExtendedRequest) original);
+    }
+
+    @Test(dataProvider = "whoAmIExtendedRequests")
+    public void testModifiableRequest(final WhoAmIExtendedRequest original) {
+        final WhoAmIExtendedRequest copy = (WhoAmIExtendedRequest) copyOf(original);
+        assertThat(copy.getOID()).isEqualTo(original.getOID());
+        assertThat(copy.getResultDecoder()).isEqualTo(original.getResultDecoder());
+        assertThat(copy.getValue()).isEqualTo(original.getValue());
+    }
+
+    @Test(dataProvider = "whoAmIExtendedRequests")
+    public void testUnmodifiableRequest(final WhoAmIExtendedRequest original) {
+        final WhoAmIExtendedRequest unmodifiable = (WhoAmIExtendedRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.getOID()).isEqualTo(original.getOID());
+        assertThat(unmodifiable.getResultDecoder()).isEqualTo(original.getResultDecoder());
+        assertThat(unmodifiable.getValue()).isEqualTo(original.getValue());
+    }
+
+    @Test(dataProvider = "whoAmIExtendedRequests")
+    public void testUnmodifiableRequestHasResult(final WhoAmIExtendedRequest original) {
+        final WhoAmIExtendedRequest unmodifiable = (WhoAmIExtendedRequest) unmodifiableOf(original);
+        assertThat(unmodifiable.hasValue()).isFalse();
+    }
+
+
+    @Test(dataProvider = "whoAmIExtendedRequests")
+    public void testModifiableRequestDecode(final WhoAmIExtendedRequest original) throws DecodeException {
+        final GenericControl control = GenericControl.newControl("1.2.3".intern());
+
+        final WhoAmIExtendedRequest copy = (WhoAmIExtendedRequest) copyOf(original);
+        copy.addControl(control);
+        assertThat(original.getControls().contains(control)).isFalse();
+
+        try {
+            final WhoAmIExtendedRequest decoded = WhoAmIExtendedRequest.DECODER.decodeExtendedRequest(copy,
+                    new DecodeOptions());
+            assertThat(decoded.getControls().contains(control)).isTrue();
+        } catch (DecodeException e) {
+            throw e;
+        }
+    }
+}

--
Gitblit v1.10.0