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.util;
019
020import static org.apache.hadoop.hbase.util.AbstractHBaseTool.EXIT_FAILURE;
021import static org.apache.hadoop.hbase.util.AbstractHBaseTool.EXIT_SUCCESS;
022import static org.junit.jupiter.api.Assertions.assertEquals;
023import static org.junit.jupiter.api.Assertions.assertFalse;
024import static org.junit.jupiter.api.Assertions.assertNull;
025import static org.junit.jupiter.api.Assertions.assertTrue;
026
027import java.util.ArrayList;
028import java.util.List;
029import org.apache.hadoop.hbase.HBaseConfiguration;
030import org.apache.hadoop.hbase.testclassification.MiscTests;
031import org.apache.hadoop.hbase.testclassification.SmallTests;
032import org.junit.jupiter.api.BeforeEach;
033import org.junit.jupiter.api.Tag;
034import org.junit.jupiter.api.Test;
035
036import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;
037import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;
038
039@Tag(MiscTests.TAG)
040@Tag(SmallTests.TAG)
041public class AbstractHBaseToolTest {
042  static final class Options {
043    static final Option REQUIRED = new Option(null, "required", true, "");
044    static final Option OPTIONAL = new Option(null, "optional", true, "");
045    static final Option BOOLEAN = new Option(null, "boolean", false, "");
046  }
047
048  /**
049   * Simple tool to test options parsing. 3 options: required, optional, and boolean 2 deprecated
050   * options to test backward compatibility: -opt (old version of --optional) and -bool (old version
051   * of --boolean).
052   */
053  private static class TestTool extends AbstractHBaseTool {
054    String requiredValue;
055    String optionalValue;
056    boolean booleanValue;
057
058    @Override
059    protected void addOptions() {
060      addRequiredOption(Options.REQUIRED);
061      addOption(Options.OPTIONAL);
062      addOption(Options.BOOLEAN);
063    }
064
065    @Override
066    protected void processOptions(CommandLine cmd) {
067      requiredValue = cmd.getOptionValue(Options.REQUIRED.getLongOpt());
068      if (cmd.hasOption(Options.OPTIONAL.getLongOpt())) {
069        optionalValue = cmd.getOptionValue(Options.OPTIONAL.getLongOpt());
070      }
071      booleanValue = booleanValue || cmd.hasOption(Options.BOOLEAN.getLongOpt());
072    }
073
074    @Override
075    protected void processOldArgs(List<String> args) {
076      List<String> invalidArgs = new ArrayList<>();
077      while (args.size() > 0) {
078        String cmd = args.remove(0);
079        if (cmd.equals("-opt")) {
080          optionalValue = args.remove(0);
081        } else if (cmd.equals("-bool")) {
082          booleanValue = true;
083        } else {
084          invalidArgs.add(cmd);
085        }
086      }
087      args.addAll(invalidArgs);
088    }
089
090    @Override
091    protected int doWork() throws Exception {
092      return EXIT_SUCCESS;
093    }
094  }
095
096  TestTool tool;
097
098  @BeforeEach
099  public void setup() {
100    tool = new TestTool();
101    tool.setConf(HBaseConfiguration.create());
102  }
103
104  @Test
105  public void testAllOptionsSet() throws Exception {
106    String[] args = new String[] { "--required=foo", "--optional=bar", "--boolean" };
107    int returnValue = tool.run(args);
108    assertEquals(EXIT_SUCCESS, returnValue);
109    assertEquals("foo", tool.requiredValue);
110    assertEquals("bar", tool.optionalValue);
111    assertTrue(tool.booleanValue);
112  }
113
114  @Test
115  public void testOptionsNotSet() throws Exception {
116    String[] args = new String[] { "--required=foo" };
117    int returnValue = tool.run(args);
118    assertEquals(EXIT_SUCCESS, returnValue);
119    assertEquals("foo", tool.requiredValue);
120    assertNull(tool.optionalValue);
121    assertFalse(tool.booleanValue);
122  }
123
124  @Test
125  public void testMissingRequiredOption() throws Exception {
126    String[] args = new String[0];
127    int returnValue = tool.run(args);
128    assertEquals(EXIT_FAILURE, returnValue);
129  }
130
131  @Test
132  public void testFailureOnUnrecognizedOption() throws Exception {
133    String[] args = new String[] { "--required=foo", "-asdfs" };
134    int returnValue = tool.run(args);
135    assertEquals(EXIT_FAILURE, returnValue);
136  }
137
138  @Test
139  public void testOldOptionsWork() throws Exception {
140    String[] args = new String[] { "--required=foo", "-opt", "bar", "-bool" };
141    int returnValue = tool.run(args);
142    assertEquals(EXIT_SUCCESS, returnValue);
143    assertEquals("foo", tool.requiredValue);
144    assertEquals("bar", tool.optionalValue);
145    assertTrue(tool.booleanValue);
146  }
147
148  @Test
149  public void testNewOptionOverridesOldOption() throws Exception {
150    String[] args = new String[] { "--required=foo", "--optional=baz", "-opt", "bar", "-bool" };
151    int returnValue = tool.run(args);
152    assertEquals(EXIT_SUCCESS, returnValue);
153    assertEquals("foo", tool.requiredValue);
154    assertEquals("baz", tool.optionalValue);
155    assertTrue(tool.booleanValue);
156  }
157}