sentry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject [3/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from sentry-provider-db into own module. Steve Moist, reviewed by Colm O hEigeartaigh.
Date Mon, 30 Apr 2018 16:35:39 GMT
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestPermissionsMigrationToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestPermissionsMigrationToolSolr.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestPermissionsMigrationToolSolr.java
new file mode 100644
index 0000000..a275d18
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestPermissionsMigrationToolSolr.java
@@ -0,0 +1,362 @@
+ /**
+ * 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.cli.tools;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.common.ProviderBackendContext;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
+import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
+import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;import org.apache.sentry.provider.file.PolicyFile;
+import org.apache.sentry.provider.file.SimpleFileProviderBackend;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+import com.google.common.collect.Table;
+import com.google.common.io.Files;
+
+public class TestPermissionsMigrationToolSolr extends SentryGenericServiceIntegrationBase {
+  private File confDir;
+  private File confPath;
+  private String requestorName = "";
+  private String service = "service1";
+
+  @Before
+  public void prepareForTest() throws Exception {
+    confDir = Files.createTempDir();
+    confPath = new File(confDir, "sentry-site.xml");
+    if (confPath.createNewFile()) {
+      FileOutputStream to = new FileOutputStream(confPath);
+      conf.writeXml(to);
+      to.close();
+    }
+    requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", "");
+    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
+    setLocalGroupMapping(requestorName, requestorUserGroupNames);
+    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
+    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
+    setLocalGroupMapping("dev", Sets.newHashSet("dev_group"));
+    setLocalGroupMapping("user", Sets.newHashSet("user_group"));
+    writePolicyFile();
+  }
+
+  @After
+  public void clearTestData() throws Exception {
+    FileUtils.deleteQuietly(confDir);
+
+    // clear roles and privileges
+    Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
+    for (TSentryRole tRole : tRoles) {
+      String role = tRole.getRoleName();
+      Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
+          requestorName, role, SOLR, service);
+      for (TSentryPrivilege privilege : privileges) {
+        client.revokePrivilege(requestorName, role, SOLR, privilege);
+      }
+      client.dropRole(requestorName, role, SOLR);
+    }
+  }
+
+  @Test
+  public void testPermissionsMigrationFromSentrySvc_v1() throws Exception {
+    initializeSentryService();
+
+    String[] args = { "-s", "1.8.0", "-c", confPath.getAbsolutePath()};
+    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
+    sentryTool.executeConfigTool(args);
+
+    Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
+    groupMapping.put("admin_role", Sets.newHashSet("admin_group"));
+    groupMapping.put("dev_role", Sets.newHashSet("dev_group"));
+    groupMapping.put("user_role", Sets.newHashSet("user_group"));
+
+    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+    privilegeMapping.put("admin_role",
+        Sets.newHashSet("admin=collections->action=*", "admin=cores->action=*"));
+    privilegeMapping.put("dev_role",
+        Sets.newHashSet("collection=*->action=*", "admin=collections->action=*", "admin=cores->action=*"));
+    privilegeMapping.put("user_role",
+        Sets.newHashSet("collection=foo->action=*"));
+
+    verifySentryServiceState(groupMapping, privilegeMapping);
+  }
+
+  @Test
+  public void testPermissionsMigrationFromSentryPolicyFile_v1() throws Exception {
+    Path policyFilePath = initializeSentryPolicyFile();
+    Path outputFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider_migrated.ini");
+
+    String[] args = { "-s", "1.8.0", "-p", policyFilePath.toFile().getAbsolutePath(),
+                      "-o", outputFilePath.toFile().getAbsolutePath() };
+    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
+    assertTrue(sentryTool.executeConfigTool(args));
+
+    Set<String> groups = new HashSet<>();
+    groups.add("admin_group");
+    groups.add("dev_group");
+    groups.add("user_group");
+
+    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+    privilegeMapping.put("admin_role",
+        Sets.newHashSet("admin=collections->action=*", "admin=cores->action=*"));
+    privilegeMapping.put("dev_role",
+        Sets.newHashSet("collection=*->action=*", "admin=collections->action=*", "admin=cores->action=*"));
+    privilegeMapping.put("user_role",
+        Sets.newHashSet("collection=foo->action=*"));
+
+    verifySentryPolicyFile(groups, privilegeMapping, outputFilePath);
+  }
+
+  @Test
+  // For permissions created with Sentry 2.x, no migration necessary
+  public void testPermissionsMigrationFromSentrySvc_v2() throws Exception {
+    initializeSentryService();
+
+    String[] args = { "-s", "2.0.0", "-c", confPath.getAbsolutePath()};
+    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
+    sentryTool.executeConfigTool(args);
+
+    Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
+    groupMapping.put("admin_role", Sets.newHashSet("admin_group"));
+    groupMapping.put("dev_role", Sets.newHashSet("dev_group"));
+    groupMapping.put("user_role", Sets.newHashSet("user_group"));
+
+    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+    privilegeMapping.put("admin_role",
+        Sets.newHashSet("collection=admin->action=*"));
+    privilegeMapping.put("dev_role",
+        Sets.newHashSet("collection=*->action=*"));
+    privilegeMapping.put("user_role",
+        Sets.newHashSet("collection=foo->action=*"));
+
+    verifySentryServiceState(groupMapping, privilegeMapping);
+  }
+
+  @Test
+  // For permissions created with Sentry 2.x, no migration necessary
+  public void testPermissionsMigrationFromSentryPolicyFile_v2() throws Exception {
+    Path policyFilePath = initializeSentryPolicyFile();
+    Path outputFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider_migrated.ini");
+
+    String[] args = { "-s", "2.0.0", "-p", policyFilePath.toFile().getAbsolutePath(),
+                      "-o", outputFilePath.toFile().getAbsolutePath() };
+    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
+    assertTrue(sentryTool.executeConfigTool(args));
+
+    Set<String> groups = new HashSet<>();
+    groups.add("admin_group");
+    groups.add("dev_group");
+    groups.add("user_group");
+
+    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+    privilegeMapping.put("admin_role",
+        Sets.newHashSet("collection=admin->action=*"));
+    privilegeMapping.put("dev_role",
+        Sets.newHashSet("collection=*->action=*"));
+    privilegeMapping.put("user_role",
+        Sets.newHashSet("collection=foo->action=*"));
+
+    verifySentryPolicyFile(groups, privilegeMapping, outputFilePath);
+  }
+
+  @Test
+  public void testDryRunOption() throws Exception {
+    initializeSentryService();
+
+    String[] args = { "-s", "1.8.0", "-c", confPath.getAbsolutePath(), "--dry_run"};
+    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
+    sentryTool.executeConfigTool(args);
+
+    Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
+    groupMapping.put("admin_role", Sets.newHashSet("admin_group"));
+    groupMapping.put("dev_role", Sets.newHashSet("dev_group"));
+    groupMapping.put("user_role", Sets.newHashSet("user_group"));
+
+    // No change in the privileges
+    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+    privilegeMapping.put("admin_role",
+        Sets.newHashSet("collection=admin->action=*"));
+    privilegeMapping.put("dev_role",
+        Sets.newHashSet("collection=*->action=*"));
+    privilegeMapping.put("user_role",
+        Sets.newHashSet("collection=foo->action=*"));
+
+    verifySentryServiceState(groupMapping, privilegeMapping);
+  }
+
+  @Test
+  public void testInvalidToolArguments() throws Exception {
+    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
+
+    {
+      String[] args = { "-c", confPath.getAbsolutePath()};
+      assertFalse("The execution should have failed due to missing source version",
+          sentryTool.executeConfigTool(args));
+    }
+
+    {
+      String[] args = { "-s", "1.8.0" };
+      sentryTool.executeConfigTool(args);
+      assertFalse("The execution should have failed due to missing Sentry config file"
+          + " (or policy file) path",
+          sentryTool.executeConfigTool(args));
+    }
+
+    {
+      String[] args = { "-s", "1.8.0", "-p", "/test/path" };
+      sentryTool.executeConfigTool(args);
+      assertFalse("The execution should have failed due to missing Sentry config output file path",
+          sentryTool.executeConfigTool(args));
+    }
+
+    {
+      String[] args = { "-s", "1.8.0", "-c", "/test/path1", "-p", "/test/path2" };
+      sentryTool.executeConfigTool(args);
+      assertFalse("The execution should have failed due to providing both Sentry config file"
+          + " as well as policy file params",
+          sentryTool.executeConfigTool(args));
+    }
+  }
+
+  private void initializeSentryService() throws SentryUserException {
+    // Define an admin role
+    client.createRoleIfNotExist(requestorName, "admin_role", SOLR);
+    client.grantRoleToGroups(requestorName, "admin_role", SOLR, Sets.newHashSet("admin_group"));
+
+    // Define a developer role
+    client.createRoleIfNotExist(requestorName, "dev_role", SOLR);
+    client.grantRoleToGroups(requestorName, "dev_role", SOLR, Sets.newHashSet("dev_group"));
+
+    // Define a user role
+    client.createRoleIfNotExist(requestorName, "user_role", SOLR);
+    client.grantRoleToGroups(requestorName, "user_role", SOLR, Sets.newHashSet("user_group"));
+
+    // Grant permissions
+    client.grantPrivilege(requestorName, "admin_role", SOLR,
+        new TSentryPrivilege(SOLR, "service1",
+            Arrays.asList(new TAuthorizable("collection", "admin")), "*"));
+    client.grantPrivilege(requestorName, "dev_role", SOLR,
+        new TSentryPrivilege(SOLR, "service1",
+            Arrays.asList(new TAuthorizable("collection", "*")), "*"));
+    client.grantPrivilege(requestorName, "user_role", SOLR,
+        new TSentryPrivilege(SOLR, "service1",
+            Arrays.asList(new TAuthorizable("collection", "foo")), "*"));
+  }
+
+  private void verifySentryServiceState(Map<String, Set<String>> groupMapping,
+      Map<String, Set<String>> privilegeMapping) throws SentryUserException {
+    // check roles
+    Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
+    assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size());
+    Set<String> roles = new HashSet<String>();
+    for (TSentryRole tRole : tRoles) {
+      roles.add(tRole.getRoleName());
+    }
+
+    for (String expectedRole : groupMapping.keySet()) {
+      assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole));
+    }
+
+    // check groups
+    for (TSentryRole tRole : tRoles) {
+      Set<String> expectedGroups = groupMapping.get(tRole.getRoleName());
+      assertEquals("Group size doesn't match for role: " + tRole.getRoleName(),
+          expectedGroups.size(), tRole.getGroups().size());
+      assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(),
+          tRole.getGroups().containsAll(expectedGroups));
+    }
+
+    // check privileges
+    GenericPrivilegeConverter convert = new GenericPrivilegeConverter(SOLR, service);
+    for (String role : roles) {
+      Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
+          requestorName, role, SOLR, service);
+      Set<String> expectedPrivileges = privilegeMapping.get(role);
+      assertEquals("Privilege set size doesn't match for role: " + role + " Actual permissions : " + privileges,
+          expectedPrivileges.size(), privileges.size());
+
+      Set<String> privilegeStrs = new HashSet<String>();
+      for (TSentryPrivilege privilege : privileges) {
+        privilegeStrs.add(convert.toString(privilege).toLowerCase());
+      }
+
+      for (String expectedPrivilege : expectedPrivileges) {
+        assertTrue("Did not find expected privilege: " + expectedPrivilege + " in " + privilegeStrs,
+            privilegeStrs.contains(expectedPrivilege));
+      }
+    }
+  }
+
+  private Path initializeSentryPolicyFile() throws Exception {
+    PolicyFile file = new PolicyFile();
+
+    file.addRolesToGroup("admin_group", "admin_role");
+    file.addRolesToGroup("dev_group", "dev_role");
+    file.addRolesToGroup("user_group", "user_role");
+
+    file.addPermissionsToRole("admin_role", "collection=admin->action=*");
+    file.addPermissionsToRole("dev_role", "collection=*->action=*");
+    file.addPermissionsToRole("user_role", "collection=foo->action=*");
+
+    Path policyFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider.ini");
+    file.write(policyFilePath.toFile());
+
+    return policyFilePath;
+  }
+
+  private void verifySentryPolicyFile (Set<String> groups, Map<String, Set<String>> privilegeMapping,
+      Path policyFilePath) throws IOException {
+    SimpleFileProviderBackend policyFileBackend = new SimpleFileProviderBackend(conf,
+        new org.apache.hadoop.fs.Path(policyFilePath.toUri()));
+    policyFileBackend.initialize(new ProviderBackendContext());
+    Table<String, String, Set<String>> groupRolePrivilegeTable =
+        policyFileBackend.getGroupRolePrivilegeTable();
+
+    assertEquals(groups, groupRolePrivilegeTable.rowKeySet());
+    assertEquals(privilegeMapping.keySet(), groupRolePrivilegeTable.columnKeySet());
+
+    for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
+      for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
+        if (groupRolePrivilegeTable.contains(groupName, roleName)) {
+          Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
+          assertEquals(privilegeMapping.get(roleName), privileges);
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolIndexer.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolIndexer.java
new file mode 100644
index 0000000..40df736
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolIndexer.java
@@ -0,0 +1,263 @@
+ /**
+ * 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.cli.tools;
+
+ import com.google.common.collect.Sets;
+ import com.google.common.io.Files;
+ import org.apache.commons.io.FileUtils;
+ import org.apache.sentry.core.common.exception.SentryConfigurationException;
+ import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
+ import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+ import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
+ import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;
+ import org.apache.sentry.service.thrift.ServiceConstants;
+ import org.junit.After;
+ import org.junit.Before;
+ import org.junit.Test;
+
+ import java.io.File;
+ import java.io.FileOutputStream;
+ import java.util.HashMap;
+ import java.util.HashSet;
+ import java.util.Map;
+ import java.util.Set;
+
+ import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
+ import static org.junit.Assert.assertEquals;
+ import static org.junit.Assert.assertTrue;
+ import static org.junit.Assert.fail;
+
+ public class TestSentryConfigToolIndexer extends SentryGenericServiceIntegrationBase {
+   private static String VALID_POLICY_INI = TestSentryConfigToolIndexer.class.getClassLoader().getResource("indexer_config_import_tool.ini").getPath() ;
+   private static String INVALID_POLICY_INI = TestSentryConfigToolIndexer.class.getClassLoader().getResource("indexer_invalid.ini").getPath();
+   private static String CASE_POLICY_INI = TestSentryConfigToolIndexer.class.getClassLoader().getResource("indexer_case.ini").getPath();
+   private File confDir;
+   private File confPath;
+   private String requestorName = "";
+   private String service = "service1";
+
+   @Before
+   public void prepareForTest() throws Exception {
+     confDir = Files.createTempDir();
+     confPath = new File(confDir, "sentry-site.xml");
+     conf.set(ServiceConstants.ClientConfig.SERVICE_NAME, service);
+     if (confPath.createNewFile()) {
+       FileOutputStream to = new FileOutputStream(confPath);
+       conf.writeXml(to);
+       to.close();
+     }
+     requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", "");
+     Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
+     setLocalGroupMapping(requestorName, requestorUserGroupNames);
+     // add ADMIN_USER for the after() in SentryServiceIntegrationBase
+     setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
+     writePolicyFile();
+   }
+
+   @After
+   public void clearTestData() throws Exception {
+     FileUtils.deleteQuietly(confDir);
+
+     // clear roles and privileges
+     Set<TSentryRole> tRoles = client.listAllRoles(requestorName, HBASE_INDEXER);
+     for (TSentryRole tRole : tRoles) {
+       String role = tRole.getRoleName();
+       Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
+           requestorName, role, HBASE_INDEXER, service);
+       for (TSentryPrivilege privilege : privileges) {
+         client.revokePrivilege(requestorName, role, HBASE_INDEXER, privilege);
+       }
+       client.dropRole(requestorName, role, HBASE_INDEXER);
+     }
+   }
+
+   @Test
+   public void testConvertIni() throws Exception {
+     runTestAsSubject(new TestOperation() {
+       @Override
+       public void runTestAsSubject() throws Exception {
+         String[] args = {"-mgr", "-f", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"};
+         SentryShellIndexer sentryTool = new SentryShellIndexer();
+         sentryTool.executeShell(args);
+
+         Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
+         groupMapping.put("corporal_role", Sets.newHashSet("corporal", "sergeant", "general", "commander_in_chief"));
+         groupMapping.put("sergeant_role", Sets.newHashSet("sergeant", "general", "commander_in_chief"));
+         groupMapping.put("general_role", Sets.newHashSet("general", "commander_in_chief"));
+         groupMapping.put("commander_in_chief_role", Sets.newHashSet("commander_in_chief"));
+
+
+         Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+         privilegeMapping.put("corporal_role",
+             Sets.newHashSet("Indexer=info->action=read", "Indexer=info->action=write"));
+         privilegeMapping.put("sergeant_role",
+             Sets.newHashSet("Indexer=info->action=write"));
+         privilegeMapping.put("general_role",
+             Sets.newHashSet("Indexer=info->action=*"));
+         privilegeMapping.put("commander_in_chief_role",
+             Sets.newHashSet("Indexer=*->action=*"));
+
+         // check roles
+         Set<TSentryRole> tRoles = client.listAllRoles(requestorName, HBASE_INDEXER);
+         assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size());
+         Set<String> roles = new HashSet<String>();
+         for (TSentryRole tRole : tRoles) {
+           roles.add(tRole.getRoleName());
+         }
+
+         for (String expectedRole : groupMapping.keySet()) {
+           assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole));
+         }
+
+         // check groups
+         for (TSentryRole tRole : tRoles) {
+           Set<String> expectedGroups = groupMapping.get(tRole.getRoleName());
+           assertEquals("Group size doesn't match for role: " + tRole.getRoleName(),
+               expectedGroups.size(), tRole.getGroups().size());
+           assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(),
+               tRole.getGroups().containsAll(expectedGroups));
+         }
+
+         // check privileges
+         GenericPrivilegeConverter convert = new GenericPrivilegeConverter(HBASE_INDEXER, service);
+         for (String role : roles) {
+           Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
+               requestorName, role, HBASE_INDEXER, service);
+           Set<String> expectedPrivileges = privilegeMapping.get(role);
+           assertEquals("Privilege set size doesn't match for role: " + role,
+               expectedPrivileges.size(), privileges.size());
+
+           Set<String> privilegeStrs = new HashSet<String>();
+           for (TSentryPrivilege privilege : privileges) {
+             privilegeStrs.add(convert.toString(privilege));
+           }
+
+           for (String expectedPrivilege : expectedPrivileges) {
+             assertTrue("Did not find expected privilege: " + expectedPrivilege,
+                 privilegeStrs.contains(expectedPrivilege));
+           }
+         }
+       }
+     });
+   }
+
+   @Test
+   public void testNoPolicyFile() throws Exception {
+     runTestAsSubject(new TestOperation() {
+       @Override
+       public void runTestAsSubject() throws Exception {
+         String[] args = { "-mgr", "-f", INVALID_POLICY_INI + "Foobar", "-conf", confPath.getAbsolutePath(), "-v", "-i"};
+         SentryShellIndexer sentryTool = new SentryShellIndexer();
+         try {
+           sentryTool.executeShell(args);
+           fail("Exception should be thrown for nonexistant ini");
+         } catch (SentryConfigurationException e) {
+           // expected exception
+         }
+       }
+     });
+   }
+
+   @Test
+   public void testNoValidateNorImport() throws Exception {
+     runTestAsSubject(new TestOperation() {
+       @Override
+       public void runTestAsSubject() throws Exception {
+         String[] args = { "-mgr", "-f", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath()};
+         SentryShellIndexer sentryTool = new SentryShellIndexer();
+         try {
+           sentryTool.executeShell(args);
+           fail("Exception should be thrown for validating invalid ini");
+         } catch (IllegalArgumentException e) {
+           // expected exception
+         }
+       }
+     });
+   }
+
+   @Test
+   public void testConvertInvalidIni() throws Exception {
+     runTestAsSubject(new TestOperation() {
+       @Override
+       public void runTestAsSubject() throws Exception {
+         // test: validate an invalid ini
+         String[] args = { "-mgr", "-f", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"};
+         SentryShellIndexer sentryTool = new SentryShellIndexer();
+         try {
+           sentryTool.executeShell(args);
+           fail("Exception should be thrown for validating invalid ini");
+         } catch (SentryConfigurationException e) {
+           // expected exception
+         }
+
+         // test without validating, should not error
+         args = new String[] { "-mgr", "-f", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i"};
+         sentryTool = new SentryShellIndexer();
+         sentryTool.executeShell(args);
+       }
+     });
+   }
+
+   @Test
+   public void testCompatCheck() throws Exception {
+     runTestAsSubject(new TestOperation() {
+       @Override
+       public void runTestAsSubject() throws Exception {
+         // test: validate an invalid ini
+         String[] args = { "-mgr", "-f", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"};
+         SentryShellIndexer sentryTool = new SentryShellIndexer();
+         try {
+           sentryTool.executeShell(args);
+           fail("Exception should be thrown for validating invalid ini");
+         } catch (SentryConfigurationException e) {
+           assertEquals("Expected error", 1, e.getConfigErrors().size());
+           String error = e.getConfigErrors().get(0);
+           assertCasedRoleNamesInMessage(error, "RoLe1", "rOlE1");
+           String warning = e.getConfigWarnings().get(0);
+           assertCasedRoleNamesInMessage(warning, "ROLE2", "RoLe1", "rOlE1");
+           assertEquals("Expected warning", 1, e.getConfigWarnings().size());
+         }
+
+         // test without compat checking
+         args = new String[] { "-mgr", "-f", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i", "-v"};
+         sentryTool = new SentryShellIndexer();
+         sentryTool.executeShell(args);
+       }
+     });
+   }
+
+   // Test that a valid compat check doesn't throw an exception
+   @Test
+   public void testCompatCheckValid() throws Exception {
+     runTestAsSubject(new TestOperation() {
+       @Override
+       public void runTestAsSubject() throws Exception {
+         String[] args = { "-mgr", "-f", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"};
+         SentryShellIndexer sentryTool = new SentryShellIndexer();
+         sentryTool.executeShell(args);
+       }
+     });
+   }
+
+   private void assertCasedRoleNamesInMessage(String message, String ... casedRoleNames) {
+     for (String casedRoleName : casedRoleNames) {
+       assertTrue("Expected cased role name: " + casedRoleName, message.contains(casedRoleName));
+     }
+   }
+ }

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolSolr.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolSolr.java
new file mode 100644
index 0000000..292521d
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolSolr.java
@@ -0,0 +1,260 @@
+ /**
+ * 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.cli.tools;
+
+import com.google.common.io.Files;
+import com.google.common.collect.Sets;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+import org.apache.sentry.core.common.exception.SentryConfigurationException;
+
+import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestSentryConfigToolSolr extends SentryGenericServiceIntegrationBase {
+  private static String VALID_POLICY_INI = TestSentryConfigToolSolr.class.getClassLoader().getResource("solr_config_import_tool.ini").getPath();
+  private static String INVALID_POLICY_INI = TestSentryConfigToolSolr.class.getClassLoader().getResource("solr_invalid.ini").getPath();
+  private static String CASE_POLICY_INI = TestSentryConfigToolSolr.class.getClassLoader().getResource("solr_case.ini").getPath();
+  private File confDir;
+  private File confPath;
+  private String requestorName = "";
+  private String service = "service1";
+
+  @Before
+  public void prepareForTest() throws Exception {
+    confDir = Files.createTempDir();
+    confPath = new File(confDir, "sentry-site.xml");
+    if (confPath.createNewFile()) {
+      FileOutputStream to = new FileOutputStream(confPath);
+      conf.writeXml(to);
+      to.close();
+    }
+    requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", "");
+    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
+    setLocalGroupMapping(requestorName, requestorUserGroupNames);
+    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
+    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
+    writePolicyFile();
+  }
+
+  @After
+  public void clearTestData() throws Exception {
+    FileUtils.deleteQuietly(confDir);
+
+    // clear roles and privileges
+    Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
+    for (TSentryRole tRole : tRoles) {
+      String role = tRole.getRoleName();
+      Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
+          requestorName, role, SOLR, service);
+      for (TSentryPrivilege privilege : privileges) {
+        client.revokePrivilege(requestorName, role, SOLR, privilege);
+      }
+      client.dropRole(requestorName, role, SOLR);
+    }
+  }
+
+  @Test
+  public void testConvertIni() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String[] args = { "-p", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"};
+        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
+        sentryTool.executeConfigTool(args);
+
+        Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
+        groupMapping.put("corporal_role", Sets.newHashSet("corporal", "sergeant", "general", "commander_in_chief"));
+        groupMapping.put("sergeant_role", Sets.newHashSet("sergeant", "general", "commander_in_chief"));
+        groupMapping.put("general_role", Sets.newHashSet("general", "commander_in_chief"));
+        groupMapping.put("commander_in_chief_role", Sets.newHashSet("commander_in_chief"));
+
+        Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+        privilegeMapping.put("corporal_role",
+            Sets.newHashSet("Collection=info->action=query", "Collection=info->action=update"));
+        privilegeMapping.put("sergeant_role",
+            Sets.newHashSet("Collection=info->action=update"));
+        privilegeMapping.put("general_role",
+            Sets.newHashSet("Collection=info->action=*"));
+        privilegeMapping.put("commander_in_chief_role",
+            Sets.newHashSet("Collection=*->action=*"));
+
+        // check roles
+        Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
+        assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size());
+        Set<String> roles = new HashSet<String>();
+        for (TSentryRole tRole : tRoles) {
+          roles.add(tRole.getRoleName());
+        }
+
+        for (String expectedRole : groupMapping.keySet()) {
+          assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole));
+        }
+
+        // check groups
+        for (TSentryRole tRole : tRoles) {
+          Set<String> expectedGroups = groupMapping.get(tRole.getRoleName());
+          assertEquals("Group size doesn't match for role: " + tRole.getRoleName(),
+              expectedGroups.size(), tRole.getGroups().size());
+          assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(),
+              tRole.getGroups().containsAll(expectedGroups));
+        }
+
+        // check privileges
+        GenericPrivilegeConverter convert = new GenericPrivilegeConverter(SOLR, service);
+        for (String role : roles) {
+          Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
+              requestorName, role, SOLR, service);
+          Set<String> expectedPrivileges = privilegeMapping.get(role);
+          assertEquals("Privilege set size doesn't match for role: " + role,
+              expectedPrivileges.size(), privileges.size());
+
+          Set<String> privilegeStrs = new HashSet<String>();
+          for (TSentryPrivilege privilege : privileges) {
+            privilegeStrs.add(convert.toString(privilege));
+          }
+
+          for (String expectedPrivilege : expectedPrivileges) {
+            assertTrue("Did not find expected privilege: " + expectedPrivilege + " in " + privilegeStrs,
+                privilegeStrs.contains(expectedPrivilege));
+          }
+        }
+      }
+    });
+  }
+
+  @Test
+  public void testNoPolicyFile() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String[] args = { "-p", INVALID_POLICY_INI + "Foobar", "-conf", confPath.getAbsolutePath(), "-v", "-i"};
+        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
+        try {
+          sentryTool.executeConfigTool(args);
+          fail("Exception should be thrown for nonexistant ini");
+        } catch (SentryConfigurationException e) {
+          // expected exception
+        }
+      }
+    });
+  }
+
+  @Test
+  public void testNoValidateNorImport() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String[] args = { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath()};
+        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
+        try {
+          sentryTool.executeConfigTool(args);
+          fail("Exception should be thrown for validating invalid ini");
+        } catch (IllegalArgumentException e) {
+          // expected exception
+        }
+      }
+    });
+  }
+
+  @Test
+  public void testConvertInvalidIni() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // test: validate an invalid ini
+        String[] args = { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"};
+        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
+        try {
+          sentryTool.executeConfigTool(args);
+          fail("Exception should be thrown for validating invalid ini");
+        } catch (SentryConfigurationException e) {
+          // expected exception
+        }
+
+        // test without validating, should not error
+        args = new String[] { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i"};
+        sentryTool = new SentryConfigToolSolr();
+        sentryTool.executeConfigTool(args);
+      }
+    });
+  }
+
+  @Test
+  public void testCompatCheck() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // test: validate an invalid ini
+        String[] args = { "-p", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"};
+        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
+        try {
+          sentryTool.executeConfigTool(args);
+          fail("Exception should be thrown for validating invalid ini");
+        } catch (SentryConfigurationException e) {
+          assertEquals("Expected error", 1, e.getConfigErrors().size());
+          String error = e.getConfigErrors().get(0);
+          assertCasedRoleNamesInMessage(error, "RoLe1", "rOlE1");
+          String warning = e.getConfigWarnings().get(0);
+          assertCasedRoleNamesInMessage(warning, "ROLE2", "RoLe1", "rOlE1");
+          assertEquals("Expected warning", 1, e.getConfigWarnings().size());
+        }
+
+        // test without compat checking
+        args = new String[] { "-p", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i", "-v"};
+        sentryTool = new SentryConfigToolSolr();
+        sentryTool.executeConfigTool(args);
+      }
+    });
+  }
+
+  // Test that a valid compat check doesn't throw an exception
+  @Test
+  public void testCompatCheckValid() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String[] args = { "-p", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"};
+        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
+        sentryTool.executeConfigTool(args);
+      }
+    });
+  }
+
+  private void assertCasedRoleNamesInMessage(String message, String ... casedRoleNames) {
+    for (String casedRoleName : casedRoleNames) {
+      assertTrue("Expected cased role name: " + casedRoleName, message.contains(casedRoleName));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentrySchemaTool.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentrySchemaTool.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentrySchemaTool.java
new file mode 100644
index 0000000..657a8fe
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentrySchemaTool.java
@@ -0,0 +1,113 @@
+/**
+ * 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.cli.tools;
+
+import java.io.File;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.service.persistent.SentryStoreSchemaInfo;
+import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Files;
+
+public class TestSentrySchemaTool {
+  private Configuration sentryConf;
+  private SentrySchemaTool schemaTool;
+
+  private static final String OLDEST_INIT_VERSION = "1.4.0";
+  private static final String sentry_db_resources = findSentryProviderDBDir()+"/sentry-provider/sentry-provider-db/src/main/resources";
+
+  @Before
+  public void defaultSetup() throws Exception {
+    System.out.println(System.getProperty("user.dir"));
+    sentryConf = new Configuration();
+    File dbDir = new File(Files.createTempDir(), "sentry_policy_db");
+    sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_URL,
+        "jdbc:derby:;databaseName=" + dbDir.getPath() + ";create=true");
+    sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_PASS, "dummy");
+    schemaTool = new SentrySchemaTool(sentry_db_resources, sentryConf,
+        "derby");
+  }
+
+  private void nonDefaultsetup() throws Exception {
+    System.out.println(System.getProperty("user.dir"));
+    sentryConf = new Configuration();
+    File dbDir = new File(Files.createTempDir(), "sentry_policy_db");
+    sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_URL,
+        "jdbc:derby:;databaseName=" + dbDir.getPath() + ";create=true");
+    sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_PASS, "dummy");
+    schemaTool = new SentrySchemaTool(sentry_db_resources, sentryConf,
+        "derby");
+  }
+
+  /**This is a pretty ugly hack.  Since the derby files are in sentry-provider-db,
+   * we need to go back a few directories to get to it.  Running in Intellij defaults
+   * to the root dir of the project, while running the unit tests on the command line
+   * defaults to the root/sentry-tools dir.  Using the .class.getResource() defaults to
+   * the target/test-classes/blah dir.  So that's not usable.
+   *
+   * @return
+   */
+  private static String findSentryProviderDBDir() {
+
+    String pathToSentryProject = System.getProperty("user.dir");
+    if(pathToSentryProject.endsWith("/sentry-tools")) {
+      return pathToSentryProject.substring(0, pathToSentryProject.length()- "/sentry-tools".length());
+    }
+    return pathToSentryProject;
+  }
+  @Test
+  public void testInitNonDefault() throws Exception {
+    nonDefaultsetup();
+    schemaTool.doInit();
+    schemaTool.verifySchemaVersion();
+  }
+
+  @Test
+  public void testInit() throws Exception {
+    schemaTool.doInit();
+    schemaTool.verifySchemaVersion();
+  }
+
+  @Test
+  public void testInitTo() throws Exception {
+    schemaTool.doInit(SentryStoreSchemaInfo.getSentryVersion());
+    schemaTool.verifySchemaVersion();
+  }
+
+  @Test(expected = SentryUserException.class)
+  public void testDryRun() throws Exception {
+    schemaTool.setDryRun(true);
+    schemaTool.doInit();
+    schemaTool.setDryRun(false);
+    // verification should fail since dryRun didn't create the actual schema
+    schemaTool.verifySchemaVersion();
+  }
+
+  @Test
+  public void testUpgrade() throws Exception {
+    schemaTool.doInit(OLDEST_INIT_VERSION);
+    schemaTool.doUpgrade();
+    schemaTool.verifySchemaVersion();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellHive.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellHive.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellHive.java
new file mode 100644
index 0000000..46dc436
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellHive.java
@@ -0,0 +1,613 @@
+/**
+ * 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.cli.tools;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
+import org.apache.sentry.provider.db.service.thrift.TSentryRole;
+import org.apache.sentry.service.thrift.SentryServiceIntegrationBase;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+import com.google.common.io.Files;
+
+public class TestSentryShellHive extends SentryServiceIntegrationBase {
+
+  private File confDir;
+  private File confPath;
+  private static String TEST_ROLE_NAME_1 = "testRole1";
+  private static String TEST_ROLE_NAME_2 = "testRole2";
+  private String requestorName = "";
+
+  @Before
+  public void prepareForTest() throws Exception {
+    confDir = Files.createTempDir();
+    confPath = new File(confDir, "sentry-site.xml");
+    if (confPath.createNewFile()) {
+      FileOutputStream to = new FileOutputStream(confPath);
+      conf.writeXml(to);
+      to.close();
+    }
+    requestorName = clientUgi.getShortUserName();
+    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
+    setLocalGroupMapping(requestorName, requestorUserGroupNames);
+    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
+    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
+    writePolicyFile();
+  }
+
+  @After
+  public void clearTestData() throws Exception {
+    FileUtils.deleteQuietly(confDir);
+  }
+
+  @Test
+  public void testCreateDropRole() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // test: create role with -cr
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        // test: create role with --create_role
+        args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+
+        // validate the result, list roles with -lr
+        args = new String[] { "-lr", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive sentryShell = new SentryShellHive();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // validate the result, list roles with --list_role
+        args = new String[] { "--list_role", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // test: drop role with -dr
+        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        // test: drop role with --drop_role
+        args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+
+        // validate the result
+        Set<TSentryRole> roles = client.listAllRoles(requestorName);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+      }
+    });
+  }
+
+  @Test
+  public void testAddDeleteRoleForGroup() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1);
+        client.createRole(requestorName, TEST_ROLE_NAME_2);
+        // test: add role to group with -arg
+        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        // test: add role to multiple groups
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup2,testGroup3",
+            "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        // test: add role to group with --add_role_group
+        args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1",
+            "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+
+        // validate the result list roles with -lr and -g
+        args = new String[] { "-lr", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive sentryShell = new SentryShellHive();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+
+        // list roles with --list_role and -g
+        args = new String[] { "--list_role", "-g", "testGroup2", "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        args = new String[] { "--list_role", "-g", "testGroup3", "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        // List the groups and roles via listGroups
+        args = new String[] { "--list_group", "-conf", confPath.getAbsolutePath()};
+        sentryShell = new SentryShellHive();
+        Set<String> groups = getShellResultWithOSRedirect(sentryShell, args, true);
+        assertEquals(3, groups.size());
+        assertTrue(groups.contains("testGroup3 = testrole1"));
+        assertTrue(groups.contains("testGroup2 = testrole1"));
+        assertTrue(groups.contains("testGroup1 = testrole2, testrole1"));
+
+        // test: delete role from group with -drg
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        // test: delete role to multiple groups
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup2,testGroup3",
+            "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        // test: delete role from group with --delete_role_group
+        args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1",
+            "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+
+        // validate the result
+        Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, "testGroup1");
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        roles = client.listRolesByGroupName(requestorName, "testGroup2");
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        roles = client.listRolesByGroupName(requestorName, "testGroup3");
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2);
+      }
+    });
+  }
+
+  @Test
+  public void testGrantRevokePrivilegeWithShortOption() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1);
+        client.createRole(requestorName, TEST_ROLE_NAME_2);
+
+        // test: grant privilege to role with -gpr
+        String[] args = { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->action=*",
+            "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true",
+            "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+
+        // test the list privilege with -lp
+        args = new String[] { "-lp", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        SentryShellHive sentryShell = new SentryShellHive();
+        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
+        // validate the result for -lp
+        assertEquals("Incorrect number of privileges", 6, privilegeStrs.size());
+        assertTrue(privilegeStrs.contains("server=server1->action=*"));
+        assertTrue(privilegeStrs.contains("server=server1->db=db1->action=select"));
+        assertTrue(privilegeStrs.contains("server=server1->db=db1->table=tbl1->action=insert"));
+        assertTrue(privilegeStrs
+            .contains("server=server1->db=db1->table=tbl1->column=col1->action=insert"));
+        assertTrue(privilegeStrs
+            .contains("server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true"));
+        assertTrue(privilegeStrs.contains("server=server1->uri=hdfs://path/testuri->action=*"));
+
+        // test: revoke privilege from role with -rpr
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
+            TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 5, privileges.size());
+
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true",
+            "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 4, privileges.size());
+
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 3, privileges.size());
+
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 2, privileges.size());
+
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 1, privileges.size());
+
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p", "server=server1->action=*",
+            "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 0, privileges.size());
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2);
+      }
+    });
+  }
+
+  @Test
+  public void testGrantRevokePrivilegeWithLongOption() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1);
+        client.createRole(requestorName, TEST_ROLE_NAME_2);
+
+        // test: grant privilege to role with -gpr
+        String[] args = { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->action=*", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true",
+            "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+
+        // test the list privilege with -lp
+        args = new String[] { "--list_privilege", "-r", TEST_ROLE_NAME_1, "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive sentryShell = new SentryShellHive();
+        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
+        // validate the result for -lp
+        assertEquals("Incorrect number of privileges", 6, privilegeStrs.size());
+        assertTrue(privilegeStrs.contains("server=server1->action=*"));
+        assertTrue(privilegeStrs.contains("server=server1->db=db1->action=select"));
+        assertTrue(privilegeStrs.contains("server=server1->db=db1->table=tbl1->action=insert"));
+        assertTrue(privilegeStrs
+            .contains("server=server1->db=db1->table=tbl1->column=col1->action=insert"));
+        assertTrue(privilegeStrs
+            .contains("server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true"));
+        assertTrue(privilegeStrs.contains("server=server1->uri=hdfs://path/testuri->action=*"));
+
+        // test: revoke privilege from role with -rpr
+        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
+            TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 5, privileges.size());
+
+        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true",
+            "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 4, privileges.size());
+
+        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 3, privileges.size());
+
+        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 2, privileges.size());
+
+        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 1, privileges.size());
+
+        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->action=*", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 0, privileges.size());
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2);
+      }
+    });
+  }
+
+  @Test
+  public void testNegativeCaseWithInvalidArgument() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        client.createRole(requestorName, TEST_ROLE_NAME_1);
+        // test: create duplicate role with -cr
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        SentryShellHive sentryShell = new SentryShellHive();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for creating duplicate role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: drop non-exist role with -dr
+        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for dropping non-exist role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: add non-exist role to group with -arg
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for granting non-exist role to group");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: drop group from non-exist role with -drg
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for drop group from non-exist role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: grant privilege to role with the error privilege format
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=*",
+            "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for the error privilege format, invalid key value.");
+        } catch (IllegalArgumentException e) {
+          // excepted exception
+        }
+
+        // test: grant privilege to role with the error privilege hierarchy
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->table=tbl1->column=col2->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for the error privilege format, invalid key value.");
+        } catch (IllegalArgumentException e) {
+          // excepted exception
+        }
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1);
+      }
+    });
+  }
+
+  @Test
+  public void testNegativeCaseWithoutRequiredArgument() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String strOptionConf = "conf";
+        client.createRole(requestorName, TEST_ROLE_NAME_1);
+        // test: the conf is required argument
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1 };
+        SentryShellHive sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
+
+        // test: -r is required when create role
+        args = new String[] { "-cr", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -r is required when drop role
+        args = new String[] { "-dr", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -r is required when add role to group
+        args = new String[] { "-arg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -g is required when add role to group
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
+
+        // test: -r is required when delete role from group
+        args = new String[] { "-drg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -g is required when delete role from group
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
+
+        // test: -r is required when grant privilege to role
+        args = new String[] { "-gpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -p is required when grant privilege to role
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+        // test: -r is required when revoke privilege from role
+        args = new String[] { "-rpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -p is required when revoke privilege from role
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+        // test: command option is required for shell
+        args = new String[] {"-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsgsContains(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + "[",
+                "-arg Add role to group",
+                "-cr Create role",
+                "-rpr Revoke privilege from role",
+                "-drg Delete role from group",
+                "-lr List role",
+                "-lp List privilege",
+                "-gpr Grant privilege to role",
+                "-dr Drop role");
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1);
+      }
+    });
+  }
+
+  // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
+  private Set<String> getShellResultWithOSRedirect(SentryShellHive sentryShell,
+      String[] args, boolean exceptedExecuteResult) throws Exception {
+    PrintStream oldOut = System.out;
+    ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+    System.setOut(new PrintStream(outContent));
+    assertEquals(exceptedExecuteResult, sentryShell.executeShell(args));
+    Set<String> resultSet = Sets.newHashSet(outContent.toString().split("\n"));
+    System.setOut(oldOut);
+    return resultSet;
+  }
+
+  private void validateRoleNames(Set<String> roleNames, String ... expectedRoleNames) {
+    if (expectedRoleNames != null && expectedRoleNames.length > 0) {
+      assertEquals("Found: " + roleNames.size() + " roles, expected: " + expectedRoleNames.length,
+          expectedRoleNames.length, roleNames.size());
+      Set<String> lowerCaseRoles = new HashSet<String>();
+      for (String role : roleNames) {
+        lowerCaseRoles.add(role.toLowerCase());
+      }
+
+      for (String expectedRole : expectedRoleNames) {
+        assertTrue("Expected role: " + expectedRole,
+            lowerCaseRoles.contains(expectedRole.toLowerCase()));
+      }
+    }
+  }
+
+  private void validateMissingParameterMsg(SentryShellHive sentryShell, String[] args,
+      String exceptedErrorMsg) throws Exception {
+    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+    assertTrue(errorMsgs.contains(exceptedErrorMsg));
+  }
+
+  private void validateMissingParameterMsgsContains(SentryShellHive sentryShell, String[] args,
+      String ... expectedErrorMsgsContains) throws Exception {
+    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+    boolean foundAllMessages = false;
+    Iterator<String> it = errorMsgs.iterator();
+    while (it.hasNext()) {
+      String errorMessage = it.next();
+      boolean missingExpected = false;
+      for (String expectedContains : expectedErrorMsgsContains) {
+        if (!errorMessage.contains(expectedContains)) {
+          missingExpected = true;
+          break;
+        }
+      }
+      if (!missingExpected) {
+        foundAllMessages = true;
+        break;
+      }
+    }
+    assertTrue(foundAllMessages);
+  }
+}


Mime
View raw message