Package org.apache.hcatalog.security

Source Code of org.apache.hcatalog.security.TestHdfsAuthorizationProvider

/**
* 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.hcatalog.security;

import static org.apache.hcatalog.HcatTestUtils.perm300;
import static org.apache.hcatalog.HcatTestUtils.perm500;
import static org.apache.hcatalog.HcatTestUtils.perm555;
import static org.apache.hcatalog.HcatTestUtils.perm700;
import static org.apache.hcatalog.HcatTestUtils.perm755;

import java.io.IOException;
import java.util.Random;

import junit.framework.Assert;

import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hive.cli.CliSessionState;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
import org.apache.hadoop.hive.metastore.Warehouse;
import org.apache.hadoop.hive.metastore.api.MetaException;
import org.apache.hadoop.hive.ql.metadata.Hive;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.metadata.Table;
import org.apache.hadoop.hive.ql.processors.CommandProcessorResponse;
import org.apache.hadoop.hive.ql.session.SessionState;
import org.apache.hadoop.hive.shims.ShimLoader;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hcatalog.HcatTestUtils;
import org.apache.hcatalog.cli.HCatDriver;
import org.apache.hcatalog.cli.SemanticAnalysis.HCatSemanticAnalyzer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestHdfsAuthorizationProvider {
 
  protected HCatDriver hcatDriver;
  protected HiveMetaStoreClient msc;
  protected HiveConf conf;
  protected String whDir;
  protected Path whPath;
  protected FileSystem whFs;
  protected Warehouse wh;
  protected Hive hive;

  @Before
  public void setUp() throws Exception {
   
    conf = new HiveConf(this.getClass());
    conf.set(ConfVars.PREEXECHOOKS.varname, "");
    conf.set(ConfVars.POSTEXECHOOKS.varname, "");
    conf.set(ConfVars.HIVE_SUPPORT_CONCURRENCY.varname, "false");
 
    conf.set("hive.metastore.local", "true");
    conf.set(ConfVars.SEMANTIC_ANALYZER_HOOK.varname, HCatSemanticAnalyzer.class.getName());
    conf.setBoolVar(HiveConf.ConfVars.HIVE_AUTHORIZATION_ENABLED, true);
    conf.setVar(HiveConf.ConfVars.HIVE_AUTHORIZATION_MANAGER,
        StorageDelegationAuthorizationProvider.class.getCanonicalName());
    conf.set("fs.pfile.impl", "org.apache.hadoop.fs.ProxyLocalFileSystem");
   
    whDir = System.getProperty("test.warehouse.dir", "/tmp/testhdfsauthorization_wh");
    conf.setVar(HiveConf.ConfVars.METASTOREWAREHOUSE, whDir);
   
    UserGroupInformation ugi = ShimLoader.getHadoopShims().getUGIForConf(conf);
    String username = ShimLoader.getHadoopShims().getShortUserName(ugi);
   
    whPath = new Path(whDir);
    whFs = whPath.getFileSystem(conf);
   
    wh = new Warehouse(conf);
    hive = Hive.get(conf);
   
    //clean up mess in HMS
    HcatTestUtils.cleanupHMS(hive, wh, perm700);
   
    whFs.delete(whPath, true);
    whFs.mkdirs(whPath, perm755);
   
    SessionState.start(new CliSessionState(conf));
    hcatDriver = new HCatDriver();
  }

  @After
  public void tearDown() throws IOException {
    whFs.close();
    hcatDriver.close();
    Hive.closeCurrent();
  }

  public Path getDbPath(String dbName) throws MetaException, HiveException {
    return HcatTestUtils.getDbPath(hive, wh, dbName);
  }
 
  public Path getTablePath(String dbName, String tableName) throws HiveException {
    Table table = hive.getTable(dbName, tableName);
    return table.getPath();
  }

  public Path getPartPath(String partName, String dbName, String tableName) throws HiveException {
    return new Path(getTablePath(dbName, tableName), partName);
  }

  /** Execute the query expecting success*/
  public void exec(String format, Object ... args) throws Exception {
    String command = String.format(format, args);
    CommandProcessorResponse resp = hcatDriver.run(command);
    Assert.assertEquals(resp.getErrorMessage(), 0, resp.getResponseCode());
    Assert.assertEquals(resp.getErrorMessage(), null, resp.getErrorMessage());
  }

  /** Execute the query expecting it to fail with AuthorizationException */
  public void execFail(String format, Object ... args) throws Exception {
    String command = String.format(format, args);
    CommandProcessorResponse resp = hcatDriver.run(command);
    Assert.assertNotSame(resp.getErrorMessage(), 0, resp.getResponseCode());
    Assert.assertTrue(resp.getResponseCode() == 403 || //hive checks fail with 403
        resp.getErrorMessage().contains("org.apache.hadoop.hive.ql.metadata.AuthorizationException"));
  }
 
  /**
   * Tests whether the warehouse directory is writable by the current user (as defined by Hadoop)
   */
  @Test
  public void testWarehouseIsWritable() throws Exception {
    Path top = new Path(whPath, "_foobarbaz12_");
    try {
      whFs.mkdirs(top);
    } finally {
      whFs.delete(top, true);
    }
  }
 
  @Test
  public void testShowDatabases() throws Exception {
    exec("CREATE DATABASE doo");
    exec("SHOW DATABASES");
   
    whFs.setPermission(whPath, perm300); //revoke r
    execFail("SHOW DATABASES");
  }
 
  @Test
  public void testDatabaseOps() throws Exception {
    exec("SHOW TABLES");
    exec("SHOW TABLE EXTENDED LIKE foo1");
   
    whFs.setPermission(whPath, perm700);
    exec("CREATE DATABASE doo");
    exec("DESCRIBE DATABASE doo");
    exec("USE doo");
    exec("SHOW TABLES");
    exec("SHOW TABLE EXTENDED LIKE foo1");
    exec("DROP DATABASE doo");
   
    //custom location
    Path dbPath = new Path(whPath, new Random().nextInt() + "/mydb");
    whFs.mkdirs(dbPath, perm700);
    exec("CREATE DATABASE doo2 LOCATION '%s'", dbPath.toUri());
    exec("DESCRIBE DATABASE doo2", dbPath.toUri());
    exec("USE doo2");
    exec("SHOW TABLES");
    exec("SHOW TABLE EXTENDED LIKE foo1");
    exec("DROP DATABASE doo2", dbPath.toUri());
   
    //custom non-existing location
    exec("CREATE DATABASE doo3 LOCATION '%s/subpath'", dbPath.toUri());
  }
 
  @Test
  public void testCreateDatabaseFail1() throws Exception {
    whFs.setPermission(whPath, perm500);
    execFail("CREATE DATABASE doo"); //in the default location
   
    whFs.setPermission(whPath, perm555);
    execFail("CREATE DATABASE doo2");
  }

  @Test
  public void testCreateDatabaseFail2() throws Exception {
    //custom location
    Path dbPath = new Path(whPath, new Random().nextInt() + "/mydb");
   
    whFs.mkdirs(dbPath, perm700);
    whFs.setPermission(dbPath, perm500);
    execFail("CREATE DATABASE doo2 LOCATION '%s'", dbPath.toUri());
  }
 
  @Test
  public void testDropDatabaseFail1() throws Exception {
    whFs.setPermission(whPath, perm700);
    exec("CREATE DATABASE doo"); //in the default location
   
    whFs.setPermission(getDbPath("doo"), perm500); //revoke write
    execFail("DROP DATABASE doo");
  }
 
  @Test
  public void testDropDatabaseFail2() throws Exception {
    //custom location
    Path dbPath = new Path(whPath, new Random().nextInt() + "/mydb");
   
    whFs.mkdirs(dbPath, perm700);
    exec("CREATE DATABASE doo2 LOCATION '%s'", dbPath.toUri());
   
    whFs.setPermission(dbPath, perm500);
    execFail("DROP DATABASE doo2");
  }
 
  @Test
  public void testDescSwitchDatabaseFail() throws Exception {
    whFs.setPermission(whPath, perm700);
    exec("CREATE DATABASE doo");
    whFs.setPermission(getDbPath("doo"), perm300); //revoke read
    execFail("DESCRIBE DATABASE doo");
    execFail("USE doo");
   
    //custom location
    Path dbPath = new Path(whPath, new Random().nextInt() + "/mydb");
    whFs.mkdirs(dbPath, perm700);
    exec("CREATE DATABASE doo2 LOCATION '%s'", dbPath.toUri());
    whFs.mkdirs(dbPath, perm300); //revoke read
    execFail("DESCRIBE DATABASE doo2", dbPath.toUri());
    execFail("USE doo2");
  }
 
  @Test
  public void testShowTablesFail() throws Exception {
    whFs.setPermission(whPath, perm700);
    exec("CREATE DATABASE doo");
    exec("USE doo");
    whFs.setPermission(getDbPath("doo"), perm300); //revoke read
    execFail("SHOW TABLES");
    execFail("SHOW TABLE EXTENDED LIKE foo1");
  }
 
  @Test
  public void testTableOps() throws Exception {
    //default db
    exec("CREATE TABLE foo1 (foo INT) STORED AS RCFILE");
    exec("DESCRIBE foo1");
    exec("DROP TABLE foo1");
   
    //default db custom location
    Path tablePath = new Path(whPath, new Random().nextInt() + "/mytable");
    whFs.mkdirs(tablePath, perm700);
    exec("CREATE EXTERNAL TABLE foo2 (foo INT) STORED AS RCFILE LOCATION '%s'", tablePath);
    exec("DESCRIBE foo2");
    exec("DROP TABLE foo2");
   
    //default db custom non existing location
    exec("CREATE EXTERNAL TABLE foo3 (foo INT) STORED AS RCFILE LOCATION '%s/subpath'", tablePath);
    exec("DESCRIBE foo3");
    exec("DROP TABLE foo3");
   
    //non default db
    exec("CREATE DATABASE doo");
    exec("USE doo");
   
    exec("CREATE TABLE foo4 (foo INT) STORED AS RCFILE");
    exec("DESCRIBE foo4");
    exec("DROP TABLE foo4");
   
    //non-default db custom location
    tablePath = new Path(whPath, new Random().nextInt() + "/mytable");
    whFs.mkdirs(tablePath, perm700);
    exec("CREATE EXTERNAL TABLE foo5 (foo INT) STORED AS RCFILE LOCATION '%s'", tablePath);
    exec("DESCRIBE foo5");
    exec("DROP TABLE foo5");
   
    //non-default db custom non existing location
    exec("CREATE EXTERNAL TABLE foo6 (foo INT) STORED AS RCFILE LOCATION '%s/subpath'", tablePath);
    exec("DESCRIBE foo6");
    exec("DROP TABLE foo6");
   
    exec("DROP TABLE IF EXISTS foo_non_exists");
   
    exec("CREATE TABLE foo1 (foo INT) STORED AS RCFILE");
    exec("DESCRIBE EXTENDED foo1");
    exec("DESCRIBE FORMATTED foo1");
    exec("DESCRIBE foo1.foo");
   
    //deep non-existing path for the table
    tablePath = new Path(whPath, new Random().nextInt() + "/mytable");
    whFs.mkdirs(tablePath, perm700);
    exec("CREATE EXTERNAL TABLE foo2 (foo INT) STORED AS RCFILE LOCATION '%s/a/a/a/'", tablePath);
  }
 
  @Test
  public void testCreateTableFail1() throws Exception {
    //default db
    whFs.mkdirs(whPath, perm500); //revoke w
    execFail("CREATE TABLE foo1 (foo INT) STORED AS RCFILE");
  }
 
  @Test
  public void testCreateTableFail2() throws Exception {
    //default db custom location
    Path tablePath = new Path(whPath, new Random().nextInt() + "/mytable");
    whFs.mkdirs(tablePath, perm500);
    execFail("CREATE EXTERNAL TABLE foo2 (foo INT) STORED AS RCFILE LOCATION '%s'", tablePath);
   
    //default db custom non existing location
    execFail("CREATE EXTERNAL TABLE foo3 (foo INT) STORED AS RCFILE LOCATION '%s/subpath'", tablePath);
  }
 
  @Test
  public void testCreateTableFail3() throws Exception {
    //non default db
    exec("CREATE DATABASE doo");
    whFs.setPermission(getDbPath("doo"), perm500);

    execFail("CREATE TABLE doo.foo4 (foo INT) STORED AS RCFILE");
   
    //non-default db custom location, permission to write to tablePath, but not on db path
    Path tablePath = new Path(whPath, new Random().nextInt() + "/mytable");
    whFs.mkdirs(tablePath, perm700);
    exec("USE doo");
    execFail("CREATE EXTERNAL TABLE foo5 (foo INT) STORED AS RCFILE LOCATION '%s'", tablePath);
  }

  @Test
  public void testCreateTableFail4() throws Exception {
    //non default db
    exec("CREATE DATABASE doo");

    //non-default db custom location
    Path tablePath = new Path(whPath, new Random().nextInt() + "/mytable");
    whFs.mkdirs(tablePath, perm500);
    execFail("CREATE EXTERNAL TABLE doo.foo5 (foo INT) STORED AS RCFILE LOCATION '%s'", tablePath);
   
    //non-default db custom non existing location
    execFail("CREATE EXTERNAL TABLE doo.foo6 (foo INT) STORED AS RCFILE LOCATION '%s/a/a/a/'", tablePath);
  }
 
  @Test
  public void testDropTableFail1() throws Exception {
    //default db
    exec("CREATE TABLE foo1 (foo INT) STORED AS RCFILE");
    whFs.mkdirs(getTablePath("default", "foo1"), perm500); //revoke w
    execFail("DROP TABLE foo1");
  }
 
  @Test
  public void testDropTableFail2() throws Exception {
    //default db custom location
    Path tablePath = new Path(whPath, new Random().nextInt() + "/mytable");
    exec("CREATE EXTERNAL TABLE foo2 (foo INT) STORED AS RCFILE LOCATION '%s'", tablePath);
    whFs.mkdirs(tablePath, perm500);
    execFail("DROP TABLE foo2");
  }

  @Test
  public void testDropTableFail4() throws Exception {
    //non default db
    exec("CREATE DATABASE doo");

    //non-default db custom location
    Path tablePath = new Path(whPath, new Random().nextInt() + "/mytable");
   
    exec("CREATE EXTERNAL TABLE doo.foo5 (foo INT) STORED AS RCFILE LOCATION '%s'", tablePath);
    whFs.mkdirs(tablePath, perm500);
    exec("USE doo"); //There is no DROP TABLE doo.foo5 support in Hive
    execFail("DROP TABLE foo5");
  }
 
  @Test
  public void testDescTableFail() throws Exception {
    //default db
    exec("CREATE TABLE foo1 (foo INT) STORED AS RCFILE");
    whFs.mkdirs(getTablePath("default", "foo1"), perm300); //revoke read
    execFail("DESCRIBE foo1");
   
    //default db custom location
    Path tablePath = new Path(whPath, new Random().nextInt() + "/mytable");
    whFs.mkdirs(tablePath, perm700);
    exec("CREATE EXTERNAL TABLE foo2 (foo INT) STORED AS RCFILE LOCATION '%s'", tablePath);
    whFs.mkdirs(tablePath, perm300); //revoke read
    execFail("DESCRIBE foo2");
  }
 
  @Test
  public void testAlterTableRename() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) STORED AS RCFILE");
    exec("ALTER TABLE foo1 RENAME TO foo2");
   
    Path tablePath = new Path(whPath, new Random().nextInt() + "/mytable");
    exec("CREATE EXTERNAL TABLE foo3 (foo INT) STORED AS RCFILE LOCATION '%s'", tablePath);
    exec("ALTER TABLE foo3 RENAME TO foo4");
  }
 
  @Test
  public void testAlterTableRenameFail() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) STORED AS RCFILE");
    whFs.mkdirs(getTablePath("default", "foo1"), perm500); //revoke write
    execFail("ALTER TABLE foo1 RENAME TO foo2");
   
    Path tablePath = new Path(whPath, new Random().nextInt() + "/mytable");
    exec("CREATE EXTERNAL TABLE foo3 (foo INT) STORED AS RCFILE LOCATION '%s'", tablePath);
    whFs.mkdirs(tablePath, perm500); //revoke write
    execFail("ALTER TABLE foo3 RENAME TO foo4");
  }
 
  @Test
  public void testAlterTableRelocate() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) STORED AS RCFILE");
    Path tablePath = new Path(whPath, new Random().nextInt() + "/mytable");
    exec("ALTER TABLE foo1 SET LOCATION '%s'", tablePath.makeQualified(whFs));
   
    tablePath = new Path(whPath, new Random().nextInt() + "/mytable2");
    exec("CREATE EXTERNAL TABLE foo3 (foo INT) STORED AS RCFILE LOCATION '%s'",
        tablePath.makeQualified(whFs));
    tablePath = new Path(whPath, new Random().nextInt() + "/mytable2");
    exec("ALTER TABLE foo3 SET LOCATION '%s'", tablePath.makeQualified(whFs));
  }
 
  @Test
  public void testAlterTableRelocateFail() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) STORED AS RCFILE");
    Path tablePath = new Path(whPath, new Random().nextInt() + "/mytable");
    whFs.mkdirs(tablePath, perm500); //revoke write
    execFail("ALTER TABLE foo1 SET LOCATION '%s'", tablePath.makeQualified(whFs));
   
    //dont have access to new table loc
    tablePath = new Path(whPath, new Random().nextInt() + "/mytable2");
    exec("CREATE EXTERNAL TABLE foo3 (foo INT) STORED AS RCFILE LOCATION '%s'",
        tablePath.makeQualified(whFs));
    tablePath = new Path(whPath, new Random().nextInt() + "/mytable2");
    whFs.mkdirs(tablePath, perm500); //revoke write
    execFail("ALTER TABLE foo3 SET LOCATION '%s'", tablePath.makeQualified(whFs));
   
    //have access to new table loc, but not old table loc
    tablePath = new Path(whPath, new Random().nextInt() + "/mytable3");
    exec("CREATE EXTERNAL TABLE foo4 (foo INT) STORED AS RCFILE LOCATION '%s'",
        tablePath.makeQualified(whFs));
    whFs.mkdirs(tablePath, perm500); //revoke write
    tablePath = new Path(whPath, new Random().nextInt() + "/mytable3");
    execFail("ALTER TABLE foo4 SET LOCATION '%s'", tablePath.makeQualified(whFs));
  }
 
  @Test
  public void testAlterTable() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) PARTITIONED BY (b STRING) STORED AS TEXTFILE");
    exec("ALTER TABLE foo1 SET TBLPROPERTIES ('foo'='bar')");
    exec("ALTER TABLE foo1 SET SERDEPROPERTIES ('foo'='bar')");
    exec("ALTER TABLE foo1 ADD COLUMNS (foo2 INT)");
  }
 
  @Test
  public void testAddDropPartition() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) PARTITIONED BY (b STRING) STORED AS TEXTFILE");
    exec("ALTER TABLE foo1 ADD PARTITION (b='2010-10-10')");
    exec("ALTER TABLE foo1 ADD IF NOT EXISTS PARTITION (b='2010-10-10')");
    String relPath = new Random().nextInt() + "/mypart";
    exec("ALTER TABLE foo1 ADD PARTITION (b='2010-10-11') LOCATION '%s'", relPath);
   
    exec("ALTER TABLE foo1 PARTITION (b='2010-10-10') SET FILEFORMAT RCFILE");
   
    exec("ALTER TABLE foo1 PARTITION (b='2010-10-10') SET FILEFORMAT INPUTFORMAT "
        + "'org.apache.hadoop.hive.ql.io.RCFileInputFormat' OUTPUTFORMAT "
        + "'org.apache.hadoop.hive.ql.io.RCFileOutputFormat' inputdriver "
        + "'mydriver' outputdriver 'yourdriver'");   
   
    exec("ALTER TABLE foo1 DROP PARTITION (b='2010-10-10')");
    exec("ALTER TABLE foo1 DROP PARTITION (b='2010-10-11')");
  }
 
  @Test
  public void testAddPartitionFail1() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) PARTITIONED BY (b STRING) STORED AS TEXTFILE");
    whFs.mkdirs(getTablePath("default", "foo1"), perm500);
    execFail("ALTER TABLE foo1 ADD PARTITION (b='2010-10-10')");
  }
 
  @Test
  public void testAddPartitionFail2() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) PARTITIONED BY (b STRING) STORED AS TEXTFILE");
    String relPath = new Random().nextInt() + "/mypart";
    Path partPath = new Path(getTablePath("default", "foo1"), relPath);
    whFs.mkdirs(partPath, perm500);
    exec("ALTER TABLE foo1 ADD PARTITION (b='2010-10-10') LOCATION '%s'", partPath);
  }
 
  @Test
  public void testDropPartitionFail1() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) PARTITIONED BY (b STRING) STORED AS TEXTFILE");
    exec("ALTER TABLE foo1 ADD PARTITION (b='2010-10-10')");
    whFs.mkdirs(getPartPath("b=2010-10-10", "default", "foo1"), perm500);
    execFail("ALTER TABLE foo1 DROP PARTITION (b='2010-10-10')");
  }

  @Test
  public void testDropPartitionFail2() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) PARTITIONED BY (b STRING) STORED AS TEXTFILE");
    String relPath = new Random().nextInt() + "/mypart";
    Path partPath = new Path(getTablePath("default", "foo1"), relPath);
    whFs.mkdirs(partPath, perm700);
    exec("ALTER TABLE foo1 ADD PARTITION (b='2010-10-10') LOCATION '%s'", partPath);
    whFs.mkdirs(partPath, perm500); //revoke write
    execFail("ALTER TABLE foo1 DROP PARTITION (b='2010-10-10')");
  }
 
  @Test
  public void testAlterTableFail() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) PARTITIONED BY (boo STRING) STORED AS TEXTFILE");
    whFs.mkdirs(getTablePath("default", "foo1"), perm500); //revoke write
    execFail("ALTER TABLE foo1 SET TBLPROPERTIES ('foo'='bar')");
    execFail("ALTER TABLE foo1 SET SERDEPROPERTIES ('foo'='bar')");
    execFail("ALTER TABLE foo1 ADD COLUMNS (foo2 INT)");
  }
 
  @Test
  public void testShowTables() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) PARTITIONED BY (boo STRING) STORED AS TEXTFILE");
    exec("SHOW PARTITIONS foo1");
   
    whFs.mkdirs(getTablePath("default", "foo1"), perm300); //revoke read
    execFail("SHOW PARTITIONS foo1");
  }
 
  @Test
  public void testAlterTablePartRename() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) PARTITIONED BY (b STRING) STORED AS RCFILE");
    Path loc = new Path(whPath, new Random().nextInt() + "/mypart");
    exec("ALTER TABLE foo1 ADD PARTITION (b='2010-10-16') LOCATION '%s'", loc);
    exec("ALTER TABLE foo1 PARTITION (b='2010-10-16') RENAME TO PARTITION (b='2010-10-17')");
  }
 
  @Test
  public void testAlterTablePartRenameFail() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) PARTITIONED BY (b STRING) STORED AS RCFILE");
    Path loc = new Path(whPath, new Random().nextInt() + "/mypart");
    exec("ALTER TABLE foo1 ADD PARTITION (b='2010-10-16') LOCATION '%s'", loc);
    whFs.setPermission(loc, perm500); //revoke w
    execFail("ALTER TABLE foo1 PARTITION (b='2010-10-16') RENAME TO PARTITION (b='2010-10-17')");
  }
 
  @Test
  public void testAlterTablePartRelocate() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) PARTITIONED BY (b STRING) STORED AS RCFILE");
    exec("ALTER TABLE foo1 ADD PARTITION (b='2010-10-16')");
    Path partPath = new Path(whPath, new Random().nextInt() + "/mypart");
    exec("ALTER TABLE foo1 PARTITION (b='2010-10-16') SET LOCATION '%s'", partPath.makeQualified(whFs));
  }

  @Test
  public void testAlterTablePartRelocateFail() throws Exception {
    exec("CREATE TABLE foo1 (foo INT) PARTITIONED BY (b STRING) STORED AS RCFILE");
   
    Path oldLoc = new Path(whPath, new Random().nextInt() + "/mypart");
    Path newLoc = new Path(whPath, new Random().nextInt() + "/mypart2");
   
    exec("ALTER TABLE foo1 ADD PARTITION (b='2010-10-16') LOCATION '%s'", oldLoc);
    whFs.mkdirs(oldLoc, perm500);
    execFail("ALTER TABLE foo1 PARTITION (b='2010-10-16') SET LOCATION '%s'", newLoc.makeQualified(whFs));
    whFs.mkdirs(oldLoc, perm700);
    whFs.mkdirs(newLoc, perm500);
    execFail("ALTER TABLE foo1 PARTITION (b='2010-10-16') SET LOCATION '%s'", newLoc.makeQualified(whFs));
  }
 
}
TOP

Related Classes of org.apache.hcatalog.security.TestHdfsAuthorizationProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.