http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataPermissions.java
----------------------------------------------------------------------
diff --git 
a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataPermissions.java
 
b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataPermissions.java
new file mode 100644
index 0000000..05420d1
--- /dev/null
+++ 
b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataPermissions.java
@@ -0,0 +1,128 @@
+/*
+ * 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.tests.e2e.hive;
+
+import java.sql.Connection;
+import java.sql.Statement;
+
+import org.junit.Assert;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.Before;
+import org.junit.Test;
+
+
+public class TestMetadataPermissions extends 
AbstractTestWithStaticConfiguration {
+  private PolicyFile policyFile;
+
+  @Before
+  public void setup() throws Exception {
+    policyFile = PolicyFile.setAdminOnServer1(ADMINGROUP);
+    policyFile.setUserGroupMapping(StaticUserGroup.getStaticMapping());
+    writePolicyFile(policyFile);
+
+    Connection adminCon = context.createConnection(ADMIN1);
+    Statement adminStmt = context.createStatement(adminCon);
+    for (String dbName : new String[] { "" + DB1, DB2 }) {
+      adminStmt.execute("USE default");
+      adminStmt.execute("DROP DATABASE IF EXISTS " + dbName + " CASCADE");
+      adminStmt.execute("CREATE DATABASE " + dbName);
+      adminStmt.execute("USE " + dbName);
+      for (String tabName : new String[] { "tab1", "tab2" }) {
+        adminStmt.execute("CREATE TABLE " + tabName + " (id int)");
+      }
+    }
+
+    policyFile
+        .addRolesToGroup(USERGROUP1, "db1_all", "db2_all")
+        .addRolesToGroup(USERGROUP2, "db1_all")
+        .addPermissionsToRole("db1_all", "server=server1->db=" + DB1)
+        .addPermissionsToRole("db2_all", "server=server1->db=" + DB2);
+
+    writePolicyFile(policyFile);
+  }
+
+  /**
+   * Ensure that a user with no privileges on a database cannot
+   * query that databases metadata.
+   */
+  @Test
+  public void testDescPrivilegesNegative() throws Exception {
+    Connection connection = context.createConnection(USER2_1);
+    Statement statement = context.createStatement(connection);
+    context.assertAuthzException(statement, "USE " + DB2);
+//    TODO when DESCRIBE db.table is supported tests should be uncommented
+//    for (String tabName : new String[] { "tab1", "tab2" }) {
+//      context.assertAuthzException(statement, "DESCRIBE " + DB1 + "." + 
tabName);
+//      context.assertAuthzException(statement, "DESCRIBE EXTENDED " + DB1 + 
"." + tabName);
+//    }
+    statement.close();
+    connection.close();
+  }
+
+  /**
+   * Ensure that a user cannot describe databases to which the user
+   * has no privilege.
+   */
+  @Test
+  public void testDescDbPrivilegesNegative() throws Exception {
+    Connection connection = context.createConnection(USER2_1);
+    Statement statement = context.createStatement(connection);
+    context.assertAuthzException(statement, "DESCRIBE DATABASE " + DB2);
+    context.assertAuthzException(statement, "DESCRIBE DATABASE EXTENDED " + 
DB2);
+    statement.close();
+    connection.close();
+  }
+
+  /**
+   * Ensure that a user with privileges on a database can describe
+   * the database.
+   */
+  @Test
+  public void testDescDbPrivilegesPositive() throws Exception {
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    for (String dbName : new String[] { DB1, DB2 }) {
+      statement.execute("USE " + dbName);
+      Assert.assertTrue(statement.executeQuery("DESCRIBE DATABASE " + 
dbName).next());
+      Assert.assertTrue(statement.executeQuery("DESCRIBE DATABASE EXTENDED " + 
dbName).next());
+    }
+    statement.close();
+    connection.close();
+  }
+
+  /**
+   * Ensure that a user with privileges on a table can describe the table.
+   */
+  @Test
+  public void testDescPrivilegesPositive() throws Exception {
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    for (String dbName : new String[] { DB1, DB2 }) {
+      statement.execute("USE " + dbName);
+      Assert.assertTrue(statement.executeQuery("DESCRIBE DATABASE " + 
dbName).next());
+      for (String tabName : new String[] { "tab1", "tab2" }) {
+        Assert.assertTrue(statement.executeQuery("DESCRIBE " + 
tabName).next());
+        Assert.assertTrue(statement.executeQuery("DESCRIBE EXTENDED " + 
tabName).next());
+
+      }
+    }
+    statement.close();
+    connection.close();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestMovingToProduction.java
----------------------------------------------------------------------
diff --git 
a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestMovingToProduction.java
 
b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestMovingToProduction.java
new file mode 100644
index 0000000..a6edf03
--- /dev/null
+++ 
b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestMovingToProduction.java
@@ -0,0 +1,220 @@
+/*
+ * 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.tests.e2e.hive;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+public class TestMovingToProduction extends 
AbstractTestWithStaticConfiguration {
+  private final String SINGLE_TYPE_DATA_FILE_NAME = "kv1.dat";
+  private PolicyFile policyFile;
+
+
+  @Before
+  public void setup() throws Exception {
+    File dataFile = new File(dataDir, SINGLE_TYPE_DATA_FILE_NAME);
+    FileOutputStream to = new FileOutputStream(dataFile);
+    Resources.copy(Resources.getResource(SINGLE_TYPE_DATA_FILE_NAME), to);
+    to.close();
+    policyFile = PolicyFile.setAdminOnServer1(ADMINGROUP)
+        .setUserGroupMapping(StaticUserGroup.getStaticMapping());
+    writePolicyFile(policyFile);
+  }
+
+  /**
+   * Steps:
+   * 1. admin create DB_1, admin create GROUP_1, GROUP_2
+   * 2. admin grant all to GROUP_1 on DB_1
+   * 3. user in GROUP_1 create table tb_1 and load data into
+   * 4. admin create table production.tb_1.
+   * 5. admin grant all to GROUP_1 on production.tb_1.
+   *   positive test cases:
+   *     a)verify user in GROUP_1 can load data from DB_1.tb_1 to 
production.tb_1
+   *     b)verify user in GROUP_1 has proper privilege on production.tb_1
+   *     (read and insert)
+   *   negative test cases:
+   *     c)verify user in GROUP_2 cannot load data from DB_1.tb_1
+   *     to production.tb_1
+   *     d)verify user in GROUP_1 cannot drop production.tb_1
+   */
+  @Test
+  public void testMovingTable1() throws Exception {
+    String tableName1 = "tb_1";
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("DROP DATABASE IF EXISTS " + DB1 + " CASCADE");
+    statement.execute("DROP DATABASE IF EXISTS " + DB2 + " CASCADE");
+    statement.execute("CREATE DATABASE " + DB1);
+    statement.execute("CREATE DATABASE " + DB2);
+    statement.execute("DROP TABLE IF EXISTS " + DB2 + "." + tableName1);
+    statement.execute("create table " + DB2 + "." + tableName1
+        + " (under_col int comment 'the under column', value string)");
+    statement.close();
+    connection.close();
+
+    policyFile
+        .addRolesToGroup(USERGROUP1, "all_db1", "load_data")
+        .addPermissionsToRole("load_data", "server=server1->uri=file://" + 
dataDir.getPath())
+        .addPermissionsToRole("all_db1", "server=server1->db="  + DB1);
+    writePolicyFile(policyFile);
+
+
+    // a
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("USE " + DB1);
+    statement.execute("DROP TABLE IF EXISTS " + tableName1);
+    statement.execute("create table " + tableName1
+        + " (under_col int comment 'the under column', value string)");
+    statement.execute("LOAD DATA LOCAL INPATH 'file://" + dataDir.getPath()
+        + "' INTO TABLE " + tableName1);
+
+    policyFile
+        .addRolesToGroup(USERGROUP1, "insert_proddb_tbl1")
+        .addPermissionsToRole("insert_proddb_tbl1", "server=server1->db="  + 
DB2 + "->table=tb_1->action=insert");
+    writePolicyFile(policyFile);
+    statement.execute("USE " + DB2);
+    statement.execute("INSERT OVERWRITE TABLE "
+        + tableName1 + " SELECT * FROM " + DB1
+        + "." + tableName1);
+
+    // b
+    policyFile
+        .addRolesToGroup(USERGROUP1, "select_proddb_tbl1")
+        .addPermissionsToRole("select_proddb_tbl1", "server=server1->db="  + 
DB2 + "->table=tb_1->action=select");
+    writePolicyFile(policyFile);
+
+    ResultSet resultSet = statement.executeQuery("SELECT * FROM " + tableName1 
+ " LIMIT 10");
+    int count = 0;
+    while(resultSet.next()) {
+      count++;
+    }
+    assertEquals(10, count);
+    statement.execute("DESCRIBE " + tableName1);
+
+    // c
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    context.assertAuthzException(statement, "USE " + DB2);
+    context.assertAuthzException(statement, "INSERT OVERWRITE TABLE "
+        + DB2 + "." + tableName1 + " SELECT * FROM " + DB1
+        + "." + tableName1);
+    context.assertAuthzException(statement, "SELECT * FROM " + DB2 + "." + 
tableName1 + " LIMIT 10");
+    statement.close();
+    connection.close();
+
+    // d
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("USE " + DB2);
+    context.assertAuthzException(statement, "DROP TABLE " + tableName1);
+    statement.close();
+    connection.close();
+  }
+
+  /**
+   * repeat above tests, only difference is don't do 'USE <database>'
+   * in this test. Instead, access table objects across database by
+   * database.table
+   * @throws Exception
+   */
+  @Test
+  public void testMovingTable2() throws Exception {
+    String tableName1 = "tb_1";
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("DROP DATABASE IF EXISTS " + DB1 + " CASCADE");
+    statement.execute("DROP DATABASE IF EXISTS " + DB2 + " CASCADE");
+    statement.execute("CREATE DATABASE " + DB1);
+    statement.execute("CREATE DATABASE " + DB2);
+    statement.execute("DROP TABLE IF EXISTS " + DB2 + "." + tableName1);
+    statement.execute("create table " + DB2 + "." + tableName1
+        + " (under_col int comment 'the under column', value string)");
+    statement.close();
+    connection.close();
+
+    policyFile
+        .addRolesToGroup(USERGROUP1, "all_db1", "load_data")
+        .addPermissionsToRole("all_db1", "server=server1->db="  + DB1)
+        .addPermissionsToRole("load_data", "server=server1->uri=file://" + 
dataDir.getPath());
+    writePolicyFile(policyFile);
+
+    // a
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("DROP TABLE IF EXISTS " + DB1 + "." + tableName1);
+    statement.execute("create table " + DB1 + "." + tableName1
+        + " (under_col int comment 'the under column', value string)");
+    statement.execute("LOAD DATA LOCAL INPATH 'file://" + dataDir.getPath()
+        + "' INTO TABLE " + DB1 + "." + tableName1);
+
+    policyFile
+        .addRolesToGroup(USERGROUP1, "insert_proddb_tbl1")
+        .addPermissionsToRole("insert_proddb_tbl1", "server=server1->db="  + 
DB2 + "->table=tb_1->action=insert");
+    writePolicyFile(policyFile);
+
+    statement.execute("INSERT OVERWRITE TABLE "
+        + DB2 + "." + tableName1 + " SELECT * FROM " + DB1
+        + "." + tableName1);
+
+    // b
+    policyFile
+        .addRolesToGroup(USERGROUP1, "select_proddb_tbl1")
+        .addPermissionsToRole("select_proddb_tbl1", "server=server1->db="  + 
DB2 + "->table=tb_1->action=select");
+    writePolicyFile(policyFile);
+
+    assertTrue("user1 should be able to select data from "
+        + DB2 + "." + DB2 + "." + tableName1, statement.execute("SELECT * FROM 
"
+            + DB2 + "." + tableName1 + " LIMIT 10"));
+    assertTrue("user1 should be able to describe table " + DB2 + "." + 
tableName1,
+        statement.execute("DESCRIBE " + DB2 + "." + tableName1));
+
+    // c
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+
+    context.assertAuthzException(statement, "INSERT OVERWRITE TABLE "
+        + DB2 + "." + tableName1 + " SELECT * FROM " + DB1
+        + "." + tableName1);
+
+    context.assertAuthzException(statement, "SELECT * FROM "
+        + DB2 + "." + tableName1 + " LIMIT 10");
+    statement.close();
+    connection.close();
+
+    // d
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("USE " + DB2);
+    context.assertAuthzException(statement, "DROP TABLE " + tableName1);
+    statement.close();
+    connection.close();
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestOperations.java
----------------------------------------------------------------------
diff --git 
a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestOperations.java
 
b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestOperations.java
new file mode 100644
index 0000000..06a5752
--- /dev/null
+++ 
b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestOperations.java
@@ -0,0 +1,1116 @@
+/**
+ * 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.tests.e2e.hive;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.sentry.provider.file.PolicyFile;
+import static org.junit.Assert.assertTrue;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestOperations extends AbstractTestWithStaticConfiguration {
+  private static final Logger LOGGER = LoggerFactory
+      .getLogger(TestOperations.class);
+
+  private PolicyFile policyFile;
+  final String tableName = "tb1";
+
+  static Map<String, String> privileges = new HashMap<String, String>();
+  static {
+    privileges.put("all_server", "server=server1->action=all");
+    privileges.put("create_server", "server=server1->action=create");
+    privileges.put("all_db1", "server=server1->db=" + DB1 + "->action=all");
+    privileges.put("select_db1", "server=server1->db=" + DB1 + 
"->action=select");
+    privileges.put("insert_db1", "server=server1->db=" + DB1 + 
"->action=insert");
+    privileges.put("create_db1", "server=server1->db=" + DB1 + 
"->action=create");
+    privileges.put("drop_db1", "server=server1->db=" + DB1 + "->action=drop");
+    privileges.put("alter_db1", "server=server1->db=" + DB1 + 
"->action=alter");
+    privileges.put("create_db2", "server=server1->db=" + DB2 + 
"->action=create");
+
+    privileges.put("all_db1_tb1", "server=server1->db=" + DB1 + 
"->table=tb1->action=all");
+    privileges.put("select_db1_tb1", "server=server1->db=" + DB1 + 
"->table=tb1->action=select");
+    privileges.put("insert_db1_tb1", "server=server1->db=" + DB1 + 
"->table=tb1->action=insert");
+    privileges.put("alter_db1_tb1", "server=server1->db=" + DB1 + 
"->table=tb1->action=alter");
+    privileges.put("alter_db1_ptab", "server=server1->db=" + DB1 + 
"->table=ptab->action=alter");
+    privileges.put("index_db1_tb1", "server=server1->db=" + DB1 + 
"->table=tb1->action=index");
+    privileges.put("lock_db1_tb1", "server=server1->db=" + DB1 + 
"->table=tb1->action=lock");
+    privileges.put("drop_db1_tb1", "server=server1->db=" + DB1 + 
"->table=tb1->action=drop");
+    privileges.put("insert_db2_tb2", "server=server1->db=" + DB2 + 
"->table=tb2->action=insert");
+    privileges.put("select_db1_view1", "server=server1->db=" + DB1 + 
"->table=view1->action=select");
+
+  }
+
+  @Before
+  public void setup() throws Exception{
+    policyFile = PolicyFile.setAdminOnServer1(ADMINGROUP)
+        .setUserGroupMapping(StaticUserGroup.getStaticMapping());
+    writePolicyFile(policyFile);
+  }
+
+  private void adminCreate(String db, String table) throws Exception{
+    adminCreate(db, table, false);
+  }
+
+  private void adminCreate(String db, String table, boolean partitioned) 
throws Exception{
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("DROP DATABASE IF EXISTS " + db + " CASCADE");
+    statement.execute("CREATE DATABASE " + db);
+    if(table !=null) {
+      if (partitioned) {
+        statement.execute("CREATE table  " + db + "." + table + " (a string) 
PARTITIONED BY (b string)");
+      } else{
+        statement.execute("CREATE table  " + db + "." + table + " (a string)");
+      }
+
+    }
+    statement.close();
+    connection.close();
+  }
+
+  private void adminCreatePartition() throws Exception{
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE " + DB1);
+    statement.execute("ALTER TABLE tb1 ADD IF NOT EXISTS PARTITION (b = '1') 
");
+    statement.close();
+    connection.close();
+  }
+
+  /* Test all operations that require create on Server
+  1. Create database : HiveOperation.CREATEDATABASE
+   */
+  @Test
+  public void testCreateOnServer() throws Exception{
+    policyFile
+        .addPermissionsToRole("create_server", privileges.get("create_server"))
+        .addRolesToGroup(USERGROUP1, "create_server");
+
+    writePolicyFile(policyFile);
+
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("Create database " + DB2);
+    statement.close();
+    connection.close();
+
+    //Negative case
+    policyFile
+        .addPermissionsToRole("create_db1", privileges.get("create_db1"))
+        .addRolesToGroup(USERGROUP2, "create_db1");
+    writePolicyFile(policyFile);
+
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    context.assertSentrySemanticException(statement, "CREATE database " + DB1, 
semanticException);
+    statement.close();
+    connection.close();
+
+  }
+
+  @Test
+  public void testInsertInto() throws Exception{
+    File dataFile;
+    dataFile = new File(dataDir, SINGLE_TYPE_DATA_FILE_NAME);
+    FileOutputStream to = new FileOutputStream(dataFile);
+    Resources.copy(Resources.getResource(SINGLE_TYPE_DATA_FILE_NAME), to);
+    to.close();
+
+    adminCreate(DB1, null);
+    policyFile
+        .addPermissionsToRole("all_db1", privileges.get("all_db1"))
+        .addPermissionsToRole("all_uri", "server=server1->uri=file://" + 
dataDir)
+        .addRolesToGroup(USERGROUP1, "all_db1", "all_uri");
+
+
+    writePolicyFile(policyFile);
+
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("create table bar (key int)");
+    statement.execute("load data local inpath '" + dataFile.getPath() + "' 
into table bar");
+    statement.execute("create table foo (key int) partitioned by (part int) 
stored as parquet");
+    statement.execute("insert into table foo PARTITION(part=1) select key from 
bar");
+
+    statement.close();
+    connection.close();
+  }
+
+  /* Test all operations that require create on Database alone
+  1. Create table : HiveOperation.CREATETABLE
+  */
+  @Test
+  public void testCreateOnDatabase() throws Exception{
+    adminCreate(DB1, null);
+    policyFile
+        .addPermissionsToRole("create_db1", privileges.get("create_db1"))
+        .addPermissionsToRole("all_db1", privileges.get("all_db1"))
+        .addRolesToGroup(USERGROUP1, "create_db1")
+        .addRolesToGroup(USERGROUP2, "all_db1");
+
+    writePolicyFile(policyFile);
+
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("CREATE TABLE " + DB1 + ".tb2(a int)");
+    statement.close();
+    connection.close();
+
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("CREATE TABLE " + DB1 + ".tb3(a int)");
+
+    statement.close();
+    connection.close();
+
+    //Negative case
+    policyFile
+        .addPermissionsToRole("all_db1_tb1", privileges.get("select_db1"))
+        .addRolesToGroup(USERGROUP3, "all_db1_tb1");
+    writePolicyFile(policyFile);
+
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    context.assertSentrySemanticException(statement, "CREATE TABLE " + DB1 + 
".tb1(a int)", semanticException);
+    statement.close();
+    connection.close();
+  }
+
+  /* Test all operations that require drop on Database alone
+  1. Drop database : HiveOperation.DROPDATABASE
+  */
+  @Test
+  public void testDropOnDatabase() throws Exception{
+    adminCreate(DB1, null);
+    policyFile
+        .addPermissionsToRole("drop_db1", privileges.get("drop_db1"))
+        .addRolesToGroup(USERGROUP1, "drop_db1");
+
+    writePolicyFile(policyFile);
+
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("DROP DATABASE " + DB1);
+    statement.close();
+    connection.close();
+
+    adminCreate(DB1, null);
+
+    policyFile
+        .addPermissionsToRole("all_db1", privileges.get("all_db1"))
+        .addRolesToGroup(USERGROUP2, "all_db1");
+    writePolicyFile(policyFile);
+
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("DROP DATABASE " + DB1);
+
+    statement.close();
+    connection.close();
+
+    //Negative case
+    adminCreate(DB1, null);
+    policyFile
+        .addPermissionsToRole("select_db1", privileges.get("select_db1"))
+        .addRolesToGroup(USERGROUP3, "select_db1");
+    writePolicyFile(policyFile);
+
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    context.assertSentrySemanticException(statement, "drop database " + DB1, 
semanticException);
+    statement.close();
+    connection.close();
+  }
+
+  /* Test all operations that require alter on Database alone
+  1. Alter database : HiveOperation.ALTERDATABASE
+   */
+  @Test
+  public void testAlterOnDatabase() throws Exception{
+    adminCreate(DB1, null);
+    policyFile
+        .addPermissionsToRole("alter_db1", privileges.get("alter_db1"))
+        .addPermissionsToRole("all_db1", privileges.get("all_db1"))
+        .addRolesToGroup(USERGROUP2, "all_db1")
+        .addRolesToGroup(USERGROUP1, "alter_db1");
+    writePolicyFile(policyFile);
+
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("ALTER DATABASE " + DB1 + " SET DBPROPERTIES 
('comment'='comment')");
+
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("ALTER DATABASE " + DB1 + " SET DBPROPERTIES 
('comment'='comment')");
+    statement.close();
+    connection.close();
+
+    //Negative case
+    adminCreate(DB1, null);
+    policyFile
+        .addPermissionsToRole("select_db1", privileges.get("select_db1"))
+        .addRolesToGroup(USERGROUP3, "select_db1");
+    writePolicyFile(policyFile);
+
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    context.assertSentrySemanticException(statement, "ALTER DATABASE " + DB1 + 
" SET DBPROPERTIES ('comment'='comment')", semanticException);
+    statement.close();
+    connection.close();
+  }
+
+  /* SELECT/INSERT on DATABASE
+   1. HiveOperation.DESCDATABASE
+   */
+  @Test
+  public void testDescDB() throws Exception {
+    adminCreate(DB1, tableName);
+    policyFile
+        .addPermissionsToRole("select_db1", privileges.get("select_db1"))
+        .addPermissionsToRole("insert_db1", privileges.get("insert_db1"))
+        .addRolesToGroup(USERGROUP1, "select_db1")
+        .addRolesToGroup(USERGROUP2, "insert_db1");
+    writePolicyFile(policyFile);
+
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("describe database " + DB1);
+    statement.close();
+    connection.close();
+
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("describe database " + DB1);
+    statement.close();
+    connection.close();
+
+    //Negative case
+    policyFile
+        .addPermissionsToRole("all_db1_tb1", privileges.get("all_db1_tb1"))
+        .addRolesToGroup(USERGROUP3, "all_db1_tb1");
+    writePolicyFile(policyFile);
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    context.assertSentrySemanticException(statement, "describe database " + 
DB1, semanticException);
+    statement.close();
+    connection.close();
+
+  }
+
+  private void assertSemanticException(Statement stmt, String command) throws 
SQLException{
+    context.assertSentrySemanticException(stmt, command, semanticException);
+  }
+
+  /*
+  1. Analyze table (HiveOperation.QUERY) : select + insert on table
+   */
+  @Test
+  public void testSelectAndInsertOnTable() throws Exception {
+    adminCreate(DB1, tableName, true);
+    adminCreatePartition();
+    policyFile
+        .addPermissionsToRole("select_db1_tb1", 
privileges.get("select_db1_tb1"))
+        .addPermissionsToRole("insert_db1_tb1", 
privileges.get("insert_db1_tb1"))
+        .addRolesToGroup(USERGROUP1, "select_db1_tb1", "insert_db1_tb1");
+    writePolicyFile(policyFile);
+
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("ANALYZE TABLE tb1 PARTITION (b='1' ) COMPUTE 
STATISTICS");
+    statement.close();
+    connection.close();
+  }
+
+  /* Operations which require select on table alone
+  1. HiveOperation.QUERY
+  2. HiveOperation.SHOW_TBLPROPERTIES
+  3. HiveOperation.SHOW_CREATETABLE
+  4. HiveOperation.SHOWINDEXES
+  5. HiveOperation.SHOWCOLUMNS
+  6. Describe tb1 : HiveOperation.DESCTABLE5.
+  7. HiveOperation.SHOWPARTITIONS
+  8. TODO: show functions?
+  9. HiveOperation.SHOW_TABLESTATUS
+   */
+  @Test
+  public void testSelectOnTable() throws Exception {
+    adminCreate(DB1, tableName, true);
+    adminCreatePartition();
+    policyFile
+        .addPermissionsToRole("select_db1_tb1", 
privileges.get("select_db1_tb1"))
+        .addRolesToGroup(USERGROUP1, "select_db1_tb1");
+    writePolicyFile(policyFile);
+
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("select * from tb1");
+
+    statement.executeQuery("SHOW Partitions tb1");
+    statement.executeQuery("SHOW TBLPROPERTIES tb1");
+    statement.executeQuery("SHOW CREATE TABLE tb1");
+    statement.executeQuery("SHOW indexes on tb1");
+    statement.executeQuery("SHOW COLUMNS from tb1");
+    statement.executeQuery("SHOW functions '.*'");
+    statement.executeQuery("SHOW TABLE EXTENDED IN " + DB1 + " LIKE 'tb*'");
+
+    statement.executeQuery("DESCRIBE tb1");
+    statement.executeQuery("DESCRIBE tb1 PARTITION (b=1)");
+
+    statement.close();
+    connection.close();
+
+    //Negative case
+    adminCreate(DB2, tableName);
+    policyFile
+        .addPermissionsToRole("insert_db1_tb1", 
privileges.get("insert_db1_tb1"))
+        .addRolesToGroup(USERGROUP3, "insert_db1_tb1");
+    writePolicyFile(policyFile);
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    context.assertSentrySemanticException(statement, "select * from tb1", 
semanticException);
+    context.assertSentrySemanticException(statement,
+        "SHOW TABLE EXTENDED IN " + DB2 + " LIKE 'tb*'", semanticException);
+
+    statement.close();
+    connection.close();
+
+
+  }
+
+  /* Operations which require insert on table alone
+  1. HiveOperation.SHOW_TBLPROPERTIES
+  2. HiveOperation.SHOW_CREATETABLE
+  3. HiveOperation.SHOWINDEXES
+  4. HiveOperation.SHOWCOLUMNS
+  5. HiveOperation.DESCTABLE
+  6. HiveOperation.SHOWPARTITIONS
+  7. TODO: show functions?
+  8. TODO: lock, unlock, Show locks
+  9. HiveOperation.SHOW_TABLESTATUS
+   */
+  @Test
+  public void testInsertOnTable() throws Exception {
+    adminCreate(DB1, tableName, true);
+    adminCreatePartition();
+    policyFile
+        .addPermissionsToRole("insert_db1_tb1", 
privileges.get("insert_db1_tb1"))
+        .addRolesToGroup(USERGROUP1, "insert_db1_tb1");
+    writePolicyFile(policyFile);
+
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    /*statement.execute("LOCK TABLE tb1 EXCLUSIVE");
+    statement.execute("UNLOCK TABLE tb1");
+    */
+    statement.executeQuery("SHOW TBLPROPERTIES tb1");
+    statement.executeQuery("SHOW CREATE TABLE tb1");
+    statement.executeQuery("SHOW indexes on tb1");
+    statement.executeQuery("SHOW COLUMNS from tb1");
+    statement.executeQuery("SHOW functions '.*'");
+    //statement.executeQuery("SHOW LOCKS tb1");
+    statement.executeQuery("SHOW TABLE EXTENDED IN " + DB1 + " LIKE 'tb*'");
+
+    //NoViableAltException
+    //statement.executeQuery("SHOW transactions");
+    //statement.executeQuery("SHOW compactions");
+    statement.executeQuery("DESCRIBE tb1");
+    statement.executeQuery("DESCRIBE tb1 PARTITION (b=1)");
+    statement.executeQuery("SHOW Partitions tb1");
+
+
+    statement.close();
+    connection.close();
+  }
+
+  /* Test all operations that require alter on table
+  1. HiveOperation.ALTERTABLE_PROPERTIES
+  2. HiveOperation.ALTERTABLE_SERDEPROPERTIES
+  3. HiveOperation.ALTERTABLE_CLUSTER_SORT
+  4. HiveOperation.ALTERTABLE_TOUCH
+  5. HiveOperation.ALTERTABLE_PROTECTMODE
+  6. HiveOperation.ALTERTABLE_FILEFORMAT
+  7. HiveOperation.ALTERTABLE_RENAMEPART
+  8. HiveOperation.ALTERPARTITION_SERDEPROPERTIES
+  9. TODO: archive partition
+  10. TODO: unarchive partition
+  11. HiveOperation.ALTERPARTITION_FILEFORMAT
+  12. TODO: partition touch (is it same as  HiveOperation.ALTERTABLE_TOUCH?)
+  13. HiveOperation.ALTERPARTITION_PROTECTMODE
+  14. HiveOperation.ALTERTABLE_RENAMECOL
+  15. HiveOperation.ALTERTABLE_ADDCOLS
+  16. HiveOperation.ALTERTABLE_REPLACECOLS
+  17. TODO: HiveOperation.ALTERVIEW_PROPERTIES
+  18. TODO: HiveOperation.ALTERTABLE_SERIALIZER
+  19. TODO: HiveOperation.ALTERPARTITION_SERIALIZER
+   */
+  @Test
+  public void testAlterTable() throws Exception {
+    adminCreate(DB1, tableName, true);
+
+    Connection connection;
+    Statement statement;
+    //Setup
+    connection = context.createConnection(ADMIN1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("ALTER TABLE tb1 ADD IF NOT EXISTS PARTITION (b = '10') 
");
+    statement.execute("ALTER TABLE tb1 ADD IF NOT EXISTS PARTITION (b = '1') 
");
+    statement.execute("DROP TABLE IF EXISTS ptab");
+    statement.execute("CREATE TABLE ptab (a int) STORED AS PARQUET");
+
+    policyFile
+      .addPermissionsToRole("alter_db1_tb1", privileges.get("alter_db1_tb1"))
+      .addPermissionsToRole("alter_db1_ptab", privileges.get("alter_db1_ptab"))
+      .addRolesToGroup(USERGROUP1, "alter_db1_tb1", "alter_db1_ptab")
+      .addPermissionsToRole("insert_db1_tb1", privileges.get("insert_db1_tb1"))
+      .addRolesToGroup(USERGROUP2, "insert_db1_tb1");
+    writePolicyFile(policyFile);
+
+    //Negative test cases
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    assertSemanticException(statement, "ALTER TABLE tb1 SET TBLPROPERTIES 
('comment' = 'new_comment')");
+    assertSemanticException(statement, "ALTER TABLE tb1 SET SERDEPROPERTIES 
('field.delim' = ',')");
+    assertSemanticException(statement, "ALTER TABLE tb1 CLUSTERED BY (a) 
SORTED BY (a) INTO 1 BUCKETS");
+    assertSemanticException(statement, "ALTER TABLE tb1 TOUCH");
+    // OFFLINE and NO_DROP were removed from tables and partitions after Hive 
2.0.0 (HIVE-11145)
+    //assertSemanticException(statement, "ALTER TABLE tb1 ENABLE NO_DROP 
cascade");
+    //assertSemanticException(statement, "ALTER TABLE tb1 DISABLE OFFLINE");
+    assertSemanticException(statement, "ALTER TABLE tb1 SET FILEFORMAT 
RCFILE");
+
+    assertSemanticException(statement, "ALTER TABLE tb1 PARTITION (b = 10) 
RENAME TO PARTITION (b = 2)");
+    assertSemanticException(statement, "ALTER TABLE tb1 PARTITION (b = 10) SET 
SERDEPROPERTIES ('field.delim' = ',')");
+    //assertSemanticException(statement, "ALTER TABLE tb1 ARCHIVE PARTITION (b 
= 2)");
+    //assertSemanticException(statement, "ALTER TABLE tb1 UNARCHIVE PARTITION 
(b = 2)");
+    assertSemanticException(statement, "ALTER TABLE tb1 PARTITION (b = 10) SET 
FILEFORMAT RCFILE");
+    assertSemanticException(statement, "ALTER TABLE tb1 TOUCH PARTITION (b = 
10)");
+    // OFFLINE and NO_DROP were removed from tables and partitions after Hive 
2.0.0 (HIVE-11145)
+    // assertSemanticException(statement, "ALTER TABLE tb1 PARTITION (b = 10) 
DISABLE NO_DROP");
+    // assertSemanticException(statement, "ALTER TABLE tb1 PARTITION (b = 10) 
DISABLE OFFLINE");
+
+    assertSemanticException(statement, "ALTER TABLE tb1 CHANGE COLUMN a c 
int");
+    assertSemanticException(statement, "ALTER TABLE tb1 ADD COLUMNS (a int)");
+    assertSemanticException(statement, "ALTER TABLE ptab REPLACE COLUMNS (a 
int, c int)");
+    assertSemanticException(statement, "MSCK REPAIR TABLE tb1");
+
+    //assertSemanticException(statement, "ALTER VIEW view1 SET TBLPROPERTIES 
('comment' = 'new_comment')");
+
+
+    statement.close();
+    connection.close();
+
+    //Positive cases
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("ALTER TABLE tb1 SET TBLPROPERTIES ('comment' = 
'new_comment')");
+    statement.execute("ALTER TABLE tb1 SET SERDEPROPERTIES ('field.delim' = 
',')");
+    statement.execute("ALTER TABLE tb1 CLUSTERED BY (a) SORTED BY (a) INTO 1 
BUCKETS");
+    statement.execute("ALTER TABLE tb1 TOUCH");
+    // OFFLINE and NO_DROP were removed from tables and partitions after Hive 
2.0.0 (HIVE-11145)
+    // statement.execute("ALTER TABLE tb1 ENABLE NO_DROP");
+    // statement.execute("ALTER TABLE tb1 DISABLE OFFLINE");
+    statement.execute("ALTER TABLE tb1 SET FILEFORMAT RCFILE");
+
+    statement.execute("ALTER TABLE tb1 PARTITION (b = 1) RENAME TO PARTITION 
(b = 2)");
+    statement.execute("ALTER TABLE tb1 PARTITION (b = 2) SET SERDEPROPERTIES 
('field.delim' = ',')");
+    //statement.execute("ALTER TABLE tb1 ARCHIVE PARTITION (b = 2)");
+    //statement.execute("ALTER TABLE tb1 UNARCHIVE PARTITION (b = 2)");
+    statement.execute("ALTER TABLE tb1 PARTITION (b = 2) SET FILEFORMAT 
RCFILE");
+    statement.execute("ALTER TABLE tb1 TOUCH PARTITION (b = 2)");
+    // OFFLINE and NO_DROP were removed from tables and partitions after Hive 
2.0.0 (HIVE-11145)
+    //statement.execute("ALTER TABLE tb1 PARTITION (b = 2) DISABLE NO_DROP");
+    //statement.execute("ALTER TABLE tb1 PARTITION (b = 2) DISABLE OFFLINE");
+
+    statement.execute("set 
hive.metastore.disallow.incompatible.col.type.changes=false");
+    statement.execute("ALTER TABLE tb1 CHANGE COLUMN a c int");
+    statement.execute("ALTER TABLE tb1 ADD COLUMNS (a int)");
+    statement.execute("ALTER TABLE ptab REPLACE COLUMNS (a int, c int)");
+    statement.execute("MSCK REPAIR TABLE tb1");
+
+    //statement.execute("ALTER VIEW view1 SET TBLPROPERTIES ('comment' = 
'new_comment')");
+
+    statement.close();
+    connection.close();
+  }
+
+  /* Test all operations that require index on table alone
+  1. Create index : HiveOperation.CREATEINDEX
+  2. Drop index : HiveOperation.DROPINDEX
+  3. HiveOperation.ALTERINDEX_REBUILD
+  4. TODO: HiveOperation.ALTERINDEX_PROPS
+  */
+  @Test
+  public void testIndexTable() throws Exception {
+    adminCreate(DB1, tableName, true);
+    policyFile
+        .addPermissionsToRole("index_db1_tb1", privileges.get("index_db1_tb1"))
+        .addRolesToGroup(USERGROUP1, "index_db1_tb1")
+        .addPermissionsToRole("insert_db1_tb1", 
privileges.get("insert_db1_tb1"))
+        .addRolesToGroup(USERGROUP2, "insert_db1_tb1");
+    writePolicyFile(policyFile);
+
+    Connection connection;
+    Statement statement;
+
+    //Positive cases
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("CREATE INDEX table01_index ON TABLE tb1 (a) AS 
'COMPACT' WITH DEFERRED REBUILD");
+    statement.execute("ALTER INDEX table01_index ON tb1 REBUILD");
+    statement.close();
+    connection.close();
+
+    //Negative case
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    assertSemanticException(statement, "CREATE INDEX table02_index ON TABLE 
tb1 (a) AS 'COMPACT' WITH DEFERRED REBUILD");
+    assertSemanticException(statement, "ALTER INDEX table01_index ON tb1 
REBUILD");
+    assertSemanticException(statement, "DROP INDEX table01_index ON tb1");
+    statement.close();
+    connection.close();
+
+    //Positive cases
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("DROP INDEX table01_index ON tb1");
+    statement.close();
+    connection.close();
+  }
+
+  /* Test all operations that require drop on table alone
+  1. Create index : HiveOperation.DROPTABLE
+  */
+  @Test
+  public void testDropTable() throws Exception {
+    adminCreate(DB1, tableName, true);
+    policyFile
+        .addPermissionsToRole("drop_db1_tb1", privileges.get("drop_db1_tb1"))
+        .addRolesToGroup(USERGROUP1, "drop_db1_tb1")
+        .addPermissionsToRole("insert_db1_tb1", 
privileges.get("insert_db1_tb1"))
+        .addRolesToGroup(USERGROUP2, "insert_db1_tb1");
+    writePolicyFile(policyFile);
+
+    Connection connection;
+    Statement statement;
+
+    //Negative case
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    assertSemanticException(statement, "drop table " + tableName);
+
+    statement.close();
+    connection.close();
+
+    //Positive cases
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("drop table " + tableName);
+
+    statement.close();
+    connection.close();
+  }
+
+  @Ignore
+  @Test
+  public void testLockTable() throws Exception {
+   //TODO
+  }
+
+  /* Operations that require alter + drop on table
+    1. HiveOperation.ALTERTABLE_DROPPARTS
+  */
+  @Test
+  public void dropPartition() throws Exception {
+    adminCreate(DB1, tableName, true);
+    policyFile
+        .addPermissionsToRole("alter_db1_tb1", privileges.get("alter_db1_tb1"))
+        .addPermissionsToRole("drop_db1_tb1", privileges.get("drop_db1_tb1"))
+        .addRolesToGroup(USERGROUP1, "alter_db1_tb1", "drop_db1_tb1")
+        .addRolesToGroup(USERGROUP2, "alter_db1_tb1");
+
+    writePolicyFile(policyFile);
+
+    Connection connection;
+    Statement statement;
+    //Setup
+    connection = context.createConnection(ADMIN1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("ALTER TABLE tb1 ADD IF NOT EXISTS PARTITION (b = '10') 
");
+
+    //Negative case
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("USE " + DB1);
+    assertSemanticException(statement, "ALTER TABLE tb1 DROP PARTITION (b = 
10)");
+
+    //Positive case
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("ALTER TABLE tb1 DROP PARTITION (b = 10)");
+    statement.close();
+    connection.close();
+  }
+
+  /*
+   1. HiveOperation.ALTERTABLE_RENAME
+   */
+  @Test
+  public void renameTable() throws Exception {
+    adminCreate(DB1, tableName);
+    policyFile
+        .addPermissionsToRole("alter_db1_tb1", privileges.get("alter_db1_tb1"))
+        .addPermissionsToRole("create_db1", privileges.get("create_db1"))
+        .addRolesToGroup(USERGROUP1, "alter_db1_tb1", "create_db1")
+        .addRolesToGroup(USERGROUP2, "create_db1")
+        .addRolesToGroup(USERGROUP3, "alter_db1_tb1");
+
+    writePolicyFile(policyFile);
+
+    Connection connection;
+    Statement statement;
+
+    //Negative cases
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    assertSemanticException(statement, "ALTER TABLE tb1 RENAME TO tb2");
+    statement.close();
+    connection.close();
+
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    assertSemanticException(statement, "ALTER TABLE tb1 RENAME TO tb2");
+    statement.close();
+    connection.close();
+
+    //Positive case
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("ALTER TABLE tb1 RENAME TO tb2");
+    statement.close();
+    connection.close();
+  }
+
+  /* Test all operations which require alter on table (+ all on URI)
+   1. HiveOperation.ALTERTABLE_LOCATION
+   2. HiveOperation.ALTERTABLE_ADDPARTS
+   3. TODO: HiveOperation.ALTERPARTITION_LOCATION
+   4. TODO: HiveOperation.ALTERTBLPART_SKEWED_LOCATION
+   */
+  @Test
+  public void testAlterOnTableAndURI() throws Exception {
+    adminCreate(DB1, tableName, true);
+    String tabLocation = dfs.getBaseDir() + "/" + Math.random();
+    policyFile
+        .addPermissionsToRole("alter_db1_tb1", privileges.get("alter_db1_tb1"))
+        .addPermissionsToRole("all_uri", "server=server1->uri=" + tabLocation)
+        .addRolesToGroup(USERGROUP1, "alter_db1_tb1", "all_uri")
+        .addRolesToGroup(USERGROUP2, "alter_db1_tb1");
+
+    writePolicyFile(policyFile);
+
+    //Case with out uri
+    Connection connection = context.createConnection(USER2_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE " + DB1);
+    assertSemanticException(statement, "ALTER TABLE tb1 SET LOCATION '" + 
tabLocation + "'");
+    assertSemanticException(statement, "ALTER TABLE tb1 ADD IF NOT EXISTS 
PARTITION (b = '3') LOCATION '" + tabLocation + "/part'");
+    statement.execute("ALTER TABLE tb1 ADD IF NOT EXISTS PARTITION (b = '1') 
");
+
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("ALTER TABLE tb1 SET LOCATION '" + tabLocation + "'");
+    statement.execute("ALTER TABLE tb1 ADD IF NOT EXISTS PARTITION (b = '3') 
LOCATION '" + tabLocation + "/part'");
+    statement.execute("ALTER TABLE tb1 ADD IF NOT EXISTS PARTITION (b = '10') 
");
+    statement.close();
+    connection.close();
+
+    //Negative case: User2_1 has privileges on table but on on uri
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    context.assertSentrySemanticException(statement, "ALTER TABLE tb1 SET 
LOCATION '" + tabLocation + "'",
+        semanticException);
+    context.assertSentrySemanticException(statement,
+        "ALTER TABLE tb1 ADD IF NOT EXISTS PARTITION (b = '3') LOCATION '" + 
tabLocation + "/part'",
+        semanticException);
+    statement.close();
+    connection.close();
+
+    //Negative case: User3_1 has only insert privileges on table
+    policyFile
+        .addPermissionsToRole("insert_db1_tb1", 
privileges.get("insert_db1_tb1"))
+        .addRolesToGroup(USERGROUP3, "insert_db1_tb1", "all_uri");
+    writePolicyFile(policyFile);
+
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    assertSemanticException(statement, "ALTER TABLE tb1 ADD IF NOT EXISTS 
PARTITION (b = '2') ");
+    assertSemanticException(statement, "ALTER TABLE tb1 SET LOCATION '" + 
tabLocation + "'");
+
+    assertSemanticException(statement, "ALTER TABLE tb1 ADD IF NOT EXISTS 
PARTITION (b = '3') LOCATION '"
+        + tabLocation + "/part'");
+    statement.close();
+    connection.close();
+
+
+  }
+
+  /* Create on Database and select on table
+  1. Create view :  HiveOperation.CREATEVIEW
+   */
+  @Test
+  public void testCreateView() throws Exception {
+    adminCreate(DB1, tableName);
+    adminCreate(DB2, null);
+    policyFile
+        .addPermissionsToRole("select_db1_tb1", 
privileges.get("select_db1_tb1"))
+        .addPermissionsToRole("create_db2", privileges.get("create_db2"))
+        .addRolesToGroup(USERGROUP1, "select_db1_tb1", "create_db2");
+    writePolicyFile(policyFile);
+
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("use " + DB2);
+    statement.execute("create view view1 as select a from " + DB1 + ".tb1");
+    statement.close();
+    connection.close();
+
+    //Negative case
+    policyFile
+        .addPermissionsToRole("insert_db1_tb1", 
privileges.get("insert_db1_tb1"))
+        .addRolesToGroup(USERGROUP3, "insert_db1_tb1", "create_db2");
+    writePolicyFile(policyFile);
+
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB2);
+    context.assertSentrySemanticException(statement, "create view view1 as 
select a from " + DB1 + ".tb1",
+        semanticException);
+    statement.close();
+    connection.close();
+
+
+  }
+
+  /*
+   1. HiveOperation.IMPORT : Create on db + all on URI
+   2. HiveOperation.EXPORT : SELECT on table + all on uri
+   */
+
+  @Test
+  public void testExportImport() throws Exception {
+    File dataFile;
+    dataFile = new File(dataDir, SINGLE_TYPE_DATA_FILE_NAME);
+    FileOutputStream to = new FileOutputStream(dataFile);
+    Resources.copy(Resources.getResource(SINGLE_TYPE_DATA_FILE_NAME), to);
+    to.close();
+
+    dropDb(ADMIN1, DB1);
+    createDb(ADMIN1, DB1);
+    createTable(ADMIN1, DB1, dataFile, tableName);
+    String location = dfs.getBaseDir() + "/" + Math.random();
+    policyFile
+        .addPermissionsToRole("create_db1", privileges.get("create_db1"))
+        .addPermissionsToRole("all_uri", "server=server1->uri="+ location)
+        .addPermissionsToRole("select_db1_tb1", 
privileges.get("select_db1_tb1"))
+        .addPermissionsToRole("insert_db1", privileges.get("insert_db1"))
+        .addRolesToGroup(USERGROUP1, "select_db1_tb1", "all_uri")
+        .addRolesToGroup(USERGROUP2, "create_db1", "all_uri")
+        .addRolesToGroup(USERGROUP3, "insert_db1", "all_uri");
+    writePolicyFile(policyFile);
+    Connection connection;
+    Statement statement;
+
+    //Negative case
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    context.assertSentrySemanticException(statement, "export table tb1 to '" + 
location + "'",
+        semanticException);
+    statement.close();
+    connection.close();
+
+    //Positive
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("export table tb1 to '" + location + "'" );
+    statement.close();
+    connection.close();
+
+    //Negative
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    context.assertSentrySemanticException(statement, "import table tb2 from '" 
+ location + "'",
+        semanticException);
+    statement.close();
+    connection.close();
+
+    //Positive
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("import table tb2 from '" + location + "'");
+    statement.close();
+    connection.close();
+
+  }
+
+  /*
+  1. HiveOperation.LOAD: INSERT on table + all on uri
+   */
+  @Test
+  public void testLoad() throws Exception {
+    File dataFile;
+    dataFile = new File(dataDir, SINGLE_TYPE_DATA_FILE_NAME);
+    FileOutputStream to = new FileOutputStream(dataFile);
+    Resources.copy(Resources.getResource(SINGLE_TYPE_DATA_FILE_NAME), to);
+    to.close();
+
+    adminCreate(DB1, tableName);
+
+    policyFile
+        .addPermissionsToRole("insert_db1_tb1", 
privileges.get("insert_db1_tb1"))
+        .addPermissionsToRole("all_uri", "server=server1->uri=file://" + 
dataDir)
+        .addRolesToGroup(USERGROUP1, "insert_db1_tb1", "all_uri");
+    writePolicyFile(policyFile);
+
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("load data local inpath '" + dataFile.getPath() + "' 
into table tb1" );
+    statement.close();
+    connection.close();
+  }
+
+  /*
+  1. HiveOperation.CREATETABLE_AS_SELECT : Create on db + select on table
+   */
+  @Test
+  public void testCTAS() throws Exception {
+    adminCreate(DB1, tableName);
+    adminCreate(DB2, null);
+
+    String location = dfs.getBaseDir() + "/" + Math.random();
+
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("Use " + DB1);
+    statement.execute("create view view1 as select a from " + DB1 + ".tb1");
+    statement.close();
+    connection.close();
+
+    policyFile
+      .addPermissionsToRole("select_db1_tb1", privileges.get("select_db1_tb1"))
+      .addPermissionsToRole("select_db1_view1", 
privileges.get("select_db1_view1"))
+      .addPermissionsToRole("create_db2", privileges.get("create_db2"))
+      .addPermissionsToRole("all_uri", "server=server1->uri=" + location)
+      .addRolesToGroup(USERGROUP1, "select_db1_tb1", "create_db2")
+      .addRolesToGroup(USERGROUP2, "select_db1_view1", "create_db2")
+      .addRolesToGroup(USERGROUP3, "select_db1_tb1", "create_db2,all_uri");
+    writePolicyFile(policyFile);
+
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB2);
+    statement.execute("create table tb2 as select a from " + DB1 + ".tb1");
+    //Ensure CTAS fails without URI
+    context.assertSentrySemanticException(statement, "create table tb3 
location '" + location +
+        "' as select a from " + DB1 + ".tb1",
+      semanticException);
+    context.assertSentrySemanticException(statement, "create table tb3 as 
select a from " + DB1 + ".view1",
+      semanticException);
+
+
+    statement.close();
+    connection.close();
+
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("Use " + DB2);
+    statement.execute("create table tb3 as select a from " + DB1 + ".view1" );
+    context.assertSentrySemanticException(statement, "create table tb4 as 
select a from " + DB1 + ".tb1",
+      semanticException);
+
+    statement.close();
+    connection.close();
+
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    //CTAS is valid with URI
+    statement.execute("Use " + DB2);
+    statement.execute("create table tb4 location '" + location +
+      "' as select a from " + DB1 + ".tb1");
+
+    statement.close();
+    connection.close();
+
+  }
+
+
+  /*
+  1. INSERT : IP: select on table, OP: insert on table + all on uri(optional)
+   */
+  @Test
+  public void testInsert() throws Exception {
+    File dataFile;
+    dataFile = new File(dataDir, SINGLE_TYPE_DATA_FILE_NAME);
+    FileOutputStream to = new FileOutputStream(dataFile);
+    Resources.copy(Resources.getResource(SINGLE_TYPE_DATA_FILE_NAME), to);
+    to.close();
+
+    dropDb(ADMIN1, DB1);
+    dropDb(ADMIN1, DB2);
+    createDb(ADMIN1, DB1);
+    createDb(ADMIN1, DB2);
+    createTable(ADMIN1, DB1, dataFile, tableName);
+    createTable(ADMIN1, DB2, null, "tb2");
+    String location = dfs.getBaseDir() + "/" + Math.random();
+
+    policyFile
+        .addPermissionsToRole("select_db1_tb1", 
privileges.get("select_db1_tb1"))
+        .addPermissionsToRole("insert_db2_tb2", 
privileges.get("insert_db2_tb2"))
+        .addRolesToGroup(USERGROUP1, "select_db1_tb1", "insert_db2_tb2")
+        .addPermissionsToRole("all_uri", "server=server1->uri=" + location)
+        .addRolesToGroup(USERGROUP2, "select_db1_tb1", "all_uri");
+    writePolicyFile(policyFile);
+
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    assertSemanticException(statement, "insert overwrite directory '" + 
location + "' select * from " + DB1 + ".tb1");
+    statement.execute("insert overwrite table " + DB2 + ".tb2 select * from " 
+ DB1 + ".tb1");
+    statement.close();
+    connection.close();
+
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("insert overwrite directory '" + location + "' select * 
from " + DB1 + ".tb1" );
+    assertSemanticException(statement, "insert overwrite table " + DB2 + ".tb2 
select * from " + DB1 + ".tb1");
+    statement.close();
+    connection.close();
+  }
+
+  @Test
+  public void testFullyQualifiedTableName() throws Exception{
+    Connection connection;
+    Statement statement;
+    connection = context.createConnection(ADMIN1);
+    statement = context.createStatement(connection);
+    statement.execute("create database " + DB1);
+    statement.execute("create table " + DB1 + ".tb1(a int)");
+    statement.execute("DROP table " + DB1 + ".tb1");
+    statement.execute("create table " + DB1 + ".tb1(a int)");
+    statement.execute("use " + DB1);
+    statement.execute("drop table tb1");
+  }
+
+  @Test
+  public void testExternalTables() throws Exception{
+    createDb(ADMIN1, DB1);
+    File externalTblDir = new File(dataDir, "exttab");
+    assertTrue("Unable to create directory for external table test" , 
externalTblDir.mkdir());
+
+    policyFile
+        .addPermissionsToRole("create_db1", privileges.get("create_db1"))
+        .addPermissionsToRole("all_uri", "server=server1->uri=file://" + 
dataDir.getPath())
+        .addRolesToGroup(USERGROUP1, "create_db1", "all_uri")
+        .addRolesToGroup(USERGROUP2, "create_db1");
+    writePolicyFile(policyFile);
+
+    Connection connection = context.createConnection(USER2_1);
+    Statement statement = context.createStatement(connection);
+    assertSemanticException(statement, "create external table " + DB1 + 
".tb1(a int) stored as " +
+        "textfile location 'file:" + externalTblDir.getAbsolutePath() + "'");
+    //Create external table on HDFS
+    assertSemanticException(statement, "create external table " + DB1 + 
".tb2(a int) location '/user/hive/warehouse/blah'");
+    statement.close();
+    connection.close();
+
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("create external table " + DB1 + ".tb1(a int) stored as 
" +
+        "textfile location 'file:" + externalTblDir.getAbsolutePath() + "'");
+    statement.close();
+    connection.close();
+
+
+  }
+
+  @Test
+  public void testCaseSensitivity() throws Exception {
+    Statement statement = null;
+    Connection connection = null;
+    try {
+      createDb(ADMIN1, DB1);
+      String scratchLikeDir = 
context.getProperty(HiveConf.ConfVars.SCRATCHDIR.varname);
+      String extParentDir = dfs.assertCreateDir(scratchLikeDir + 
"/ABC/hhh").toUri().toString();
+      String extTableDir = dfs.assertCreateDir(scratchLikeDir + 
"/abc/hhh").toUri().toString();
+      LOGGER.info("Created extParentDir = " + extParentDir + ", extTableDir = 
" + extTableDir);
+      policyFile
+          .addPermissionsToRole("all_db1", privileges.get("all_db1"))
+          .addPermissionsToRole("all_uri", "server=server1->uri=" + 
extParentDir)
+          .addRolesToGroup(USERGROUP1, "all_db1", "all_uri");
+      writePolicyFile(policyFile);
+      connection = context.createConnection(USER1_1);
+      statement = context.createStatement(connection);
+      assertSemanticException(statement,
+          "create external table " + DB1 + ".tb1(a int) location '" + 
extTableDir + "'");
+    } finally {
+      if (statement != null) {
+        statement.close();
+      }
+      if (connection != null) {
+        connection.close();
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDBConfiguration.java
----------------------------------------------------------------------
diff --git 
a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDBConfiguration.java
 
b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDBConfiguration.java
new file mode 100644
index 0000000..985f969
--- /dev/null
+++ 
b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDBConfiguration.java
@@ -0,0 +1,408 @@
+/*
+ * 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.tests.e2e.hive;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.apache.sentry.policy.db.SimpleDBPolicyEngine;
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+/**
+ * Test privileges per database policy files
+ */
+public class TestPerDBConfiguration extends 
AbstractTestWithStaticConfiguration {
+
+  private static final String MULTI_TYPE_DATA_FILE_NAME = "emp.dat";
+  private static final String DB2_POLICY_FILE = "db2-policy-file.ini";
+
+  private static File dataFile;
+  private PolicyFile policyFile;
+  private static String prefix;
+
+  @BeforeClass
+  public static void setupTestStaticConfiguration() throws Exception {
+    AbstractTestWithStaticConfiguration.setupTestStaticConfiguration();
+  }
+
+  @Before
+  public void setup() throws Exception {
+    String hiveServer2 = System.getProperty("sentry.e2etest.hiveServer2Type", 
"InternalHiveServer2");
+    String policyOnHDFS = 
System.getProperty("sentry.e2etest.hive.policyOnHDFS", "true");
+    if(policyOnHDFS.trim().equalsIgnoreCase("true") && 
(hiveServer2.equals("UnmanagedHiveServer2") )){
+      String policyLocation = 
System.getProperty("sentry.e2etest.hive.policy.location", "/user/hive/sentry");
+      prefix = "hdfs://" + policyLocation + "/";
+    }else {
+      prefix = "file://" + context.getPolicyFile().getParent() + "/";
+    }
+
+    policyFile = super.setupPolicy();
+    super.setup();
+    prepareDBDataForTest();
+  }
+
+  protected static void prepareDBDataForTest() throws Exception {
+    // copy data file to test dir
+    dataDir = context.getDataDir();
+    dataFile = new File(dataDir, MULTI_TYPE_DATA_FILE_NAME);
+    FileOutputStream to = new FileOutputStream(dataFile);
+    Resources.copy(Resources.getResource(MULTI_TYPE_DATA_FILE_NAME), to);
+    to.close();
+
+    // setup db objects needed by the test
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+
+    statement.execute("DROP DATABASE IF EXISTS " + DB1 + " CASCADE");
+    statement.execute("CREATE DATABASE " + DB1);
+    statement.execute("USE " + DB1);
+    statement.execute("CREATE TABLE tbl1(B INT, A STRING) "
+        + " row format delimited fields terminated by '|'  stored as 
textfile");
+    statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' 
INTO TABLE tbl1");
+
+    statement.execute("DROP DATABASE IF EXISTS " + DB2 + " CASCADE");
+    statement.execute("CREATE DATABASE " + DB2);
+    statement.execute("USE " + DB2);
+    statement.execute("CREATE TABLE tbl2(B INT, A STRING) "
+        + " row format delimited fields terminated by '|'  stored as 
textfile");
+    statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' 
INTO TABLE tbl2");
+    statement.execute("CREATE TABLE tbl5(B INT, A STRING) "
+        + " row format delimited fields terminated by '|'  stored as 
textfile");
+
+    statement.execute("DROP DATABASE IF EXISTS db3 CASCADE");
+    statement.execute("CREATE DATABASE db3");
+    statement.execute("USE db3");
+    statement.execute("CREATE TABLE tbl3(B INT, A STRING) "
+        + " row format delimited fields terminated by '|'  stored as 
textfile");
+    statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' 
INTO TABLE tbl3");
+
+    statement.execute("DROP DATABASE IF EXISTS db4 CASCADE");
+    statement.execute("CREATE DATABASE db4");
+    statement.execute("USE db4");
+    statement.execute("CREATE TABLE tbl4(B INT, A STRING) "
+        + " row format delimited fields terminated by '|'  stored as 
textfile");
+    statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' 
INTO TABLE tbl4");
+    statement.close();
+    connection.close();
+  }
+
+  @After
+  public void teardown() throws Exception {
+    // one test turns this on so let's disable it in the teardown method
+    
System.setProperty(SimpleDBPolicyEngine.ACCESS_ALLOW_URI_PER_DB_POLICYFILE, 
"false");
+  }
+
+  @Test
+  public void testPerDB() throws Exception {
+    PolicyFile db2PolicyFile = new PolicyFile();
+    File db2PolicyFileHandle = new File(context.getPolicyFile().getParent(), 
DB2_POLICY_FILE);
+    db2PolicyFile
+        .addRolesToGroup(USERGROUP2, "select_tbl2")
+        .addPermissionsToRole("select_tbl2", "server=server1->db="  + DB2 + 
"->table=tbl2->action=select")
+        .write(db2PolicyFileHandle);
+
+    policyFile
+        .addRolesToGroup(USERGROUP1, "select_tbl1")
+        .addRolesToGroup(USERGROUP2, "select_tbl2")
+        .addPermissionsToRole("select_tbl1", "server=server1->db=" + DB1 
+"->table=tbl1->action=select")
+        .addDatabase(DB2, prefix + db2PolicyFileHandle.getName())
+        .setUserGroupMapping(StaticUserGroup.getStaticMapping())
+        .write(context.getPolicyFile());
+
+    // test execution
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE "  + DB1);
+    // test user1 can execute query on tbl1
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl1", 1, 12);
+
+    // user1 cannot query db2.tbl2
+    context.assertAuthzException(statement, "USE "  + DB2);
+    context.assertAuthzException(statement, "SELECT COUNT(*) FROM " + DB2 + 
".tbl2");
+    statement.close();
+    connection.close();
+
+    // test per-db file for db2
+
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("USE "  + DB2);
+    // test user2 can execute query on tbl2
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl2", 1, 12);
+
+    // user2 cannot query db1.tbl1
+    context.assertAuthzException(statement, "SELECT COUNT(*) FROM " + DB1 + 
".tbl1");
+    context.assertAuthzException(statement, "USE "  + DB1);
+
+    statement.close();
+    connection.close();
+
+  }
+
+  /**
+   * Multiple DB files with some containing badly formatted rules
+   * The privileges should work for good files
+   * No access for bad formatted ones
+   * @throws Exception
+   */
+  @Test
+  public void testMultiPerDBwithErrors() throws Exception {
+    String DB3_POLICY_FILE = "db3-policy-file.ini";
+    String DB4_POLICY_FILE = "db4-policy-file.ini";
+
+    File db2PolicyFileHandle = new File(context.getPolicyFile().getParent(), 
DB2_POLICY_FILE);
+    File db3PolicyFileHandle = new File(context.getPolicyFile().getParent(), 
DB3_POLICY_FILE);
+    File db4PolicyFileHandle = new File(context.getPolicyFile().getParent(), 
DB4_POLICY_FILE);
+
+    PolicyFile db2PolicyFile = new PolicyFile();
+    PolicyFile db3PolicyFile = new PolicyFile();
+    PolicyFile db4PolicyFile = new PolicyFile();
+    db2PolicyFile
+        .addRolesToGroup(USERGROUP2, "select_tbl2")
+        .addPermissionsToRole("select_tbl2", "server=server1->db="  + DB2 + 
"->table=tbl2->action=select")
+        .write(db2PolicyFileHandle);
+    db3PolicyFile
+        .addRolesToGroup(USERGROUP3, "select_tbl3_BAD")
+        .addPermissionsToRole("select_tbl3_BAD", 
"server=server1->db=db3------>table->action=select")
+        .write(db3PolicyFileHandle);
+    db4PolicyFile
+        .addRolesToGroup(USERGROUP4, "select_tbl4")
+        .addPermissionsToRole("select_tbl4", 
"server=server1->db=db4->table=tbl4->action=select")
+        .write(db4PolicyFileHandle);
+    policyFile
+        .addRolesToGroup(USERGROUP1, "select_tbl1")
+        .addRolesToGroup(USERGROUP2, "select_tbl2")
+        .addPermissionsToRole("select_tbl1", "server=server1->db=" + DB1 
+"->table=tbl1->action=select")
+        .addDatabase(DB2, prefix + db2PolicyFileHandle.getName())
+        .addDatabase("db3", prefix + db3PolicyFileHandle.getName())
+        .addDatabase("db4", prefix + db4PolicyFileHandle.getName())
+        .setUserGroupMapping(StaticUserGroup.getStaticMapping())
+        .write(context.getPolicyFile());
+
+    // test execution
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE "  + DB1);
+    // test user1 can execute query on tbl1
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl1", 1, 12);
+    connection.close();
+
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("USE "  + DB2);
+    // test user1 can execute query on tbl1
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl2", 1, 12);
+    connection.close();
+
+    // verify no access to db3 due to badly formatted rule in db3 policy file
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    context.assertAuthzException(statement, "USE db3");
+    // test user1 can execute query on tbl1
+    context.assertAuthzException(statement, "SELECT COUNT(*) FROM db3.tbl3");
+    connection.close();
+
+    connection = context.createConnection(USER4_1);
+    statement = context.createStatement(connection);
+    statement.execute("USE db4");
+    // test user1 can execute query on tbl1
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl4", 1, 12);
+    connection.close();
+  }
+
+  @Test
+  public void testPerDBPolicyFileWithURI() throws Exception {
+    File db2PolicyFileHandle = new File(context.getPolicyFile().getParent(), 
DB2_POLICY_FILE);
+    PolicyFile db2PolicyFile = new PolicyFile();
+    db2PolicyFile
+        .addRolesToGroup(USERGROUP2, "select_tbl5", "data_read", "insert_tbl5")
+        .addPermissionsToRole("select_tbl5",
+            "server=server1->db=" + DB2 + "->table=tbl5->action=select")
+        .addPermissionsToRole("insert_tbl5",
+            "server=server1->db=" + DB2 + "->table=tbl5->action=insert")
+        .addPermissionsToRole("data_read", "server=server1->URI=file://" + 
dataFile)
+        .write(db2PolicyFileHandle);
+
+    policyFile
+        .addRolesToGroup(USERGROUP1, "select_tbl1")
+        .addRolesToGroup(USERGROUP2, "select_tbl5")
+        .addPermissionsToRole("select_tbl1", "server=server1->db=" + DB1 
+"->table=tbl1->action=select")
+        .addDatabase(DB2, prefix + db2PolicyFileHandle.getName())
+        .setUserGroupMapping(StaticUserGroup.getStaticMapping())
+        .write(context.getPolicyFile());
+
+    // ugly hack: needs to go away once this becomes a config property. Note 
that this property
+    // will not be set with external HS and this test will fail. Hope is this 
fix will go away
+    // by then.
+    
System.setProperty(SimpleDBPolicyEngine.ACCESS_ALLOW_URI_PER_DB_POLICYFILE, 
"true");
+    // test execution
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE "  + DB1);
+    // test user1 can execute query on tbl1
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl1", 1, 12);
+
+    // user1 cannot query db2.tbl5
+    context.assertAuthzException(statement, "USE "  + DB2);
+    context.assertAuthzException(statement, "SELECT COUNT(*) FROM " + DB2 + 
".tbl5");
+    statement.close();
+    connection.close();
+
+    // test per-db file for db2
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("USE "  + DB2);
+    // test user2 can execute query on tbl5
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl5", 1, 0);
+
+    // verify user2 can execute LOAD
+    statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' 
INTO TABLE tbl5");
+
+    // user2 cannot query db1.tbl1
+    context.assertAuthzException(statement, "SELECT COUNT(*) FROM " + DB1 + 
".tbl1");
+    context.assertAuthzException(statement, "USE "  + DB1);
+
+    // once we disable this property all queries should fail
+    
System.setProperty(SimpleDBPolicyEngine.ACCESS_ALLOW_URI_PER_DB_POLICYFILE, 
"false");
+    context.assertAuthzException(statement, "USE "  + DB2);
+
+    // re-enable for clean
+    
System.setProperty(SimpleDBPolicyEngine.ACCESS_ALLOW_URI_PER_DB_POLICYFILE, 
"true");
+
+    statement.close();
+    connection.close();
+  }
+
+  /**
+   * Test 'use default' statement. It should work as long as the user as 
privilege to assess any object in system
+   * @throws Exception
+   */
+  @Test
+  public void testDefaultDb() throws Exception {
+    policyFile
+        .addRolesToGroup(USERGROUP1, "select_tbl1")
+        .addPermissionsToRole("select_tbl1", "server=server1->db=" + DB1 
+"->table=tbl1->action=select")
+        .setUserGroupMapping(StaticUserGroup.getStaticMapping())
+        .write(context.getPolicyFile());
+
+    // user_1 should be able to access default
+    Connection connection = context.createConnection(USER1_1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE default");
+    statement.close();
+    connection.close();
+
+    // user_2 should NOT be able to access default since it does have access 
to any other object
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    context.assertAuthzException(statement, "USE default");
+    statement.close();
+    connection.close();
+
+  }
+
+  @Test
+  public void testDefaultDBwithDbPolicy() throws Exception {
+    File db2PolicyFileHandle = new File(context.getPolicyFile().getParent(), 
DB2_POLICY_FILE);
+    File defaultPolicyFileHandle = new 
File(context.getPolicyFile().getParent(), "default.ini");
+
+    policyFile
+        .addRolesToGroup(USERGROUP1, "select_tbl1")
+        .addRolesToGroup(USERGROUP2, "select_tbl2")
+        .addPermissionsToRole("select_tbl1", "server=server1->db=" + DB1 
+"->table=tbl1->action=select")
+        .addDatabase(DB2, prefix + db2PolicyFileHandle.getName())
+        .addDatabase("default", prefix + defaultPolicyFileHandle.getName())
+        .setUserGroupMapping(StaticUserGroup.getStaticMapping())
+        .write(context.getPolicyFile());
+
+    PolicyFile db2PolicyFile = new PolicyFile();
+    db2PolicyFile
+        .addRolesToGroup(USERGROUP2, "select_tbl2")
+        .addPermissionsToRole("select_tbl2", "server=server1->db="  + DB2 + 
"->table=tbl2->action=select")
+        .write(db2PolicyFileHandle);
+
+    PolicyFile defaultPolicyFile = new PolicyFile();
+    defaultPolicyFile
+        .addRolesToGroup(USERGROUP2, "select_def")
+        .addPermissionsToRole("select_def", 
"server=server1->db=default->table=dtab->action=select")
+        .write(defaultPolicyFileHandle);
+
+    // setup db objects needed by the test
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE default");
+    statement.execute("DROP TABLE IF EXISTS dtab");
+    statement.execute("CREATE TABLE dtab(B INT, A STRING) "
+        + " row format delimited fields terminated by '|'  stored as 
textfile");
+    // user_1 should be able to switch to default, but not the tables from 
default
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    statement.execute("USE "  + DB1);
+    statement.execute("USE default");
+    context.assertAuthzException(statement, "SELECT * FROM dtab");
+    statement.execute("USE "  + DB1);
+    context.assertAuthzException(statement, "SELECT * FROM default.dtab");
+
+    statement.close();
+    connection.close();
+
+    // user_2 should be able to access default and select from default's tables
+    connection = context.createConnection(USER2_1);
+    statement = context.createStatement(connection);
+    statement.execute("USE "  + DB2);
+    statement.execute("USE default");
+    statement.execute("SELECT * FROM dtab");
+    statement.execute("USE "  + DB2);
+    statement.execute("SELECT * FROM default.dtab");
+    statement.close();
+    connection.close();
+
+    // user_3 should NOT be able to switch to default since it doesn't have 
access to any objects
+    connection = context.createConnection(USER3_1);
+    statement = context.createStatement(connection);
+    context.assertAuthzException(statement, "USE default");
+    statement.close();
+    connection.close();
+  }
+
+  private void verifyCount(Statement statement, String query, int 
exceptedCountRows,
+      int exceptedCount) throws SQLException {
+    ResultSet resultSet = statement.executeQuery(query);
+    int count = 0;
+    int countRows = 0;
+
+    while (resultSet.next()) {
+      count = resultSet.getInt(1);
+      countRows++;
+    }
+    assertTrue("Incorrect row count:" + countRows, countRows == 
exceptedCountRows);
+    assertTrue("Incorrect result:" + count, count == exceptedCount);
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/bfb354f2/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDatabasePolicyFile.java
----------------------------------------------------------------------
diff --git 
a/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDatabasePolicyFile.java
 
b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDatabasePolicyFile.java
new file mode 100644
index 0000000..c8712e7
--- /dev/null
+++ 
b/sentry-tests/sentry-tests-hive-v2/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDatabasePolicyFile.java
@@ -0,0 +1,118 @@
+/*
+ * 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.tests.e2e.hive;
+
+import com.google.common.io.Resources;
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.sql.Connection;
+import java.sql.Statement;
+
+public class TestPerDatabasePolicyFile extends 
AbstractTestWithStaticConfiguration {
+  private static final String SINGLE_TYPE_DATA_FILE_NAME = "kv1.dat";
+  private PolicyFile policyFile;
+  private File dataDir;
+  private File dataFile;
+
+  @Before
+  public void setup() throws Exception {
+    policyFile = PolicyFile.setAdminOnServer1(ADMINGROUP);
+    writePolicyFile(policyFile);
+    dataDir = context.getDataDir();
+    dataFile = new File(dataDir, SINGLE_TYPE_DATA_FILE_NAME);
+    FileOutputStream to = new FileOutputStream(dataFile);
+    Resources.copy(Resources.getResource(SINGLE_TYPE_DATA_FILE_NAME), to);
+    to.close();
+  }
+
+  private void createSampleDbTable(Statement statement, String db, String 
table)
+      throws Exception {
+    statement.execute("DROP DATABASE IF EXISTS " + db + " CASCADE");
+    statement.execute("CREATE DATABASE " + db);
+    statement.execute("USE " + db);
+    statement.execute("CREATE TABLE " + table + "(a STRING)");
+    statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' 
INTO TABLE " + table);
+
+  }
+
+  /**
+   * Ensure that db specific file cannot grant to other db
+   */
+  @Test
+  public void testDbSpecificFileGrantsToOtherDb() throws Exception {
+    doTestDbSpecificFileGrants("server=server1->db=" + DB1);
+  }
+  /**
+   * Ensure that db specific file cannot grant to all db
+   */
+  @Test
+  public void testDbSpecificFileGrantsToAllDb() throws Exception {
+    doTestDbSpecificFileGrants("server=server1");
+  }
+  /**
+   * Ensure that db specific file cannot grant to all servers
+   */
+  @Test
+  public void testDbSpecificFileGrantsToAllServers() throws Exception {
+    doTestDbSpecificFileGrants("server=*");
+  }
+  /**
+   * Ensure that db specific file cannot grant to all
+   */
+  @Test
+  public void testDbSpecificFileGrantsToAll() throws Exception {
+    doTestDbSpecificFileGrants("*");
+  }
+
+  public void doTestDbSpecificFileGrants(String grant) throws Exception {
+
+    policyFile
+        .setUserGroupMapping(StaticUserGroup.getStaticMapping());
+    writePolicyFile(policyFile);
+
+
+    // setup db objects needed by the test
+    Connection connection = context.createConnection(ADMIN1);
+    Statement statement = context.createStatement(connection);
+    createSampleDbTable(statement, DB1, "tbl1");
+    createSampleDbTable(statement, DB2, "tbl1");
+    statement.close();
+    connection.close();
+
+    File specificPolicyFileFile = new File(baseDir, "db2-policy.ini");
+
+    PolicyFile specificPolicyFile = new PolicyFile()
+    .addPermissionsToRole("db1_role", grant)
+    .addRolesToGroup("group1", "db1_role");
+    specificPolicyFile.write(specificPolicyFileFile);
+
+    policyFile.addDatabase(DB2, specificPolicyFileFile.getPath());
+    writePolicyFile(policyFile);
+
+    // test execution
+    connection = context.createConnection(USER1_1);
+    statement = context.createStatement(connection);
+    // test user can query table
+    context.assertAuthzException(statement, "USE " + DB1);
+    context.assertAuthzException(statement, "SELECT COUNT(a) FROM " + DB1 + 
".tbl1");
+  }
+}
\ No newline at end of file

Reply via email to