private Table createTableWithCapabilities(Map<String, Object> props) throws Exception {
      String catalog = (String)props.getOrDefault("CATALOG", MetaStoreUtils.getDefaultCatalog(conf));
      String dbName = (String)props.getOrDefault("DBNAME", "simpdb");
      String tblName = (String)props.getOrDefault("TBLNAME", "test_table");
      TableType type = (TableType)props.getOrDefault("TBLTYPE", TableType.MANAGED_TABLE);
      int buckets = ((Integer)props.getOrDefault("BUCKETS", -1)).intValue();
      String properties = (String)props.getOrDefault("PROPERTIES", "");
      String location = (String)(props.get("LOCATION"));
      boolean dropDb = ((Boolean)props.getOrDefault("DROPDB", Boolean.TRUE)).booleanValue();
      int partitionCount = ((Integer)props.getOrDefault("PARTITIONS", 0)).intValue();

      final String typeName = "Person";

      if (type == TableType.EXTERNAL_TABLE) {
        if (!properties.contains("EXTERNAL=TRUE")) {
          properties.concat(";EXTERNAL=TRUE;");
        }
      }

      Map<String,String> table_params = new HashMap();
      if (properties.length() > 0) {
        String[] propArray = properties.split(";");
        for (String prop : propArray) {
          String[] keyValue = prop.split("=");
          table_params.put(keyValue[0], keyValue[1]);
        }
      }

      Catalog cat = null;
      try {
        cat = client.getCatalog(catalog);
      } catch (NoSuchObjectException e) {
        LOG.info("Catalog does not exist, creating a new one");
        try {
          if (cat == null) {
            cat = new Catalog();
            cat.setName(catalog.toLowerCase());
            Warehouse wh = new Warehouse(conf);
            cat.setLocationUri(wh.getWhRootExternal().toString() + File.separator + catalog);
            cat.setDescription("Non-hive catalog");
            client.createCatalog(cat);
            LOG.info("Catalog " + catalog + " created");
          }
        } catch (Exception ce) {
          LOG.warn("Catalog " + catalog + " could not be created");
        }
      } catch (Exception e) {
        LOG.error("Creation of a new catalog failed, aborting test");
        throw e;
      }

      try {
        client.dropTable(dbName, tblName);
      } catch (Exception e) {
        LOG.info("Drop table failed for " + dbName + "." + tblName);
      }

      try {
        if (dropDb)
          silentDropDatabase(dbName);
      } catch (Exception e) {
        LOG.info("Drop database failed for " + dbName);
      }

      if (dropDb)
        new DatabaseBuilder()
          .setName(dbName)
          .setCatalogName(catalog)
          .create(client, conf);

      try {
        client.dropType(typeName);
      } catch (Exception e) {
        LOG.info("Drop type failed for " + typeName);
      }

      Type typ1 = new Type();
      typ1.setName(typeName);
      typ1.setFields(new ArrayList<>(2));
      typ1.getFields().add(
          new FieldSchema("name", ColumnType.STRING_TYPE_NAME, ""));
      typ1.getFields().add(
          new FieldSchema("income", ColumnType.INT_TYPE_NAME, ""));
      client.createType(typ1);

      TableBuilder builder = new TableBuilder()
          .setCatName(catalog)
          .setDbName(dbName)
          .setTableName(tblName)
          .setCols(typ1.getFields())
          .setType(type.name())
          .setLocation(location)
          .setNumBuckets(buckets)
          .setTableParams(table_params)
          .addBucketCol("name")
          .addStorageDescriptorParam("test_param_1", "Use this for comments etc");

      if (location != null)
        builder.setLocation(location);

      if (buckets > 0)
        builder.setNumBuckets(buckets).addBucketCol("name");

      if (partitionCount > 0) {
        builder.addPartCol("partcol", "string");
      }

      if (type == TableType.MANAGED_TABLE) {
        if (properties.contains("transactional=true") && !properties.contains("transactional_properties=insert_only")) {
          builder.setInputFormat("org.apache.hadoop.hive.ql.io.orc.OrcInputFormat");
          builder.setOutputFormat("org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat");
          builder.setSerdeLib("org.apache.hadoop.hive.ql.io.orc.OrcSerde");
          builder.addStorageDescriptorParam("inputFormat", "org.apache.hadoop.hive.ql.io.orc.OrcInputFormat");
          builder.addStorageDescriptorParam("outputFormat", "org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat");
        }
      }

      Table tbl = builder.create(client, conf);
      LOG.info("Table " + tbl.getTableName() + " created:type=" + tbl.getTableType());

      if (partitionCount > 0) {
        List<Partition> partitions = new ArrayList<>();

        List<List<String>> partValues = new ArrayList<>();
        for (int i = 1; i <= partitionCount; i++) {
          partValues.add(Lists.newArrayList("" + i));
        }

        for(List<String> vals : partValues){
          addPartition(client, tbl, vals);
        }
      }

      if (isThriftClient) {
        // the createTable() above does not update the location in the 'tbl'
        // object when the client is a thrift client and the code below relies
        // on the location being present in the 'tbl' object - so get the table
        // from the metastore
        tbl = client.getTable(catalog, dbName, tblName);
        LOG.info("Fetched Table " + tbl.getTableName() + " created:type=" + tbl.getTableType());
      }
    return tbl;
  }
EXTERNAL_TABLE
  1) Old table (name in upper case) with no capabilities
  2) Old table with no capabilities
  3a) New table with capabilities with no client requirements
  3b) New table with capabilities with no matching client requirements
  3c) New table with capabilities with partial match requirements
  3d) New table with capabilities with full match requirements
itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetastoreTransformer.java