You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by el...@apache.org on 2014/03/11 19:25:27 UTC

[18/23] git commit: Merge branch '1.5.2-SNAPSHOT' into 1.6.0-SNAPSHOT

Merge branch '1.5.2-SNAPSHOT' into 1.6.0-SNAPSHOT

Conflicts:
	core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
	core/src/test/java/org/apache/accumulo/core/util/shell/ShellTest.java
	proxy/src/test/java/org/apache/accumulo/proxy/SimpleProxyIT.java
	test/src/test/java/org/apache/accumulo/test/ShellServerIT.java


Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/da7f937b
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/da7f937b
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/da7f937b

Branch: refs/heads/ACCUMULO-2061
Commit: da7f937b1d7d88ba7508b22a92ff7d0d110954ae
Parents: 4223d66 4cc25ca
Author: Josh Elser <el...@apache.org>
Authored: Mon Mar 10 18:15:28 2014 -0400
Committer: Josh Elser <el...@apache.org>
Committed: Mon Mar 10 18:15:28 2014 -0400

----------------------------------------------------------------------
 .../apache/accumulo/core/util/shell/Shell.java  |  20 +--
 .../core/util/shell/ShellConfigTest.java        |   5 +-
 .../core/util/shell/ShellSetInstanceTest.java   |   3 +-
 .../accumulo/core/util/shell/ShellTest.java     |   5 +-
 .../apache/accumulo/proxy/SimpleProxyIT.java    |  98 +++++++++----
 .../org/apache/accumulo/test/ShellServerIT.java | 145 ++++++++++++++-----
 6 files changed, 196 insertions(+), 80 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/da7f937b/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
index 420d465,6943b37..0c2cf3c
--- a/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
+++ b/core/src/main/java/org/apache/accumulo/core/util/shell/Shell.java
@@@ -219,111 -200,114 +219,109 @@@ public class Shell extends ShellOption
    private boolean logErrorsToConsole = false;
    private PrintWriter writer = null;
    private boolean masking = false;
 -  
 +
    public Shell() throws IOException {
-     this(new ConsoleReader());
+     this(new ConsoleReader(), new PrintWriter(
+         new OutputStreamWriter(System.out,
+         System.getProperty("jline.WindowsTerminal.output.encoding", System.getProperty("file.encoding")))));
    }
 -  
 +
-   public Shell(ConsoleReader reader) {
+   public Shell(ConsoleReader reader, PrintWriter writer) {
      super();
      this.reader = reader;
-   }
- 
-   public Shell(ConsoleReader reader, PrintWriter writer) {
-     this(reader);
      this.writer = writer;
    }
 -  
 +
    // Not for client use
    public boolean config(String... args) {
 -    
 -    CommandLine cl;
 +    ShellOptionsJC options = new ShellOptionsJC();
 +    JCommander jc = new JCommander();
 +
 +    jc.setProgramName("accumulo shell");
 +    jc.addObject(options);
      try {
 -      cl = new BasicParser().parse(opts, args);
 -      if (cl.getArgs().length > 0)
 -        throw new ParseException("Unrecognized arguments: " + cl.getArgList());
 -      
 -      if (cl.hasOption(helpOpt.getOpt())) {
 -        configError = true;
 -        printHelp("shell", SHELL_DESCRIPTION, opts);
 -        return true;
 -      }
 -      
 -      setDebugging(cl.hasOption(debugOption.getLongOpt()));
 -      authTimeout = Integer.parseInt(cl.getOptionValue(authTimeoutOpt.getLongOpt(), DEFAULT_AUTH_TIMEOUT)) * 60 * 1000;
 -      disableAuthTimeout = cl.hasOption(disableAuthTimeoutOpt.getLongOpt());
 -      
 -      if (cl.hasOption(zooKeeperInstance.getOpt()) && cl.getOptionValues(zooKeeperInstance.getOpt()).length != 2)
 -        throw new MissingArgumentException(zooKeeperInstance);
 -      
 -    } catch (Exception e) {
 +      jc.parse(args);
 +    } catch (ParameterException e) {
        configError = true;
 -      printException(e);
 -      printHelp("shell", SHELL_DESCRIPTION, opts);
 +    }
 +
 +    if (options.isHelpEnabled()) {
 +      configError = true;
 +    }
 +
 +    if (!configError && options.getUnrecognizedOptions() != null) {
 +      configError = true;
 +      logError("Unrecognized Options: " + options.getUnrecognizedOptions().toString());
 +    }
 +
 +    if (configError) {
 +      jc.usage();
        return true;
      }
 -    
 +
 +    setDebugging(options.isDebugEnabled());
 +    authTimeout = options.getAuthTimeout() * 60 * 1000; // convert minutes to milliseconds
 +    disableAuthTimeout = options.isAuthTimeoutDisabled();
 +
      // get the options that were parsed
 -    String sysUser = System.getProperty("user.name");
 -    if (sysUser == null)
 -      sysUser = "root";
 -    String user = cl.getOptionValue(usernameOption.getOpt(), sysUser);
 -    
 -    String passw = cl.getOptionValue(passwOption.getOpt(), null);
 -    tabCompletion = !cl.hasOption(tabCompleteOption.getLongOpt());
 -    String[] loginOptions = cl.getOptionValues(loginOption.getOpt());
 -    
 +    String user = options.getUsername();
 +    String password = options.getPassword();
 +
 +    tabCompletion = !options.isTabCompletionDisabled();
 +
      // Use a fake (Mock), ZK, or HdfsZK Accumulo instance
 -    setInstance(cl);
 -    
 +    setInstance(options);
 +
 +    // AuthenticationToken options
 +    token = options.getAuthenticationToken();
 +    Map<String,String> loginOptions = options.getTokenProperties();
 +
      // process default parameters if unspecified
      try {
 -      if (loginOptions != null && !cl.hasOption(tokenOption.getOpt()))
 -        throw new IllegalArgumentException("Must supply '-" + tokenOption.getOpt() + "' option with '-" + loginOption.getOpt() + "' option");
 -      
 -      if (loginOptions == null && cl.hasOption(tokenOption.getOpt()))
 -        throw new IllegalArgumentException("Must supply '-" + loginOption.getOpt() + "' option with '-" + tokenOption.getOpt() + "' option");
 -      
 -      if (passw != null && cl.hasOption(tokenOption.getOpt()))
 -        throw new IllegalArgumentException("Can not supply '-" + passwOption.getOpt() + "' option with '-" + tokenOption.getOpt() + "' option");
 -      
 -      if (user == null)
 -        throw new MissingArgumentException(usernameOption);
 -      
 -      if (loginOptions != null && cl.hasOption(tokenOption.getOpt())) {
 -        Properties props = new Properties();
 -        for (String loginOption : loginOptions)
 -          for (String lo : loginOption.split(",")) {
 -            String[] split = lo.split("=");
 -            props.put(split[0], split[1]);
 -          }
 -        
 -        this.token = Class.forName(cl.getOptionValue(tokenOption.getOpt())).asSubclass(AuthenticationToken.class).newInstance();
 -        this.token.init(props);
 -      }
 -      
 -      if (!cl.hasOption(fakeOption.getLongOpt())) {
 -        DistributedTrace.enable(instance, new ZooReader(instance.getZooKeepers(), instance.getZooKeepersSessionTimeOut()), "shell", InetAddress.getLocalHost()
 -            .getHostName());
 +      boolean hasToken = (token != null);
 +      boolean hasTokenOptions = !loginOptions.isEmpty();
 +
 +      if (hasToken && password != null) {
 +        throw new ParameterException("Can not supply '--pass' option with '--tokenClass' option");
        }
 -      
 +
        Runtime.getRuntime().addShutdownHook(new Thread() {
          @Override
 -        public void start() {
 -          reader.getTerminal().enableEcho();
 +        public void run() {
 +          reader.getTerminal().setEchoEnabled(true);
          }
        });
 -      
 -      if (passw != null) {
 -        this.token = new PasswordToken(passw);
 +
 +      // Need either both a token and options, or neither, but not just one.
 +      if (hasToken != hasTokenOptions) {
 +        throw new ParameterException("Must supply either both or neither of '--tokenClass' and '--tokenProperty'");
 +      } else if (hasToken) { // implied hasTokenOptions
 +        // Fully qualified name so we don't shadow java.util.Properties
 +        org.apache.accumulo.core.client.security.tokens.AuthenticationToken.Properties props;
 +        // and line wrap it because the package name is so long
 +        props = new org.apache.accumulo.core.client.security.tokens.AuthenticationToken.Properties();
 +
 +        props.putAllStrings(loginOptions);
 +        token.init(props);
 +      } else {
 +        // Read password if the user explicitly asked for it, or didn't specify anything at all
 +        if ("stdin".equals(password) || password == null) {
 +          password = reader.readLine("Password: ", '*');
 +        }
 +
 +        if (password == null) {
 +          // User cancel, e.g. Ctrl-D pressed
 +          throw new ParameterException("No password or token option supplied");
 +        } else {
 +          this.token = new PasswordToken(password);
 +        }
        }
 -      
 -      if (this.token == null) {
 -        passw = readMaskedLine("Password: ", '*');
 -        if (passw != null)
 -          this.token = new PasswordToken(passw);
 +
 +      if (!options.isFake()) {
 +        ZooReader zr = new ZooReader(instance.getZooKeepers(), instance.getZooKeepersSessionTimeOut());
 +        DistributedTrace.enable(instance, zr, "shell", InetAddress.getLocalHost().getHostName());
        }
 -      
 -      if (this.token == null) {
 -        reader.printNewline();
 -        throw new MissingArgumentException("No password or token option supplied");
 -      } // user canceled
 -      
 +
        this.setTableName("");
        this.principal = user;
        connector = instance.getConnector(this.principal, token);
@@@ -1053,17 -939,13 +1051,13 @@@
    private final void printHelp(String usage, String description, Options opts) {
      printHelp(usage, description, opts, Integer.MAX_VALUE);
    }
 -  
 +
    private final void printHelp(String usage, String description, Options opts, int width) {
-     PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.err, Constants.UTF8));
-     new HelpFormatter().printHelp(pw, width, usage, description, opts, 2, 5, null, true);
-     pw.flush();
-     if (logErrorsToConsole && writer != null) {
-       new HelpFormatter().printHelp(writer, width, usage, description, opts, 2, 5, null, true);
-       writer.flush();
-     }
+     // TODO Use the OutputStream from the JLine ConsoleReader if we can ever get access to it
+     new HelpFormatter().printHelp(writer, width, usage, description, opts, 2, 5, null, true);
+     writer.flush();
    }
 -  
 +
    public int getExitCode() {
      return exitCode;
    }

http://git-wip-us.apache.org/repos/asf/accumulo/blob/da7f937b/core/src/test/java/org/apache/accumulo/core/util/shell/ShellConfigTest.java
----------------------------------------------------------------------
diff --cc core/src/test/java/org/apache/accumulo/core/util/shell/ShellConfigTest.java
index c9914da,0000000..43d2e12
mode 100644,000000..100644
--- a/core/src/test/java/org/apache/accumulo/core/util/shell/ShellConfigTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/util/shell/ShellConfigTest.java
@@@ -1,89 -1,0 +1,90 @@@
 +/*
 + * 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.accumulo.core.util.shell;
 +
 +import static org.junit.Assert.assertFalse;
 +import static org.junit.Assert.assertTrue;
 +
 +import java.io.FileDescriptor;
 +import java.io.FileInputStream;
 +import java.io.PrintStream;
++import java.io.PrintWriter;
 +
 +import jline.console.ConsoleReader;
 +
 +import org.apache.accumulo.core.client.security.tokens.PasswordToken;
 +import org.apache.accumulo.core.util.shell.ShellTest.TestOutputStream;
 +import org.apache.log4j.Level;
 +import org.junit.After;
 +import org.junit.Before;
 +import org.junit.Test;
 +
 +import com.beust.jcommander.ParameterException;
 +
 +public class ShellConfigTest {
 +  TestOutputStream output;
 +  Shell shell;
 +  PrintStream out;
 +  
 +  @Before
 +  public void setUp() throws Exception {
 +    Shell.log.setLevel(Level.ERROR);
 +    
 +    out = System.out;
 +    output = new TestOutputStream();
 +    System.setOut(new PrintStream(output));
-     
-     shell = new Shell(new ConsoleReader(new FileInputStream(FileDescriptor.in), output));
++
++    shell = new Shell(new ConsoleReader(new FileInputStream(FileDescriptor.in), output), new PrintWriter(output));
 +    shell.setLogErrorsToConsole();
 +  }
 +  
 +  @After
 +  public void teardown() throws Exception {
 +    shell.shutdown();
 +    output.clear();
 +    System.setOut(out);
 +  }
 +  
 +  @Test
 +  public void testHelp() {
 +    assertTrue(shell.config("--help"));
 +    assertTrue("Did not print usage", output.get().startsWith("Usage"));
 +  }
 +  
 +  @Test
 +  public void testBadArg() {
 +    assertTrue(shell.config("--bogus"));
 +    assertTrue("Did not print usage", output.get().startsWith("Usage"));
 +  }
 +  
 +  @Test
 +  public void testToken() {
 +    assertTrue(shell.config("--fake", "-tc", PasswordToken.class.getCanonicalName()));
 +    assertTrue(output.get().contains(ParameterException.class.getCanonicalName()));
 +  }
 +  
 +  @Test
 +  public void testTokenAndOption() {
 +    assertFalse(shell.config("--fake", "-tc", PasswordToken.class.getCanonicalName(), "-u", "foo", "-l", "password=foo"));
 +  }
 +  
 +  @Test
 +  public void testTokenAndOptionAndPassword() {
 +    assertTrue(shell.config("--fake", "-tc", PasswordToken.class.getCanonicalName(), "-l", "password=foo", "-p", "bar"));
 +    assertTrue(output.get().contains(ParameterException.class.getCanonicalName()));
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/da7f937b/core/src/test/java/org/apache/accumulo/core/util/shell/ShellSetInstanceTest.java
----------------------------------------------------------------------
diff --cc core/src/test/java/org/apache/accumulo/core/util/shell/ShellSetInstanceTest.java
index 2929b04,0000000..ad24e6d
mode 100644,000000..100644
--- a/core/src/test/java/org/apache/accumulo/core/util/shell/ShellSetInstanceTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/util/shell/ShellSetInstanceTest.java
@@@ -1,240 -1,0 +1,241 @@@
 +/*
 + * 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.accumulo.core.util.shell;
 +
 +import static org.easymock.EasyMock.anyObject;
 +import static org.easymock.EasyMock.expect;
 +import static org.powermock.api.easymock.PowerMock.createMock;
 +import static org.powermock.api.easymock.PowerMock.expectLastCall;
 +import static org.powermock.api.easymock.PowerMock.expectNew;
 +import static org.powermock.api.easymock.PowerMock.mockStatic;
 +import static org.powermock.api.easymock.PowerMock.replay;
 +import static org.powermock.api.easymock.PowerMock.verify;
 +
 +import java.io.FileDescriptor;
 +import java.io.FileInputStream;
 +import java.io.IOException;
 +import java.io.OutputStream;
++import java.io.PrintWriter;
 +import java.util.Collections;
 +import java.util.List;
 +import java.util.UUID;
 +
 +import jline.console.ConsoleReader;
 +
 +import org.apache.accumulo.core.client.ClientConfiguration;
 +import org.apache.accumulo.core.client.ClientConfiguration.ClientProperty;
 +import org.apache.accumulo.core.client.ZooKeeperInstance;
 +import org.apache.accumulo.core.client.mock.MockInstance;
 +import org.apache.accumulo.core.conf.AccumuloConfiguration;
 +import org.apache.accumulo.core.conf.ConfigSanityCheck;
 +import org.apache.accumulo.core.conf.Property;
 +import org.apache.accumulo.core.conf.SiteConfiguration;
 +import org.apache.accumulo.core.zookeeper.ZooUtil;
 +import org.apache.hadoop.fs.Path;
 +import org.apache.log4j.Level;
 +import org.easymock.EasyMock;
 +import org.junit.After;
 +import org.junit.AfterClass;
 +import org.junit.Before;
 +import org.junit.BeforeClass;
 +import org.junit.Test;
 +import org.junit.runner.RunWith;
 +import org.powermock.core.classloader.annotations.PrepareForTest;
 +import org.powermock.modules.junit4.PowerMockRunner;
 +
 +@RunWith(PowerMockRunner.class)
 +@PrepareForTest({Shell.class, ZooUtil.class, ConfigSanityCheck.class})
 +public class ShellSetInstanceTest {
 +  public static class TestOutputStream extends OutputStream {
 +    StringBuilder sb = new StringBuilder();
 +
 +    @Override
 +    public void write(int b) throws IOException {
 +      sb.append((char) (0xff & b));
 +    }
 +
 +    public String get() {
 +      return sb.toString();
 +    }
 +
 +    public void clear() {
 +      sb.setLength(0);
 +    }
 +  }
 +
 +  @BeforeClass
 +  public static void setupClass() {
 +    // This is necessary because PowerMock messes with Hadoop's ability to
 +    // determine the current user (see security.UserGroupInformation).
 +    System.setProperty("HADOOP_USER_NAME", "test");
 +  }
 +  @AfterClass
 +  public static void teardownClass() {
 +    System.clearProperty("HADOOP_USER_NAME");
 +  }
 +
 +  private TestOutputStream output;
 +  private Shell shell;
 +
 +  @Before
 +  public void setup() throws IOException {
 +    Shell.log.setLevel(Level.OFF);
 +    output = new TestOutputStream();
-     shell = new Shell(new ConsoleReader(new FileInputStream(FileDescriptor.in), output));
++    shell = new Shell(new ConsoleReader(new FileInputStream(FileDescriptor.in), output), new PrintWriter(output));
 +    shell.setLogErrorsToConsole();
 +  }
 +  @After
 +  public void tearDown() {
 +    shell.shutdown();
 +    SiteConfiguration.clearInstance();
 +  }
 +
 +  @Test
 +  public void testSetInstance_Fake() throws Exception {
 +    ShellOptionsJC opts = createMock(ShellOptionsJC.class);
 +    expect(opts.isFake()).andReturn(true);
 +    replay(opts);
 +    MockInstance theInstance = createMock(MockInstance.class);
 +    expectNew(MockInstance.class, "fake").andReturn(theInstance);
 +    replay(theInstance, MockInstance.class);
 +
 +    shell.setInstance(opts);
 +    verify(theInstance, MockInstance.class);
 +  }
 +  @Test
 +  public void testSetInstance_HdfsZooInstance_Explicit() throws Exception {
 +    testSetInstance_HdfsZooInstance(true, false, false);
 +  }
 +  @Test
 +  public void testSetInstance_HdfsZooInstance_InstanceGiven() throws Exception {
 +    testSetInstance_HdfsZooInstance(false, true, false);
 +  }
 +  @Test
 +  public void testSetInstance_HdfsZooInstance_HostsGiven() throws Exception {
 +    testSetInstance_HdfsZooInstance(false, false, true);
 +  }
 +  @Test
 +  public void testSetInstance_HdfsZooInstance_Implicit() throws Exception {
 +    testSetInstance_HdfsZooInstance(false, false, false);
 +  }
 +  
 +  private void testSetInstance_HdfsZooInstance(boolean explicitHdfs, boolean onlyInstance, boolean onlyHosts)
 +    throws Exception {
 +    ClientConfiguration clientConf = createMock(ClientConfiguration.class);
 +    ShellOptionsJC opts = createMock(ShellOptionsJC.class);
 +    expect(opts.isFake()).andReturn(false);
 +    expect(opts.getClientConfiguration()).andReturn(clientConf);
 +    expect(opts.isHdfsZooInstance()).andReturn(explicitHdfs);
 +    if (!explicitHdfs) {
 +      expect(opts.getZooKeeperInstance())
 +        .andReturn(Collections.<String>emptyList());
 +      if (onlyInstance) {
 +        expect(opts.getZooKeeperInstanceName()).andReturn("instance");
 +        expect(clientConf.withInstance("instance")).andReturn(clientConf);
 +      } else {
 +        expect(opts.getZooKeeperInstanceName()).andReturn(null);
 +      }
 +      if (onlyHosts) {
 +        expect(opts.getZooKeeperHosts()).andReturn("host3,host4");
 +        expect(clientConf.withZkHosts("host3,host4")).andReturn(clientConf);
 +      } else {
 +        expect(opts.getZooKeeperHosts()).andReturn(null);
 +      }
 +    }
 +    replay(opts);
 +
 +    if (!onlyInstance) {
 +      expect(clientConf.get(ClientProperty.INSTANCE_NAME)).andReturn(null);
 +    }
 +
 +    mockStatic(ConfigSanityCheck.class);
 +    ConfigSanityCheck.validate(EasyMock.<AccumuloConfiguration>anyObject());
 +    expectLastCall().atLeastOnce();
 +    replay(ConfigSanityCheck.class);
 +
 +    if (!onlyHosts) {
 +      expect(clientConf.containsKey(Property.INSTANCE_ZK_HOST.getKey())).andReturn(true).atLeastOnce();
 +      expect(clientConf.getString(Property.INSTANCE_ZK_HOST.getKey())).andReturn("host1,host2").atLeastOnce();
 +      expect(clientConf.withZkHosts("host1,host2")).andReturn(clientConf);
 +    }
 +    if (!onlyInstance) {
 +      expect(clientConf.containsKey(Property.INSTANCE_VOLUMES.getKey())).andReturn(false).atLeastOnce();
 +      expect(clientConf.containsKey(Property.INSTANCE_DFS_DIR.getKey())).andReturn(true).atLeastOnce();
 +      expect(clientConf.containsKey(Property.INSTANCE_DFS_URI.getKey())).andReturn(true).atLeastOnce();
 +      expect(clientConf.getString(Property.INSTANCE_DFS_URI.getKey())).andReturn("hdfs://nn1").atLeastOnce();
 +      expect(clientConf.getString(Property.INSTANCE_DFS_DIR.getKey())).andReturn("/dfs").atLeastOnce();
 +    }
 +
 +    UUID randomUUID = null;
 +    if (!onlyInstance) {
 +      mockStatic(ZooUtil.class);
 +      randomUUID = UUID.randomUUID();
 +      expect(ZooUtil.getInstanceIDFromHdfs(anyObject(Path.class), anyObject(AccumuloConfiguration.class)))
 +        .andReturn(randomUUID.toString());
 +      replay(ZooUtil.class);
 +      expect(clientConf.withInstance(randomUUID)).andReturn(clientConf);
 +    }
 +    replay(clientConf);
 +
 +    ZooKeeperInstance theInstance = createMock(ZooKeeperInstance.class);
 +    
 +    expectNew(ZooKeeperInstance.class, clientConf).andReturn(theInstance);
 +    replay(theInstance, ZooKeeperInstance.class);
 +
 +    shell.setInstance(opts);
 +    verify(theInstance, ZooKeeperInstance.class);
 +  }
 +  @Test
 +  public void testSetInstance_ZKInstance_DashZ() throws Exception {
 +    testSetInstance_ZKInstance(true);
 +  }
 +  @Test
 +  public void testSetInstance_ZKInstance_DashZIandZH() throws Exception {
 +    testSetInstance_ZKInstance(false);
 +  }
 +  private void testSetInstance_ZKInstance(boolean dashZ) throws Exception {
 +    ClientConfiguration clientConf = createMock(ClientConfiguration.class);
 +    ShellOptionsJC opts = createMock(ShellOptionsJC.class);
 +    expect(opts.isFake()).andReturn(false);
 +    expect(opts.getClientConfiguration()).andReturn(clientConf);
 +    expect(opts.isHdfsZooInstance()).andReturn(false);
 +    if (dashZ) {
 +      expect(clientConf.withInstance("foo")).andReturn(clientConf);
 +      expect(clientConf.withZkHosts("host1,host2")).andReturn(clientConf);
 +      List<String> zl = new java.util.ArrayList<String>();
 +      zl.add("foo");
 +      zl.add("host1,host2");
 +      expect(opts.getZooKeeperInstance()).andReturn(zl);
 +      expectLastCall().anyTimes();
 +    } else {
 +      expect(clientConf.withInstance("bar")).andReturn(clientConf);
 +      expect(clientConf.withZkHosts("host3,host4")).andReturn(clientConf);
 +      expect(opts.getZooKeeperInstance()).andReturn(Collections.<String>emptyList());
 +      expect(opts.getZooKeeperInstanceName()).andReturn("bar");
 +      expect(opts.getZooKeeperHosts()).andReturn("host3,host4");
 +    }
 +    replay(clientConf);
 +    replay(opts);
 +
 +    ZooKeeperInstance theInstance = createMock(ZooKeeperInstance.class);
 +    expectNew(ZooKeeperInstance.class, clientConf).andReturn(theInstance);
 +    replay(theInstance, ZooKeeperInstance.class);
 +
 +    shell.setInstance(opts);
 +    verify(theInstance, ZooKeeperInstance.class);
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/da7f937b/core/src/test/java/org/apache/accumulo/core/util/shell/ShellTest.java
----------------------------------------------------------------------
diff --cc core/src/test/java/org/apache/accumulo/core/util/shell/ShellTest.java
index 4771f2c,8505370..82d1f34
--- a/core/src/test/java/org/apache/accumulo/core/util/shell/ShellTest.java
+++ b/core/src/test/java/org/apache/accumulo/core/util/shell/ShellTest.java
@@@ -19,18 -19,16 +19,20 @@@ package org.apache.accumulo.core.util.s
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertTrue;
  
 -import java.io.FileDescriptor;
 -import java.io.FileInputStream;
  import java.io.IOException;
 +import java.io.InputStream;
  import java.io.OutputStream;
+ import java.io.OutputStreamWriter;
+ import java.io.PrintWriter;
 +import java.text.DateFormat;
 +import java.text.SimpleDateFormat;
 +import java.util.Date;
  
 -import jline.ConsoleReader;
 +import jline.console.ConsoleReader;
  
 +import org.apache.accumulo.core.util.format.DateStringFormatter;
  import org.apache.log4j.Level;
 +import org.junit.After;
  import org.junit.Before;
  import org.junit.Test;
  
@@@ -103,8 -82,8 +105,9 @@@ public class ShellTest 
    public void setup() throws IOException {
      Shell.log.setLevel(Level.OFF);
      output = new TestOutputStream();
 -    PrintWriter pw = new PrintWriter( new OutputStreamWriter(output));
 -    shell = new Shell(new ConsoleReader(new FileInputStream(FileDescriptor.in), new OutputStreamWriter(output)), pw);
 +    input = new StringInputStream();
-     shell = new Shell(new ConsoleReader(input, output));
++    PrintWriter pw = new PrintWriter(new OutputStreamWriter(output));
++    shell = new Shell(new ConsoleReader(input, output), pw);
      shell.setLogErrorsToConsole();
      shell.config("--fake", "-u", "test", "-p", "secret");
    }