diff --git a/src/com/google/enterprise/adaptor/ad/AdServer.java b/src/com/google/enterprise/adaptor/ad/AdServer.java
index 33046b0..aaefd1f 100644
--- a/src/com/google/enterprise/adaptor/ad/AdServer.java
+++ b/src/com/google/enterprise/adaptor/ad/AdServer.java
@@ -14,7 +14,7 @@
 
 package com.google.enterprise.adaptor.ad;
 
-import com.google.common.base.Strings;
+import com.google.common.annotations.VisibleForTesting;
 
 import java.io.IOException;
 import java.sql.Timestamp;
@@ -48,18 +48,14 @@
   private static final Logger LOGGER
       = Logger.getLogger(AdServer.class.getName());
 
-  protected LdapContext ldapContext = null;
-  private SearchControls searchCtls;
+  private final LdapContext ldapContext;
+  private final SearchControls searchCtls;
 
   // properties necessary for connection
-  private String hostName;
-  private int port;
-  private String principal;
-  private String password;
+  private final String hostName;
 
   // retrieved properties of the Active Directory controller
   private String nETBIOSName;
-  private Method connectMethod;
   private String dn;
   private String configurationNamingContext;
   private String dsServiceName;
@@ -67,10 +63,27 @@
   private long highestCommittedUSN;
   private String invocationID;
   private String dnsRoot;
-  private Timestamp lastFullSync;
 
   public AdServer(Method connectMethod, String hostName,
       int port, String principal, String password) {
+    this(hostName, createLdapContext(connectMethod, hostName, port,
+        principal, password));
+  }
+
+  @VisibleForTesting
+  AdServer(String hostName, LdapContext ldapContext) {
+    this.hostName = hostName;
+    this.ldapContext = ldapContext;
+    searchCtls = new SearchControls();
+    searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+  }
+
+  /**
+   * Called (only) by public constructor
+   */
+  private static LdapContext createLdapContext(Method connectMethod,
+      String hostName, int port, String principal, String password) {
+    Hashtable<String, String> env = new Hashtable<String, String>();
     if (null == connectMethod || null == hostName
         || null == principal || null == password) {
       throw new NullPointerException();
@@ -84,86 +97,63 @@
     if ("".equals(password)) {
       throw new IllegalArgumentException("password needs to be non-empty");
     }
-    this.hostName = hostName;
-    this.port = port;
-    this.principal = principal;
-    this.password = password;
-    searchCtls = new SearchControls();
-    searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
-    this.connectMethod = connectMethod;
+
+    // Use the built-in LDAP support.
+    env.put(Context.INITIAL_CONTEXT_FACTORY,
+        "com.sun.jndi.ldap.LdapCtxFactory");
+    // Connecting to configuration naming context is very slow for crawl users
+    // in large multidomain environment, which belong to thousands of groups
+    // TODO: make this configurable
+    env.put("com.sun.jndi.ldap.read.timeout", "90000");
+    env.put(Context.SECURITY_AUTHENTICATION, "simple");
+    env.put(Context.SECURITY_PRINCIPAL, principal);
+    env.put(Context.SECURITY_CREDENTIALS, password);
+
+    String ldapUrl = connectMethod.protocol() + hostName + ":" + port;
+    LOGGER.config("LDAP provider url: " + ldapUrl);
+    env.put(Context.PROVIDER_URL, ldapUrl);
+    try {
+      return new InitialLdapContext(env, null);
+    } catch (NamingException ne) {
+      throw new AssertionError(ne);
+    }
   }
 
   /**
    * Connects to the Active Directory server and retrieves AD configuration
    * information.
-   * 
-   * This method is used for crawling as well as authorization of credentials 
+   *
+   * This method is used for crawling as well as authorization of credentials
    * against Active Directory.
    */
   public void connect() throws CommunicationException, NamingException {
-    Hashtable<String, String> env = new Hashtable<String, String>();
-
-    // Use the built-in LDAP support.
-    env.put(Context.INITIAL_CONTEXT_FACTORY,
-        AdConstants.COM_SUN_JNDI_LDAP_LDAP_CTX_FACTORY);
-    // Connecting to configuration naming context is very slow for crawl users
-    // in large multidomain environment, which belong to thousands of groups
-    // TODO: make this configurable
-    env.put("com.sun.jndi.ldap.read.timeout", "90000");
-    if (Strings.isNullOrEmpty(principal)) {
-      env.put(Context.SECURITY_AUTHENTICATION, 
-          AdConstants.AUTHN_TYPE_ANONYMOUS);
-    } else {
-      env.put(Context.SECURITY_AUTHENTICATION,
-          AdConstants.AUTHN_TYPE_SIMPLE);
-      env.put(Context.SECURITY_PRINCIPAL, principal);
-      env.put(Context.SECURITY_CREDENTIALS, password);
-    }
-
-    String ldapUrl =
-        connectMethod.protocol() + hostName + AdConstants.COLON + port;
-    LOGGER.info("LDAP provider url: " + ldapUrl);
-    env.put(Context.PROVIDER_URL, ldapUrl);
-    ldapContext = new InitialLdapContext(env, null);
-
-    Attributes attributes = ldapContext.getAttributes(AdConstants.EMPTY);
-    dn = attributes.get(
-        AdConstants.ATTR_DEFAULTNAMINGCONTEXT).get(0).toString();
-    dsServiceName = attributes.get(
-        AdConstants.ATTR_DSSERVICENAME).get(0).toString();
+    Attributes attributes = ldapContext.getAttributes("");
+    dn = attributes.get("defaultNamingContext").get(0).toString();
+    dsServiceName = attributes.get("dsServiceName").get(0).toString();
     highestCommittedUSN = Long.parseLong(attributes.get(
-        AdConstants.ATTR_HIGHESTCOMMITTEDUSN).get(0).toString());
+        "highestCommittedUSN").get(0).toString());
     configurationNamingContext = attributes.get(
-        AdConstants.ATTR_CONFIGURATIONNAMINGCONTEXT).get(0).toString();
+        "configurationNamingContext").get(0).toString();
   }
 
   public void initialize() {
     try {
       connect();
-      sid = AdEntity.getTextSid((byte[])get(
-          AdConstants.ATTR_DISTINGUISHEDNAME + AdConstants.EQUALS + dn,
-          AdConstants.ATTR_OBJECTSID, dn));
+      sid = AdEntity.getTextSid((byte[]) get(
+          "distinguishedName=" + dn, "objectSid;binary", dn));
       invocationID = AdEntity.getTextGuid((byte[]) get(
-          AdConstants.ATTR_DISTINGUISHEDNAME
-          + AdConstants.EQUALS + dsServiceName,
-          AdConstants.ATTR_INVOCATIONID,
-          dsServiceName));
-    } catch (CommunicationException e) {
-      throw new IllegalStateException(e);
-    } catch (AuthenticationNotSupportedException e) {
-      throw new IllegalStateException(e);
-    } catch (AuthenticationException e) {
-      throw new IllegalStateException(e);
+          "distinguishedName=" + dsServiceName,
+          "invocationID;binary", dsServiceName));
     } catch (NamingException e) {
-      throw new IllegalStateException(e);
+      throw new RuntimeException(e);
     }
 
-    LOGGER.info("Sucessfully created an Initial LDAP context");
+    LOGGER.info("Successfully created an Initial LDAP context");
 
     nETBIOSName = (String) get("(ncName=" + dn + ")",
-        AdConstants.ATTR_NETBIOSNAME, configurationNamingContext);
-    dnsRoot = (String) get("(ncName=" + dn + ")",
-        AdConstants.ATTR_DNSROOT, configurationNamingContext);
+        "nETBIOSName", configurationNamingContext);
+    dnsRoot = (String) get("(ncName=" + dn + ")", "dnsRoot",
+        configurationNamingContext);
     LOGGER.log(Level.INFO, "Connected to domain (dn = " + dn + ", netbios = "
         + nETBIOSName + ", hostname = " + hostName + ", dsServiceName = "
         + dsServiceName + ", highestCommittedUSN = " + highestCommittedUSN
@@ -200,7 +190,7 @@
   }
 
   /**
-   * Set request controls on the LDAP query 
+   * Set request controls on the LDAP query
    * @param deleted include deleted control
    */
   private void setControls(boolean deleted) {
@@ -245,7 +235,7 @@
           SearchResult sr = ldapResults.next();
           try {
             results.add(new AdEntity(sr));
-          } catch (Exception ex) {           
+          } catch (Exception ex) {
             // It is possible that Search Result returned is missing
             // few attributes required to construct AD Entity object.
             // Such results will be ignored.
@@ -279,8 +269,8 @@
         int batch = g.getMembers().size();
         int start = g.getMembers().size();
         do {
-          String memberRange = String.format(AdConstants.ATTR_MEMBER_RANGE, 
-              start, start + batch - 1);
+          String memberRange = String.format("member;Range=%d-%d", start,
+              start + batch - 1);
           LOGGER.finest(
               "Retrieving additional groups for [" + g + "] " + memberRange);
           searchCtls.setReturningAttributes(new String[] {memberRange});
@@ -305,26 +295,6 @@
   }
 
   /**
-   * Generate properties to be used for parameter binding in JDBC
-   * @return map of names and properties of current object
-   */
-  public Map<String, Object> getSqlParams() {
-    HashMap<String, Object> map = new HashMap<String, Object>();
-    map.put(AdConstants.DB_DN, dn);
-    map.put(AdConstants.DB_DSSERVICENAME, dsServiceName);
-    map.put(AdConstants.DB_INVOCATIONID, invocationID);
-    map.put(AdConstants.DB_HIGHESTCOMMITTEDUSN, highestCommittedUSN);
-    map.put(AdConstants.DB_NETBIOSNAME, nETBIOSName);
-    map.put(AdConstants.DB_SID, sid);
-    map.put(AdConstants.DB_DNSROOT, dnsRoot);
-    if (lastFullSync != null) {
-      map.put(AdConstants.DB_LASTFULLSYNC,
-          new java.sql.Timestamp(lastFullSync.getTime()));
-    }
-    return map;
-  }
-
-  /**
    * @return the distinguished Name
    */
   public final String getDn() {
@@ -374,20 +344,6 @@
     }
   }
 
-  /**
-   * @return the lastFullSync
-   */
-  public Timestamp getLastFullSync() {
-    return lastFullSync;
-  }
-
-  /**
-   * @param lastFullSync the lastFullSync to set
-   */
-  public void setLastFullSync(Timestamp lastFullSync) {
-    this.lastFullSync = lastFullSync;
-  }
-  
   @Override
   public String toString() {
     return "[" + nETBIOSName + "] ";
diff --git a/test/com/google/enterprise/adaptor/ad/AdServerTest.java b/test/com/google/enterprise/adaptor/ad/AdServerTest.java
new file mode 100644
index 0000000..b80a81a
--- /dev/null
+++ b/test/com/google/enterprise/adaptor/ad/AdServerTest.java
@@ -0,0 +1,415 @@
+// Copyright 2013 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.enterprise.adaptor.ad;
+
+import static org.junit.Assert.*;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.naming.ldap.*;
+
+import java.util.*;
+
+/** Test cases for {@link AdServer}. */
+public class AdServerTest {
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  @Test
+  public void testStandardServer() throws Exception {
+    AdServer adServer = new AdServer("hostname", new MockLdapContext());
+    assertEquals("hostname", adServer.getHostName());
+  }
+
+  @Test
+  public void testNPEOnNullConnectMethod() {
+    thrown.expect(NullPointerException.class);
+    AdServer adServer = new AdServer(null, "hostname", 1234, "principal", "pw");
+  }
+
+  @Test
+  public void testNPEOnNullHostname() {
+    thrown.expect(NullPointerException.class);
+    AdServer adServer = new AdServer(Method.SSL, null, 1234, "principal", "pw");
+  }
+
+  @Test
+  public void testIAEOnEmptyHostname() {
+    thrown.expect(IllegalArgumentException.class);
+    AdServer adServer = new AdServer(Method.SSL, "", 1234, "principal", "pw");
+  }
+
+  @Test
+  public void testNPEOnNullPrincipal() {
+    thrown.expect(NullPointerException.class);
+    AdServer adServer = new AdServer(Method.SSL, "hostname", 1234, null, "pw");
+  }
+
+  @Test
+  public void testIAEOnEmptyPrincipal() throws Exception {
+    thrown.expect(IllegalArgumentException.class);
+    AdServer adServer = new AdServer(Method.SSL, "hostname", 1234, "", "pw");
+  }
+
+  @Test
+  public void testNPEOnNullPassword() {
+    thrown.expect(NullPointerException.class);
+    AdServer adServer = new AdServer(Method.SSL, "host", 1234, "princ", null);
+  }
+
+  @Test
+  public void testIAEOnEmptyPassword() {
+    thrown.expect(IllegalArgumentException.class);
+    AdServer adServer = new AdServer(Method.SSL, "hostname", 1234, "princ", "");
+  }
+
+  @Test
+  public void testPublicConstructor() {
+    thrown.expect(AssertionError.class);
+    AdServer adServer = new AdServer(Method.SSL, "localhost", 389, " ", " ");
+  }
+
+  @Test
+  public void testStandardServerInitialize() throws Exception {
+    MockLdapContext ldapContext = new MockLdapContext();
+    addStandardKeysAndResults(ldapContext);
+    // populate additional attributes with values we can test
+    ldapContext.addSearchResult("dn=empty", "empty", "empty", "")
+               .addSearchResult("dn=empty", "attr1", "basedn", "val1");
+    AdServer adServer = new AdServer("localhost", ldapContext);
+    assertEquals("localhost", adServer.getHostName());
+    adServer.initialize();
+    assertEquals("DN_for_default_naming_context", adServer.getDn());
+    assertEquals("ds_service_name", adServer.getDsServiceName());
+    assertEquals(12345678L, adServer.getHighestCommittedUSN());
+    assertEquals("S-1-0-0", adServer.getSid());
+    assertEquals("0x0123456789abc", adServer.getInvocationID());
+    assertEquals("GSA-CONNECTORS", adServer.getnETBIOSName());
+    assertEquals("[GSA-CONNECTORS] ", adServer.toString());
+    assertEquals("", adServer.get("dn=empty", "empty", "empty"));
+    assertNull(adServer.get("dn=ds_service_name", "null", "null"));
+    assertEquals("val1", adServer.get("dn=empty", "attr1", "basedn"));
+    assertNull(adServer.get("dn=empty", "attr2", "basedn"));
+  }
+
+  @Test
+  /*
+   * This tests a code path that the author doesn't think can actually happen
+   *
+   * <p> where <code>ldapResults</code> is not <code>null</code>, but where
+   * <code>attrs.get(attribute)</code> does return <code>null</code>.
+   */
+  public void testGetNotReturningAttribute() throws Exception {
+    MockLdapContext ldapContext = new MockLdapContext() {
+      @Override
+      public NamingEnumeration<SearchResult> search(String base, String filter,
+        SearchControls searchControls) throws NamingException {
+        if (!("dn=empty".equals(filter))) {
+          return super.search(base, filter, searchControls);
+        }
+        // prepare "broken" SearchResult
+        Vector<SearchResult> brokenSRs = new Vector<SearchResult>();
+        brokenSRs.add(new SearchResult("search result name", brokenSRs,
+            new BasicAttributes()));
+        return new MockLdapContext.SearchResultsNamingEnumeration(brokenSRs);
+      }
+    };
+    addStandardKeysAndResults(ldapContext);
+    ldapContext.addSearchResult("dn=empty", "attr1", "basedn", "val1");
+    AdServer adServer = new AdServer("localhost", ldapContext);
+    adServer.initialize();
+    assertNull(adServer.get("dn=empty", "attr1", "basedn"));
+  }
+
+  @Test
+  public void testGetThrowsNamingException() throws Exception {
+    MockLdapContext ldapContext = new MockLdapContext() {
+      @Override
+      public NamingEnumeration<SearchResult> search(String base, String filter,
+        SearchControls searchControls) throws NamingException {
+        if (!("dn=empty".equals(filter))) {
+          return super.search(base, filter, searchControls);
+        }
+        throw new NamingException("Gotcha");
+      }
+    };
+    addStandardKeysAndResults(ldapContext);
+    ldapContext.addSearchResult("dn=empty", "attr1", "basedn", "val1");
+    AdServer adServer = new AdServer("localhost", ldapContext);
+    adServer.initialize();
+    assertNull(adServer.get("dn=empty", "attr1", "basedn"));
+  }
+
+  @Test
+  public void testConnectThrowsNamingException() throws Exception {
+    thrown.expect(RuntimeException.class);
+    MockLdapContext ldapContext = new MockLdapContext() {
+      @Override
+      public Attributes getAttributes(String name) throws NamingException {
+        throw new NamingException("Can't connect");
+      }
+    };
+    addStandardKeysAndResults(ldapContext);
+    ldapContext.addSearchResult("dn=empty", "attr1", "basedn", "val1");
+    AdServer adServer = new AdServer("localhost", ldapContext);
+    adServer.initialize();
+  }
+
+  @Test
+  public void testSearchReturnsOneUser() throws Exception {
+    MockLdapContext ldapContext = new MockLdapContext();
+    addStandardKeysAndResults(ldapContext);
+    // populate additional attributes with values we can test
+    final String filter = "ou=Users";
+    final String userDn = "DN_for_default_naming_context";
+    ldapContext.addSearchResult(filter, "cn", userDn, "user1")
+               .addSearchResult(filter, "primaryGroupId", userDn, "users")
+               .addSearchResult(filter, "objectGUID;binary", userDn,
+                   hexStringToByteArray("000102030405060708090a0b0c"));
+    AdServer adServer = new AdServer("localhost", ldapContext);
+    adServer.initialize();
+    Set<AdEntity> resultSet = adServer.search(filter, false,
+        new String[] { "cn", "primaryGroupId", "objectGUID;binary" });
+    assertEquals(1, resultSet.size());
+    for (AdEntity ae : resultSet) {
+      assertEquals("name under", ae.getCommonName());
+    }
+  }
+
+  @Test
+  public void testSearchReturnsNoUsersWhenMissingGUID() throws Exception {
+    MockLdapContext ldapContext = new MockLdapContext();
+    addStandardKeysAndResults(ldapContext);
+    // populate additional attributes with values we can test
+    final String filter = "ou=Users";
+    final String userDn = "DN_for_default_naming_context";
+    ldapContext.addSearchResult(filter, "cn", userDn, "user1")
+               .addSearchResult(filter, "primaryGroupId", userDn, "users");
+    AdServer adServer = new AdServer("localhost", ldapContext);
+    adServer.initialize();
+    Set<AdEntity> resultSet = adServer.search(filter, false,
+        new String[] { "cn", "primaryGroupId", "objectGUID;binary" });
+    assertEquals(0, resultSet.size());
+  }
+
+  @Test
+  public void testSetControlsThrowsException() throws Exception {
+    MockLdapContext ldapContext = new MockLdapContext() {
+      @Override
+      public void setRequestControls(Control[] requestControls)
+          throws NamingException {
+        controls = requestControls;
+        throw new NamingException("testing exception path");
+      }
+    };
+    addStandardKeysAndResults(ldapContext);
+    // populate additional attributes with values we can test
+    final String filter = "ou=Users";
+    final String userDn = "DN_for_default_naming_context";
+    ldapContext.addSearchResult(filter, "cn", userDn, "user1")
+               .addSearchResult(filter, "primaryGroupId", userDn, "users");
+    AdServer adServer = new AdServer("localhost", ldapContext);
+    adServer.initialize();
+    Set<AdEntity> resultSet = adServer.search(filter, false,
+        new String[] { "cn", "primaryGroupId", "objectGUID;binary" });
+    assertEquals(0, resultSet.size());
+  }
+
+  @Test
+  public void testSearchReturnsOneDeletedUser() throws Exception {
+    MockLdapContext ldapContext = new MockLdapContext();
+    addStandardKeysAndResults(ldapContext);
+    // populate additional attributes with values we can test
+    final String filter = "ou=Users";
+    final String userDn = "DN_for_default_naming_context";
+    ldapContext.addSearchResult(filter, "cn", userDn, "user1")
+               .addSearchResult(filter, "primaryGroupId", userDn, "users")
+               .addSearchResult(filter, "objectGUID;binary", userDn,
+                   hexStringToByteArray("000102030405060708090a0b0c"));
+    AdServer adServer = new AdServer("localhost", ldapContext);
+    adServer.initialize();
+    Set<AdEntity> resultSet = adServer.search(filter, true,
+        new String[] { "cn", "primaryGroupId", "objectGUID;binary" });
+    assertEquals(1, resultSet.size());
+    for (AdEntity ae : resultSet) {
+      assertEquals("name under", ae.getCommonName());
+    }
+    // now verify the DeletedControl is exactly as we expect
+    assertEquals(2, ldapContext.getResponseControls().length);
+    Control deletedControl = ldapContext.getResponseControls()[1];
+    assertArrayEquals(new byte[0], deletedControl.getEncodedValue());
+    assertEquals("1.2.840.113556.1.4.417", deletedControl.getID());
+    assertTrue(deletedControl.isCritical());
+  }
+
+  @Test
+  public void testSearchReturnsOneEmptyGroup() throws Exception {
+    MockLdapContext ldapContext = new MockLdapContext();
+    addStandardKeysAndResults(ldapContext);
+    // populate additional attributes with values we can test
+    final String filter = "ou=Users";
+    final String userDn = "DN_for_default_naming_context";
+    ldapContext.addSearchResult(filter, "cn", userDn, "users")
+               .addSearchResult(filter, "objectGUID;binary", userDn,
+                   hexStringToByteArray("000102030405060708090a0b0c"));
+    AdServer adServer = new AdServer("localhost", ldapContext);
+    adServer.initialize();
+    Set<AdEntity> resultSet = adServer.search(filter, true,
+        new String[] { "cn", "members", "objectGUID;binary" });
+    assertEquals(1, resultSet.size());
+    for (AdEntity ae : resultSet) {
+      assertEquals("name under", ae.getCommonName());
+    }
+  }
+
+  @Test
+  public void testSearchReturnsOneNonemptyGroup() throws Exception {
+    MockLdapContext ldapContext = new MockLdapContext();
+    addStandardKeysAndResults(ldapContext);
+    // populate additional attributes with values we can test
+    final String filter = "ou=Users";
+    final String userDn = "DN_for_default_naming_context";
+    List<String> members = Arrays.asList("dn_for_user_1", "dn_for_user_2");
+    ldapContext.addSearchResult(filter, "cn", userDn, "users")
+               .addSearchResult(filter, "objectGUID;binary", userDn,
+                   hexStringToByteArray("000102030405060708090a0b0c"))
+               .addSearchResult(filter, "member", userDn, members);
+    AdServer adServer = new AdServer("localhost", ldapContext);
+    adServer.initialize();
+    Set<AdEntity> resultSet = adServer.search(filter, false,
+        new String[] { "cn", "member", "objectGUID;binary" });
+    assertEquals(1, resultSet.size());
+    for (AdEntity ae : resultSet) {
+      assertEquals(new HashSet<String>(members), ae.getMembers());
+    }
+  }
+
+  @Test
+  public void testSearchReturnsMembersinTwoRanges() throws Exception {
+    MockLdapContext ldapContext = new MockLdapContext();
+    addStandardKeysAndResults(ldapContext);
+    // populate additional attributes with values we can test
+    final String filter = "ou=Users";
+    final String filter2 = "(sAMAccountName=sam)";
+    final String userDn = "DN_for_default_naming_context";
+    List<String> members = Arrays.asList("dn_for_user_0", "dn_for_user_1");
+    List<String> moreMembers = Arrays.asList("dn_for_user_2", "dn_for_user_3");
+    ldapContext.addSearchResult(filter, "cn", userDn, "users")
+               .addSearchResult(filter, "objectGUID;binary", userDn,
+                   hexStringToByteArray("000102030405060708090a0b0c"))
+               .addSearchResult(filter, "sAMAccountName", userDn, "sam")
+               .addSearchResult(filter, "member;Range=0-1", userDn, members);
+    ldapContext.addSearchResult(filter2, "cn", userDn, "users")
+               .addSearchResult(filter2, "objectGUID;binary", userDn,
+                   hexStringToByteArray("000102030405060708090a0b0c"))
+               .addSearchResult(filter2, "sAMAccountName", userDn, "sam2")
+               .addSearchResult(filter2, "member;Range=2-3*", userDn,
+                    moreMembers);
+    AdServer adServer = new AdServer("localhost", ldapContext);
+    adServer.initialize();
+    Set<AdEntity> resultSet = adServer.search(filter, false,
+        // need the ranged members for MockLdapContext, not for "real" AD.
+        new String[] { "cn", "member", "member;Range=0-1", "member;Range=2-3",
+                       "objectGUID;binary", "sAMAccountName" });
+    assertEquals(1, resultSet.size());
+    HashSet<String> expectedMembers = new HashSet<String>(members);
+    expectedMembers.addAll(moreMembers);
+    for (AdEntity ae : resultSet) {
+      assertEquals(expectedMembers, ae.getMembers());
+    }
+  }
+
+  @Test
+  public void testSearchReturnsMembersinThreeRanges() throws Exception {
+    MockLdapContext ldapContext = new MockLdapContext();
+    addStandardKeysAndResults(ldapContext);
+    // populate additional attributes with values we can test
+    final String filter = "ou=Users";
+    final String filter2 = "(sAMAccountName=sam)";
+    final String userDn = "DN_for_default_naming_context";
+    List<String> members = Arrays.asList("dn_for_user_0", "dn_for_user_1");
+    List<String> moreMembers = Arrays.asList("dn_for_user_2", "dn_for_user_3");
+    List<String> evenMore = Arrays.asList("dn_for_user_4");
+    ldapContext.addSearchResult(filter, "cn", userDn, "users")
+               .addSearchResult(filter, "objectGUID;binary", userDn,
+                   hexStringToByteArray("000102030405060708090a0b0c"))
+               .addSearchResult(filter, "sAMAccountName", userDn, "sam")
+               .addSearchResult(filter, "member;Range=0-1", userDn, members);
+    ldapContext.addSearchResult(filter2, "cn", userDn, "users")
+               .addSearchResult(filter2, "objectGUID;binary", userDn,
+                   hexStringToByteArray("000102030405060708090a0b0c"))
+               .addSearchResult(filter2, "sAMAccountName", userDn, "sam2")
+               .addSearchResult(filter2, "member;Range=2-3", userDn,
+                    moreMembers)
+               .addSearchResult(filter2, "member;Range=4-5*", userDn,
+                    evenMore);
+    AdServer adServer = new AdServer("localhost", ldapContext);
+    adServer.initialize();
+    Set<AdEntity> resultSet = adServer.search(filter, false,
+        // need the ranged members for MockLdapContext, not for "real" AD.
+        new String[] { "cn", "member", "member;Range=0-1", "member;Range=2-3",
+                       "member;Range=4-5*", "objectGUID;binary",
+                       "sAMAccountName" });
+    assertEquals(1, resultSet.size());
+    HashSet<String> expectedMembers = new HashSet<String>(members);
+    expectedMembers.addAll(moreMembers);
+    expectedMembers.addAll(evenMore);
+    for (AdEntity ae : resultSet) {
+      assertEquals(expectedMembers, ae.getMembers());
+    }
+  }
+
+  /**
+    * Generate a common LdapContext used for various tests above
+    */
+  private void addStandardKeysAndResults(MockLdapContext ldapContext) {
+    // populate the attributes with values we can test
+    ldapContext.addKey("defaultNamingContext", "DN_for_default_naming_context")
+               .addKey("dsServiceName", "ds_service_name")
+               .addKey("highestCommittedUSN", "12345678")
+               .addKey("configurationNamingContext", "naming_context")
+               .addSearchResult(
+                 "distinguishedName=DN_for_default_naming_context",
+                 "objectSid;binary",
+                 "DN_for_default_naming_context",
+                 hexStringToByteArray("010100000000000000000000")) // S-1-0-0
+               .addSearchResult("distinguishedName=ds_service_name",
+                 "invocationID;binary",
+                 "ds_service_name",
+                 hexStringToByteArray("000102030405060708090a0b0c"))
+               .addSearchResult("(ncName=DN_for_default_naming_context)",
+                 "nETBIOSName",
+                 "naming_context",
+                 "GSA-CONNECTORS")
+               .addSearchResult("(ncName=DN_for_default_naming_context)",
+                 "dnsRoot",
+                 "naming_context",
+                 "gsa-connectors.com");
+  }
+
+  public static byte[] hexStringToByteArray(String s) {
+    int len = s.length();
+    byte[] data = new byte[len / 2];
+    for (int i = 0; i < len; i += 2) {
+      data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+                           + Character.digit(s.charAt(i+1), 16));
+    }
+    return data;
+  }
+}
diff --git a/test/com/google/enterprise/adaptor/ad/MockLdapContext.java b/test/com/google/enterprise/adaptor/ad/MockLdapContext.java
new file mode 100644
index 0000000..cfc87ac
--- /dev/null
+++ b/test/com/google/enterprise/adaptor/ad/MockLdapContext.java
@@ -0,0 +1,175 @@
+// Copyright 2013 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.enterprise.adaptor.ad;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.*;
+import java.util.*;
+
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.naming.ldap.Control;
+import javax.naming.ldap.InitialLdapContext;
+
+/**
+ * Mock of {@link LdapContext}.
+ */
+public class MockLdapContext extends InitialLdapContext {
+  private BasicAttributes attributes = new BasicAttributes();
+  private Hashtable<String, Object> searchResults
+      = new Hashtable<String, Object>();
+  @VisibleForTesting
+  Control[] controls = new Control[0];
+
+  public MockLdapContext() throws NamingException {
+  }
+
+  @Override
+  public Attributes getAttributes(String name) throws NamingException {
+    return attributes;
+  }
+
+  /** Normal way to add things to this Mock */
+  public MockLdapContext addKey(String key, Object value) {
+    attributes.put(key, value);
+    return this;
+  }
+
+  public MockLdapContext removeKey(String key) {
+    attributes.remove(key);
+    return this;
+  }
+
+  public static String makeKey(String filter, String attribute, String baseDn) {
+    return filter + "|" + attribute + "|" + baseDn;
+  }
+
+  public MockLdapContext addSearchResult(String filter,
+      String attribute, String baseDn, Object value) {
+    searchResults.put(makeKey(filter, attribute, baseDn), value);
+    return this;
+  }
+
+  /** Returns a <code>NamingEnumeration</code> of <code>SearchResult</code>s */
+  public NamingEnumeration<SearchResult> search(String base, String filter,
+      SearchControls searchControls) throws NamingException {
+    Vector<SearchResult> results = new Vector<SearchResult>();
+    SearchResult currentResult = null;
+    for (String attribute : searchControls.getReturningAttributes()) {
+      Object o = searchResults.get(makeKey(filter, attribute, base));
+      if (o == null) {
+        // hack to make search for member;Range=X-Y succeed when that's the
+        // final range present
+        if (attribute.startsWith("member;Range=")) {
+          attribute += "*";
+          o = searchResults.get(makeKey(filter, attribute, base));
+        }
+      }
+      if (o != null) {
+        if (currentResult == null) {
+          currentResult = makeSearchResult(attribute, o, base);
+          results.add(currentResult);
+        } else {
+          Attributes attrs = currentResult.getAttributes();
+          this.addAttribute(attrs, attribute, o);
+          currentResult.setAttributes(attrs);
+        }
+      }
+    }
+    return new SearchResultsNamingEnumeration(results);
+  }
+
+  /** properly handle collections as we add a new attribute */
+  private static void addAttribute(Attributes attrs, String newAttr,
+      Object value) {
+    attrs.put(newAttr, value);
+    if (value instanceof Collection<?>) {
+      Attribute attr = attrs.get(newAttr);
+      attr.clear();
+      for (Object member: (Collection<?>) value) {
+        attr.add(member);
+      }
+    }
+  }
+
+  /** Creates a <code>SearchResults</code> wrapper with a single attribute */
+  private static SearchResult makeSearchResult(String attribute, Object o,
+      String baseDn) {
+    SearchResult sr = new SearchResult("search result name", o,
+        new BasicAttributes());
+    addAttribute(sr.getAttributes(), attribute, o);
+    sr.setNameInNamespace("cn=name\\ under," + baseDn);
+    return sr;
+  }
+
+  @Override
+  public Control[] getResponseControls() throws NamingException {
+    return controls;
+  };
+
+  /** Sets the controls (which this class does nothing with) */
+  @Override
+  public void setRequestControls(Control[] requestControls)
+      throws NamingException {
+    controls = requestControls;
+  };
+
+  @VisibleForTesting
+  static class SearchResultsNamingEnumeration
+      implements NamingEnumeration<SearchResult> {
+    private final Enumeration<SearchResult> results;
+    private SearchResult nextElement = null;
+
+    SearchResultsNamingEnumeration(Vector<SearchResult> results) {
+      this.results = results.elements();
+    }
+
+    private SearchResult getNextElement() {
+      if (results.hasMoreElements()) {
+        return results.nextElement();
+      }
+      return null;
+    }
+
+    public boolean hasMore() {
+      if (nextElement != null) {
+        return true;
+      }
+      nextElement = getNextElement();
+      return (nextElement != null);
+    }
+
+    public boolean hasMoreElements() {
+      return hasMore();
+    }
+
+    public SearchResult next() {
+      if (!hasMore()) {
+        throw new NoSuchElementException();
+      }
+      SearchResult res = nextElement;
+      nextElement = null;
+      return res;
+    }
+
+    public SearchResult nextElement() {
+      return next();
+    }
+
+    public void close() {
+    }
+  }
+}
