You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by sh...@apache.org on 2013/09/21 01:38:57 UTC

[8/9] SENTRY-16: Move sentry-tests to sentry-tests-hive package (Gregory Chanan via Shreepadma Venugopalan)

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestEndToEnd.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestEndToEnd.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestEndToEnd.java
new file mode 100644
index 0000000..8a32e5f
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestEndToEnd.java
@@ -0,0 +1,143 @@
+/*
+ * 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.Statement;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+public class TestEndToEnd extends AbstractTestWithStaticLocalFS {
+  private Context context;
+  private final String SINGLE_TYPE_DATA_FILE_NAME = "kv1.dat";
+  private File dataFile;
+  private PolicyFile policyFile;
+
+
+  @Before
+  public void setup() throws Exception {
+    context = createContext();
+    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.createAdminOnServer1(ADMIN1);
+
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if (context != null) {
+      context.close();
+    }
+  }
+
+  /**
+   * Steps:
+   * 1. admin create a new experimental database
+   * 2. admin create a new production database, create table, load data
+   * 3. admin create new user group, and add user into it
+   * 4. admin grant privilege all@'experimental database' to group
+   * 5. user create table, load data in experimental DB
+   * 6. user create view based on table in experimental DB
+   * 7. admin create table (same name) in production DB
+   * 8. admin grant read@productionDB.table to group
+   *    admin grant select@productionDB.table to group
+   * 9. user load data from experimental table to production table
+   */
+  @Test
+  public void testEndToEnd1() throws Exception {
+    policyFile.write(context.getPolicyFile());
+
+    String dbName1 = "db_1";
+    String dbName2 = "productionDB";
+    String tableName1 = "tb_1";
+    String tableName2 = "tb_2";
+    String viewName1 = "view_1";
+    Connection connection = context.createConnection("admin1", "foo");
+    Statement statement = context.createStatement(connection);
+    // 1
+    statement.execute("DROP DATABASE IF EXISTS " + dbName1 + " CASCADE");
+    statement.execute("CREATE DATABASE " + dbName1);
+    // 2
+    statement.execute("DROP DATABASE IF EXISTS " + dbName2 + " CASCADE");
+    statement.execute("CREATE DATABASE " + dbName2);
+    statement.execute("USE " + dbName2);
+    statement.execute("DROP TABLE IF EXISTS " + dbName2 + "." + tableName2);
+    statement.execute("create table " + dbName2 + "." + tableName2
+        + " (under_col int comment 'the under column', value string)");
+    statement.execute("load data local inpath '" + dataFile.getPath()
+            + "' into table " + tableName2);
+    statement.close();
+    connection.close();
+
+    // 3
+    policyFile.addGroupsToUser("user1", "group1");
+
+    // 4
+    policyFile
+        .addRolesToGroup("group1", "all_db1", "data_uri", "select_tb1", "insert_tb1")
+        .addPermissionsToRole("all_db1", "server=server1->db=db_1")
+        .addPermissionsToRole("select_tb1", "server=server1->db=productionDB->table=tb_1->action=select")
+        .addPermissionsToRole("insert_tb2", "server=server1->db=productionDB->table=tb_2->action=insert")
+        .addPermissionsToRole("insert_tb1", "server=server1->db=productionDB->table=tb_2->action=insert")
+        .addPermissionsToRole("data_uri", "server=server1->uri=file://" + dataDir.getPath());
+    policyFile.write(context.getPolicyFile());
+
+    // 5
+    connection = context.createConnection("user1", "foo");
+    statement = context.createStatement(connection);
+    statement.execute("USE " + dbName1);
+    statement.execute("DROP TABLE IF EXISTS " + dbName1 + "." + tableName1);
+    statement.execute("create table " + dbName1 + "." + tableName1
+        + " (under_col int comment 'the under column', value string)");
+    statement.execute("load data local inpath '" + dataFile.getPath()
+            + "' into table " + tableName1);
+    // 6
+    statement.execute("CREATE VIEW " + viewName1 + " (value) AS SELECT value from " + tableName1 + " LIMIT 10");
+    statement.close();
+    connection.close();
+
+    // 7
+    connection = context.createConnection("admin1", "foo");
+    statement = context.createStatement(connection);
+    statement.execute("USE " + dbName2);
+    statement.execute("DROP TABLE IF EXISTS " + dbName1 + "." + tableName1);
+    statement.execute("create table " + dbName1 + "." + tableName1
+        + " (under_col int comment 'the under column', value string)");
+    statement.close();
+    connection.close();
+
+    // 9
+    connection = context.createConnection("user1", "foo");
+    statement = context.createStatement(connection);
+    statement.execute("USE " + dbName2);
+    statement.execute("INSERT OVERWRITE TABLE " +
+        dbName2 + "." + tableName2 + " SELECT * FROM " + dbName1
+        + "." + tableName1);
+    statement.close();
+    connection.close();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestExportImportPrivileges.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestExportImportPrivileges.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestExportImportPrivileges.java
new file mode 100644
index 0000000..c2403f8
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestExportImportPrivileges.java
@@ -0,0 +1,154 @@
+/*
+ * 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.Statement;
+
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+public class TestExportImportPrivileges extends AbstractTestWithStaticDFS {
+  private File dataFile;
+  private PolicyFile policyFile;
+
+  @Before
+  public void setup() throws Exception {
+    context = createContext();
+    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.createAdminOnServer1(ADMIN1);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if (context != null) {
+      context.close();
+    }
+  }
+
+  @Test
+  public void testInsertToDirPrivileges() throws Exception {
+    Connection connection = null;
+    Statement statement = null;
+    String dumpDir = context.getDFSUri().toString() + "/hive_data_dump";
+
+    policyFile
+        .addRolesToGroup("user_group1", "db1_read", "db1_write", "data_dump")
+        .addRolesToGroup("user_group2", "db1_read", "db1_write")
+        .addPermissionsToRole("db1_write", "server=server1->db=" + DB1 + "->table=" + TBL1 + "->action=INSERT")
+        .addPermissionsToRole("db1_read", "server=server1->db=" + DB1 + "->table=" + TBL1 + "->action=SELECT")
+        .addPermissionsToRole("data_dump", "server=server1->URI=" + dumpDir)
+        .addGroupsToUser("user1", "user_group1")
+        .addGroupsToUser("user2", "user_group2");
+    policyFile.write(context.getPolicyFile());
+
+    dropDb(ADMIN1, DB1);
+    createDb(ADMIN1, DB1);
+    createTable(ADMIN1, DB1, dataFile, TBL1);
+
+    // Negative test, user2 doesn't have access to write to dir
+    connection = context.createConnection(USER2, "password");
+    statement = context.createStatement(connection);
+    statement.execute("use " + DB1);
+    context.assertAuthzException(statement, "INSERT OVERWRITE DIRECTORY '" + dumpDir + "' SELECT * FROM " + TBL1);
+    statement.close();
+    connection.close();
+
+    // Negative test, user2 doesn't have access to dir that's similar to scratch dir
+    String scratchDumpDir = context.getProperty(HiveConf.ConfVars.SCRATCHDIR.varname) + "_foo" + "/bar";
+    connection = context.createConnection(USER2, "password");
+    statement = context.createStatement(connection);
+    statement.execute("use " + DB1);
+    context.assertAuthzException(statement, "INSERT OVERWRITE DIRECTORY '" + scratchDumpDir + "' SELECT * FROM " + TBL1);
+    statement.close();
+    connection.close();
+
+    // positive test, user1 has access to write to dir
+    connection = context.createConnection(USER1, "password");
+    statement = context.createStatement(connection);
+    statement.execute("use " + DB1);
+    assertTrue(statement.executeQuery("SELECT * FROM " + TBL1).next());
+    statement.execute("INSERT OVERWRITE DIRECTORY '" + dumpDir + "' SELECT * FROM " + TBL1);
+  }
+
+  @Test
+  public void testExportImportPrivileges() throws Exception {
+    Connection connection = null;
+    Statement statement = null;
+    String exportDir = context.getDFSUri().toString() + "/hive_export1";
+
+    policyFile
+        .addRolesToGroup("user_group1", "tab1_read", "tab1_write", "db1_all", "data_read", "data_export")
+        .addRolesToGroup("user_group2", "tab1_write", "tab1_read")
+        .addPermissionsToRole("tab1_write", "server=server1->db=" + DB1 + "->table=" + TBL1 + "->action=INSERT")
+        .addPermissionsToRole("tab1_read", "server=server1->db=" + DB1 + "->table=" + TBL1 + "->action=SELECT")
+        .addPermissionsToRole("db1_all", "server=server1->db=" + DB1)
+        .addPermissionsToRole("data_read", "server=server1->URI=file://" + dataFile.getPath())
+        .addPermissionsToRole("data_export", "server=server1->URI=" + exportDir)
+        .addGroupsToUser("user1", "user_group1")
+        .addGroupsToUser("user2", "user_group2");
+    policyFile.write(context.getPolicyFile());
+
+    dropDb(ADMIN1, DB1);
+    createDb(ADMIN1, DB1);
+    createTable(ADMIN1, DB1, dataFile, TBL1);
+
+    // Negative test, user2 doesn't have access to the file being loaded
+    connection = context.createConnection(USER2, "password");
+    statement = context.createStatement(connection);
+    statement.execute("use " + DB1);
+    context.assertAuthzException(statement, "EXPORT TABLE " + TBL1 + " TO '" + exportDir + "'");
+    statement.close();
+    connection.close();
+
+    // Positive test, user1 have access to the target directory
+    connection = context.createConnection(USER1, "password");
+    statement = context.createStatement(connection);
+    statement.execute("use " + DB1);
+    statement.execute("EXPORT TABLE " + TBL1 + " TO '" + exportDir + "'");
+    statement.close();
+    connection.close();
+
+    // Negative test, user2 doesn't have access to the directory loading from
+    connection = context.createConnection(USER2, "password");
+    statement = context.createStatement(connection);
+    statement.execute("use " + DB1);
+    context.assertAuthzException(statement, "IMPORT TABLE " + TBL2 + " FROM '" + exportDir + "'");
+    statement.close();
+    connection.close();
+
+    // Positive test, user1 have access to the target directory
+    connection = context.createConnection(USER1, "password");
+    statement = context.createStatement(connection);
+    statement.execute("use " + DB1);
+    statement.execute("IMPORT TABLE " + TBL2 + " FROM '" + exportDir + "'");
+    statement.close();
+    connection.close();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataObjectRetrieval.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataObjectRetrieval.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataObjectRetrieval.java
new file mode 100644
index 0000000..a16db9b
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataObjectRetrieval.java
@@ -0,0 +1,453 @@
+/*
+ * 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.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.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+public class TestMetadataObjectRetrieval extends
+AbstractTestWithStaticLocalFS {
+  private PolicyFile policyFile;
+  private File dataFile;
+
+  @Before
+  public void setup() throws Exception {
+    policyFile = PolicyFile.createAdminOnServer1(ADMIN1);
+    context = createContext();
+    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();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if (context != null) {
+      context.close();
+    }
+  }
+
+  /**
+   * Method called to run positive tests:
+   *  describe table
+   *  describe table column
+   *  show columns from table
+   *  show create table table
+   *  show tblproperties table
+   *
+   * The table is assumed to have two colums under_col int and value string.
+   */
+  private void positiveDescribeShowTests(String user, String db, String table) throws Exception {
+    Connection connection = context.createConnection(user, "password");
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE " + db);
+    ResultSet rs = statement.executeQuery("DESCRIBE " + table);
+    assertTrue(rs.next());
+    
+    assertTrue("describe table fail", rs.getString(1).trim().equals("under_col"));
+    assertTrue("describe table fail", rs.getString(2).trim().equals("int"));
+    assertTrue(rs.next());
+    assertTrue("describe table fail", rs.getString(1).trim().equals("value"));
+    assertTrue("describe table fail", rs.getString(2).trim().equals("string"));
+
+    rs = statement.executeQuery("DESCRIBE " + table + " under_col");
+    assertTrue(rs.next());
+    assertTrue("describe table fail", rs.getString(1).trim().equals("under_col"));
+    assertTrue("describe table fail", rs.getString(2).trim().equals("int"));
+
+    rs = statement.executeQuery("DESCRIBE " + table + " value");
+    assertTrue(rs.next());
+    assertTrue("describe table fail", rs.getString(1).trim().equals("value"));
+    assertTrue("describe table fail", rs.getString(2).trim().equals("string"));
+
+    rs = statement.executeQuery("SHOW COLUMNS FROM " + table);
+    assertTrue(rs.next());
+    assertTrue("show columns from fail", rs.getString(1).trim().equals("under_col"));
+    assertTrue(rs.next());
+    assertTrue("show columns from fail", rs.getString(1).trim().equals("value"));
+
+    rs = statement.executeQuery("SHOW CREATE TABLE " + table);
+    assertTrue("SHOW CREATE TABLE fail", rs.next());
+
+    rs = statement.executeQuery("SHOW TBLPROPERTIES " + table);
+    assertTrue("SHOW TBLPROPERTIES fail", rs.next());
+
+    statement.close();
+    connection.close();
+  }
+  /**
+   * Method called to run negative tests:
+   *  describe table
+   *  describe table column
+   *  show columns from table
+   *  show create table table
+   *  show tblproperties table
+   *
+   * The table is assumed to have two columns under_col int and value string.
+   */
+  private void negativeDescribeShowTests(String user, String db, String table) throws Exception {
+    Connection connection = context.createConnection(user, "password");
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE " + db);
+    context.assertAuthzException(statement, "DESCRIBE " + table);
+    context.assertAuthzException(statement, "DESCRIBE " + table + " under_col");
+    context.assertAuthzException(statement, "DESCRIBE " + table + " value");
+    context.assertAuthzException(statement, "SHOW COLUMNS FROM " + table);
+    context.assertAuthzException(statement, "SHOW CREATE TABLE " + table);
+    context.assertAuthzException(statement, "SHOW TBLPROPERTIES " + table);
+    statement.close();
+    connection.close();
+  }
+
+
+  /**
+   * Tests to ensure a user with all on server,
+   * insert|select on table can view metadata while
+   * a user with all on a different table cannot
+   * view the metadata.
+
+   * Test both positive and negative of:
+   *  describe table
+   *  describe table column
+   *  show columns from table
+   *  show create table table
+   *  show tblproperties table
+   *
+   * Positive tests are run with:
+   *  all@server
+   *  select@table
+   *  insert@table
+   * Negative tests are run three times:
+   *  none
+   *  insert@different table
+   */
+  @Test
+  public void testAllOnServerSelectInsertNegativeNoneAllOnDifferentTable()
+      throws Exception {
+    policyFile
+    .addPermissionsToRole(GROUP1_ROLE, "server=server1->db=" + DB1 + "->table=" + TBL2)
+    .addRolesToGroup(GROUP1, GROUP1_ROLE)
+    .addGroupsToUser(USER1, GROUP1)
+    .write(context.getPolicyFile());
+    dropDb(ADMIN1, DB1);
+    createDb(ADMIN1, DB1);
+    createTable(ADMIN1, DB1, dataFile, TBL1);
+    positiveDescribeShowTests(ADMIN1, DB1, TBL1);
+    negativeDescribeShowTests(USER1, DB1, TBL1);
+    policyFile
+    .addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_TBL1)
+    .write(context.getPolicyFile());
+    positiveDescribeShowTests(USER1, DB1, TBL1);
+    policyFile.removePermissionsFromRole(GROUP1_ROLE, SELECT_DB1_TBL1);
+    policyFile
+    .addPermissionsToRole(GROUP1_ROLE, INSERT_DB1_TBL1)
+    .write(context.getPolicyFile());
+    positiveDescribeShowTests(USER1, DB1, TBL1);
+  }
+
+  /**
+   * Tests to ensure that a user is able to view metadata
+   * with all on db
+   *
+   * Test positive:
+   *  describe table
+   *  describe table column
+   *  show columns from table
+   *  show create table table
+   *  show tblproperties table
+   *
+   * Positive tests are run twice:
+   *  all@server
+   *  all@db
+   */
+  @Test
+  public void testAllOnServerAndAllOnDb() throws Exception {
+    policyFile
+    .addPermissionsToRole(GROUP1_ROLE, "server=server1->db=" + DB1)
+    .addRolesToGroup(GROUP1, GROUP1_ROLE)
+    .addGroupsToUser(USER1, GROUP1)
+    .write(context.getPolicyFile());
+    dropDb(ADMIN1, DB1);
+    createDb(ADMIN1, DB1);
+    createTable(ADMIN1, DB1, dataFile, TBL1);
+    positiveDescribeShowTests(ADMIN1, DB1, TBL1);
+    positiveDescribeShowTests(USER1, DB1, TBL1);
+  }
+
+  /**
+   * Test to ensure that all on view do not result in
+   * metadata privileges on the underlying table
+   *
+   * Test both positive and negative of:
+   *  describe table
+   *  describe table column
+   *  show columns from table
+   *  show create table table
+   *  show tblproperties table
+   *
+   * Positive tests are run with all@server
+   * Negative tests are run three times:
+   *  none
+   *  all@view
+   */
+  @Test
+  public void testAllOnServerNegativeAllOnView() throws Exception {
+    policyFile
+    .addPermissionsToRole(GROUP1_ROLE, "server=server1->db=" + DB1 + "->table=" + VIEW1)
+    .addRolesToGroup(GROUP1, GROUP1_ROLE)
+    .addGroupsToUser(USER1, GROUP1)
+    .write(context.getPolicyFile());
+    dropDb(ADMIN1, DB1);
+    createDb(ADMIN1, DB1);
+    createTable(ADMIN1, DB1, dataFile, TBL1);
+    Connection connection = context.createConnection(ADMIN1, "password");
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE " + DB1);
+    statement.execute("DROP VIEW IF EXISTS " + VIEW1);
+    statement.execute("CREATE VIEW " + VIEW1 + " (value) AS SELECT value from " + TBL1 + " LIMIT 10");
+    positiveDescribeShowTests(ADMIN1, DB1, TBL1);
+    statement.close();
+    connection.close();
+    negativeDescribeShowTests(USER1, DB1, TBL1);
+  }
+
+  /**
+   * Tests to ensure that a user is able to view metadata
+   * with all on table
+   *
+   * Test positive:
+   *  describe table
+   *  describe table column
+   *  show columns from table
+   *  show create table table
+   *  show tblproperties table
+   *
+   * Positive tests are run twice:
+   *  all@server
+   *  all@table
+   */
+  @Test
+  public void testAllOnServerAndAllOnTable() throws Exception {
+    policyFile
+    .addPermissionsToRole(GROUP1_ROLE, "server=server1->db=" + DB1 + "->table=" + TBL1)
+    .addRolesToGroup(GROUP1, GROUP1_ROLE)
+    .addGroupsToUser(USER1, GROUP1)
+    .write(context.getPolicyFile());
+    dropDb(ADMIN1, DB1);
+    createDb(ADMIN1, DB1);
+    createTable(ADMIN1, DB1, dataFile, TBL1);
+    positiveDescribeShowTests(ADMIN1, DB1, TBL1);
+    positiveDescribeShowTests(USER1, DB1, TBL1);
+  }
+
+
+  /**
+   * Tests that admin and all@db can describe database
+   * and describe database extended. Also tests that a user
+   * with no privileges on a db cannot describe database.
+   */
+  @Test
+  public void testDescribeDatabasesWithAllOnServerAndAllOnDb()
+      throws Exception {
+    policyFile
+    .addPermissionsToRole(GROUP1_ROLE, "server=server1->db=" + DB1)
+    .addRolesToGroup(GROUP1, GROUP1_ROLE)
+    .addGroupsToUser(USER1, GROUP1)
+    .write(context.getPolicyFile());
+    dropDb(ADMIN1, DB1, DB2);
+    createDb(ADMIN1, DB1, DB2);
+    createTable(ADMIN1, DB1, dataFile, TBL1);
+
+    Connection connection = context.createConnection(ADMIN1, "password");
+    Statement statement = context.createStatement(connection);
+    assertTrue(statement.executeQuery("DESCRIBE DATABASE " + DB1).next());
+    assertTrue(statement.executeQuery("DESCRIBE DATABASE EXTENDED " + DB1).next());
+    statement.close();
+    connection.close();
+
+    connection = context.createConnection(USER1, "password");
+    statement = context.createStatement(connection);
+    assertTrue(statement.executeQuery("DESCRIBE DATABASE " + DB1).next());
+    assertTrue(statement.executeQuery("DESCRIBE DATABASE EXTENDED " + DB1).next());
+    context.assertAuthzException(statement, "DESCRIBE DATABASE " + DB2);
+    context.assertAuthzException(statement, "DESCRIBE DATABASE EXTENDED " + DB2);
+    policyFile.addPermissionsToRole(GROUP1_ROLE, INSERT_DB2_TBL1)
+    .write(context.getPolicyFile());
+    context.assertAuthzException(statement, "DESCRIBE DATABASE " + DB2);
+    context.assertAuthzException(statement, "DESCRIBE DATABASE EXTENDED " + DB2);
+    statement.close();
+    connection.close();
+  }
+
+  /**
+   * Tests that a user without db level privileges cannot describe default
+   */
+  @Test
+  public void testDescribeDefaultDatabase() throws Exception {
+    policyFile
+    .addPermissionsToRole(GROUP1_ROLE, "server=server1->db=default->table=" + TBL1 + "->action=select",
+        "server=server1->db=" + DB1 + "->table=" + TBL1 + "->action=select")
+        .addRolesToGroup(GROUP1, GROUP1_ROLE)
+        .addGroupsToUser(USER1, GROUP1)
+        .write(context.getPolicyFile());
+    dropDb(ADMIN1, DB1, DB2);
+    createDb(ADMIN1, DB1, DB2);
+    Connection connection = context.createConnection(ADMIN1, "password");
+    Statement statement = context.createStatement(connection);
+    assertTrue(statement.executeQuery("DESCRIBE DATABASE default").next());
+    statement.execute("USE " + DB1);
+    assertTrue(statement.executeQuery("DESCRIBE DATABASE default").next());
+    assertTrue(statement.executeQuery("DESCRIBE DATABASE " + DB1).next());
+    assertTrue(statement.executeQuery("DESCRIBE DATABASE " + DB2).next());
+    statement.close();
+    connection.close();
+
+    connection = context.createConnection(USER1, "password");
+    statement = context.createStatement(connection);
+    context.assertAuthzException(statement, "DESCRIBE DATABASE default");
+    context.assertAuthzException(statement, "DESCRIBE DATABASE " + DB1);
+    statement.execute("USE " + DB1);
+    context.assertAuthzException(statement, "DESCRIBE DATABASE " + DB1);
+    context.assertAuthzException(statement, "DESCRIBE DATABASE " + DB2);
+    statement.close();
+    connection.close();
+  }
+
+  /**
+   * Tests that users without privileges cannot execute show indexes
+   * and that users with all on table can execute show indexes
+   */
+  @Test
+  public void testShowIndexes1() throws Exception {
+    // grant privilege to non-existent table to allow use db1
+    policyFile.addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_NONTABLE)
+    .addRolesToGroup(GROUP1, GROUP1_ROLE)
+    .addGroupsToUser(USER1, GROUP1)
+    .write(context.getPolicyFile());
+    dropDb(ADMIN1, DB1);
+    createDb(ADMIN1, DB1);
+    createTable(ADMIN1, DB1, dataFile, TBL1);
+    Connection connection = context.createConnection(ADMIN1, "password");
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE " + DB1);
+    statement.execute("DROP INDEX IF EXISTS " + INDEX1 + " ON " + TBL1);
+    statement
+    .execute("CREATE INDEX "
+        + INDEX1
+        + " ON TABLE "
+        + TBL1
+        + "(value) AS 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' WITH DEFERRED REBUILD");
+    statement.execute("DROP VIEW IF EXISTS " + VIEW1);
+    statement.execute("CREATE VIEW " + VIEW1 + " (value) AS SELECT value from " + TBL1 + " LIMIT 10");
+    statement.close();
+    connection.close();
+    connection = context.createConnection(USER1, "password");
+    statement = context.createStatement(connection);
+    statement.execute("USE " + DB1);
+    context.assertAuthzException(statement, "SHOW INDEX ON " + TBL1);
+    policyFile
+    .addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_VIEW1)
+    .write(context.getPolicyFile());
+    context.assertAuthzException(statement, "SHOW INDEX ON " + TBL1);
+    policyFile.removePermissionsFromRole(GROUP1_ROLE, SELECT_DB1_VIEW1)
+    .addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_TBL1)
+    .write(context.getPolicyFile());
+    verifyIndex(statement, TBL1, INDEX1);
+    policyFile.removePermissionsFromRole(GROUP1_ROLE, SELECT_DB1_TBL1)
+    .addPermissionsToRole(GROUP1_ROLE, INSERT_DB1_TBL1)
+    .write(context.getPolicyFile());
+    verifyIndex(statement, TBL1, INDEX1);
+    statement.close();
+    connection.close();
+  }
+
+  private void verifyIndex(Statement statement, String table, String index) throws Exception {
+    ResultSet rs = statement.executeQuery("SHOW INDEX ON " + table);
+    assertTrue(rs.next());
+    assertEquals(index, rs.getString(1).trim());
+    assertEquals(table, rs.getString(2).trim());
+    assertEquals("value", rs.getString(3).trim());
+    assertEquals("db_1__tb_1_index_1__", rs.getString(4).trim());
+    assertEquals("compact", rs.getString(5).trim());
+  }
+
+  /**
+   * Tests that users without privileges cannot execute show partitions
+   * and that users with select on table can execute show partitions
+   */
+  @Test
+  public void testShowPartitions1() throws Exception {
+    // grant privilege to non-existent table to allow use db1
+    policyFile.addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_NONTABLE)
+    .addRolesToGroup(GROUP1, GROUP1_ROLE)
+    .addGroupsToUser(USER1, GROUP1)
+    .write(context.getPolicyFile());
+    dropDb(ADMIN1, DB1);
+    createDb(ADMIN1, DB1);
+    Connection connection = context.createConnection(ADMIN1, "password");
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE " + DB1);
+    statement.execute("DROP TABLE IF EXISTS " + TBL1);
+    statement.execute("create table " + TBL1
+        + " (under_col int, value string) PARTITIONED BY (dt INT)");
+    statement.execute("load data local inpath '" + dataFile.getPath()
+        + "' into table " + TBL1 + " PARTITION (dt=3)");
+    statement.execute("DROP VIEW IF EXISTS " + VIEW1);
+    statement.execute("CREATE VIEW " + VIEW1 + " (value) AS SELECT value from " + TBL1 + " LIMIT 10");
+    statement.close();
+    connection.close();
+    connection = context.createConnection(USER1, "password");
+    statement = context.createStatement(connection);
+    statement.execute("USE " + DB1);
+    context.assertAuthzException(statement, "SHOW PARTITIONS " + TBL1);
+    policyFile
+    .addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_VIEW1)
+    .write(context.getPolicyFile());
+    context.assertAuthzException(statement, "SHOW PARTITIONS " + TBL1);
+    policyFile
+    .removePermissionsFromRole(GROUP1_ROLE, SELECT_DB1_VIEW1)
+    .addPermissionsToRole(GROUP1_ROLE, SELECT_DB1_TBL1)
+    .write(context.getPolicyFile());
+    verifyParition(statement, TBL1);
+    policyFile.removePermissionsFromRole(GROUP1_ROLE, SELECT_DB1_TBL1)
+    .addPermissionsToRole(GROUP1_ROLE, INSERT_DB1_TBL1)
+    .write(context.getPolicyFile());
+    verifyParition(statement, TBL1);
+    statement.close();
+    connection.close();
+  }
+
+  private void verifyParition(Statement statement, String table) throws Exception {
+    ResultSet rs = statement.executeQuery("SHOW PARTITIONS " + TBL1);
+    assertTrue(rs.next());
+    assertEquals("dt=3", rs.getString(1).trim());
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataPermissions.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataPermissions.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataPermissions.java
new file mode 100644
index 0000000..cddd1d7
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMetadataPermissions.java
@@ -0,0 +1,158 @@
+/*
+ * 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.SQLException;
+import java.sql.Statement;
+
+import junit.framework.Assert;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+
+public class TestMetadataPermissions extends AbstractTestWithStaticLocalFS {
+  private Context context;
+  private PolicyFile policyFile;
+
+  @Before
+  public void setup() throws Exception {
+    context = createContext();
+    policyFile = PolicyFile.createAdminOnServer1(ADMIN1);
+
+/*
+    String testPolicies[] = {
+        "[groups]",
+        "admin_group = admin_role",
+        "user_group1 = db1_all,db2_all",
+        "user_group2 = db1_all",
+        "[roles]",
+        "db1_all = server=server1->db=db1",
+        "db2_all = server=server1->db=db2",
+        "admin_role = server=server1",
+        "[users]",
+        "user1 = user_group1",
+        "user2 = user_group2",
+        "admin = admin_group"
+        };
+    context.makeNewPolicy(testPolicies);
+*/
+    policyFile
+        .addRolesToGroup("user_group1", "db1_all", "db2_all")
+        .addRolesToGroup("user_group2", "db1_all")
+        .addPermissionsToRole("db1_all", "server=server1->db=db1")
+        .addPermissionsToRole("db2_all", "server=server1->db=db2")
+        .addGroupsToUser("user1", "user_group1")
+        .addGroupsToUser("user2", "user_group2")
+        .write(context.getPolicyFile());
+
+    Connection adminCon = context.createConnection(ADMIN1, "foo");
+    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)");
+      }
+    }
+    context.close();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if (context != null) {
+      context.close();
+    }
+  }
+
+  /**
+   * Ensure that a user with no privileges on a database cannot
+   * query that databases metadata.
+   */
+  @Test
+  public void testDescPrivilegesNegative() throws Exception {
+    String dbName = "db2";
+    Connection connection = context.createConnection("user2", "password");
+    Statement statement = context.createStatement(connection);
+    context.assertAuthzException(statement, "USE " + dbName);
+//    TODO when DESCRIBE db.table is supported tests should be uncommented
+//    for (String tabName : new String[] { "tab1", "tab2" }) {
+//      context.assertAuthzException(statement, "DESCRIBE " + dbName + "." + tabName);
+//      context.assertAuthzException(statement, "DESCRIBE EXTENDED " + dbName + "." + 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 {
+    String dbName = "db2";
+    Connection connection = context.createConnection("user2", "password");
+    Statement statement = context.createStatement(connection);
+    context.assertAuthzException(statement, "DESCRIBE DATABASE " + dbName);
+    context.assertAuthzException(statement, "DESCRIBE DATABASE EXTENDED " + dbName);
+    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", "password");
+    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", "password");
+    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/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMovingToProduction.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMovingToProduction.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMovingToProduction.java
new file mode 100644
index 0000000..ae3105c
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestMovingToProduction.java
@@ -0,0 +1,231 @@
+/*
+ * 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.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 junit.framework.Assert;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+public class TestMovingToProduction extends AbstractTestWithStaticLocalFS {
+  private Context context;
+  private final String SINGLE_TYPE_DATA_FILE_NAME = "kv1.dat";
+  private PolicyFile policyFile;
+
+
+  @Before
+  public void setUp() throws Exception {
+    context = createContext();
+    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.createAdminOnServer1(ADMIN1);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if (context != null) {
+      context.close();
+    }
+  }
+
+  /**
+   * 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 {
+    policyFile
+        .addRolesToGroup("group1", "all_db1", "load_data", "select_proddb_tbl1", "insert_proddb_tbl1")
+        .addPermissionsToRole("load_data", "server=server1->uri=file://" + dataDir.getPath())
+        .addPermissionsToRole("all_db1", "server=server1->db=db_1")
+        .addGroupsToUser("user1", "group1")
+        .addGroupsToUser("user2", "group2")
+        .write(context.getPolicyFile());
+
+    String dbName1 = "db_1";
+    String dbName2 = "proddb";
+    String tableName1 = "tb_1";
+
+    Connection connection = context.createConnection(ADMIN1, "foo");
+    Statement statement = context.createStatement(connection);
+    statement.execute("DROP DATABASE IF EXISTS " + dbName1 + " CASCADE");
+    statement.execute("DROP DATABASE IF EXISTS " + dbName2 + " CASCADE");
+    statement.execute("CREATE DATABASE " + dbName1);
+    statement.execute("CREATE DATABASE " + dbName2);
+    statement.execute("DROP TABLE IF EXISTS " + dbName2 + "." + tableName1);
+    statement.execute("create table " + dbName2 + "." + tableName1
+        + " (under_col int comment 'the under column', value string)");
+    statement.close();
+    connection.close();
+
+    // a
+    connection = context.createConnection("user1", "foo");
+    statement = context.createStatement(connection);
+    statement.execute("USE " + dbName1);
+    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 INPATH 'file://" + dataDir.getPath()
+        + "' INTO TABLE " + tableName1);
+
+    policyFile
+        .addPermissionsToRole("insert_proddb_tbl1", "server=server1->db=proddb->table=tb_1->action=insert")
+        .write(context.getPolicyFile());
+    statement.execute("USE " + dbName2);
+    statement.execute("INSERT OVERWRITE TABLE "
+        + tableName1 + " SELECT * FROM " + dbName1
+        + "." + tableName1);
+
+    // b
+    policyFile
+        .addPermissionsToRole("select_proddb_tbl1", "server=server1->db=proddb->table=tb_1->action=select")
+        .write(context.getPolicyFile());
+    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", "foo");
+    statement = context.createStatement(connection);
+    context.assertAuthzException(statement, "USE " + dbName2);
+    context.assertAuthzException(statement, "INSERT OVERWRITE TABLE "
+        + dbName2 + "." + tableName1 + " SELECT * FROM " + dbName1
+        + "." + tableName1);
+    context.assertAuthzException(statement, "SELECT * FROM " + dbName2 + "." + tableName1 + " LIMIT 10");
+    statement.close();
+    connection.close();
+
+    // d
+    connection = context.createConnection("user1", "foo");
+    statement = context.createStatement(connection);
+    statement.execute("USE " + dbName2);
+    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 {
+    policyFile
+        .addRolesToGroup("group1", "all_db1", "load_data", "select_proddb_tbl1", "insert_proddb_tbl1")
+        .addPermissionsToRole("all_db1", "server=server1->db=db_1")
+        .addPermissionsToRole("load_data", "server=server1->uri=file://" + dataDir.getPath())
+        .addGroupsToUser("user1", "group1")
+        .addGroupsToUser("user2", "group2")
+        .write(context.getPolicyFile());
+
+    String dbName1 = "db_1";
+    String dbName2 = "proddb";
+    String tableName1 = "tb_1";
+    Connection connection = context.createConnection("admin1", "foo");
+    Statement statement = context.createStatement(connection);
+    statement.execute("DROP DATABASE IF EXISTS " + dbName1 + " CASCADE");
+    statement.execute("DROP DATABASE IF EXISTS " + dbName2 + " CASCADE");
+    statement.execute("CREATE DATABASE " + dbName1);
+    statement.execute("CREATE DATABASE " + dbName2);
+    statement.execute("DROP TABLE IF EXISTS " + dbName2 + "." + tableName1);
+    statement.execute("create table " + dbName2 + "." + tableName1
+        + " (under_col int comment 'the under column', value string)");
+    statement.close();
+    connection.close();
+
+    // a
+    connection = context.createConnection("user1", "foo");
+    statement = context.createStatement(connection);
+    statement.execute("DROP TABLE IF EXISTS " + dbName1 + "." + tableName1);
+    statement.execute("create table " + dbName1 + "." + tableName1
+        + " (under_col int comment 'the under column', value string)");
+    statement.execute("LOAD DATA INPATH 'file://" + dataDir.getPath()
+        + "' INTO TABLE " + dbName1 + "." + tableName1);
+
+    policyFile
+        .addPermissionsToRole("insert_proddb_tbl1", "server=server1->db=proddb->table=tb_1->action=insert")
+        .write(context.getPolicyFile());
+    statement.execute("INSERT OVERWRITE TABLE "
+        + dbName2 + "." + tableName1 + " SELECT * FROM " + dbName1
+        + "." + tableName1);
+
+    // b
+    policyFile
+        .addPermissionsToRole("select_proddb_tbl1", "server=server1->db=proddb->table=tb_1->action=select")
+        .write(context.getPolicyFile());
+    assertTrue("user1 should be able to select data from "
+        + dbName2 + "." + dbName2 + "." + tableName1, statement.execute("SELECT * FROM "
+            + dbName2 + "." + tableName1 + " LIMIT 10"));
+    assertTrue("user1 should be able to describe table " + dbName2 + "." + tableName1,
+        statement.execute("DESCRIBE " + dbName2 + "." + tableName1));
+
+    // c
+    connection = context.createConnection("user2", "foo");
+    statement = context.createStatement(connection);
+
+    context.assertAuthzException(statement, "INSERT OVERWRITE TABLE "
+        + dbName2 + "." + tableName1 + " SELECT * FROM " + dbName1
+        + "." + tableName1);
+
+    context.assertAuthzException(statement, "SELECT * FROM "
+        + dbName2 + "." + tableName1 + " LIMIT 10");
+    statement.close();
+    connection.close();
+
+    // d
+    connection = context.createConnection("user1", "foo");
+    statement = context.createStatement(connection);
+    statement.execute("USE " + dbName2);
+    context.assertAuthzException(statement, "DROP TABLE " + tableName1);
+    statement.close();
+    connection.close();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDBConfiguration.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDBConfiguration.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDBConfiguration.java
new file mode 100644
index 0000000..17f4de1
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDBConfiguration.java
@@ -0,0 +1,486 @@
+/*
+ * 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.provider.file.PolicyFile;
+import org.apache.sentry.provider.file.SimplePolicyEngine;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Joiner;
+import com.google.common.io.Files;
+import com.google.common.io.Resources;
+
+/**
+ * Test privileges per database policy files
+ */
+public class TestPerDBConfiguration extends AbstractTestWithStaticLocalFS {
+  private static final String MULTI_TYPE_DATA_FILE_NAME = "emp.dat";
+  private static final String DB2_POLICY_FILE = "db2-policy-file.ini";
+
+  private Context context;
+  private File dataFile;
+  private PolicyFile policyFile;
+
+  @Before
+  public void setup() throws Exception {
+    context = createContext();
+    policyFile = PolicyFile.createAdminOnServer1(ADMIN1);
+
+    File dataDir = context.getDataDir();
+    //copy data file to test dir
+    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();
+
+  }
+
+  @After
+  public void teardown() throws Exception {
+    if (context != null) {
+      context.close();
+    }
+  }
+
+  @Test
+  public void testPerDB() throws Exception {
+    PolicyFile db2PolicyFile = new PolicyFile();
+    File db2PolicyFileHandle = new File(context.getPolicyFile().getParent(), DB2_POLICY_FILE);
+    db2PolicyFile
+        .addRolesToGroup("user_group2", "select_tbl2")
+        .addPermissionsToRole("select_tbl2", "server=server1->db=db2->table=tbl2->action=select")
+        .write(db2PolicyFileHandle);
+
+    policyFile
+        .addRolesToGroup("user_group1", "select_tbl1")
+        .addRolesToGroup("user_group2", "select_tbl2")
+        .addPermissionsToRole("select_tbl1", "server=server1->db=db1->table=tbl1->action=select")
+        .addGroupsToUser("user1", "user_group1")
+        .addGroupsToUser("user2", "user_group2")
+        .addDatabase("db2", db2PolicyFileHandle.getPath())
+        .write(context.getPolicyFile());
+
+    // setup db objects needed by the test
+    Connection connection = context.createConnection(ADMIN1, "hive");
+    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("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.close();
+    connection.close();
+
+    // test execution
+    connection = context.createConnection("user1", "password");
+    statement = context.createStatement(connection);
+    statement.execute("USE db1");
+    // test user1 can execute query on tbl1
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl1");
+
+    // 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", "password");
+    statement = context.createStatement(connection);
+    statement.execute("USE db2");
+    // test user2 can execute query on tbl2
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl2");
+
+    // user2 cannot query db1.tbl1
+    context.assertAuthzException(statement, "SELECT COUNT(*) FROM db1.tbl1");
+    context.assertAuthzException(statement, "USE db1");
+
+    statement.close();
+    connection.close();
+
+    //test cleanup
+    connection = context.createConnection(ADMIN1, "hive");
+    statement = context.createStatement(connection);
+    statement.execute("DROP DATABASE db1 CASCADE");
+    statement.execute("DROP DATABASE db2 CASCADE");
+    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("user_group2", "select_tbl2")
+        .addPermissionsToRole("select_tbl2", "server=server1->db=db2->table=tbl2->action=select")
+        .write(db2PolicyFileHandle);
+    db3PolicyFile
+        .addRolesToGroup("user_group3", "select_tbl3_BAD")
+        .addPermissionsToRole("select_tbl3_BAD", "server=server1->db=db3------>table->action=select")
+        .write(db3PolicyFileHandle);
+    db4PolicyFile
+        .addRolesToGroup("user_group4", "select_tbl4")
+        .addPermissionsToRole("select_tbl4", "server=server1->db=db4->table=tbl4->action=select")
+        .write(db4PolicyFileHandle);
+    policyFile
+        .addRolesToGroup("user_group1", "select_tbl1")
+        .addRolesToGroup("user_group2", "select_tbl2")
+        .addPermissionsToRole("select_tbl1", "server=server1->db=db1->table=tbl1->action=select")
+        .addGroupsToUser("user1", "user_group1")
+        .addGroupsToUser("user2", "user_group2")
+        .addGroupsToUser("user3", "user_group3")
+        .addGroupsToUser("user4", "user_group4")
+        .addDatabase("db2", db2PolicyFileHandle.getPath())
+        .addDatabase("db3", db3PolicyFileHandle.getPath())
+        .addDatabase("db4", db4PolicyFileHandle.getPath())
+        .write(context.getPolicyFile());
+
+    // setup db objects needed by the test
+    Connection connection = context.createConnection(ADMIN1, "hive");
+    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("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();
+
+    // test execution
+    connection = context.createConnection("user1", "password");
+    statement = context.createStatement(connection);
+    statement.execute("USE db1");
+    // test user1 can execute query on tbl1
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl1");
+    connection.close();
+
+    connection = context.createConnection("user2", "password");
+    statement = context.createStatement(connection);
+    statement.execute("USE db2");
+    // test user1 can execute query on tbl1
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl2");
+    connection.close();
+
+    // verify no access to db3 due to badly formatted rule in db3 policy file
+    connection = context.createConnection("user3", "password");
+    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", "password");
+    statement = context.createStatement(connection);
+    statement.execute("USE db4");
+    // test user1 can execute query on tbl1
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl4");
+    connection.close();
+
+    //test cleanup
+    connection = context.createConnection(ADMIN1, "hive");
+    statement = context.createStatement(connection);
+    statement.execute("DROP DATABASE db1 CASCADE");
+    statement.execute("DROP DATABASE db2 CASCADE");
+    statement.execute("DROP DATABASE db3 CASCADE");
+    statement.execute("DROP DATABASE db4 CASCADE");
+    statement.close();
+    connection.close();
+  }
+
+  @Test
+  public void testPerDBPolicyFileWithURI() throws Exception {
+    File db2PolicyFileHandle = new File(context.getPolicyFile().getParent(), DB2_POLICY_FILE);
+
+    policyFile
+        .addRolesToGroup("user_group1", "select_tbl1")
+        .addRolesToGroup("user_group2", "select_tbl2")
+        .addPermissionsToRole("select_tbl1", "server=server1->db=db1->table=tbl1->action=select")
+        .addGroupsToUser("user1", "user_group1")
+        .addGroupsToUser("user2", "user_group2")
+        .addDatabase("db2", db2PolicyFileHandle.getPath())
+        .write(context.getPolicyFile());
+
+    PolicyFile db2PolicyFile = new PolicyFile();
+    db2PolicyFile
+        .addRolesToGroup("user_group2", "select_tbl2", "data_read", "insert_tbl2")
+        .addPermissionsToRole("select_tbl2", "server=server1->db=db2->table=tbl2->action=select")
+        .addPermissionsToRole("insert_tbl2", "server=server1->db=db2->table=tbl2->action=insert")
+        .addPermissionsToRole("data_read", "server=server1->URI=file://" + dataFile)
+        .write(db2PolicyFileHandle);
+    // 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(SimplePolicyEngine.ACCESS_ALLOW_URI_PER_DB_POLICYFILE, "true");
+    // setup db objects needed by the test
+    Connection connection = context.createConnection(ADMIN1, "hive");
+    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("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.close();
+    connection.close();
+
+    // test execution
+    connection = context.createConnection("user1", "password");
+    statement = context.createStatement(connection);
+    statement.execute("USE db1");
+    // test user1 can execute query on tbl1
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl1");
+
+    // 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", "password");
+    statement = context.createStatement(connection);
+    statement.execute("USE db2");
+    // test user2 can execute query on tbl2
+    verifyCount(statement, "SELECT COUNT(*) FROM tbl2");
+
+    // verify user2 can execute LOAD
+    statement.execute("LOAD DATA LOCAL INPATH '" + dataFile.getPath() + "' INTO TABLE tbl2");
+
+    // user2 cannot query db1.tbl1
+    context.assertAuthzException(statement, "SELECT COUNT(*) FROM db1.tbl1");
+    context.assertAuthzException(statement, "USE db1");
+
+    statement.close();
+    connection.close();
+
+    //test cleanup
+    connection = context.createConnection(ADMIN1, "hive");
+    statement = context.createStatement(connection);
+    statement.execute("DROP DATABASE db1 CASCADE");
+    statement.execute("DROP DATABASE db2 CASCADE");
+    statement.close();
+    connection.close();
+    System.setProperty(SimplePolicyEngine.ACCESS_ALLOW_URI_PER_DB_POLICYFILE, "false");
+  }
+
+  /**
+   * 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("user_group1", "select_tbl1")
+        .addPermissionsToRole("select_tbl1", "server=server1->db=db1->table=tbl1->action=select")
+        .addGroupsToUser("user_1", "user_group1")
+        .addGroupsToUser("user_2", "user_group2")
+        .write(context.getPolicyFile());
+
+    // setup db objects needed by the test
+    Connection connection = context.createConnection(ADMIN1, "hive");
+    Statement statement = context.createStatement(connection);
+
+    statement.execute("USE default");
+
+    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("DROP DATABASE IF EXISTS db2 CASCADE");
+    statement.close();
+    connection.close();
+
+    // user_1 should be able to access default
+    connection = context.createConnection("user_1", "password");
+    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("user_2", "password");
+    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("user_group1", "select_tbl1")
+        .addRolesToGroup("user_group2", "select_tbl2")
+        .addPermissionsToRole("select_tbl1", "server=server1->db=db1->table=tbl1->action=select")
+        .addGroupsToUser("user_1", "user_group1")
+        .addGroupsToUser("user_2", "user_group2")
+        .addGroupsToUser("user_3", "user_group3")
+        .addDatabase("db2", db2PolicyFileHandle.getPath())
+        .addDatabase("default", defaultPolicyFileHandle.getPath())
+        .write(context.getPolicyFile());
+
+    PolicyFile db2PolicyFile = new PolicyFile();
+    db2PolicyFile
+        .addRolesToGroup("user_group2", "select_tbl2")
+        .addPermissionsToRole("select_tbl2", "server=server1->db=db2->table=tbl2->action=select")
+        .write(db2PolicyFileHandle);
+
+    PolicyFile defaultPolicyFile = new PolicyFile();
+    defaultPolicyFile
+        .addRolesToGroup("user_group2", "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, "hive");
+    Statement statement = context.createStatement(connection);
+    statement.execute("USE default");
+    statement.execute("CREATE TABLE dtab(B INT, A STRING) " +
+                      " row format delimited fields terminated by '|'  stored as textfile");
+
+    statement.execute("DROP DATABASE IF EXISTS db1 CASCADE");
+    statement.execute("DROP DATABASE IF EXISTS db2 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("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.close();
+    connection.close();
+
+    // user_1 should be able to switch to default, but not the tables from default
+    connection = context.createConnection("user_1", "password");
+    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("user_2", "password");
+    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("user_3", "password");
+    statement = context.createStatement(connection);
+    context.assertAuthzException(statement, "USE default");
+    statement.close();
+    connection.close();
+  }
+
+  private void verifyCount(Statement statement, String query) 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 == 1);
+    assertTrue("Incorrect result", count == 12);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDatabasePolicyFile.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDatabasePolicyFile.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDatabasePolicyFile.java
new file mode 100644
index 0000000..a89988a
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPerDatabasePolicyFile.java
@@ -0,0 +1,134 @@
+/*
+ * 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.Statement;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+public class TestPerDatabasePolicyFile extends AbstractTestWithStaticLocalFS {
+  private static final String SINGLE_TYPE_DATA_FILE_NAME = "kv1.dat";
+  private static final String ADMIN1 = "admin1";
+  private Context context;
+  private PolicyFile policyFile;
+  private File globalPolicyFile;
+  private File dataDir;
+  private File dataFile;
+
+  @Before
+  public void setup() throws Exception {
+    policyFile = PolicyFile.createAdminOnServer1(ADMIN1);
+    context = createContext();
+    globalPolicyFile = context.getPolicyFile();
+    dataDir = context.getDataDir();
+    assertTrue("Could not delete " + globalPolicyFile, context.deletePolicyFile());
+    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();
+  }
+
+  @After
+  public void teardown() throws Exception {
+    if (context != null) {
+      context.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.write(context.getPolicyFile());
+
+    // setup db objects needed by the test
+    Connection connection = context.createConnection(ADMIN1, "password");
+    Statement statement = context.createStatement(connection);
+    createSampleDbTable(statement, "db1", "tbl1");
+    createSampleDbTable(statement, "db2", "tbl1");
+    statement.close();
+    connection.close();
+
+    File specificPolicyFileFile = new File(context.getBaseDir(), "db2-policy.ini");
+
+    PolicyFile specificPolicyFile = new PolicyFile()
+    .addPermissionsToRole("db1_role", grant)
+    .addRolesToGroup("group1", "db1_role")
+    .addGroupsToUser("user1", "group1");
+    specificPolicyFile.write(specificPolicyFileFile);
+
+    policyFile.addDatabase("db2", specificPolicyFileFile.getPath());
+    policyFile.write(context.getPolicyFile());
+
+
+
+    // test execution
+    connection = context.createConnection("user1", "password");
+    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

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/aef404c6/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPrivilegeAtTransform.java
----------------------------------------------------------------------
diff --git a/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPrivilegeAtTransform.java b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPrivilegeAtTransform.java
new file mode 100644
index 0000000..0b71c87
--- /dev/null
+++ b/sentry-tests/sentry-tests-hive/src/test/java/org/apache/sentry/tests/e2e/hive/TestPrivilegeAtTransform.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 static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.sql.Connection;
+import java.sql.Statement;
+
+import org.apache.sentry.provider.file.PolicyFile;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Resources;
+
+public class TestPrivilegeAtTransform extends AbstractTestWithStaticLocalFS {
+  private Context context;
+  private final String SINGLE_TYPE_DATA_FILE_NAME = "kv1.dat";
+  private File dataDir;
+  private File dataFile;
+  private PolicyFile policyFile;
+
+  @Before
+  public void setup() throws Exception {
+    context = createContext();
+    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();
+    policyFile = PolicyFile.createAdminOnServer1("admin1");
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    if (context != null) {
+      context.close();
+    }
+  }
+
+  /**
+   * Steps:
+   * 1. admin create database, create table, load data into it
+   * 2. all@server can issue transforms command
+   * 3. all@database cannot issue transform command
+   * 4. insert@table select@table cannot issue transform command
+   * 5. select@view cannot issue transform command
+   * 6. transform@server can issue the transform command
+   */
+  @Test
+  public void testTransform1() throws Exception {
+    policyFile
+      .addGroupsToUser("user1", "group1")
+      .addPermissionsToRole("all_db1", "server=server1->db=db_1")
+      .addRolesToGroup("group1", "all_db1");
+    policyFile.write(context.getPolicyFile());
+
+    // verify by SQL
+    // 1, 2
+    String dbName1 = "db_1";
+    String tableName1 = "tb_1";
+    String query = "select TRANSFORM(a.under_col, a.value) USING 'cat' AS (tunder_col, tvalue) FROM " + dbName1 + "." + tableName1 + " a";
+    Connection connection = context.createConnection("admin1", "foo");
+    Statement statement = context.createStatement(connection);
+    statement.execute("DROP DATABASE IF EXISTS " + dbName1 + " CASCADE");
+    statement.execute("CREATE DATABASE " + dbName1);
+    statement.execute("DROP TABLE IF EXISTS " + dbName1 + "." + tableName1);
+    statement.execute("create table " + dbName1 + "." + tableName1
+        + " (under_col int, value string)");
+     statement.execute("load data local inpath '" + dataFile.getPath()
+            + "' into table " + dbName1 + "." + tableName1);
+    assertTrue(query, statement.execute(query));
+
+    statement.close();
+    connection.close();
+
+    connection = context.createConnection("user1", "foo");
+    statement = context.createStatement(connection);
+
+    // 3
+    context.assertAuthzExecHookException(statement, query);
+
+    // 4
+    policyFile
+      .addPermissionsToRole("select_tb1", "server=server1->db=db_1->table=tb_1->action=select")
+      .addPermissionsToRole("insert_tb1", "server=server1->db=db_1->table=tb_1->action=insert")
+      .addRolesToGroup("group1", "select_tb1", "insert_tb1");
+    policyFile.write(context.getPolicyFile());
+    context.assertAuthzExecHookException(statement, query);
+
+    // 5
+    policyFile
+      .addPermissionsToRole("all_server1", "server=server1")
+      .addRolesToGroup("group1", "all_server1");
+    policyFile.write(context.getPolicyFile());
+    assertTrue(query, statement.execute(query));
+    statement.close();
+    connection.close();
+  }
+}