You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by sp...@apache.org on 2018/05/31 03:32:28 UTC

[50/86] sentry git commit: SENTRY-2208: Refactor out Sentry service into own module from sentry-provider-db (Anthony Young-Garner, reviewed by Sergio Pena, Steve Moist, Na Li)

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/SentryStoreIntegrationBase.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/SentryStoreIntegrationBase.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/SentryStoreIntegrationBase.java
new file mode 100644
index 0000000..3fe5b6a
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/SentryStoreIntegrationBase.java
@@ -0,0 +1,91 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sentry.provider.db.generic.service.persistent;
+
+import java.io.File;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.provider.file.PolicyFile;
+import org.apache.sentry.service.common.ServiceConstants.ServerConfig;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+import com.google.common.io.Files;
+
+public abstract class SentryStoreIntegrationBase {
+  protected final static String[] adminGroups = { "adminGroup" };
+  private static File dataDir;
+  private static File policyFilePath;
+  protected static Configuration conf;
+  protected static DelegateSentryStore sentryStore;
+  protected static PolicyFile policyFile;
+
+  @BeforeClass
+  public static void setup() throws Exception {
+    conf = new Configuration(false);
+    setup(conf);
+    sentryStore = new DelegateSentryStore(conf);
+  }
+
+  private static void setup(Configuration conf) throws Exception {
+    dataDir = new File(Files.createTempDir(), "sentry_policy_db");
+    conf.set(ServerConfig.SENTRY_VERIFY_SCHEM_VERSION, "false");
+    conf.set(ServerConfig.SENTRY_STORE_JDBC_URL,
+        "jdbc:derby:;databaseName=" + dataDir.getPath() + ";create=true");
+    conf.set(ServerConfig.SENTRY_STORE_JDBC_PASS, "dummy");
+    conf.setStrings(ServerConfig.ADMIN_GROUPS, adminGroups);
+    conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING,
+        ServerConfig.SENTRY_STORE_LOCAL_GROUP_MAPPING);
+
+    policyFilePath = new File(Files.createTempDir(), "local_policy_file.ini");
+    conf.set(ServerConfig.SENTRY_STORE_GROUP_MAPPING_RESOURCE,
+        policyFilePath.getPath());
+  }
+
+  @After
+  public void clearData() throws Exception{
+    sentryStore.clearAllTables();
+  }
+
+  @AfterClass
+  public static void teardown() {
+    if (sentryStore != null) {
+      sentryStore.close();
+    }
+    if (dataDir != null) {
+      FileUtils.deleteQuietly(dataDir);
+    }
+    if (policyFilePath != null) {
+      FileUtils.deleteQuietly(policyFilePath);
+    }
+  }
+
+  public static void addGroupsToUser(String user, String... groupNames) {
+    policyFile.addGroupsToUser(user, groupNames);
+  }
+
+  public static void writePolicyFile() throws Exception {
+    policyFile.write(policyFilePath);
+  }
+
+  public String[] getAdminGroups() {
+    return adminGroups;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestDelegateSentryStore.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestDelegateSentryStore.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestDelegateSentryStore.java
new file mode 100644
index 0000000..69d1623
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestDelegateSentryStore.java
@@ -0,0 +1,182 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sentry.provider.db.generic.service.persistent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Set;
+
+import org.apache.sentry.core.common.exception.SentryAlreadyExistsException;
+import org.apache.sentry.core.common.exception.SentryNoSuchObjectException;
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+
+public class TestDelegateSentryStore extends SentryStoreIntegrationBase{
+  private static final String SEARCH = "solr";
+
+  @Before
+  public void configure() throws Exception {
+    /**
+     * add the admin user to admin groups
+     */
+    policyFile = new PolicyFile();
+    addGroupsToUser("admin", getAdminGroups());
+    writePolicyFile();
+  }
+
+  @Test
+  public void testCreateDropRole() throws Exception {
+    String roleName = "test-drop-role";
+    String grantor = "grantor";
+    sentryStore.createRole(SEARCH, roleName, grantor);
+    sentryStore.dropRole(SEARCH, roleName, grantor);
+  }
+
+  @Test
+  public void testCaseInsensitiveCreateDropRole() throws Exception {
+    String roleName1 = "test";
+    String roleName2 = "TeSt";
+    String grantor = "grantor";
+    sentryStore.createRole(SEARCH, roleName1, grantor);
+    try {
+      sentryStore.createRole(SEARCH, roleName2, grantor);
+      fail("Fail to throw Exception");
+    } catch (SentryAlreadyExistsException e) {
+      //ignore the exception
+    }
+
+    try {
+      sentryStore.dropRole(SEARCH, roleName2, grantor);
+    } catch (SentryNoSuchObjectException e) {
+      fail("Shouldn't throw SentryNoSuchObjectException");
+    }
+  }
+
+  @Test(expected=Exception.class)
+  public void testCreateDuplicateRole() throws Exception {
+    String roleName = "test-dup-role";
+    String grantor = "grantor";
+    sentryStore.createRole(SEARCH, roleName, grantor);
+    sentryStore.createRole(SEARCH, roleName, grantor);
+  }
+
+  @Test(expected=SentryNoSuchObjectException.class)
+  public void testDropNotExistRole() throws Exception {
+    String roleName = "not-exist";
+    String grantor = "grantor";
+    sentryStore.dropRole(SEARCH, roleName, grantor);
+  }
+
+  @Test(expected = SentryNoSuchObjectException.class)
+  public void testAddGroupsNonExistantRole()
+      throws Exception {
+    String roleName = "non-existant-role";
+    String grantor = "grantor";
+    sentryStore.alterRoleAddGroups(SEARCH, roleName, Sets.newHashSet("g1"), grantor);
+  }
+
+  @Test(expected = SentryNoSuchObjectException.class)
+  public void testDeleteGroupsNonExistantRole()
+      throws Exception {
+    String roleName = "non-existant-role";
+    String grantor = "grantor";
+    sentryStore.alterRoleDeleteGroups(SEARCH, roleName, Sets.newHashSet("g1"), grantor);
+  }
+
+  @Test
+  public void testAddDeleteRoleToGroups() throws Exception {
+    String role1 = "r1", role2 = "r2";
+    Set<String> twoGroups = Sets.newHashSet("g1", "g2");
+    Set<String> oneGroup = Sets.newHashSet("g3");
+    String grantor = "grantor";
+
+    sentryStore.createRole(SEARCH, role1, grantor);
+    sentryStore.createRole(SEARCH, role2, grantor);
+
+    sentryStore.alterRoleAddGroups(SEARCH, role1, twoGroups, grantor);
+    assertEquals(twoGroups, sentryStore.getGroupsByRoles(SEARCH,Sets.newHashSet(role1)));
+
+    assertEquals(Sets.newHashSet(role1), sentryStore.getRolesByGroups(SEARCH, twoGroups));
+
+    sentryStore.alterRoleAddGroups(SEARCH, role2, oneGroup, grantor);
+    assertEquals(oneGroup, sentryStore.getGroupsByRoles(SEARCH, Sets.newHashSet(role2)));
+
+    sentryStore.alterRoleDeleteGroups(SEARCH, role1, Sets.newHashSet("g1"), grantor);
+    assertEquals(Sets.newHashSet("g2"), sentryStore.getGroupsByRoles(SEARCH, Sets.newHashSet(role1)));
+
+    sentryStore.alterRoleDeleteGroups(SEARCH, role2, oneGroup, grantor);
+    assertEquals(Sets.newHashSet(), sentryStore.getGroupsByRoles(SEARCH, Sets.newHashSet(role2)));
+  }
+
+  @Test
+  public void testGetRolesByGroupNames() throws Exception {
+    String role1 = "r1", role2 = "r2";
+    Set<String> twoGroups = Sets.newHashSet("g1", "g2");
+    String grantor = "grantor";
+
+    sentryStore.createRole(SEARCH, role1, grantor);
+    sentryStore.createRole(SEARCH, role2, grantor);
+
+    sentryStore.alterRoleAddGroups(SEARCH, role1, twoGroups, grantor);
+    sentryStore.alterRoleAddGroups(SEARCH, role2, twoGroups, grantor);
+
+    assertEquals(Sets.newHashSet(role1,role2), sentryStore.getRolesByGroups(SEARCH, twoGroups));
+  }
+
+  @Test
+  public void testGetGroupsByRoleNames() throws Exception {
+    String role1 = "r1", role2 = "r2";
+    Set<String> twoGroups = Sets.newHashSet("g1", "g2");
+    String grantor = "grantor";
+
+    sentryStore.createRole(SEARCH, role1, grantor);
+    sentryStore.createRole(SEARCH, role2, grantor);
+
+    sentryStore.alterRoleAddGroups(SEARCH, role1, twoGroups, grantor);
+    sentryStore.alterRoleAddGroups(SEARCH, role2, twoGroups, grantor);
+
+    assertEquals(twoGroups, sentryStore.getGroupsByRoles(SEARCH, Sets.newHashSet(role1)));
+    assertEquals(twoGroups, sentryStore.getGroupsByRoles(SEARCH, Sets.newHashSet(role2)));
+    assertEquals(twoGroups, sentryStore.getGroupsByRoles(SEARCH, Sets.newHashSet(role1,role2)));
+  }
+
+  @Test
+  public void testGetAllRoles() throws Exception {
+    String role1 = "r1", role2 = "r2";
+    Set<String> twoGroups = Sets.newHashSet("g1", "g2");
+    String grantor = "grantor";
+
+    sentryStore.createRole(SEARCH, role1, grantor);
+    sentryStore.createRole(SEARCH, role2, grantor);
+
+    sentryStore.alterRoleAddGroups(SEARCH, role1, twoGroups, grantor);
+    sentryStore.alterRoleAddGroups(SEARCH, role2, twoGroups, grantor);
+
+    //test get all roles by groupName=null
+    String groupName = null;
+    Set<String> groups = Sets.newHashSet(groupName);
+    assertEquals(Sets.newHashSet(role1,role2), sentryStore.getRolesByGroups(SEARCH, groups));
+
+    groups.clear();
+    assertEquals(0, sentryStore.getRolesByGroups(SEARCH, groups).size());
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestPrivilegeOperatePersistence.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestPrivilegeOperatePersistence.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestPrivilegeOperatePersistence.java
new file mode 100644
index 0000000..246b2be
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestPrivilegeOperatePersistence.java
@@ -0,0 +1,1138 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sentry.provider.db.generic.service.persistent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.core.common.Authorizable;
+import org.apache.sentry.core.common.BitFieldAction;
+import org.apache.sentry.core.common.BitFieldActionFactory;
+import org.apache.sentry.core.model.solr.Collection;
+import org.apache.sentry.core.model.solr.Field;
+import org.apache.sentry.core.model.solr.SolrConstants;
+import org.apache.sentry.core.model.sqoop.SqoopActionConstant;
+import org.apache.sentry.core.common.exception.SentryGrantDeniedException;
+import org.apache.sentry.provider.db.generic.service.persistent.PrivilegeObject.Builder;
+import org.apache.sentry.provider.file.PolicyFile;
+import org.apache.sentry.service.common.ServiceConstants;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+
+/**
+ * The test cases are used for search component The authorizables are COLLECTION and Field
+ * The actions of search privilege are ALL,QUERY and UPDATE
+ */
+public class TestPrivilegeOperatePersistence extends SentryStoreIntegrationBase {
+  private static final String SEARCH = "solr";
+  private static final String ADMIN_USER = "solr";
+  private static final String GRANT_OPTION_USER = "user_grant_option";
+  private static final String[] GRANT_OPTION_GROUP = { "group_grant_option" };
+  private static final String NO_GRANT_OPTION_USER = "user_no_grant_option";
+  private static final String[] NO_GRANT_OPTION_GROUP = { "group_no_grant_option" };
+
+  private static final String SERVICE = "service";
+  private static final String COLLECTION_NAME = "collection1";
+  private static final String NOT_COLLECTION_NAME = "not_collection1";
+  private static final String FIELD_NAME = "field1";
+  private static final String NOT_FIELD_NAME = "not_field1";
+
+  @Before
+  public void configure() throws Exception {
+    /**
+     * add the solr user to admin groups
+     */
+    policyFile = new PolicyFile();
+    addGroupsToUser(ADMIN_USER, getAdminGroups());
+    writePolicyFile();
+  }
+
+  /**
+   * Grant query privilege to role r1
+   */
+  @Test
+  public void testGrantPrivilege() throws Exception {
+    testGrantPrivilege(sentryStore, SEARCH);
+  }
+
+  @Test
+  public void testGrantPrivilegeTwice() throws Exception {
+    String roleName = "r1";
+    /**
+     * grantor is admin, there is no need to check grant option
+     */
+    String grantor = ADMIN_USER;
+    sentryStore.createRole(SEARCH, roleName, grantor);
+
+    PrivilegeObject queryPrivilegeWithOption = new Builder()
+    .setComponent(SEARCH)
+    .setAction(SolrConstants.QUERY)
+    .setService(SERVICE)
+    .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+    .withGrantOption(true)
+    .build();
+
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithOption, grantor);
+    assertEquals(1,sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)).size());
+    //grant again
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithOption, grantor);
+    assertEquals(1,sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)).size());
+
+    PrivilegeObject queryPrivilegeWithNoOption = new Builder()
+    .setComponent(SEARCH)
+    .setAction(SolrConstants.QUERY)
+    .setService(SERVICE)
+    .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+    .withGrantOption(false)
+    .build();
+
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithNoOption, grantor);
+    assertEquals(2,sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)).size());
+    //grant again
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithNoOption, grantor);
+    assertEquals(2,sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)).size());
+
+    PrivilegeObject queryPrivilegeWithNullGrant = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+        .withGrantOption(null)
+        .build();
+
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithNullGrant, grantor);
+
+    assertEquals(3,sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)).size());
+    //grant again
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilegeWithNullGrant, grantor);
+    assertEquals(3,sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)).size());
+
+  }
+
+  /**
+   * Grant query privilege to role r1 and there is ALL privilege related this
+   * collection existed
+   */
+  @Test
+  public void testGrantPrivilegeWithAllPrivilegeExist() throws Exception {
+    String roleName = "r1";
+    /**
+     * grantor is admin, there is no need to check grant option
+     */
+    String grantor = ADMIN_USER;
+    PrivilegeObject allPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.ALL)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+        .build();
+
+    sentryStore.createRole(SEARCH, roleName, grantor);
+    /**
+     * grant all privilege to role r1
+     */
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, allPrivilege, grantor);
+    /**
+     * check role r1 truly has the privilege been granted
+     */
+    assertEquals(Sets.newHashSet(allPrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)));
+
+    PrivilegeObject queryPrivilege = new Builder(allPrivilege)
+        .setAction(SolrConstants.QUERY)
+        .build();
+
+    /**
+     * grant query privilege to role r1
+     */
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilege, grantor);
+    /**
+     * all privilege has been existed, the query privilege will not persistent
+     */
+    assertEquals(Sets.newHashSet(allPrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)));
+  }
+
+  /**
+   * Grant query privilege to role r1 and there are query and update privileges
+   * related this collection existed
+   */
+  @Test
+  public void testGrantALLPrivilegeWithOtherPrivilegesExist() throws Exception {
+    String roleName1 = "r1";
+    String roleName2 = "r2";
+    /**
+     * grantor is admin, there is no need to check grant option
+     */
+    String grantor = ADMIN_USER;
+
+    PrivilegeObject queryPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+        .build();
+
+    PrivilegeObject updatePrivilege = new Builder(queryPrivilege)
+        .setAction(SolrConstants.UPDATE)
+        .build();
+
+    sentryStore.createRole(SEARCH, roleName1, grantor);
+    sentryStore.createRole(SEARCH, roleName2, grantor);
+    /**
+     * grant query and update privilege to role r1 and role r2
+     */
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, updatePrivilege,grantor);
+    assertEquals(Sets.newHashSet(queryPrivilege, updatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1)));
+
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, queryPrivilege, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, updatePrivilege,grantor);
+    assertEquals(Sets.newHashSet(queryPrivilege, updatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2)));
+
+    PrivilegeObject allPrivilege = new Builder(queryPrivilege)
+        .setAction(SolrConstants.ALL)
+        .build();
+
+    /**
+     * grant all privilege to role r1
+     */
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, allPrivilege, grantor);
+
+    /**
+     * check the query and update privileges of roleName1 will be removed because of ALl privilege
+     * granted
+     */
+    assertEquals(Sets.newHashSet(allPrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1)));
+
+    /**
+     * check the query and update privileges of roleName2 will not affected and exist
+     */
+    assertEquals(Sets.newHashSet(queryPrivilege, updatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2)));
+  }
+
+  @Test
+  public void testGrantRevokeCheckWithGrantOption() throws Exception {
+
+    addGroupsToUser(GRANT_OPTION_USER, GRANT_OPTION_GROUP);
+    addGroupsToUser(NO_GRANT_OPTION_USER, NO_GRANT_OPTION_GROUP);
+    writePolicyFile();
+
+    String roleName1 = "r1";
+    String roleName2 = "r2";
+    String grantor = "g1";
+    sentryStore.createRole(SEARCH, roleName1, grantor);
+    sentryStore.createRole(SEARCH, roleName2, grantor);
+    /**
+     * grant query privilege to role r1 with grant option
+     */
+    PrivilegeObject queryPrivilege1 = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+        .withGrantOption(true)
+        .build();
+
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege1,
+        ADMIN_USER);
+    assertEquals(Sets.newHashSet(queryPrivilege1),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1)));
+    /**
+     * grant query privilege to role r2 no grant option
+     */
+    PrivilegeObject queryPrivilege2 = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+        .withGrantOption(false).build();
+
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, queryPrivilege2,
+        ADMIN_USER);
+    assertEquals(Sets.newHashSet(queryPrivilege2),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2)));
+
+    sentryStore.alterRoleAddGroups(SEARCH, roleName1,
+        Sets.newHashSet(GRANT_OPTION_GROUP), grantor);
+    sentryStore.alterRoleAddGroups(SEARCH, roleName2,
+        Sets.newHashSet(NO_GRANT_OPTION_GROUP), grantor);
+
+    String roleName3 = "r3";
+    sentryStore.createRole(SEARCH, roleName3, grantor);
+    /**
+     * the user with grant option grant query privilege to rolr r3
+     */
+    try{
+      sentryStore.alterRoleGrantPrivilege(SEARCH, roleName3, queryPrivilege1,
+          GRANT_OPTION_USER);
+    } catch (SentryGrantDeniedException e) {
+      fail("SentryGrantDeniedException shouldn't have been thrown");
+    }
+
+    /**
+     * the user with grant option revoke query privilege to rolr r3
+     */
+    try{
+      sentryStore.alterRoleRevokePrivilege(SEARCH, roleName3, queryPrivilege1,
+          GRANT_OPTION_USER);
+    } catch (SentryGrantDeniedException e) {
+      fail("SentryGrantDeniedException shouldn't have been thrown");
+    }
+
+    /**
+     * the user with no grant option grant query privilege to rolr r3, it will
+     * throw SentryGrantDeniedException
+     */
+    try {
+      sentryStore.alterRoleGrantPrivilege(SEARCH, roleName3, queryPrivilege2,
+          NO_GRANT_OPTION_USER);
+      fail("SentryGrantDeniedException should have been thrown");
+    } catch (SentryGrantDeniedException e) {
+      //ignore the exception
+    }
+
+    /**
+     * the user with no grant option revoke query privilege to rolr r3, it will
+     * throw SentryGrantDeniedException
+     */
+    try {
+      sentryStore.alterRoleGrantPrivilege(SEARCH, roleName3, queryPrivilege2,
+          NO_GRANT_OPTION_USER);
+      fail("SentryGrantDeniedException should have been thrown");
+    } catch (SentryGrantDeniedException e) {
+      //ignore the exception
+    }
+  }
+
+  @Test
+  public void testGrantWithGrantOption() throws Exception {
+
+    addGroupsToUser(GRANT_OPTION_USER, GRANT_OPTION_GROUP);
+    addGroupsToUser(NO_GRANT_OPTION_USER, NO_GRANT_OPTION_GROUP);
+    writePolicyFile();
+
+    String roleName1 = "r1";
+    String grantor = "g1";
+    sentryStore.createRole(SEARCH, roleName1, grantor);
+    /**
+     * grant query privilege to role r1 with grant option
+     */
+    PrivilegeObject queryPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+        .withGrantOption(true)
+        .build();
+
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege,ADMIN_USER);
+    sentryStore.alterRoleAddGroups(SEARCH, roleName1,
+        Sets.newHashSet(GRANT_OPTION_GROUP), grantor);
+
+    /**
+     * the user with grant option grant query privilege to rolr r2
+     */
+    String roleName2 = "r2";
+    sentryStore.createRole(SEARCH, roleName2, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, queryPrivilege, GRANT_OPTION_USER);
+
+    assertEquals(Sets.newHashSet(queryPrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2)));
+
+  }
+
+
+  /**
+   * Grant query and update privileges to role r1 and revoke query privilege
+   * there is left update privilege related to role r1
+   */
+  @Test
+  public void testRevokePrivilege() throws Exception {
+    String roleName = "r1";
+    /**
+     * grantor is admin, there is no need to check grant option
+     */
+    String grantor = ADMIN_USER;
+    PrivilegeObject queryPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME)))
+        .build();
+
+    PrivilegeObject updatePrivilege = new Builder(queryPrivilege)
+        .setAction(SolrConstants.UPDATE)
+        .build();
+
+    sentryStore.createRole(SEARCH, roleName, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilege, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, updatePrivilege, grantor);
+
+    assertEquals(Sets.newHashSet(queryPrivilege,updatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)));
+    /**
+     * revoke query privilege
+     */
+    sentryStore.alterRoleRevokePrivilege(SEARCH, roleName, queryPrivilege, grantor);
+    assertEquals(Sets.newHashSet(updatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)));
+  }
+
+  /**
+   * Grant query and update privileges to role r1 and revoke all privilege,
+   * there is no privilege related to role r1
+   */
+  @Test
+  public void testRevokeAllPrivilege() throws Exception {
+    String roleName = "r1";
+    /**
+     * grantor is admin, there is no need to check grant option
+     */
+    String grantor = ADMIN_USER;
+    PrivilegeObject queryPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME),new Field(FIELD_NAME)))
+        .build();
+
+    PrivilegeObject updatePrivilege = new Builder(queryPrivilege)
+        .setAction(SolrConstants.UPDATE)
+        .build();
+
+    sentryStore.createRole(SEARCH, roleName, grantor);
+
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilege, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, updatePrivilege, grantor);
+
+    assertEquals(Sets.newHashSet(queryPrivilege,updatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)));
+    /**
+     * revoke all privilege
+     */
+    PrivilegeObject allPrivilege = new Builder(queryPrivilege)
+        .setAction(SolrConstants.ALL)
+        .build();
+
+    sentryStore.alterRoleRevokePrivilege(SEARCH, roleName, allPrivilege, grantor);
+
+    assertEquals(Sets.newHashSet(),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)));
+  }
+
+  /**
+   * Grant all privilege to role r1 and revoke query privilege
+   * there is update privilege related to role r1
+   */
+  @Test
+  public void testRevokePrivilegeWithAllPrivilegeExist() throws Exception {
+    String roleName = "r1";
+    /**
+     * grantor is admin, there is no need to check grant option
+     */
+    String grantor = ADMIN_USER;
+    PrivilegeObject allPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.ALL)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME)))
+        .build();
+
+    sentryStore.createRole(SEARCH, roleName, grantor);
+
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, allPrivilege, grantor);
+
+    assertEquals(Sets.newHashSet(allPrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)));
+    /**
+     * revoke update privilege
+     */
+    PrivilegeObject updatePrivilege = new Builder(allPrivilege)
+        .setAction(SolrConstants.UPDATE)
+        .build();
+
+    PrivilegeObject queryPrivilege = new Builder(allPrivilege)
+        .setAction(SolrConstants.QUERY)
+        .build();
+
+    sentryStore.alterRoleRevokePrivilege(SEARCH, roleName, updatePrivilege, grantor);
+
+    assertEquals(Sets.newHashSet(queryPrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)));
+  }
+
+  /**
+   * Grant update, query and all privilege to role r1
+   * Revoke query privilege from role r1
+   * there is update privilege related to role r1
+   */
+  @Test
+  public void testRevokePrivilegeWithAllPrivilegesGranted() throws Exception {
+    String roleName = "r1";
+    /**
+     * grantor is admin, there is no need to check grant option
+     */
+    String grantor = ADMIN_USER;
+    PrivilegeObject allPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.ALL)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME)))
+        .build();
+
+    PrivilegeObject updatePrivilege = new Builder(allPrivilege)
+        .setAction(SolrConstants.UPDATE)
+        .build();
+
+    PrivilegeObject queryPrivilege = new Builder(allPrivilege)
+        .setAction(SolrConstants.QUERY)
+        .build();
+
+    sentryStore.createRole(SEARCH, roleName, grantor);
+    //grant query to role r1
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilege, grantor);
+    assertEquals(Sets.newHashSet(queryPrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)));
+
+    //grant update to role r1
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, updatePrivilege, grantor);
+    assertEquals(Sets.newHashSet(queryPrivilege, updatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)));
+    /**
+     * grant all action privilege to role r1, because all action includes query and update action,
+     * The role r1 only has the action all privilege
+     */
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, allPrivilege, grantor);
+    assertEquals(Sets.newHashSet(allPrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)));
+    /**
+     * revoke update privilege from role r1, the query privilege has been left
+     */
+    sentryStore.alterRoleRevokePrivilege(SEARCH, roleName, updatePrivilege, grantor);
+    assertEquals(Sets.newHashSet(queryPrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)));
+  }
+
+  @Test
+  public void testRevokeParentPrivilegeWithChildsExist() throws Exception {
+    String roleName = "r1";
+    /**
+     * grantor is admin, there is no need to check grant option
+     */
+    String grantor = ADMIN_USER;
+    PrivilegeObject updatePrivilege1 = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.UPDATE)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME)))
+        .build();
+
+    PrivilegeObject queryPrivilege1 = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME),new Field(FIELD_NAME)))
+        .build();
+
+    PrivilegeObject queryPrivilege2 = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(NOT_COLLECTION_NAME)))
+        .build();
+
+    sentryStore.createRole(SEARCH, roleName, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, updatePrivilege1, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilege1, grantor);
+
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName, queryPrivilege2, grantor);
+
+    /**
+     * revoke all privilege with collection[COLLECTION_NAME=collection1] and its child privileges
+     */
+    PrivilegeObject allPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.ALL)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+        .build();
+
+    sentryStore.alterRoleRevokePrivilege(SEARCH, roleName, allPrivilege, grantor);
+    assertEquals(Sets.newHashSet(queryPrivilege2),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName)));
+  }
+
+  @Test
+  public void testRevokeWithGrantOption() throws Exception {
+
+    addGroupsToUser(GRANT_OPTION_USER, GRANT_OPTION_GROUP);
+    addGroupsToUser(NO_GRANT_OPTION_USER, NO_GRANT_OPTION_GROUP);
+    writePolicyFile();
+
+    String roleName1 = "r1";
+    String grantor = "g1";
+    sentryStore.createRole(SEARCH, roleName1, grantor);
+    /**
+     * grant query privilege to role r1 with grant option
+     */
+    PrivilegeObject queryPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+        .withGrantOption(true)
+        .build();
+
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege,
+        ADMIN_USER);
+    assertEquals(Sets.newHashSet(queryPrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1)));
+
+    sentryStore.alterRoleAddGroups(SEARCH, roleName1,
+        Sets.newHashSet(GRANT_OPTION_GROUP), grantor);
+
+    String roleName2 = "r2";
+    sentryStore.createRole(SEARCH, roleName2, grantor);
+    /**
+     * the user with grant option grant query privilege to rolr r2
+     */
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, queryPrivilege,
+        GRANT_OPTION_USER);
+    assertEquals(Sets.newHashSet(queryPrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2)));
+
+    /**
+     * the user with grant option revoke query privilege to rolr r3
+     */
+    sentryStore.alterRoleRevokePrivilege(SEARCH, roleName2, queryPrivilege, GRANT_OPTION_USER);
+    assertEquals(Sets.newHashSet(),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2)));
+  }
+
+  @Test
+  public void testDropPrivilege() throws Exception{
+    String roleName1 = "r1";
+    String roleName2 = "r2";
+    String grantor = ADMIN_USER;
+
+    PrivilegeObject queryPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME)))
+        .build();
+
+    PrivilegeObject updatePrivilege = new Builder(queryPrivilege)
+        .setAction(SolrConstants.UPDATE)
+        .build();
+
+    /**
+     * grant query and update privilege to role r1 and r2
+     */
+    sentryStore.createRole(SEARCH, roleName1, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, updatePrivilege, grantor);
+
+    sentryStore.createRole(SEARCH, roleName2, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, queryPrivilege, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, updatePrivilege, grantor);
+
+    assertEquals(Sets.newHashSet(queryPrivilege,updatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1)));
+
+    assertEquals(Sets.newHashSet(queryPrivilege,updatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2)));
+    /**
+     * drop query privilege
+     */
+    sentryStore.dropPrivilege(SEARCH, queryPrivilege, grantor);
+
+    assertEquals(Sets.newHashSet(updatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1)));
+
+    assertEquals(Sets.newHashSet(updatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2)));
+
+    /**
+     * drop ALL privilege
+     */
+    PrivilegeObject allPrivilege = new Builder(queryPrivilege)
+        .setAction(SolrConstants.ALL)
+        .build();
+
+    sentryStore.dropPrivilege(SEARCH, allPrivilege, grantor);
+
+    assertEquals(Sets.newHashSet(),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1)));
+
+    assertEquals(Sets.newHashSet(),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2)));
+
+    /**
+     * grant query and update field scope[collection1,field1] privilege to role r1
+     * drop collection scope[collection1] privilege
+     * there is no privilege
+     */
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, updatePrivilege, grantor);
+
+    PrivilegeObject parentPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.ALL)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+        .build();
+
+    sentryStore.dropPrivilege(SEARCH, parentPrivilege, grantor);
+    assertEquals(Sets.newHashSet(),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1)));
+  }
+
+  @Test
+  public void testRenamePrivilege() throws Exception{
+    String roleName1 = "r1";
+    String roleName2 = "r2";
+    String grantor = ADMIN_USER;
+
+    List<? extends Authorizable> oldAuthoriables = Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME));
+    List<? extends Authorizable> newAuthoriables = Arrays.asList(new Collection(COLLECTION_NAME), new Field(NOT_FIELD_NAME));
+
+    PrivilegeObject oldQueryPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(oldAuthoriables)
+        .build();
+
+    PrivilegeObject oldUpdatePrivilege = new Builder(oldQueryPrivilege)
+        .setAction(SolrConstants.UPDATE)
+        .build();
+
+    PrivilegeObject oldALLPrivilege = new Builder(oldQueryPrivilege)
+        .setAction(SolrConstants.ALL)
+        .build();
+
+
+    PrivilegeObject newQueryPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(newAuthoriables)
+        .build();
+
+    PrivilegeObject newUpdatePrivilege = new Builder(newQueryPrivilege)
+        .setAction(SolrConstants.UPDATE)
+        .build();
+
+    PrivilegeObject newALLPrivilege = new Builder(newQueryPrivilege)
+        .setAction(SolrConstants.ALL)
+        .build();
+
+
+    /**
+     * grant query and update privilege to role r1
+     * grant all privilege to role r2
+     */
+    sentryStore.createRole(SEARCH, roleName1, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, oldQueryPrivilege, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, oldUpdatePrivilege, grantor);
+
+    sentryStore.createRole(SEARCH, roleName2, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, oldALLPrivilege, grantor);
+
+    assertEquals(Sets.newHashSet(oldQueryPrivilege,oldUpdatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1)));
+
+    assertEquals(Sets.newHashSet(oldALLPrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2)));
+    /**
+     * rename old query privilege to new query privilege
+     */
+    sentryStore.renamePrivilege(SEARCH, SERVICE,
+                                      oldAuthoriables,
+                                      newAuthoriables,
+                                      grantor);
+
+    assertEquals(Sets.newHashSet(newQueryPrivilege,newUpdatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1)));
+
+    assertEquals(Sets.newHashSet(newALLPrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2)));
+    /**
+     * rename collection scope[collection=collection1] privilege to [collection=not_collection1]
+     * These privileges belong to collection scope[collection=collection1] will change to
+     * [collection=not_collection1]
+     */
+
+    List<? extends Authorizable> newAuthoriables1 = Arrays.asList(new Collection(NOT_COLLECTION_NAME),new Field(NOT_FIELD_NAME));
+
+    PrivilegeObject newQueryPrivilege1 = new Builder(newQueryPrivilege)
+          .setAuthorizables(newAuthoriables1)
+          .build();
+
+    PrivilegeObject newUpdatePrivilege1 = new Builder(newUpdatePrivilege)
+          .setAuthorizables(newAuthoriables1)
+          .build();
+
+    PrivilegeObject newALLPrivilege1 = new Builder(newALLPrivilege)
+          .setAuthorizables(newAuthoriables1)
+          .build();
+
+    sentryStore.renamePrivilege(SEARCH, SERVICE,
+        Arrays.asList(new Collection(COLLECTION_NAME)),
+        Arrays.asList(new Collection(NOT_COLLECTION_NAME)),
+        grantor);
+
+    assertEquals(Sets.newHashSet(newQueryPrivilege1,newUpdatePrivilege1),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1)));
+
+    assertEquals(Sets.newHashSet(newALLPrivilege1),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName2)));
+  }
+
+  @Test
+  public void testGetPrivilegesByRoleName() throws Exception {
+    String roleName1 = "r1";
+    String roleName2 = "r2";
+    String grantor = "g1";
+
+    PrivilegeObject queryPrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+        .build();
+
+    sentryStore.createRole(SEARCH, roleName1, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege,
+        ADMIN_USER);
+
+    PrivilegeObject updatePrivilege = new Builder()
+        .setComponent(SEARCH)
+        .setAction(SolrConstants.QUERY)
+        .setService(SERVICE)
+        .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+        .build();
+
+    sentryStore.createRole(SEARCH, roleName2, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, updatePrivilege,
+        ADMIN_USER);
+
+    assertEquals(Sets.newHashSet(queryPrivilege,updatePrivilege),
+        sentryStore.getPrivilegesByRole(SEARCH, Sets.newHashSet(roleName1,roleName2)));
+
+  }
+
+  @Test
+  public void testGetPrivilegesByProvider() throws Exception {
+    String roleName1 = "r1";
+    String roleName2 = "r2";
+    String roleName3 = "r3";
+    String group = "g3";
+    String grantor = ADMIN_USER;
+
+    String service1 = "service1";
+
+    PrivilegeObject queryPrivilege1 = new Builder()
+         .setComponent(SEARCH)
+         .setAction(SolrConstants.QUERY)
+         .setService(service1)
+         .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+         .build();
+
+    PrivilegeObject updatePrivilege1 = new Builder()
+         .setComponent(SEARCH)
+         .setAction(SolrConstants.UPDATE)
+         .setService(service1)
+         .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME)))
+         .build();
+
+    PrivilegeObject queryPrivilege2 = new Builder()
+         .setComponent(SEARCH)
+         .setAction(SolrConstants.QUERY)
+         .setService(service1)
+         .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+         .build();
+
+    PrivilegeObject updatePrivilege2 = new Builder()
+         .setComponent(SEARCH)
+         .setAction(SolrConstants.UPDATE)
+         .setService(service1)
+         .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME)))
+         .build();
+
+    sentryStore.createRole(SEARCH, roleName1, grantor);
+    sentryStore.createRole(SEARCH, roleName2, grantor);
+    sentryStore.createRole(SEARCH, roleName3, grantor);
+
+    sentryStore.alterRoleAddGroups(SEARCH, roleName3, Sets.newHashSet(group), grantor);
+
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege1, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, updatePrivilege1, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, queryPrivilege2, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName3, updatePrivilege2, grantor);
+
+    assertEquals(Sets.newHashSet(updatePrivilege1, queryPrivilege1),
+        sentryStore.getPrivilegesByProvider(SEARCH, service1, Sets.newHashSet(roleName1), null, null));
+
+    assertEquals(Sets.newHashSet(updatePrivilege1, queryPrivilege1, queryPrivilege2),
+        sentryStore.getPrivilegesByProvider(SEARCH, service1, Sets.newHashSet(roleName1,roleName2),
+            null, null));
+
+    assertEquals(Sets.newHashSet(updatePrivilege1, queryPrivilege1, queryPrivilege2, updatePrivilege2),
+        sentryStore.getPrivilegesByProvider(SEARCH, service1, Sets.newHashSet(roleName1,roleName2),
+            Sets.newHashSet(group), null));
+
+    List<? extends Authorizable> authorizables = Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME));
+    assertEquals(Sets.newHashSet(updatePrivilege1, updatePrivilege2),
+        sentryStore.getPrivilegesByProvider(SEARCH, service1, Sets.newHashSet(roleName1,roleName2),
+            Sets.newHashSet(group), authorizables));
+  }
+
+  @Test
+  public void testGetPrivilegesByAuthorizable() throws Exception {
+    String roleName1 = "r1";
+    String roleName2 = "r2";
+    String roleName3 = "r3";
+    String grantor = ADMIN_USER;
+
+    String service1 = "service1";
+
+    PrivilegeObject queryPrivilege1 = new Builder()
+    .setComponent(SEARCH)
+    .setAction(SolrConstants.QUERY)
+    .setService(service1)
+    .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+    .build();
+
+    PrivilegeObject updatePrivilege1 = new Builder()
+    .setComponent(SEARCH)
+    .setAction(SolrConstants.UPDATE)
+    .setService(service1)
+    .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME)))
+    .build();
+
+    PrivilegeObject queryPrivilege2 = new Builder()
+    .setComponent(SEARCH)
+    .setAction(SolrConstants.QUERY)
+    .setService(service1)
+    .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME)))
+    .build();
+
+    PrivilegeObject updatePrivilege2 = new Builder()
+    .setComponent(SEARCH)
+    .setAction(SolrConstants.UPDATE)
+    .setService(service1)
+    .setAuthorizables(Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME)))
+    .build();
+
+    sentryStore.createRole(SEARCH, roleName1, grantor);
+    sentryStore.createRole(SEARCH, roleName2, grantor);
+    sentryStore.createRole(SEARCH, roleName3, grantor);
+
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, queryPrivilege1, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName1, updatePrivilege1, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName2, queryPrivilege2, grantor);
+    sentryStore.alterRoleGrantPrivilege(SEARCH, roleName3, updatePrivilege2, grantor);
+
+    assertEquals(0, sentryStore.getPrivilegesByAuthorizable(SEARCH, service1, null,
+        Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME))).size());
+    assertEquals(1, sentryStore.getPrivilegesByAuthorizable(SEARCH, service1, Sets.newHashSet(roleName1),
+    Arrays.asList(new Collection(COLLECTION_NAME), new Field(FIELD_NAME))).size());
+    assertEquals(2, sentryStore.getPrivilegesByAuthorizable(SEARCH, service1,
+        Sets.newHashSet(roleName1), null).size());
+    assertEquals(2, sentryStore.getPrivilegesByAuthorizable(SEARCH, service1,
+        Sets.newHashSet(roleName1,roleName2), null).size());
+    assertEquals(2, sentryStore.getPrivilegesByAuthorizable(SEARCH, service1,
+        Sets.newHashSet(roleName1,roleName2, roleName3), null).size());
+  }
+
+  @Test(expected = Exception.class)
+  public void testGrantPrivilegeExternalComponentMissingConf() throws Exception {
+    testGrantPrivilege(sentryStore, "externalComponent");
+  }
+
+  @Test(expected = Exception.class)
+  public void testGrantPrivilegeExternalComponentInvalidConf() throws Exception {
+    String externalComponent = "mycomponent";
+    Configuration confCopy = new Configuration(conf);
+    confCopy.set(String.format(ServiceConstants.ServerConfig.SENTRY_COMPONENT_ACTION_FACTORY_FORMAT, externalComponent),
+                 InvalidActionFactory.class.getName());
+    SentryStoreLayer store = new DelegateSentryStore(confCopy);
+    testGrantPrivilege(store, externalComponent);
+  }
+
+  @Test
+  public void testGrantPrivilegeExternalComponent() throws Exception {
+    String externalComponent = "mycomponent";
+    Configuration confCopy = new Configuration(conf);
+    confCopy.set(String.format(ServiceConstants.ServerConfig.SENTRY_COMPONENT_ACTION_FACTORY_FORMAT, externalComponent),
+                 MyComponentActionFactory.class.getName());
+    SentryStoreLayer store = new DelegateSentryStore(confCopy);
+    testGrantPrivilege(store, externalComponent);
+  }
+
+  @Test
+  public void testGrantPrivilegeExternalComponentCaseInsensitivity() throws Exception {
+    String externalComponent = "MyCoMpOnEnT";
+    Configuration confCopy = new Configuration(conf);
+    confCopy.set(String.format(ServiceConstants.ServerConfig.SENTRY_COMPONENT_ACTION_FACTORY_FORMAT, "mycomponent"),
+                 MyComponentActionFactory.class.getName());
+    SentryStoreLayer store = new DelegateSentryStore(confCopy);
+    testGrantPrivilege(store, externalComponent);
+  }
+
+  private void testGrantPrivilege(SentryStoreLayer sentryStore, String component) throws Exception {
+    String roleName = "r1";
+    /**
+     * grantor is admin, there is no need to check grant option
+     */
+    String grantor = ADMIN_USER;
+    PrivilegeObject queryPrivilege = new Builder()
+      .setComponent(component)
+      .setAction(SolrConstants.QUERY)
+      .setService(SERVICE)
+      .setAuthorizables(Collections.singletonList(new Collection(COLLECTION_NAME)))
+      .withGrantOption(null)
+      .build();
+
+    sentryStore.createRole(component, roleName, grantor);
+    sentryStore.alterRoleGrantPrivilege(component, roleName, queryPrivilege, grantor);
+
+    assertEquals(Sets.newHashSet(queryPrivilege),
+                 sentryStore.getPrivilegesByRole(component, Sets.newHashSet(roleName)));
+
+    PrivilegeObject queryPrivilegeWithOption = new Builder()
+      .setComponent(component)
+      .setAction(SolrConstants.QUERY)
+      .setService(SERVICE)
+      .setAuthorizables(Collections.singletonList(new Collection(COLLECTION_NAME)))
+      .withGrantOption(true)
+      .build();
+
+    sentryStore.alterRoleGrantPrivilege(component, roleName, queryPrivilegeWithOption, grantor);
+
+    assertEquals(Sets.newHashSet(queryPrivilege, queryPrivilegeWithOption),
+                 sentryStore.getPrivilegesByRole(component, Sets.newHashSet(roleName)));
+
+    PrivilegeObject queryPrivilegeWithNoOption = new Builder()
+      .setComponent(component)
+      .setAction(SolrConstants.QUERY)
+      .setService(SERVICE)
+      .setAuthorizables(Collections.singletonList(new Collection(COLLECTION_NAME)))
+      .withGrantOption(false)
+      .build();
+
+    sentryStore.alterRoleGrantPrivilege(component, roleName, queryPrivilegeWithNoOption, grantor);
+
+    assertEquals(Sets.newHashSet(queryPrivilege, queryPrivilegeWithOption, queryPrivilegeWithNoOption),
+                 sentryStore.getPrivilegesByRole(component, Sets.newHashSet(roleName)));
+  }
+
+  public static final class InvalidActionFactory {
+
+  }
+
+  public static final class MyComponentActionFactory extends BitFieldActionFactory {
+
+    public enum MyComponentActionType {
+      FOO("foo", 1),
+      BAR("bar", 2),
+      QUERY(SolrConstants.QUERY, 4),
+      ALL("*", FOO.getCode() | BAR.getCode() | QUERY.getCode());
+
+      private String name;
+      private int code;
+      MyComponentActionType(String name, int code) {
+        this.name = name;
+        this.code = code;
+      }
+
+      public int getCode() {
+        return code;
+      }
+
+      public String getName() {
+        return name;
+      }
+
+      static MyComponentActionType getActionByName(String name) {
+        for (MyComponentActionType action : MyComponentActionType.values()) {
+          if (action.name.equalsIgnoreCase(name)) {
+            return action;
+          }
+        }
+        throw new RuntimeException("can't get MyComponentActionType by name:" + name);
+      }
+
+      static List<MyComponentActionType> getActionByCode(int code) {
+        List<MyComponentActionType> actions = Lists.newArrayList();
+        for (MyComponentActionType action : MyComponentActionType.values()) {
+          if ((action.code & code) == action.code && action != MyComponentActionType.ALL) {
+            //MyComponentActionType.ALL action should not return in the list
+            actions.add(action);
+          }
+        }
+        if (actions.isEmpty()) {
+          throw new RuntimeException("can't get sqoopActionType by code:" + code);
+        }
+        return actions;
+      }
+    }
+
+    public static class MyComponentAction extends BitFieldAction {
+      public MyComponentAction(String name) {
+        this(MyComponentActionType.getActionByName(name));
+      }
+      public MyComponentAction(MyComponentActionType myComponentActionType) {
+        super(myComponentActionType.name, myComponentActionType.code);
+      }
+    }
+
+    @Override
+    public List<? extends BitFieldAction> getActionsByCode(int actionCode) {
+      List<MyComponentAction> actions = Lists.newArrayList();
+      for (MyComponentActionType action : MyComponentActionType.getActionByCode(actionCode)) {
+        actions.add(new MyComponentAction(action));
+      }
+      return actions;
+    }
+
+    @Override
+    public BitFieldAction getActionByName(String name) {
+      // Check the name is All
+      if (SqoopActionConstant.ALL_NAME.equalsIgnoreCase(name)) {
+        return new MyComponentAction(MyComponentActionType.ALL);
+      }
+      return new MyComponentAction(name);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryGMPrivilege.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryGMPrivilege.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryGMPrivilege.java
new file mode 100644
index 0000000..03abb4e
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryGMPrivilege.java
@@ -0,0 +1,207 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sentry.provider.db.generic.service.persistent;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+
+import org.apache.sentry.core.model.db.AccessConstants;
+import org.apache.sentry.core.model.solr.Collection;
+import org.apache.sentry.core.model.solr.Field;
+import org.apache.sentry.core.model.solr.SolrConstants;
+import org.apache.sentry.provider.db.service.model.MSentryGMPrivilege;
+import org.junit.Test;
+
+public class TestSentryGMPrivilege {
+
+  @Test
+  public void testValidateAuthorizables() throws Exception {
+    try {
+      new MSentryGMPrivilege("solr",
+          "service1", Arrays.asList(new Collection("c1"), new Field("f1")),SolrConstants.QUERY, false);
+    } catch (IllegalStateException e) {
+      fail("unexpect happend: it is a validated privilege");
+    }
+
+    try {
+      new MSentryGMPrivilege("solr",
+          "service1", Arrays.asList(new Collection(""), new Field("f1")),SolrConstants.QUERY, false);
+      fail("unexpect happend: it is not a validated privilege, The empty name of authorizable can't be empty");
+    } catch (IllegalStateException e) {
+    }
+
+    try {
+      new MSentryGMPrivilege("solr",
+          "service1", Arrays.asList(null, new Field("f1")),SolrConstants.QUERY, false);
+      fail("unexpect happend: it is not a validated privilege, The authorizable can't be null");
+    } catch (IllegalStateException e) {
+    }
+  }
+
+  @Test
+  public void testImpliesWithServerScope() throws Exception {
+    //The persistent privilege is server scope
+    MSentryGMPrivilege serverPrivilege = new MSentryGMPrivilege("solr",
+        "service1", null,SolrConstants.QUERY, false);
+
+    MSentryGMPrivilege collectionPrivilege = new MSentryGMPrivilege("solr",
+        "service1", Arrays.asList(new Collection("c1")),
+        SolrConstants.QUERY, false);
+    assertTrue(serverPrivilege.implies(collectionPrivilege));
+
+    MSentryGMPrivilege fieldPrivilege = new MSentryGMPrivilege("solr",
+        "service1", Arrays.asList(new Collection("c1"), new Field("f1")),
+        SolrConstants.QUERY, false);
+    assertTrue(serverPrivilege.implies(fieldPrivilege));
+    assertTrue(collectionPrivilege.implies(fieldPrivilege));
+
+    serverPrivilege.setAction(SolrConstants.UPDATE);
+    assertFalse(serverPrivilege.implies(collectionPrivilege));
+    assertFalse(serverPrivilege.implies(fieldPrivilege));
+
+    serverPrivilege.setAction(SolrConstants.ALL);
+    assertTrue(serverPrivilege.implies(collectionPrivilege));
+    assertTrue(serverPrivilege.implies(fieldPrivilege));
+  }
+  /**
+   * The requested privilege has the different authorizable size with the persistent privilege
+   * @throws Exception
+   */
+  @Test
+  public void testImpliesDifferentAuthorizable() throws Exception {
+    /**
+     * Test the scope of persistent privilege is the larger than the requested privilege
+     */
+    MSentryGMPrivilege serverPrivilege = new MSentryGMPrivilege("solr",
+        "service1", null, SolrConstants.QUERY, false);
+
+    MSentryGMPrivilege collectionPrivilege = new MSentryGMPrivilege("solr",
+        "service1", Arrays.asList(new Collection("c1")),
+        SolrConstants.QUERY, false);
+
+    MSentryGMPrivilege fieldPrivilege = new MSentryGMPrivilege("solr",
+        "service1", Arrays.asList(new Collection("c1"), new Field("f1")),
+        SolrConstants.QUERY, false);
+    assertTrue(serverPrivilege.implies(collectionPrivilege));
+    assertTrue(serverPrivilege.implies(fieldPrivilege));
+    assertTrue(collectionPrivilege.implies(fieldPrivilege));
+    /**
+     * Test the scope of persistent privilege is less than  the request privilege
+     */
+    assertFalse(fieldPrivilege.implies(collectionPrivilege));
+    assertFalse(fieldPrivilege.implies(serverPrivilege));
+    assertFalse(collectionPrivilege.implies(serverPrivilege));
+
+    /**
+     * Test the scope of persistent privilege is less than  the request privilege,
+     * but the name of left authorizable is ALL
+     */
+    MSentryGMPrivilege fieldAllPrivilege = new MSentryGMPrivilege("solr",
+        "service1", Arrays.asList(new Collection("c1"), new Field(AccessConstants.ALL)),
+        SolrConstants.QUERY, false);
+
+    assertTrue(fieldAllPrivilege.implies(collectionPrivilege));
+
+    /**
+     * Test the scope of persistent privilege has the same scope as request privilege
+     */
+    MSentryGMPrivilege fieldPrivilege1 = new MSentryGMPrivilege("solr",
+        "service1", Arrays.asList(new Collection("c1"), new Field("f1")),
+        SolrConstants.QUERY, false);
+
+    MSentryGMPrivilege fieldPrivilege2 = new MSentryGMPrivilege("solr",
+        "service1", Arrays.asList(new Collection("c2"), new Field("f2")),
+        SolrConstants.QUERY, false);
+    assertFalse(fieldPrivilege1.implies(fieldPrivilege2));
+  }
+
+  /**
+   * The requested privilege has the same authorizable size as with the persistent privilege
+   * @throws Exception
+   */
+  @Test
+  public void testSearchImpliesEqualAuthorizable() throws Exception {
+
+    MSentryGMPrivilege serverPrivilege1 = new MSentryGMPrivilege("solr",
+        "service1", null,SolrConstants.QUERY, false);
+
+    MSentryGMPrivilege serverPrivilege2 = new MSentryGMPrivilege("solr",
+        "service2", null,SolrConstants.QUERY, false);
+
+    assertFalse(serverPrivilege1.implies(serverPrivilege2));
+
+    MSentryGMPrivilege collectionPrivilege1 = new MSentryGMPrivilege("solr",
+        "service1", Arrays.asList(new Collection("c1")),
+        SolrConstants.QUERY, false);
+
+    MSentryGMPrivilege collectionPrivilege2 = new MSentryGMPrivilege("solr",
+        "service1", Arrays.asList(new Collection("c2")),
+        SolrConstants.QUERY, false);
+
+    assertFalse(collectionPrivilege1.implies(collectionPrivilege2));
+
+    MSentryGMPrivilege fieldPrivilege1 = new MSentryGMPrivilege("solr",
+        "service1", Arrays.asList(new Collection("c1"), new Field("f1")),
+        SolrConstants.QUERY, false);
+
+    MSentryGMPrivilege fieldPrivilege2 = new MSentryGMPrivilege("solr",
+        "service1", Arrays.asList(new Collection("c1"), new Field("f2")),
+        SolrConstants.QUERY, false);
+
+    assertFalse(fieldPrivilege1.implies(fieldPrivilege2));
+
+    /**
+     * The authorizables aren't equal,but the persistent privilege has the ALL name
+     */
+    collectionPrivilege2.setAuthorizables(Arrays.asList(new Collection(AccessConstants.ALL)));
+    collectionPrivilege2.implies(collectionPrivilege1);
+
+    fieldPrivilege2.setAuthorizables(Arrays.asList(new Collection("c1"), new Field(AccessConstants.ALL)));
+    fieldPrivilege2.implies(fieldPrivilege1);
+  }
+
+  @Test
+  public void testSearchImpliesAction() throws Exception {
+    /**
+     * action is equal
+     */
+    MSentryGMPrivilege fieldPrivilege1 = new MSentryGMPrivilege("solr",
+        "service1", Arrays.asList(new Collection("c1"), new Field("f2")),
+        SolrConstants.QUERY, false);
+
+    MSentryGMPrivilege fieldPrivilege2 = new MSentryGMPrivilege("solr",
+        "service1", Arrays.asList(new Collection("c1"), new Field("f2")),
+        SolrConstants.QUERY, false);
+
+    assertTrue(fieldPrivilege1.implies(fieldPrivilege2));
+
+    /**
+     * action isn't equal
+     */
+    fieldPrivilege2.setAction(SolrConstants.UPDATE);
+    assertFalse(fieldPrivilege1.implies(fieldPrivilege2));
+    /**
+     * action isn't equal,but the persistent privilege has the ALL action
+     */
+    fieldPrivilege1.setAction(SolrConstants.ALL);
+    assertTrue(fieldPrivilege1.implies(fieldPrivilege2));
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/7db84b2f/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryRole.java
----------------------------------------------------------------------
diff --git a/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryRole.java b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryRole.java
new file mode 100644
index 0000000..65d26c0
--- /dev/null
+++ b/sentry-service/sentry-service-server/src/test/java/org/apache/sentry/provider/db/generic/service/persistent/TestSentryRole.java
@@ -0,0 +1,542 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sentry.provider.db.generic.service.persistent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Properties;
+import java.util.List;
+
+import javax.jdo.JDOHelper;
+import javax.jdo.PersistenceManager;
+import javax.jdo.PersistenceManagerFactory;
+import javax.jdo.Query;
+import javax.jdo.Transaction;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.model.solr.Collection;
+import org.apache.sentry.provider.db.service.model.MSentryGMPrivilege;
+import org.apache.sentry.provider.db.service.model.MSentryPrivilege;
+import org.apache.sentry.provider.db.service.model.MSentryRole;
+import org.apache.sentry.provider.db.service.persistent.SentryStore;
+import org.apache.sentry.service.common.ServiceConstants.ServerConfig;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.base.Preconditions;
+import com.google.common.io.Files;
+/**
+ * The class tests that the new feature SENTRY-398 generic model adds the new field in the MSentryRole
+ * will not affect the functionality of the origin hive/impala authorization model
+ * Some Tests below make sure that privileges are removed from sentry storage the moment they are not associated to any role.
+ * This avoid the need for PrivCleaner to perform periodic cleanup.
+ */
+public class TestSentryRole {
+  private static PersistenceManagerFactory pmf;
+  private static File dataDir;
+
+  @Before
+  public void setup() throws Exception {
+    dataDir = new File(Files.createTempDir(), "sentry_policy_db");
+    Properties prop = new Properties();
+    prop.setProperty(ServerConfig.JAVAX_JDO_URL, "jdbc:derby:;databaseName=" + dataDir.getPath() + ";create=true");
+    prop.setProperty(ServerConfig.JAVAX_JDO_USER, "Sentry");
+    prop.setProperty(ServerConfig.JAVAX_JDO_PASS, "Sentry");
+    prop.setProperty(ServerConfig.JAVAX_JDO_DRIVER_NAME, "org.apache.derby.jdbc.EmbeddedDriver");
+    prop.setProperty("datanucleus.schema.autoCreateAll", "true");
+    prop.setProperty("datanucleus.NontransactionalRead", "false");
+    prop.setProperty("datanucleus.NontransactionalWrite", "false");
+    pmf = JDOHelper.getPersistenceManagerFactory(prop);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    pmf.close();
+    FileUtils.deleteQuietly(dataDir);
+  }
+
+  @Test
+  public void grantMixedPrivilegeTest() throws Exception {
+    String roleName = "r1";
+    //hive/impala privilege
+    MSentryPrivilege hivePrivilege = new MSentryPrivilege();
+    hivePrivilege.setServerName("hive.server1");
+    hivePrivilege.setDbName("db1");
+    hivePrivilege.setTableName("tb1");
+    hivePrivilege.setPrivilegeScope("table");
+    hivePrivilege.setAction("select");
+    hivePrivilege.setGrantOption(true);
+    //solr privilege
+    MSentryGMPrivilege solrPrivilege = new MSentryGMPrivilege();
+    solrPrivilege.setComponentName("solr");
+    solrPrivilege.setServiceName("solr.server1");
+    solrPrivilege.setAuthorizables(Arrays.asList(new Collection("c1")));
+    solrPrivilege.setAction("query");
+    solrPrivilege.setGrantOption(true);
+
+    PersistenceManager pm = null;
+    //create role
+    pm = openTransaction();
+    pm.makePersistent(new MSentryRole(roleName, System.currentTimeMillis()));
+    commitTransaction(pm);
+    //add hivePrivilege to role
+    pm = openTransaction();
+    MSentryRole role = getMSentryRole(pm, roleName);
+    hivePrivilege.appendRole(role);
+    pm.makePersistent(hivePrivilege);
+    commitTransaction(pm);
+    //check hivePrivlege and solrPrivilege
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    pm.retrieve(role);
+    assertEquals(1, role.getPrivileges().size());
+    assertEquals(0, role.getGmPrivileges().size());
+    commitTransaction(pm);
+    //add solrPrivilege to role
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    pm.retrieve(role);
+    solrPrivilege.appendRole(role);
+    pm.makePersistent(solrPrivilege);
+    commitTransaction(pm);
+    //check hivePrivlege and solrPrivilege
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    pm.retrieve(role);
+    assertEquals(1, role.getPrivileges().size());
+    assertEquals(1, role.getGmPrivileges().size());
+    commitTransaction(pm);
+  }
+
+  @Test
+  public void testWantGrantPrivilegeTwice() throws Exception {
+    String roleName = "r1";
+    //hive/impala privilege
+    MSentryPrivilege hivePrivilege = new MSentryPrivilege();
+    hivePrivilege.setServerName("hive.server1");
+    hivePrivilege.setDbName("db1");
+    hivePrivilege.setTableName("tb1");
+    hivePrivilege.setPrivilegeScope("table");
+    hivePrivilege.setAction("select");
+    hivePrivilege.setURI(SentryStore.NULL_COL);
+    hivePrivilege.setColumnName(SentryStore.NULL_COL);
+    hivePrivilege.setGrantOption(true);
+    //The same hivePrivilege
+    MSentryPrivilege hivePrivilege2 = new MSentryPrivilege(hivePrivilege);
+    //solr privilege
+    MSentryGMPrivilege solrPrivilege = new MSentryGMPrivilege();
+    solrPrivilege.setComponentName("solr");
+    solrPrivilege.setServiceName("solr.server1");
+    solrPrivilege.setAuthorizables(Arrays.asList(new Collection("c1")));
+    solrPrivilege.setAction("query");
+    solrPrivilege.setGrantOption(true);
+    //The same solrPrivilege
+    MSentryGMPrivilege solrPrivilege2 = new MSentryGMPrivilege(solrPrivilege);
+
+    PersistenceManager pm = null;
+    //create role
+    pm = openTransaction();
+    pm.makePersistent(new MSentryRole(roleName, System.currentTimeMillis()));
+    commitTransaction(pm);
+
+    //grant hivePrivilege and solrPrivilege to role
+    pm = openTransaction();
+    MSentryRole role = getMSentryRole(pm, roleName);
+    solrPrivilege.appendRole(role);
+    hivePrivilege.appendRole(role);
+    pm.makePersistent(solrPrivilege);
+    pm.makePersistent(hivePrivilege);
+    commitTransaction(pm);
+    //check
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    pm.retrieve(role);
+    assertEquals(1, role.getPrivileges().size());
+    assertEquals(1, role.getGmPrivileges().size());
+    commitTransaction(pm);
+
+    //want to grant the same hivePrivilege and solrPrivilege to role again
+    //hivePrivilege2 is equal to hivePrivilege
+    //solrPrivilege2 is equal to solrPrivilege
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    pm.retrieve(role);
+    if (!role.getGmPrivileges().contains(solrPrivilege2)) {
+      fail("unexpect happend: the MSentryGMPrivilege:" + solrPrivilege2 + " already be granted");
+    }
+    if (!role.getPrivileges().contains(hivePrivilege2)) {
+      fail("unexpect happend: the MSentryPrivilege:" + hivePrivilege2 + " already be granted");
+    }
+    commitTransaction(pm);
+  }
+
+  @Test
+  public void testMixedRevokePrivilege() throws Exception {
+    String roleName = "r1";
+    //hive/impala privilege
+    MSentryPrivilege hivePrivilege = new MSentryPrivilege();
+    hivePrivilege.setServerName("hive.server1");
+    hivePrivilege.setDbName("db1");
+    hivePrivilege.setTableName("tb1");
+    hivePrivilege.setPrivilegeScope("table");
+    hivePrivilege.setAction("select");
+    hivePrivilege.setURI(SentryStore.NULL_COL);
+    hivePrivilege.setColumnName(SentryStore.NULL_COL);
+    hivePrivilege.setGrantOption(true);
+
+    //solr privilege
+    MSentryGMPrivilege solrPrivilege = new MSentryGMPrivilege();
+    solrPrivilege.setComponentName("solr");
+    solrPrivilege.setServiceName("solr.server1");
+    solrPrivilege.setAuthorizables(Arrays.asList(new Collection("c1")));
+    solrPrivilege.setAction("query");
+    solrPrivilege.setGrantOption(true);
+
+    PersistenceManager pm = null;
+    //create role
+    pm = openTransaction();
+    pm.makePersistent(new MSentryRole(roleName, System.currentTimeMillis()));
+    commitTransaction(pm);
+
+    //grant hivePrivilege and solrPrivilege to role
+    pm = openTransaction();
+    MSentryRole role = getMSentryRole(pm, roleName);
+    hivePrivilege.appendRole(role);
+    solrPrivilege.appendRole(role);
+    pm.makePersistent(hivePrivilege);
+    pm.makePersistent(solrPrivilege);
+    commitTransaction(pm);
+
+    //check
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    pm.retrieve(role);
+    assertEquals(1, role.getPrivileges().size());
+    assertEquals(1, role.getGmPrivileges().size());
+    commitTransaction(pm);
+
+    //revoke solrPrivilege from role
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    solrPrivilege = (MSentryGMPrivilege)role.getGmPrivileges().toArray()[0];
+    solrPrivilege.removeRole(role);
+    pm.makePersistent(solrPrivilege);
+    commitTransaction(pm);
+
+    //check
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    pm.retrieve(role);
+    assertEquals(1, role.getPrivileges().size());
+    assertEquals(0, role.getGmPrivileges().size());
+    commitTransaction(pm);
+
+    //revoke hivePrivilege from role
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    pm.retrieve(role);
+    hivePrivilege = (MSentryPrivilege)role.getPrivileges().toArray()[0];
+    hivePrivilege.removeRole(role);
+    pm.makePersistent(hivePrivilege);
+    commitTransaction(pm);
+
+    //check
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    pm.retrieve(role);
+    assertEquals(0, role.getPrivileges().size());
+    assertEquals(0, role.getGmPrivileges().size());
+    commitTransaction(pm);
+  }
+
+  @Test
+  public void testDeletePrivilegeAndRole() throws Exception {
+    String roleName = "r1";
+    //hive/impala privilege
+    MSentryPrivilege hivePrivilege = new MSentryPrivilege();
+    hivePrivilege.setServerName("hive.server1");
+    hivePrivilege.setDbName("db1");
+    hivePrivilege.setTableName("tb1");
+    hivePrivilege.setPrivilegeScope("table");
+    hivePrivilege.setAction("select");
+    hivePrivilege.setURI(SentryStore.NULL_COL);
+    hivePrivilege.setColumnName(SentryStore.NULL_COL);
+    hivePrivilege.setGrantOption(true);
+
+    //solr privilege
+    MSentryGMPrivilege solrPrivilege = new MSentryGMPrivilege();
+    solrPrivilege.setComponentName("solr");
+    solrPrivilege.setServiceName("solr.server1");
+    solrPrivilege.setAuthorizables(Arrays.asList(new Collection("c1")));
+    solrPrivilege.setAction("query");
+    solrPrivilege.setGrantOption(true);
+
+    PersistenceManager pm = null;
+    //create role
+    pm = openTransaction();
+    pm.makePersistent(new MSentryRole(roleName, System.currentTimeMillis()));
+    commitTransaction(pm);
+
+    //grant hivePrivilege and solrPrivilege to role
+    pm = openTransaction();
+    MSentryRole role = getMSentryRole(pm, roleName);
+    hivePrivilege.appendRole(role);
+    solrPrivilege.appendRole(role);
+    pm.makePersistent(hivePrivilege);
+    pm.makePersistent(solrPrivilege);
+    commitTransaction(pm);
+
+    //check
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    pm.retrieve(role);
+    assertEquals(1, role.getPrivileges().size());
+    assertEquals(1, role.getGmPrivileges().size());
+    commitTransaction(pm);
+
+    //remove all privileges
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    role.removeGMPrivileges();
+    role.removePrivileges();
+    pm.makePersistent(role);
+    commitTransaction(pm);
+
+    //check
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    pm.retrieve(role);
+    assertEquals(0, role.getPrivileges().size());
+    assertEquals(0, role.getGmPrivileges().size());
+    commitTransaction(pm);
+
+    //delete role
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    pm.deletePersistent(role);
+    commitTransaction(pm);
+
+    //check
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    assertTrue(role == null);
+    commitTransaction(pm);
+  }
+
+  /**
+   * Removes a role and makes sure that privileges are removed from sentry storage
+   * moment they are not associated to any role.
+   * @throws Exception
+   */
+  @Test
+  public void testDeleteRole() throws Exception {
+    String roleName = "r1";
+    //hive/impala privilege
+    MSentryPrivilege hivePrivilege = new MSentryPrivilege();
+    hivePrivilege.setServerName("hive.server1");
+    hivePrivilege.setDbName("db1");
+    hivePrivilege.setTableName("tb1");
+    hivePrivilege.setPrivilegeScope("table");
+    hivePrivilege.setAction("select");
+    hivePrivilege.setURI(SentryStore.NULL_COL);
+    hivePrivilege.setColumnName(SentryStore.NULL_COL);
+    hivePrivilege.setGrantOption(true);
+
+    //solr privilege
+    MSentryGMPrivilege solrPrivilege = new MSentryGMPrivilege();
+    solrPrivilege.setComponentName("solr");
+    solrPrivilege.setServiceName("solr.server1");
+    solrPrivilege.setAuthorizables(Arrays.asList(new Collection("c1")));
+    solrPrivilege.setAction("query");
+    solrPrivilege.setGrantOption(true);
+
+    PersistenceManager pm = null;
+    //create role
+    pm = openTransaction();
+    pm.makePersistent(new MSentryRole(roleName, System.currentTimeMillis()));
+    commitTransaction(pm);
+
+    //grant hivePrivilege and solrPrivilege to role
+    pm = openTransaction();
+    MSentryRole role = getMSentryRole(pm, roleName);
+    hivePrivilege.appendRole(role);
+    solrPrivilege.appendRole(role);
+    pm.makePersistent(hivePrivilege);
+    pm.makePersistent(solrPrivilege);
+    pm.makePersistent(role);
+    commitTransaction(pm);
+
+    //check
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    pm.retrieve(role);
+    assertEquals(1, role.getPrivileges().size());
+    assertEquals(1, role.getGmPrivileges().size());
+    commitTransaction(pm);
+
+    //delete role
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+
+    //  pm.deletePersistent(role);
+    role.removePrivileges();
+    role.removeGMPrivileges();
+    pm.deletePersistent(role);
+    commitTransaction(pm);
+
+    //check for privileges
+    //There shouldn't be any privilages
+    pm = openTransaction();
+    Query query = pm.newQuery(MSentryPrivilege.class);
+    List<MSentryPrivilege> results = (List<MSentryPrivilege>) query.execute();
+    assertEquals(1, results.size());
+    Query query1 = pm.newQuery(MSentryGMPrivilege.class);
+    List<MSentryGMPrivilege> results1 = (List<MSentryGMPrivilege>) query1.execute();
+    assertEquals(1, results1.size());
+    commitTransaction(pm);
+
+    //check
+    pm = openTransaction();
+    role = getMSentryRole(pm, roleName);
+    assertTrue(role == null);
+    commitTransaction(pm);
+  }
+
+  /**
+   * Removes a role and makes sure that privileges are not removed from sentry storage if
+   * they are associated to any other role as well.
+   * @throws Exception
+   */
+  @Test
+  public void testDeleteRole1() throws Exception {
+    String roleName1 = "r1";
+    String roleName2 = "r2";
+    //hive/impala privilege
+    MSentryPrivilege hivePrivilege = new MSentryPrivilege();
+    hivePrivilege.setServerName("hive.server1");
+    hivePrivilege.setDbName("db1");
+    hivePrivilege.setTableName("tb1");
+    hivePrivilege.setPrivilegeScope("table");
+    hivePrivilege.setAction("select");
+    hivePrivilege.setURI(SentryStore.NULL_COL);
+    hivePrivilege.setColumnName(SentryStore.NULL_COL);
+    hivePrivilege.setGrantOption(true);
+
+    //solr privilege
+    MSentryGMPrivilege solrPrivilege = new MSentryGMPrivilege();
+    solrPrivilege.setComponentName("solr");
+    solrPrivilege.setServiceName("solr.server1");
+    solrPrivilege.setAuthorizables(Arrays.asList(new Collection("c1")));
+    solrPrivilege.setAction("query");
+    solrPrivilege.setGrantOption(true);
+
+    PersistenceManager pm = null;
+    //create role1
+    pm = openTransaction();
+    pm.makePersistent(new MSentryRole(roleName1, System.currentTimeMillis()));
+    commitTransaction(pm);
+
+    //create role2
+    pm = openTransaction();
+    pm.makePersistent(new MSentryRole(roleName2, System.currentTimeMillis()));
+    commitTransaction(pm);
+
+    //grant hivePrivilege and solrPrivilege to role1 and role2
+    pm = openTransaction();
+    MSentryRole role1 = getMSentryRole(pm, roleName1);
+    MSentryRole role2 = getMSentryRole(pm, roleName2);
+    hivePrivilege.appendRole(role1);
+    solrPrivilege.appendRole(role1);
+    hivePrivilege.appendRole(role2);
+    solrPrivilege.appendRole(role2);
+    pm.makePersistent(hivePrivilege);
+    pm.makePersistent(solrPrivilege);
+    pm.makePersistent(role1);
+    pm.makePersistent(role2);
+    commitTransaction(pm);
+
+    //check
+    pm = openTransaction();
+    role1 = getMSentryRole(pm, roleName1);
+    pm.retrieve(role1);
+    assertEquals(1, role1.getPrivileges().size());
+    assertEquals(1, role1.getGmPrivileges().size());
+    role2 = getMSentryRole(pm, roleName2);
+    pm.retrieve(role2);
+    assertEquals(1, role2.getPrivileges().size());
+    assertEquals(1, role2.getGmPrivileges().size());
+    commitTransaction(pm);
+
+    //delete role
+    pm = openTransaction();
+    role1 = getMSentryRole(pm, roleName1);
+    role1.removePrivileges();
+    role1.removeGMPrivileges();
+    pm.deletePersistent(role1);
+    commitTransaction(pm);
+
+    //check for privileges
+    //Privileges should be present
+    pm = openTransaction();
+    Query query = pm.newQuery(MSentryPrivilege.class);
+    List<MSentryPrivilege> results = (List<MSentryPrivilege>) query.execute();
+    assertEquals(1, results.size());
+    Query query1 = pm.newQuery(MSentryGMPrivilege.class);
+    List<MSentryGMPrivilege> results1 = (List<MSentryGMPrivilege>) query1.execute();
+    assertEquals(1, results1.size());
+    commitTransaction(pm);
+
+    //check
+    pm = openTransaction();
+    role1 = getMSentryRole(pm, roleName1);
+    assertTrue(role1 == null);
+    commitTransaction(pm);
+  }
+  private PersistenceManager openTransaction() {
+    PersistenceManager pm = pmf.getPersistenceManager();
+    Transaction currentTransaction = pm.currentTransaction();
+    currentTransaction.begin();
+    return pm;
+  }
+
+  private void commitTransaction(PersistenceManager pm) {
+    Transaction currentTransaction = pm.currentTransaction();
+    try {
+      Preconditions.checkState(currentTransaction.isActive(), "Transaction is not active");
+      currentTransaction.commit();
+    } finally {
+      pm.close();
+    }
+  }
+
+  private MSentryRole getMSentryRole(PersistenceManager pm, String roleName) {
+    Query query = pm.newQuery(MSentryRole.class);
+    query.setFilter("this.roleName == t");
+    query.declareParameters("java.lang.String t");
+    query.setUnique(true);
+    MSentryRole sentryRole = (MSentryRole) query.execute(roleName);
+    return sentryRole;
+  }
+
+
+}