From bd1b11e58eecbbb7ce1a8c3f8989fd48809a56ac Mon Sep 17 00:00:00 2001
From: Ludovic Poitou <ludovic.poitou@forgerock.com>
Date: Thu, 23 Oct 2014 09:00:51 +0000
Subject: [PATCH] Fix for OPENDJ-1586: Changes in processSearch to iterate through nested groups members when a search is based on a filter of the isMemberOf attribute. Adding unit test.

---
 opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProviderTestCase.java |   94 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProviderTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProviderTestCase.java
index cc5f8e9..05ad783 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProviderTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/IsMemberOfVirtualAttributeProviderTestCase.java
@@ -1294,7 +1294,101 @@
     assertEquals(deleteOperation.getResultCode(), ResultCode.SUCCESS);
   }
 
+  /**
+   * Tests the {@code processSearch} method when dealing with nested groups.
+   * This is a test for issue OPENDJ-1586. Before the fix the method would
+   * only return the direct members of the groups. Now it should return
+   * all.
+   *
+   * @throws  Exception  If an unexpected problem occurs.
+   */
+  @Test
+  public void testProcessSearchWithNestedGroup() throws Exception
+  {
+    TestCaseUtils.initializeTestBackend(true);
+    TestCaseUtils.addEntries(
+        "dn: ou=People,o=test",
+        "objectClass: top",
+        "objectClass: organizationalUnit",
+        "ou: People",
+        "",
+        "dn: uid=test.user,ou=People,o=test",
+        "objectClass: top",
+        "objectClass: person",
+        "objectClass: organizationalPerson",
+        "objectClass: inetOrgPerson",
+        "uid: test.user",
+        "givenName: Test",
+        "sn: User",
+        "cn: Test User",
+        "userPassword: password",
+        "",
+        "dn: uid=test.user2,ou=People,o=test",
+        "objectClass: top",
+        "objectClass: person",
+        "objectClass: organizationalPerson",
+        "objectClass: inetOrgPerson",
+        "uid: test.user2",
+        "givenName: Test",
+        "sn: User2",
+        "cn: Test User2",
+        "userPassword: password",
+        "",
+        "dn: ou=Groups,o=test",
+        "objectClass: top",
+        "objectClass: organizationalUnit",
+        "ou: Groups",
+        "",
+        "dn: cn=Test Group 1,ou=Groups,o=test",
+        "objectClass: top",
+        "objectClass: groupOfNames",
+        "cn: Test Group 1",
+        "member: uid=test.user,ou=People,o=test",
+        "",
+        "dn: cn=Test Group 2,ou=Groups,o=test",
+        "objectClass: top",
+        "objectClass: groupOfNames",
+        "cn: Test Group 2",
+        "member: uid=test.user2,ou=People,o=test",
+        "",
+        "dn: cn=Test Group 3,ou=Groups,o=test",
+        "objectClass: top",
+        "objectClass: groupOfNames",
+        "cn: Test Group 3",
+        "member: cn=Test Group 1,ou=Groups,o=test");
 
+    IsMemberOfVirtualAttributeProvider provider =
+        new IsMemberOfVirtualAttributeProvider();
+
+    VirtualAttributeRule rule =
+        new VirtualAttributeRule(isMemberOfType, provider,
+            Collections.<DN>emptySet(), SearchScope.WHOLE_SUBTREE,
+            Collections.<DN>emptySet(),
+            Collections.<SearchFilter>emptySet(),
+            VirtualAttributeCfgDefn.ConflictBehavior.
+                VIRTUAL_OVERRIDES_REAL);
+
+    InternalClientConnection conn =
+        InternalClientConnection.getRootConnection();
+    InternalSearchOperation searchOperation =
+        new InternalSearchOperation(conn,
+            InternalClientConnection.nextOperationID(),
+            InternalClientConnection.nextMessageID(),
+            null,
+            DN.decode("o=test"),
+            SearchScope.WHOLE_SUBTREE,
+            DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false,
+            SearchFilter.createFilterFromString("isMemberOf=cn=Test Group 3,ou=Groups,o=test"),
+            null, null);
+    provider.processSearch(rule, new LocalBackendSearchOperation(searchOperation));
+
+    List<SearchResultEntry> entries = searchOperation.getSearchEntries();
+    assertEquals(entries.size(), 2, "Expecting 2 entries, but got " + entries.size());
+    // First direct members
+    assertEquals(entries.get(0).getDN().toNormalizedString(), "cn=test group 1,ou=groups,o=test");
+    // Then indirect members
+    assertEquals(entries.get(1).getDN().toNormalizedString(), "uid=test.user,ou=people,o=test");
+  }
 
   /**
    * Tests if a search using ismemberof works for a dynamic group with large

--
Gitblit v1.10.0