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() == 40000) || (resp.getResponseCode() == 403));
        if (resp.getErrorMessage() != null) {
            Assert.assertTrue(resp.getErrorMessage().contains("org.apache.hadoop.security.AccessControlException"));
        }
    }


    /**
     * 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.