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 2016/07/11 03:03:31 UTC

[13/16] accumulo git commit: Merge branch '1.7' into 1.8

Merge branch '1.7' into 1.8


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

Branch: refs/heads/master
Commit: 6aa47cf9eb48f9eff36c980db2ec6a0361ce6c8c
Parents: 512a25f 1d5cd11
Author: Josh Elser <el...@apache.org>
Authored: Sun Jul 10 22:19:34 2016 -0400
Committer: Josh Elser <el...@apache.org>
Committed: Sun Jul 10 22:19:34 2016 -0400

----------------------------------------------------------------------
 .../accumulo/harness/SharedMiniClusterBase.java | 28 ++++++++++++++++----
 .../test/ArbitraryTablePropertiesIT.java        | 12 +++++++++
 .../test/CreateTableWithNewTableConfigIT.java   | 12 +++++++++
 .../org/apache/accumulo/test/ShellServerIT.java | 17 ++++++++++--
 .../accumulo/test/SplitCancelsMajCIT.java       | 12 +++++++++
 .../accumulo/test/functional/CleanUpIT.java     | 12 +++++++++
 .../functional/DeletedTablesDontFlushIT.java    | 12 +++++++++
 .../functional/TabletStateChangeIteratorIT.java | 12 +++++++++
 .../accumulo/test/proxy/SimpleProxyBase.java    |  2 ++
 .../accumulo/test/proxy/TBinaryProxyIT.java     |  2 ++
 .../accumulo/test/proxy/TCompactProxyIT.java    |  2 ++
 .../test/proxy/TJsonProtocolProxyIT.java        |  2 ++
 .../accumulo/test/proxy/TTupleProxyIT.java      |  2 ++
 .../test/replication/StatusCombinerMacIT.java   | 12 +++++++++
 14 files changed, 132 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/6aa47cf9/test/src/main/java/org/apache/accumulo/harness/SharedMiniClusterBase.java
----------------------------------------------------------------------
diff --cc test/src/main/java/org/apache/accumulo/harness/SharedMiniClusterBase.java
index cb0fa7b,0000000..544b5de
mode 100644,000000..100644
--- a/test/src/main/java/org/apache/accumulo/harness/SharedMiniClusterBase.java
+++ b/test/src/main/java/org/apache/accumulo/harness/SharedMiniClusterBase.java
@@@ -1,186 -1,0 +1,204 @@@
 +/*
 + * 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.harness;
 +
 +import static org.junit.Assert.assertTrue;
 +
 +import java.io.File;
 +import java.io.IOException;
 +import java.util.Random;
 +
 +import org.apache.accumulo.cluster.ClusterUser;
 +import org.apache.accumulo.cluster.ClusterUsers;
 +import org.apache.accumulo.core.client.Connector;
 +import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
 +import org.apache.accumulo.core.client.security.tokens.KerberosToken;
 +import org.apache.accumulo.core.client.security.tokens.PasswordToken;
 +import org.apache.accumulo.core.conf.Property;
 +import org.apache.accumulo.core.security.TablePermission;
 +import org.apache.accumulo.minicluster.impl.MiniAccumuloClusterImpl;
 +import org.apache.hadoop.conf.Configuration;
 +import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
 +import org.apache.hadoop.security.UserGroupInformation;
- import org.junit.AfterClass;
- import org.junit.BeforeClass;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +
 +/**
 + * Convenience class which starts a single MAC instance for a test to leverage.
 + *
 + * There isn't a good way to build this off of the {@link AccumuloClusterHarness} (as would be the logical place) because we need to start the
 + * MiniAccumuloCluster in a static BeforeClass-annotated method. Because it is static and invoked before any other BeforeClass methods in the implementation,
 + * the actual test classes can't expose any information to tell the base class that it is to perform the one-MAC-per-class semantics.
++ *
++ * Implementations of this class must be sure to invoke {@link #startMiniCluster()} or {@link #startMiniClusterWithConfig(MiniClusterConfigurationCallback)} in
++ * a method annotated with the {@link org.junit.BeforeClass} JUnit annotation and {@link #stopMiniCluster()} in a method annotated with the
++ * {@link org.junit.AfterClass} JUnit annotation.
 + */
 +public abstract class SharedMiniClusterBase extends AccumuloITBase implements ClusterUsers {
 +  private static final Logger log = LoggerFactory.getLogger(SharedMiniClusterBase.class);
 +  public static final String TRUE = Boolean.toString(true);
 +
 +  private static String principal = "root";
 +  private static String rootPassword;
 +  private static AuthenticationToken token;
 +  private static MiniAccumuloClusterImpl cluster;
 +  private static TestingKdc krb;
 +
-   @BeforeClass
++  /**
++   * Starts a MiniAccumuloCluster instance with the default configuration.
++   */
 +  public static void startMiniCluster() throws Exception {
++    startMiniClusterWithConfig(MiniClusterConfigurationCallback.NO_CALLBACK);
++  }
++
++  /**
++   * Starts a MiniAccumuloCluster instance with the default configuration but also provides the caller the opportunity to update the configuration before the
++   * MiniAccumuloCluster is started.
++   *
++   * @param miniClusterCallback
++   *          A callback to configure the minicluster before it is started.
++   */
++  public static void startMiniClusterWithConfig(MiniClusterConfigurationCallback miniClusterCallback) throws Exception {
 +    File baseDir = new File(System.getProperty("user.dir") + "/target/mini-tests");
 +    assertTrue(baseDir.mkdirs() || baseDir.isDirectory());
 +
 +    // Make a shared MAC instance instead of spinning up one per test method
 +    MiniClusterHarness harness = new MiniClusterHarness();
 +
 +    if (TRUE.equals(System.getProperty(MiniClusterHarness.USE_KERBEROS_FOR_IT_OPTION))) {
 +      krb = new TestingKdc();
 +      krb.start();
 +      // Enabled krb auth
 +      Configuration conf = new Configuration(false);
 +      conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION, "kerberos");
 +      UserGroupInformation.setConfiguration(conf);
 +      // Login as the client
 +      ClusterUser rootUser = krb.getRootUser();
 +      // Get the krb token
 +      UserGroupInformation.loginUserFromKeytab(rootUser.getPrincipal(), rootUser.getKeytab().getAbsolutePath());
 +      token = new KerberosToken();
 +    } else {
 +      rootPassword = "rootPasswordShared1";
 +      token = new PasswordToken(rootPassword);
 +    }
 +
-     cluster = harness.create(SharedMiniClusterBase.class.getName(), System.currentTimeMillis() + "_" + new Random().nextInt(Short.MAX_VALUE), token, krb);
++    cluster = harness.create(SharedMiniClusterBase.class.getName(), System.currentTimeMillis() + "_" + new Random().nextInt(Short.MAX_VALUE), token,
++        miniClusterCallback, krb);
 +    cluster.start();
 +
 +    if (null != krb) {
 +      final String traceTable = Property.TRACE_TABLE.getDefaultValue();
 +      final ClusterUser systemUser = krb.getAccumuloServerUser(), rootUser = krb.getRootUser();
 +      // Login as the trace user
 +      // Open a connector as the system user (ensures the user will exist for us to assign permissions to)
 +      UserGroupInformation.loginUserFromKeytab(systemUser.getPrincipal(), systemUser.getKeytab().getAbsolutePath());
 +      Connector conn = cluster.getConnector(systemUser.getPrincipal(), new KerberosToken());
 +
 +      // Then, log back in as the "root" user and do the grant
 +      UserGroupInformation.loginUserFromKeytab(rootUser.getPrincipal(), rootUser.getKeytab().getAbsolutePath());
 +      conn = cluster.getConnector(principal, token);
 +
 +      // Create the trace table
 +      conn.tableOperations().create(traceTable);
 +
 +      // Trace user (which is the same kerberos principal as the system user, but using a normal KerberosToken) needs
 +      // to have the ability to read, write and alter the trace table
 +      conn.securityOperations().grantTablePermission(systemUser.getPrincipal(), traceTable, TablePermission.READ);
 +      conn.securityOperations().grantTablePermission(systemUser.getPrincipal(), traceTable, TablePermission.WRITE);
 +      conn.securityOperations().grantTablePermission(systemUser.getPrincipal(), traceTable, TablePermission.ALTER_TABLE);
 +    }
 +  }
 +
-   @AfterClass
++  /**
++   * Stops the MiniAccumuloCluster and related services if they are running.
++   */
 +  public static void stopMiniCluster() throws Exception {
 +    if (null != cluster) {
 +      try {
 +        cluster.stop();
 +      } catch (Exception e) {
 +        log.error("Failed to stop minicluster", e);
 +      }
 +    }
 +    if (null != krb) {
 +      try {
 +        krb.stop();
 +      } catch (Exception e) {
 +        log.error("Failed to stop KDC", e);
 +      }
 +    }
 +  }
 +
 +  public static String getRootPassword() {
 +    return rootPassword;
 +  }
 +
 +  public static AuthenticationToken getToken() {
 +    if (token instanceof KerberosToken) {
 +      try {
 +        UserGroupInformation.loginUserFromKeytab(getPrincipal(), krb.getRootUser().getKeytab().getAbsolutePath());
 +      } catch (IOException e) {
 +        throw new RuntimeException("Failed to login", e);
 +      }
 +    }
 +    return token;
 +  }
 +
 +  public static String getPrincipal() {
 +    return principal;
 +  }
 +
 +  public static MiniAccumuloClusterImpl getCluster() {
 +    return cluster;
 +  }
 +
 +  public static File getMiniClusterDir() {
 +    return cluster.getConfig().getDir();
 +  }
 +
 +  public static Connector getConnector() {
 +    try {
 +      return getCluster().getConnector(principal, getToken());
 +    } catch (Exception e) {
 +      throw new RuntimeException(e);
 +    }
 +  }
 +
 +  public static TestingKdc getKdc() {
 +    return krb;
 +  }
 +
 +  @Override
 +  public ClusterUser getAdminUser() {
 +    if (null == krb) {
 +      return new ClusterUser(getPrincipal(), getRootPassword());
 +    } else {
 +      return krb.getRootUser();
 +    }
 +  }
 +
 +  @Override
 +  public ClusterUser getUser(int offset) {
 +    if (null == krb) {
 +      String user = SharedMiniClusterBase.class.getName() + "_" + testName.getMethodName() + "_" + offset;
 +      // Password is the username
 +      return new ClusterUser(user, user);
 +    } else {
 +      return krb.getClientPrincipal(offset);
 +    }
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6aa47cf9/test/src/main/java/org/apache/accumulo/test/ArbitraryTablePropertiesIT.java
----------------------------------------------------------------------
diff --cc test/src/main/java/org/apache/accumulo/test/ArbitraryTablePropertiesIT.java
index 44124e4,0000000..0c38464
mode 100644,000000..100644
--- a/test/src/main/java/org/apache/accumulo/test/ArbitraryTablePropertiesIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/ArbitraryTablePropertiesIT.java
@@@ -1,198 -1,0 +1,210 @@@
 +/*
 + * 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.test;
 +
 +import java.util.Map.Entry;
 +
 +import org.apache.accumulo.cluster.ClusterUser;
 +import org.apache.accumulo.core.client.AccumuloSecurityException;
 +import org.apache.accumulo.core.client.Connector;
 +import org.apache.accumulo.core.client.security.tokens.AuthenticationToken;
 +import org.apache.accumulo.core.client.security.tokens.PasswordToken;
 +import org.apache.accumulo.core.conf.Property;
 +import org.apache.accumulo.core.security.TablePermission;
 +import org.apache.accumulo.harness.SharedMiniClusterBase;
++import org.junit.AfterClass;
 +import org.junit.Assert;
++import org.junit.BeforeClass;
 +import org.junit.Test;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +
 +public class ArbitraryTablePropertiesIT extends SharedMiniClusterBase {
 +  private static final Logger log = LoggerFactory.getLogger(ArbitraryTablePropertiesIT.class);
 +
 +  @Override
 +  protected int defaultTimeoutSeconds() {
 +    return 30;
 +  }
 +
++  @BeforeClass
++  public static void setup() throws Exception {
++    SharedMiniClusterBase.startMiniCluster();
++  }
++
++  @AfterClass
++  public static void teardown() throws Exception {
++    SharedMiniClusterBase.stopMiniCluster();
++  }
++
 +  // Test set, get, and remove arbitrary table properties on the root account
 +  @Test
 +  public void setGetRemoveTablePropertyRoot() throws Exception {
 +    log.debug("Starting setGetRemoveTablePropertyRoot test ------------------------");
 +
 +    // make a table
 +    final String tableName = getUniqueNames(1)[0];
 +    final Connector conn = getConnector();
 +    conn.tableOperations().create(tableName);
 +
 +    // Set variables for the property name to use and the initial value
 +    String propertyName = "table.custom.description";
 +    String description1 = "Description";
 +
 +    // Make sure the property name is valid
 +    Assert.assertTrue(Property.isValidPropertyKey(propertyName));
 +    // Set the property to the desired value
 +    conn.tableOperations().setProperty(tableName, propertyName, description1);
 +
 +    // Loop through properties to make sure the new property is added to the list
 +    int count = 0;
 +    for (Entry<String,String> property : conn.tableOperations().getProperties(tableName)) {
 +      if (property.getKey().equals(propertyName) && property.getValue().equals(description1))
 +        count++;
 +    }
 +    Assert.assertEquals(count, 1);
 +
 +    // Set the property as something different
 +    String description2 = "set second";
 +    conn.tableOperations().setProperty(tableName, propertyName, description2);
 +
 +    // / Loop through properties to make sure the new property is added to the list
 +    count = 0;
 +    for (Entry<String,String> property : conn.tableOperations().getProperties(tableName)) {
 +      if (property.getKey().equals(propertyName) && property.getValue().equals(description2))
 +        count++;
 +    }
 +    Assert.assertEquals(count, 1);
 +
 +    // Remove the property and make sure there is no longer a value associated with it
 +    conn.tableOperations().removeProperty(tableName, propertyName);
 +
 +    // / Loop through properties to make sure the new property is added to the list
 +    count = 0;
 +    for (Entry<String,String> property : conn.tableOperations().getProperties(tableName)) {
 +      if (property.getKey().equals(propertyName))
 +        count++;
 +    }
 +    Assert.assertEquals(count, 0);
 +  }
 +
 +  // Tests set, get, and remove of user added arbitrary properties using a non-root account with permissions to alter tables
 +  @Test
 +  public void userSetGetRemoveTablePropertyWithPermission() throws Exception {
 +    log.debug("Starting userSetGetRemoveTablePropertyWithPermission test ------------------------");
 +
 +    // Make a test username and password
 +    ClusterUser user = getUser(0);
 +    String testUser = user.getPrincipal();
 +    AuthenticationToken testToken = user.getToken();
 +
 +    // Create a root user and create the table
 +    // Create a test user and grant that user permission to alter the table
 +    final String tableName = getUniqueNames(1)[0];
 +    final Connector c = getConnector();
 +    c.securityOperations().createLocalUser(testUser, (testToken instanceof PasswordToken ? (PasswordToken) testToken : null));
 +    c.tableOperations().create(tableName);
 +    c.securityOperations().grantTablePermission(testUser, tableName, TablePermission.ALTER_TABLE);
 +
 +    // Set variables for the property name to use and the initial value
 +    String propertyName = "table.custom.description";
 +    String description1 = "Description";
 +
 +    // Make sure the property name is valid
 +    Assert.assertTrue(Property.isValidPropertyKey(propertyName));
 +
 +    // Getting a fresh token will ensure we're logged in as this user (if necessary)
 +    Connector testConn = c.getInstance().getConnector(testUser, user.getToken());
 +    // Set the property to the desired value
 +    testConn.tableOperations().setProperty(tableName, propertyName, description1);
 +
 +    // Loop through properties to make sure the new property is added to the list
 +    int count = 0;
 +    for (Entry<String,String> property : testConn.tableOperations().getProperties(tableName)) {
 +      if (property.getKey().equals(propertyName) && property.getValue().equals(description1))
 +        count++;
 +    }
 +    Assert.assertEquals(count, 1);
 +
 +    // Set the property as something different
 +    String description2 = "set second";
 +    testConn.tableOperations().setProperty(tableName, propertyName, description2);
 +
 +    // / Loop through properties to make sure the new property is added to the list
 +    count = 0;
 +    for (Entry<String,String> property : testConn.tableOperations().getProperties(tableName)) {
 +      if (property.getKey().equals(propertyName) && property.getValue().equals(description2))
 +        count++;
 +    }
 +    Assert.assertEquals(count, 1);
 +
 +    // Remove the property and make sure there is no longer a value associated with it
 +    testConn.tableOperations().removeProperty(tableName, propertyName);
 +
 +    // / Loop through properties to make sure the new property is added to the list
 +    count = 0;
 +    for (Entry<String,String> property : testConn.tableOperations().getProperties(tableName)) {
 +      if (property.getKey().equals(propertyName))
 +        count++;
 +    }
 +    Assert.assertEquals(count, 0);
 +
 +  }
 +
 +  // Tests set and get of user added arbitrary properties using a non-root account without permissions to alter tables
 +  @Test
 +  public void userSetGetTablePropertyWithoutPermission() throws Exception {
 +    log.debug("Starting userSetGetTablePropertyWithoutPermission test ------------------------");
 +
 +    // Make a test username and password
 +    ClusterUser user = getUser(1);
 +    String testUser = user.getPrincipal();
 +    AuthenticationToken testToken = user.getToken();
 +
 +    // Create a root user and create the table
 +    // Create a test user and grant that user permission to alter the table
 +    final String tableName = getUniqueNames(1)[0];
 +    final Connector c = getConnector();
 +    c.securityOperations().createLocalUser(testUser, (testToken instanceof PasswordToken ? (PasswordToken) testToken : null));
 +    c.tableOperations().create(tableName);
 +
 +    // Set variables for the property name to use and the initial value
 +    String propertyName = "table.custom.description";
 +    String description1 = "Description";
 +
 +    // Make sure the property name is valid
 +    Assert.assertTrue(Property.isValidPropertyKey(propertyName));
 +
 +    // Getting a fresh token will ensure we're logged in as this user (if necessary)
 +    Connector testConn = c.getInstance().getConnector(testUser, user.getToken());
 +
 +    // Try to set the property to the desired value.
 +    // If able to set it, the test fails, since permission was never granted
 +    try {
 +      testConn.tableOperations().setProperty(tableName, propertyName, description1);
 +      Assert.fail("Was able to set property without permissions");
 +    } catch (AccumuloSecurityException e) {}
 +
 +    // Loop through properties to make sure the new property is not added to the list
 +    int count = 0;
 +    for (Entry<String,String> property : testConn.tableOperations().getProperties(tableName)) {
 +      if (property.getKey().equals(propertyName))
 +        count++;
 +    }
 +    Assert.assertEquals(count, 0);
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/accumulo/blob/6aa47cf9/test/src/main/java/org/apache/accumulo/test/CreateTableWithNewTableConfigIT.java
----------------------------------------------------------------------
diff --cc test/src/main/java/org/apache/accumulo/test/CreateTableWithNewTableConfigIT.java
index a78b583,0000000..7fd2dd1
mode 100644,000000..100644
--- a/test/src/main/java/org/apache/accumulo/test/CreateTableWithNewTableConfigIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/CreateTableWithNewTableConfigIT.java
@@@ -1,193 -1,0 +1,205 @@@
 +/*
 + * 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.test;
 +
 +import java.util.HashMap;
 +import java.util.Map;
 +import java.util.Map.Entry;
 +
 +import org.apache.accumulo.core.client.AccumuloException;
 +import org.apache.accumulo.core.client.Connector;
 +import org.apache.accumulo.core.client.Scanner;
 +import org.apache.accumulo.core.client.TableNotFoundException;
 +import org.apache.accumulo.core.client.admin.NewTableConfiguration;
 +import org.apache.accumulo.core.client.admin.TimeType;
 +import org.apache.accumulo.core.conf.Property;
 +import org.apache.accumulo.core.data.Key;
 +import org.apache.accumulo.core.data.Value;
 +import org.apache.accumulo.core.metadata.MetadataTable;
 +import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection.ServerColumnFamily;
 +import org.apache.accumulo.core.security.Authorizations;
 +import org.apache.accumulo.harness.SharedMiniClusterBase;
++import org.junit.AfterClass;
 +import org.junit.Assert;
++import org.junit.BeforeClass;
 +import org.junit.Test;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +
 +import com.google.common.collect.Iterators;
 +
 +/**
 + *
 + */
 +public class CreateTableWithNewTableConfigIT extends SharedMiniClusterBase {
 +  static private final Logger log = LoggerFactory.getLogger(CreateTableWithNewTableConfigIT.class);
 +
 +  @Override
 +  protected int defaultTimeoutSeconds() {
 +    return 30;
 +  }
 +
++  @BeforeClass
++  public static void setup() throws Exception {
++    SharedMiniClusterBase.startMiniCluster();
++  }
++
++  @AfterClass
++  public static void teardown() throws Exception {
++    SharedMiniClusterBase.stopMiniCluster();
++  }
++
 +  public int numProperties(Connector connector, String tableName) throws AccumuloException, TableNotFoundException {
 +    return Iterators.size(connector.tableOperations().getProperties(tableName).iterator());
 +  }
 +
 +  public int compareProperties(Connector connector, String tableNameOrig, String tableName, String changedProp) throws AccumuloException,
 +      TableNotFoundException {
 +    boolean inNew = false;
 +    int countOrig = 0;
 +    for (Entry<String,String> orig : connector.tableOperations().getProperties(tableNameOrig)) {
 +      countOrig++;
 +      for (Entry<String,String> entry : connector.tableOperations().getProperties(tableName)) {
 +        if (entry.equals(orig)) {
 +          inNew = true;
 +          break;
 +        } else if (entry.getKey().equals(orig.getKey()) && !entry.getKey().equals(changedProp))
 +          Assert.fail("Property " + orig.getKey() + " has different value than deprecated method");
 +      }
 +      if (!inNew)
 +        Assert.fail("Original property missing after using the new create method");
 +    }
 +    return countOrig;
 +  }
 +
 +  public boolean checkTimeType(Connector connector, String tableName, TimeType expectedTimeType) throws TableNotFoundException {
 +    final Scanner scanner = connector.createScanner(MetadataTable.NAME, Authorizations.EMPTY);
 +    String tableID = connector.tableOperations().tableIdMap().get(tableName) + "<";
 +    for (Entry<Key,Value> entry : scanner) {
 +      Key k = entry.getKey();
 +
 +      if (k.getRow().toString().equals(tableID) && k.getColumnQualifier().toString().equals(ServerColumnFamily.TIME_COLUMN.getColumnQualifier().toString())) {
 +        if (expectedTimeType == TimeType.MILLIS && entry.getValue().toString().charAt(0) == 'M')
 +          return true;
 +        if (expectedTimeType == TimeType.LOGICAL && entry.getValue().toString().charAt(0) == 'L')
 +          return true;
 +      }
 +    }
 +    return false;
 +  }
 +
 +  @SuppressWarnings("deprecation")
 +  @Test
 +  public void tableNameOnly() throws Exception {
 +    log.info("Starting tableNameOnly");
 +
 +    // Create a table with the initial properties
 +    Connector connector = getConnector();
 +    String tableName = getUniqueNames(2)[0];
 +    connector.tableOperations().create(tableName, new NewTableConfiguration());
 +
 +    String tableNameOrig = "original";
 +    connector.tableOperations().create(tableNameOrig, true);
 +
 +    int countNew = numProperties(connector, tableName);
 +    int countOrig = compareProperties(connector, tableNameOrig, tableName, null);
 +
 +    Assert.assertEquals("Extra properties using the new create method", countOrig, countNew);
 +    Assert.assertTrue("Wrong TimeType", checkTimeType(connector, tableName, TimeType.MILLIS));
 +  }
 +
 +  @SuppressWarnings("deprecation")
 +  @Test
 +  public void tableNameAndLimitVersion() throws Exception {
 +    log.info("Starting tableNameAndLimitVersion");
 +
 +    // Create a table with the initial properties
 +    Connector connector = getConnector();
 +    String tableName = getUniqueNames(2)[0];
 +    boolean limitVersion = false;
 +    connector.tableOperations().create(tableName, new NewTableConfiguration().withoutDefaultIterators());
 +
 +    String tableNameOrig = "originalWithLimitVersion";
 +    connector.tableOperations().create(tableNameOrig, limitVersion);
 +
 +    int countNew = numProperties(connector, tableName);
 +    int countOrig = compareProperties(connector, tableNameOrig, tableName, null);
 +
 +    Assert.assertEquals("Extra properties using the new create method", countOrig, countNew);
 +    Assert.assertTrue("Wrong TimeType", checkTimeType(connector, tableName, TimeType.MILLIS));
 +  }
 +
 +  @SuppressWarnings("deprecation")
 +  @Test
 +  public void tableNameLimitVersionAndTimeType() throws Exception {
 +    log.info("Starting tableNameLimitVersionAndTimeType");
 +
 +    // Create a table with the initial properties
 +    Connector connector = getConnector();
 +    String tableName = getUniqueNames(2)[0];
 +    boolean limitVersion = false;
 +    TimeType tt = TimeType.LOGICAL;
 +    connector.tableOperations().create(tableName, new NewTableConfiguration().withoutDefaultIterators().setTimeType(tt));
 +
 +    String tableNameOrig = "originalWithLimitVersionAndTimeType";
 +    connector.tableOperations().create(tableNameOrig, limitVersion, tt);
 +
 +    int countNew = numProperties(connector, tableName);
 +    int countOrig = compareProperties(connector, tableNameOrig, tableName, null);
 +
 +    Assert.assertEquals("Extra properties using the new create method", countOrig, countNew);
 +    Assert.assertTrue("Wrong TimeType", checkTimeType(connector, tableName, tt));
 +  }
 +
 +  @SuppressWarnings("deprecation")
 +  @Test
 +  public void addCustomPropAndChangeExisting() throws Exception {
 +    log.info("Starting addCustomPropAndChangeExisting");
 +
 +    // Create and populate initial properties map for creating table 1
 +    Map<String,String> properties = new HashMap<>();
 +    String propertyName = Property.TABLE_SPLIT_THRESHOLD.getKey();
 +    String volume = "10K";
 +    properties.put(propertyName, volume);
 +
 +    String propertyName2 = "table.custom.testProp";
 +    String volume2 = "Test property";
 +    properties.put(propertyName2, volume2);
 +
 +    // Create a table with the initial properties
 +    Connector connector = getConnector();
 +    String tableName = getUniqueNames(2)[0];
 +    connector.tableOperations().create(tableName, new NewTableConfiguration().setProperties(properties));
 +
 +    String tableNameOrig = "originalWithTableName";
 +    connector.tableOperations().create(tableNameOrig, true);
 +
 +    int countNew = numProperties(connector, tableName);
 +    int countOrig = compareProperties(connector, tableNameOrig, tableName, propertyName);
 +
 +    for (Entry<String,String> entry : connector.tableOperations().getProperties(tableName)) {
 +      if (entry.getKey().equals(Property.TABLE_SPLIT_THRESHOLD.getKey()))
 +        Assert.assertTrue("TABLE_SPLIT_THRESHOLD has been changed", entry.getValue().equals("10K"));
 +      if (entry.getKey().equals("table.custom.testProp"))
 +        Assert.assertTrue("table.custom.testProp has been changed", entry.getValue().equals("Test property"));
 +    }
 +
 +    Assert.assertEquals("Extra properties using the new create method", countOrig + 1, countNew);
 +    Assert.assertTrue("Wrong TimeType", checkTimeType(connector, tableName, TimeType.MILLIS));
 +
 +  }
 +}