001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.mapreduce;
019
020import static org.junit.jupiter.api.Assertions.assertNotNull;
021import static org.junit.jupiter.api.Assertions.assertTrue;
022import static org.mockito.Mockito.verify;
023
024import java.io.IOException;
025import java.security.PrivilegedAction;
026import java.util.ArrayList;
027import java.util.List;
028import org.apache.hadoop.conf.Configuration;
029import org.apache.hadoop.fs.FileSystem;
030import org.apache.hadoop.fs.Path;
031import org.apache.hadoop.hbase.HBaseTestingUtil;
032import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
033import org.apache.hadoop.hbase.testclassification.MapReduceTests;
034import org.apache.hadoop.hbase.testclassification.MediumTests;
035import org.apache.hadoop.mapreduce.Job;
036import org.apache.hadoop.mapreduce.lib.partition.TotalOrderPartitioner;
037import org.apache.hadoop.security.UserGroupInformation;
038import org.junit.jupiter.api.AfterEach;
039import org.junit.jupiter.api.BeforeEach;
040import org.junit.jupiter.api.Tag;
041import org.junit.jupiter.api.Test;
042import org.mockito.Mockito;
043import org.slf4j.Logger;
044import org.slf4j.LoggerFactory;
045
046@Tag(MapReduceTests.TAG)
047@Tag(MediumTests.TAG)
048public class TestConfigurePartitioner {
049
050  private static final Logger LOG = LoggerFactory.getLogger(TestConfigurePartitioner.class);
051
052  private static final HBaseTestingUtil UTIL = new HBaseTestingUtil();
053
054  @BeforeEach
055  public void setUp() throws Exception {
056    UTIL.startMiniDFSCluster(1);
057  }
058
059  @AfterEach
060  public void tearDown() throws IOException {
061    UTIL.shutdownMiniDFSCluster();
062  }
063
064  @Test
065  public void testConfigurePartitioner() throws Exception {
066    Configuration conf = UTIL.getConfiguration();
067    // Create a user who is not the current user
068    String fooUserName = "foo1234";
069    String fooGroupName = "group1";
070    UserGroupInformation ugi =
071      UserGroupInformation.createUserForTesting(fooUserName, new String[] { fooGroupName });
072    // Get user's home directory
073    Path fooHomeDirectory = ugi.doAs(new PrivilegedAction<Path>() {
074      @Override
075      public Path run() {
076        try (FileSystem fs = FileSystem.get(conf)) {
077          return fs.makeQualified(fs.getHomeDirectory());
078        } catch (IOException ioe) {
079          LOG.error("Failed to get foo's home directory", ioe);
080        }
081        return null;
082      }
083    });
084    // create the home directory and chown
085    FileSystem fs = FileSystem.get(conf);
086    fs.mkdirs(fooHomeDirectory);
087    fs.setOwner(fooHomeDirectory, fooUserName, fooGroupName);
088
089    Job job = Mockito.mock(Job.class);
090    Mockito.doReturn(conf).when(job).getConfiguration();
091    ImmutableBytesWritable writable = new ImmutableBytesWritable();
092    List<ImmutableBytesWritable> splitPoints = new ArrayList<ImmutableBytesWritable>();
093    splitPoints.add(writable);
094
095    ugi.doAs(new PrivilegedAction<Void>() {
096      @Override
097      public Void run() {
098        try {
099          HFileOutputFormat2.configurePartitioner(job, splitPoints, false);
100        } catch (IOException ioe) {
101          LOG.error("Failed to configure partitioner", ioe);
102        }
103        return null;
104      }
105    });
106    // verify that the job uses TotalOrderPartitioner
107    verify(job).setPartitionerClass(TotalOrderPartitioner.class);
108    // verify that TotalOrderPartitioner.setPartitionFile() is called.
109    String partitionPathString = conf.get("mapreduce.totalorderpartitioner.path");
110    assertNotNull(partitionPathString);
111    // Make sure the partion file is in foo1234's home directory, and that
112    // the file exists.
113    assertTrue(partitionPathString.startsWith(fooHomeDirectory.toString()));
114    assertTrue(fs.exists(new Path(partitionPathString)));
115  }
116}