This is an automated email from the ASF dual-hosted git repository.

zghao pushed a commit to branch HBASE-14850
in repository https://gitbox.apache.org/repos/asf/hbase.git

commit 9a794e2219c717106de5086bfb1e4779a6e5aa0b
Author: tedyu <[email protected]>
AuthorDate: Mon Mar 6 14:59:39 2017 -0800

    HBASE-17680 Run mini cluster through JNI in tests
---
 hbase-native-client/Makefile                       |   4 +-
 hbase-native-client/connection/BUCK                |  12 +-
 hbase-native-client/core/BUCK                      |  30 +-
 .../core/async-rpc-retrying-test.cc                |  11 +-
 hbase-native-client/core/client-test.cc            |  49 +--
 hbase-native-client/core/filter-test.cc            |  23 +-
 hbase-native-client/core/location-cache-test.cc    |  42 ++-
 hbase-native-client/core/location-cache.cc         |   3 +-
 hbase-native-client/security/BUCK                  |   4 +-
 hbase-native-client/serde/BUCK                     |  52 +++-
 hbase-native-client/test-util/BUCK                 |  24 +-
 hbase-native-client/test-util/mini-cluster.cc      | 345 +++++++++++++++++++++
 hbase-native-client/test-util/mini-cluster.h       |  84 +++++
 hbase-native-client/test-util/test-util.cc         |  36 ++-
 hbase-native-client/test-util/test-util.h          |  30 +-
 hbase-native-client/third-party/BUCK               |   4 +-
 16 files changed, 635 insertions(+), 118 deletions(-)

diff --git a/hbase-native-client/Makefile b/hbase-native-client/Makefile
index b926220..166c6ab 100644
--- a/hbase-native-client/Makefile
+++ b/hbase-native-client/Makefile
@@ -26,13 +26,13 @@ MODULES = connection core serde test-util utils security 
exceptions
 SRC_DIR = $(MODULES)
 DEBUG_BUILD_DIR = $(addprefix $(DEBUG_PATH)/,$(MODULES))
 RELEASE_BUILD_DIR = $(addprefix $(RELEASE_PATH)/,$(MODULES))
-INCLUDE_DIR = . build/
+INCLUDE_DIR = . build/ $(JAVA_HOME)/include/ $(JAVA_HOME)/include/linux
 
 #flags to pass to the CPP compiler & linker
 CPPFLAGS_DEBUG = -D_GLIBCXX_USE_CXX11_ABI=0 -g -Wall -std=c++14 -pedantic -fPIC
 CPPFLAGS_RELEASE = -D_GLIBCXX_USE_CXX11_ABI=0 -DNDEBUG -O2 -Wall -std=c++14 
-pedantic -fPIC
 LDFLAGS = -lprotobuf -lzookeeper_mt -lsasl2 -lfolly -lwangle
-LINKFLAG = -shared
+LINKFLAG = -shared -L$(JAVA_HOME)/jre/lib/amd64/server -ljvm
 
 #define list of source files and object files
 ALLSRC = $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.cc))
diff --git a/hbase-native-client/connection/BUCK 
b/hbase-native-client/connection/BUCK
index 19536d5..bc05be0 100644
--- a/hbase-native-client/connection/BUCK
+++ b/hbase-native-client/connection/BUCK
@@ -50,8 +50,14 @@ cxx_library(
         "//third-party:wangle",
     ],
     compiler_flags=['-Weffc++'],
-    visibility=['//core/...',],)
+    visibility=[
+        '//core/...',
+    ],)
 cxx_test(
     name="connection-pool-test",
-    srcs=["connection-pool-test.cc",],
-    deps=[":connection",],)
+    srcs=[
+        "connection-pool-test.cc",
+    ],
+    deps=[
+        ":connection",
+    ],)
diff --git a/hbase-native-client/core/BUCK b/hbase-native-client/core/BUCK
index 2f4f6c1..95fb8b5 100644
--- a/hbase-native-client/core/BUCK
+++ b/hbase-native-client/core/BUCK
@@ -70,11 +70,15 @@ cxx_library(
         "//third-party:wangle",
         "//third-party:zookeeper_mt",
     ],
-    compiler_flags=['-Weffc++'],
-    visibility=['PUBLIC',],)
+    compiler_flags=['-Weffc++', '-ggdb'],
+    visibility=[
+        'PUBLIC',
+    ],)
 cxx_test(
     name="location-cache-test",
-    srcs=["location-cache-test.cc",],
+    srcs=[
+        "location-cache-test.cc",
+    ],
     deps=[
         ":core",
         "//test-util:test-util",
@@ -82,12 +86,18 @@ cxx_test(
     run_test_separately=True,)
 cxx_test(
     name="cell-test",
-    srcs=["cell-test.cc",],
-    deps=[":core",],
+    srcs=[
+        "cell-test.cc",
+    ],
+    deps=[
+        ":core",
+    ],
     run_test_separately=True,)
 cxx_test(
     name="filter-test",
-    srcs=["filter-test.cc",],
+    srcs=[
+        "filter-test.cc",
+    ],
     deps=[
         ":core",
         "//if:if",
@@ -145,7 +155,9 @@ cxx_test(
     run_test_separately=True,)
 cxx_test(
     name="client-test",
-    srcs=["client-test.cc",],
+    srcs=[
+        "client-test.cc",
+    ],
     deps=[
         ":core",
         "//if:if",
@@ -155,5 +167,7 @@ cxx_test(
     run_test_separately=True,)
 cxx_binary(
     name="simple-client",
-    srcs=["simple-client.cc",],
+    srcs=[
+        "simple-client.cc",
+    ],
     deps=[":core", "//connection:connection"],)
diff --git a/hbase-native-client/core/async-rpc-retrying-test.cc 
b/hbase-native-client/core/async-rpc-retrying-test.cc
index a9b0017..d2435b9 100644
--- a/hbase-native-client/core/async-rpc-retrying-test.cc
+++ b/hbase-native-client/core/async-rpc-retrying-test.cc
@@ -148,9 +148,9 @@ TEST(AsyncRpcRetryTest, TestGetBasic) {
 
   // Using TestUtil to populate test data
   hbase::TestUtil* test_util = new hbase::TestUtil();
-  test_util->RunShellCmd("create 't', 'd'");
-  test_util->RunShellCmd("put 't', 'test2', 'd:2', 'value2'");
-  test_util->RunShellCmd("put 't', 'test2', 'd:extra', 'value for extra'");
+  test_util->CreateTable("t", "d");
+  test_util->TablePut("t", "test2", "d", "2", "value2");
+  test_util->TablePut("t", "test2", "d", "extra", "value for extra");
 
   // Create TableName and Row to be fetched from HBase
   auto tn = folly::to<hbase::pb::TableName>("t");
@@ -159,11 +159,8 @@ TEST(AsyncRpcRetryTest, TestGetBasic) {
   // Get to be performed on above HBase Table
   hbase::Get get(row);
 
-  // Create Configuration
-  hbase::Configuration conf;
-
   // Create a client
-  Client client(conf);
+  Client client(*(test_util->conf()));
 
   // Get connection to HBase Table
   auto table = client.Table(tn);
diff --git a/hbase-native-client/core/client-test.cc 
b/hbase-native-client/core/client-test.cc
index 0a45fff..afca847 100644
--- a/hbase-native-client/core/client-test.cc
+++ b/hbase-native-client/core/client-test.cc
@@ -27,7 +27,7 @@
 #include "serde/table-name.h"
 #include "test-util/test-util.h"
 
-class ClientTest {
+class ClientTest : public ::testing::Test {
  public:
   const static std::string kDefHBaseConfPath;
 
@@ -45,10 +45,6 @@ class ClientTest {
 
   static void CreateHBaseConf(const std::string &dir, const std::string &file,
                               const std::string xml_data) {
-    // Directory will be created if not present
-    if (!boost::filesystem::exists(dir)) {
-      boost::filesystem::create_directories(dir);
-    }
     // Remove temp file always
     boost::filesystem::remove((dir + file).c_str());
     WriteDataToFile((dir + file), xml_data);
@@ -57,10 +53,16 @@ class ClientTest {
   static void CreateHBaseConfWithEnv() {
     // Creating Empty Config Files so that we dont get a Configuration 
exception @Client
     CreateHBaseConf(kDefHBaseConfPath, kHBaseDefaultXml, kHBaseXmlData);
-    CreateHBaseConf(kDefHBaseConfPath, kHBaseSiteXml, kHBaseXmlData);
+    // the hbase-site.xml would be persisted by MiniCluster
     setenv("HBASE_CONF", kDefHBaseConfPath.c_str(), 1);
   }
+  static std::unique_ptr<hbase::TestUtil> test_util;
+
+  static void SetUpTestCase() {
+    test_util = std::make_unique<hbase::TestUtil>(2, 
ClientTest::kDefHBaseConfPath.c_str());
+  }
 };
+std::unique_ptr<hbase::TestUtil> ClientTest::test_util = nullptr;
 
 const std::string 
ClientTest::kDefHBaseConfPath("./build/test-data/client-test/conf/");
 
@@ -109,16 +111,15 @@ TEST(Client, DefaultConfiguration) {
   client.Close();
 }
 
-TEST(Client, Get) {
+TEST_F(ClientTest, Get) {
   // Remove already configured env if present.
   unsetenv("HBASE_CONF");
   ClientTest::CreateHBaseConfWithEnv();
 
   // Using TestUtil to populate test data
-  hbase::TestUtil *test_util = new hbase::TestUtil();
-  test_util->RunShellCmd(
-      "create 't', 'd'; put 't', 'test2', 'd:2', 'value2'; put 't', 'test2', 
'd:extra', 'value for "
-      "extra'");
+  ClientTest::test_util->CreateTable("t", "d");
+  ClientTest::test_util->TablePut("t", "test2", "d", "2", "value2");
+  ClientTest::test_util->TablePut("t", "test2", "d", "extra", "value for 
extra");
 
   // Create TableName and Row to be fetched from HBase
   auto tn = folly::to<hbase::pb::TableName>("t");
@@ -141,12 +142,6 @@ TEST(Client, Get) {
   // Perform the Get
   auto result = table->Get(get);
 
-  // Stopping the connection as we are getting segfault due to some folly issue
-  // The connection stays open and we don't want that.
-  // So we are stopping the connection.
-  // We can remove this once we have fixed the folly part
-  delete test_util;
-
   // Test the values, should be same as in put executed on hbase shell
   ASSERT_TRUE(!result->IsEmpty()) << "Result shouldn't be empty.";
   EXPECT_EQ("test2", result->Row());
@@ -162,9 +157,6 @@ TEST(Client, GetForNonExistentTable) {
   unsetenv("HBASE_CONF");
   ClientTest::CreateHBaseConfWithEnv();
 
-  // Using TestUtil to populate test data
-  hbase::TestUtil *test_util = new hbase::TestUtil();
-
   // Create TableName and Row to be fetched from HBase
   auto tn = folly::to<hbase::pb::TableName>("t_not_exists");
   auto row = "test2";
@@ -186,24 +178,17 @@ TEST(Client, GetForNonExistentTable) {
   // Perform the Get
   ASSERT_ANY_THROW(table->Get(get)) << "Table does not exist. We should get an 
exception";
 
-  // Stopping the connection as we are getting segfault due to some folly issue
-  // The connection stays open and we don't want that.
-  // So we are stopping the connection.
-  // We can remove this once we have fixed the folly part
-  delete test_util;
-
   table->Close();
   client.Close();
 }
 
-TEST(Client, GetForNonExistentRow) {
+TEST_F(ClientTest, GetForNonExistentRow) {
   // Remove already configured env if present.
   unsetenv("HBASE_CONF");
   ClientTest::CreateHBaseConfWithEnv();
 
   // Using TestUtil to populate test data
-  hbase::TestUtil *test_util = new hbase::TestUtil();
-  test_util->RunShellCmd("create 't_exists', 'd'");
+  ClientTest::test_util->CreateTable("t_exists", "d");
 
   // Create TableName and Row to be fetched from HBase
   auto tn = folly::to<hbase::pb::TableName>("t_exists");
@@ -227,12 +212,6 @@ TEST(Client, GetForNonExistentRow) {
   auto result = table->Get(get);
   ASSERT_TRUE(result->IsEmpty()) << "Result should  be empty.";
 
-  // Stopping the connection as we are getting segfault due to some folly issue
-  // The connection stays open and we don't want that.
-  // So we are stopping the connection.
-  // We can remove this once we have fixed the folly part
-  delete test_util;
-
   table->Close();
   client.Close();
 }
diff --git a/hbase-native-client/core/filter-test.cc 
b/hbase-native-client/core/filter-test.cc
index ff683b6..6529b5a 100644
--- a/hbase-native-client/core/filter-test.cc
+++ b/hbase-native-client/core/filter-test.cc
@@ -39,7 +39,9 @@ using hbase::Comparator;
 
 class FilterTest : public ::testing::Test {
  protected:
-  static void SetUpTestCase() { test_util_ = std::make_unique<TestUtil>(); }
+  static void SetUpTestCase() {
+    test_util_ = std::make_unique<TestUtil>();
+  }
 
   static void TearDownTestCase() { test_util_.release(); }
 
@@ -49,13 +51,15 @@ class FilterTest : public ::testing::Test {
   static std::unique_ptr<TestUtil> test_util_;
 };
 
+
 std::unique_ptr<TestUtil> FilterTest::test_util_ = nullptr;
 
 TEST_F(FilterTest, GetWithColumnPrefixFilter) {
   // write row1 with 3 columns (column_1, column_2, and foo_column)
-  FilterTest::test_util_->RunShellCmd(
-      "create 't', 'd'; put 't', 'row1', 'd:column_1', 'value1'; put 't', 
'row1', 'd:column_2', "
-      "'value2'; put 't', 'row1', 'd:foo_column', 'value3'");
+  FilterTest::test_util_->CreateTable("t", "d");
+  FilterTest::test_util_->TablePut("t", "row1", "d", "column_1", "value1");
+  FilterTest::test_util_->TablePut("t", "row1", "d", "column_2", "value2");
+  FilterTest::test_util_->TablePut("t", "row1", "d", "foo_column", "value3");
 
   // Create TableName and Row to be fetched from HBase
   auto tn = folly::to<hbase::pb::TableName>("t");
@@ -70,7 +74,7 @@ TEST_F(FilterTest, GetWithColumnPrefixFilter) {
   get_two.SetFilter(FilterFactory::ColumnPrefixFilter("column_"));
 
   // Create a client
-  hbase::Client client(Configuration{});
+  hbase::Client client(*(FilterTest::test_util_->conf()));
 
   // Get connection to HBase Table
   auto table = client.Table(tn);
@@ -101,9 +105,10 @@ TEST_F(FilterTest, GetWithColumnPrefixFilter) {
 
 TEST_F(FilterTest, GetWithQualifierFilter) {
   // write row1 with 3 columns (a,b,c)
-  FilterTest::test_util_->RunShellCmd(
-      "create 't1', 'd'; put 't1', 'row1', 'd:a', 'value1'; put 't1', 'row1', 
'd:b', "
-      "'value2'; put 't1', 'row1', 'd:c', 'value3'");
+  FilterTest::test_util_->CreateTable("t1", "d");
+  FilterTest::test_util_->TablePut("t1", "row1", "d", "a", "value1");
+  FilterTest::test_util_->TablePut("t1", "row1", "d", "b", "value2");
+  FilterTest::test_util_->TablePut("t1", "row1", "d", "c", "value3");
 
   // Create TableName and Row to be fetched from HBase
   auto tn = folly::to<hbase::pb::TableName>("t1");
@@ -115,7 +120,7 @@ TEST_F(FilterTest, GetWithQualifierFilter) {
                                                
*ComparatorFactory::BinaryComparator("b")));
 
   // Create a client
-  hbase::Client client(Configuration{});
+  hbase::Client client(*(FilterTest::test_util_->conf()));
 
   // Get connection to HBase Table
   auto table = client.Table(tn);
diff --git a/hbase-native-client/core/location-cache-test.cc 
b/hbase-native-client/core/location-cache-test.cc
index 9a778c6..75a56d1 100644
--- a/hbase-native-client/core/location-cache-test.cc
+++ b/hbase-native-client/core/location-cache-test.cc
@@ -30,13 +30,29 @@
 using namespace hbase;
 using namespace std::chrono;
 
-TEST(LocationCacheTest, TestGetMetaNodeContents) {
-  TestUtil test_util{};
+class LocationCacheTest : public ::testing::Test {
+ protected:
+  static void SetUpTestCase() {
+    test_util_ = std::make_unique<TestUtil>();
+  }
+  static void TearDownTestCase() { test_util_.release(); }
+
+  virtual void SetUp() {}
+  virtual void TearDown() {}
+
+ public:
+  static std::unique_ptr<TestUtil> test_util_;
+};
+
+std::unique_ptr<TestUtil> LocationCacheTest::test_util_ = nullptr;
+
+
+TEST_F(LocationCacheTest, TestGetMetaNodeContents) {
   auto cpu = std::make_shared<wangle::CPUThreadPoolExecutor>(4);
   auto io = std::make_shared<wangle::IOThreadPoolExecutor>(4);
   auto codec = std::make_shared<KeyValueCodec>();
   auto cp = std::make_shared<ConnectionPool>(io, codec);
-  LocationCache cache{test_util.conf(), cpu, cp};
+  LocationCache cache{LocationCacheTest::test_util_->conf(), cpu, cp};
   auto f = cache.LocateMeta();
   auto result = f.get();
   ASSERT_FALSE(f.hasException());
@@ -47,19 +63,18 @@ TEST(LocationCacheTest, TestGetMetaNodeContents) {
   cp->Close();
 }
 
-TEST(LocationCacheTest, TestGetRegionLocation) {
-  TestUtil test_util{};
+TEST_F(LocationCacheTest, TestGetRegionLocation) {
   auto cpu = std::make_shared<wangle::CPUThreadPoolExecutor>(4);
   auto io = std::make_shared<wangle::IOThreadPoolExecutor>(4);
   auto codec = std::make_shared<KeyValueCodec>();
   auto cp = std::make_shared<ConnectionPool>(io, codec);
-  LocationCache cache{test_util.conf(), cpu, cp};
+  LocationCache cache{LocationCacheTest::test_util_->conf(), cpu, cp};
 
   // If there is no table this should throw an exception
   auto tn = folly::to<hbase::pb::TableName>("t");
   auto row = "test";
   ASSERT_ANY_THROW(cache.LocateFromMeta(tn, row).get(milliseconds(1000)));
-  test_util.RunShellCmd("create 't', 'd'");
+  LocationCacheTest::test_util_->CreateTable("t", "d");
   auto loc = cache.LocateFromMeta(tn, row).get(milliseconds(1000));
   ASSERT_TRUE(loc != nullptr);
   cpu->stop();
@@ -67,13 +82,12 @@ TEST(LocationCacheTest, TestGetRegionLocation) {
   cp->Close();
 }
 
-TEST(LocationCacheTest, TestCaching) {
-  TestUtil test_util{};
+TEST_F(LocationCacheTest, TestCaching) {
   auto cpu = std::make_shared<wangle::CPUThreadPoolExecutor>(4);
   auto io = std::make_shared<wangle::IOThreadPoolExecutor>(4);
   auto codec = std::make_shared<KeyValueCodec>();
   auto cp = std::make_shared<ConnectionPool>(io, codec);
-  LocationCache cache{test_util.conf(), cpu, cp};
+  LocationCache cache{LocationCacheTest::test_util_->conf(), cpu, cp};
 
   auto tn_1 = folly::to<hbase::pb::TableName>("t1");
   auto tn_2 = folly::to<hbase::pb::TableName>("t2");
@@ -83,8 +97,7 @@ TEST(LocationCacheTest, TestCaching) {
   // test location pulled from meta gets cached
   ASSERT_ANY_THROW(cache.LocateRegion(tn_1, row_a).get(milliseconds(1000)));
   ASSERT_ANY_THROW(cache.LocateFromMeta(tn_1, row_a).get(milliseconds(1000)));
-
-  test_util.RunShellCmd("create 't1', 'd'");
+  LocationCacheTest::test_util_->CreateTable("t1", "d");
 
   ASSERT_FALSE(cache.IsLocationCached(tn_1, row_a));
   auto loc = cache.LocateRegion(tn_1, row_a).get(milliseconds(1000));
@@ -92,7 +105,8 @@ TEST(LocationCacheTest, TestCaching) {
   ASSERT_EQ(loc, cache.GetCachedLocation(tn_1, row_a));
 
   // test with two regions
-  test_util.RunShellCmd("create 't2', 'd', SPLITS => ['b']");
+  std::string empty;
+  LocationCacheTest::test_util_->CreateTable("t2", "d", "b", empty);
 
   ASSERT_FALSE(cache.IsLocationCached(tn_2, "a"));
   loc = cache.LocateRegion(tn_2, "a").get(milliseconds(1000));
@@ -107,7 +121,7 @@ TEST(LocationCacheTest, TestCaching) {
   ASSERT_EQ(loc, cache.GetCachedLocation(tn_2, "ba"));
 
   // test with three regions
-  test_util.RunShellCmd("create 't3', 'd', SPLITS => ['b', 'c']");
+  LocationCacheTest::test_util_->CreateTable("t3", "d", "b", "c");
 
   ASSERT_FALSE(cache.IsLocationCached(tn_3, "c"));
   ASSERT_FALSE(cache.IsLocationCached(tn_3, "ca"));
diff --git a/hbase-native-client/core/location-cache.cc 
b/hbase-native-client/core/location-cache.cc
index 17032fe..9550614 100644
--- a/hbase-native-client/core/location-cache.cc
+++ b/hbase-native-client/core/location-cache.cc
@@ -107,7 +107,8 @@ ServerName LocationCache::ReadMetaLocation() {
                           reinterpret_cast<char *>(buf->writableData()), &len, 
nullptr);
   if (zk_result != ZOK || len < 9) {
     LOG(ERROR) << "Error getting meta location.";
-    throw runtime_error("Error getting meta location");
+    throw runtime_error("Error getting meta location. Quorum " +
+                        conf_->Get(kHBaseZookeeperQuorum_, ""));
   }
   buf->append(len);
 
diff --git a/hbase-native-client/security/BUCK 
b/hbase-native-client/security/BUCK
index e176c90..d602ff3 100644
--- a/hbase-native-client/security/BUCK
+++ b/hbase-native-client/security/BUCK
@@ -19,7 +19,9 @@
 # to a single server.
 cxx_library(
     name="security",
-    exported_headers=["user.h",],
+    exported_headers=[
+        "user.h",
+    ],
     srcs=[],
     deps=[],
     compiler_flags=['-Weffc++'],
diff --git a/hbase-native-client/serde/BUCK b/hbase-native-client/serde/BUCK
index 38e7b4d..76d1c72 100644
--- a/hbase-native-client/serde/BUCK
+++ b/hbase-native-client/serde/BUCK
@@ -41,28 +41,54 @@ cxx_library(
         ":region-info-deserializer-test",
     ],
     compiler_flags=['-Weffc++'],
-    visibility=['PUBLIC',],)
+    visibility=[
+        'PUBLIC',
+    ],)
 cxx_test(
     name="table-name-test",
-    srcs=["table-name-test.cc",],
-    deps=[":serde",],)
+    srcs=[
+        "table-name-test.cc",
+    ],
+    deps=[
+        ":serde",
+    ],)
 cxx_test(
     name="server-name-test",
-    srcs=["server-name-test.cc",],
-    deps=[":serde",],)
+    srcs=[
+        "server-name-test.cc",
+    ],
+    deps=[
+        ":serde",
+    ],)
 cxx_test(
     name="client-serializer-test",
-    srcs=["client-serializer-test.cc",],
-    deps=[":serde",],)
+    srcs=[
+        "client-serializer-test.cc",
+    ],
+    deps=[
+        ":serde",
+    ],)
 cxx_test(
     name="client-deserializer-test",
-    srcs=["client-deserializer-test.cc",],
-    deps=[":serde",],)
+    srcs=[
+        "client-deserializer-test.cc",
+    ],
+    deps=[
+        ":serde",
+    ],)
 cxx_test(
     name="zk-deserializer-test",
-    srcs=["zk-deserializer-test.cc",],
-    deps=[":serde",],)
+    srcs=[
+        "zk-deserializer-test.cc",
+    ],
+    deps=[
+        ":serde",
+    ],)
 cxx_test(
     name="region-info-deserializer-test",
-    srcs=["region-info-deserializer-test.cc",],
-    deps=[":serde",],)
+    srcs=[
+        "region-info-deserializer-test.cc",
+    ],
+    deps=[
+        ":serde",
+    ],)
diff --git a/hbase-native-client/test-util/BUCK 
b/hbase-native-client/test-util/BUCK
index c6e41f1..4998614 100644
--- a/hbase-native-client/test-util/BUCK
+++ b/hbase-native-client/test-util/BUCK
@@ -14,16 +14,34 @@
 # 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.
+import os
 
 cxx_library(name="test-util",
   exported_headers=[
-    "test-util.h",
+    "test-util.h","mini-cluster.h"
   ],
-  srcs=["test-util.cc"],
+  srcs=["test-util.cc","mini-cluster.cc"],
   deps=[
     "//third-party:folly",
-    "//core:core"
+    "//core:core",
     ],
+    preprocessor_flags= [
+    '-I' + os.environ['JAVA_HOME'] + '/include',
+    '-I' + os.environ['JAVA_HOME'] + '/include/darwin',
+    '-I' + os.environ['JAVA_HOME'] + '/include/linux'],
+    exported_preprocessor_flags= [
+    '-I' + os.environ['JAVA_HOME'] + '/include',
+    '-I' + os.environ['JAVA_HOME'] + '/include/darwin',
+    '-I' + os.environ['JAVA_HOME'] + '/include/linux'],
+    compiler_flags = [
+    '-I' + os.environ['JAVA_HOME'] + '/include',
+    '-I' + os.environ['JAVA_HOME'] + '/include/darwin',
+    '-I' + os.environ['JAVA_HOME'] + '/include/linux', '-ggdb'],
+    linker_flags = ['-ljvm',
+    '-L' + os.environ['JAVA_HOME'] + '/jre/lib/amd64/server', '-ggdb'],
+    exported_linker_flags = ['-ljvm',
+    '-L' + os.environ['JAVA_HOME'] + '/jre/lib/amd64/server',
+    '-Wl,-rpath=' + os.environ['JAVA_HOME'] + '/jre/lib/amd64/server'],
               visibility=[
                 'PUBLIC',
             ],
diff --git a/hbase-native-client/test-util/mini-cluster.cc 
b/hbase-native-client/test-util/mini-cluster.cc
new file mode 100644
index 0000000..b40b689
--- /dev/null
+++ b/hbase-native-client/test-util/mini-cluster.cc
@@ -0,0 +1,345 @@
+/*
+ * 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.
+ *
+ */
+
+#include "test-util/mini-cluster.h"
+#include <glog/logging.h>
+#include <gtest/gtest.h>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <fstream>
+#include "core/client.h"
+#include "core/configuration.h"
+#include "core/get.h"
+#include "core/hbase_configuration_loader.h"
+#include "core/result.h"
+#include "core/table.h"
+#include "serde/table-name.h"
+
+using hbase::MiniCluster;
+
+JNIEnv *MiniCluster::CreateVM(JavaVM **jvm) {
+  JavaVMInitArgs args;
+  JavaVMOption jvm_options;
+  args.version = JNI_VERSION_1_6;
+  args.nOptions = 1;
+  char *classpath = getenv("CLASSPATH");
+  std::string clspath;
+  if (classpath == NULL || strstr(classpath, "-tests.jar") == NULL) {
+    std::string clsPathFilePath("../target/cached_classpath.txt");
+    std::ifstream fd(clsPathFilePath);
+    std::string prefix("");
+    if (fd.is_open()) {
+      if (classpath == NULL) {
+        LOG(INFO) << "got empty classpath";
+      } else {
+        // prefix bootstrapper.jar
+        prefix.assign(classpath);
+      }
+      std::string line;
+      if (getline(fd, line)) {
+        clspath = prefix + ":" + line;
+        int ret = setenv("CLASSPATH", clspath.c_str(), 1);
+        LOG(INFO) << "set clspath " << ret;
+      } else {
+        LOG(INFO) << "nothing read from " << clsPathFilePath;
+        exit(-1);
+      }
+    } else {
+      LOG(INFO) << "nothing read from " << clsPathFilePath;
+      exit(-1);
+    }
+    fd.close();
+  }
+  auto options = std::string {"-Djava.class.path="} + clspath;
+  jvm_options.optionString = const_cast<char *>(options.c_str());
+  args.options = &jvm_options;
+  args.ignoreUnrecognized = 0;
+  int rv;
+  rv = JNI_CreateJavaVM(jvm, reinterpret_cast<void **>(&env_), &args);
+  if (rv < 0 || !env_) {
+    LOG(INFO) << "Unable to Launch JVM " << rv;
+  } else {
+    LOG(INFO) << "Launched JVM! " << options;
+  }
+  return env_;
+}
+
+void MiniCluster::WriteConf(jobject conf, const std::string& filepath) {
+  jclass class_fdesc = env_->FindClass("java/io/FileDescriptor");
+  // construct a new FileDescriptor
+  jmethodID const_fdesc = env_->GetMethodID(class_fdesc, "<init>", "()V");
+
+  jobject file = env_->NewObject(class_fdesc, const_fdesc);
+  jfieldID field_fd = env_->GetFieldID(class_fdesc, "fd", "I");
+
+  int fd = open(filepath.c_str(), O_RDWR | O_NONBLOCK | O_CREAT, S_IRWXU);
+  if (fd < 0) {
+    LOG(INFO) << "Couldn't open file " << filepath.c_str();
+    exit(-1);
+  }
+  env_->SetIntField(file, field_fd, fd);
+
+  jclass cls_outstream = env_->FindClass("java/io/FileOutputStream");
+  jmethodID ctor_stream = env_->GetMethodID(cls_outstream, "<init>", 
"(Ljava/io/FileDescriptor;)V");
+  if (ctor_stream == NULL) {
+    LOG(INFO) << "Couldn't get ctor for FileOutputStream";
+    exit(-1);
+  }
+  jobject file_outstream = env_->NewObject(cls_outstream, ctor_stream, file);
+  if (file_outstream == NULL) {
+    LOG(INFO) << "Couldn't create FileOutputStream";
+    exit(-1);
+  }
+  jmethodID writeXmlMid = env_->GetMethodID(conf_class_, "writeXml", 
"(Ljava/io/OutputStream;)V");
+  env_->CallObjectMethod(conf, writeXmlMid, file_outstream);
+}
+void MiniCluster::Setup() {
+  jmethodID constructor;
+  pthread_mutex_lock(&count_mutex_);
+  if (env_ == NULL) {
+    env_ = CreateVM(&jvm);
+    if (env_ == NULL) {
+      exit(-1);
+    }
+    testing_util_class_ = 
env_->FindClass("org/apache/hadoop/hbase/HBaseTestingUtility");
+    // this should be converted to a globalref I think to avoid the underlying 
java obj getting
+    // GC'ed
+    if (testing_util_class_ == NULL) {
+      LOG(INFO) << "Couldn't find class HBaseTestingUtility";
+      exit(-1);
+    }
+    jmethodID mid = env_->GetStaticMethodID(testing_util_class_, 
"createLocalHTU",
+                                           
"()Lorg/apache/hadoop/hbase/HBaseTestingUtility;");
+    htu_ = env_->CallStaticObjectMethod(testing_util_class_, mid);
+    // this should be converted to a globalref I think to avoid the underlying 
java obj getting
+    // GC'ed
+    if (htu_ == NULL) {
+      LOG(INFO) << "Couldn't invoke method createLocalHTU in 
HBaseTestingUtility";
+      exit(-1);
+    }
+    get_conn_mid_ = env_->GetMethodID(testing_util_class_, "getConnection",
+                                  
"()Lorg/apache/hadoop/hbase/client/Connection;");
+    jclass connClass = 
env_->FindClass("org/apache/hadoop/hbase/client/Connection");
+    get_admin_mid_ =
+        env_->GetMethodID(connClass, "getAdmin", 
"()Lorg/apache/hadoop/hbase/client/Admin;");
+    get_table_mid_ = env_->GetMethodID(
+        connClass, "getTable",
+        
"(Lorg/apache/hadoop/hbase/TableName;)Lorg/apache/hadoop/hbase/client/Table;");
+    if (get_table_mid_ == NULL) {
+      LOG(INFO) << "Couldn't find getConnection";
+      exit(-1);
+    }
+    jclass adminClass = 
env_->FindClass("org/apache/hadoop/hbase/client/Admin");
+    move_mid_ = env_->GetMethodID(adminClass, "move", "([B[B)V");
+    if (move_mid_ == NULL) {
+      LOG(INFO) << "Couldn't find move";
+      exit(-1);
+    }
+    create_table_mid_ = env_->GetMethodID(testing_util_class_, "createTable",
+                                      
"(Lorg/apache/hadoop/hbase/TableName;Ljava/lang/String;)Lorg/"
+                                      "apache/hadoop/hbase/client/Table;");
+    create_table_with_split_mid_ = env_->GetMethodID(
+        testing_util_class_, "createTable",
+        
"(Lorg/apache/hadoop/hbase/TableName;[[B[[B)Lorg/apache/hadoop/hbase/client/Table;");
+    if (create_table_with_split_mid_ == NULL) {
+      LOG(INFO) << "Couldn't find method createTable with split";
+      exit(-1);
+    }
+
+    table_name_class_ = env_->FindClass("org/apache/hadoop/hbase/TableName");
+    tbl_name_value_of_mid_ = env_->GetStaticMethodID(
+        table_name_class_, "valueOf", 
"(Ljava/lang/String;)Lorg/apache/hadoop/hbase/TableName;");
+    if (tbl_name_value_of_mid_ == NULL) {
+      LOG(INFO) << "Couldn't find method valueOf in TableName";
+      exit(-1);
+    }
+    jclass hbaseMiniClusterClass = 
env_->FindClass("org/apache/hadoop/hbase/MiniHBaseCluster");
+    stop_rs_mid_ =
+        env_->GetMethodID(hbaseMiniClusterClass, "stopRegionServer",
+                         
"(I)Lorg/apache/hadoop/hbase/util/JVMClusterUtil$RegionServerThread;");
+    get_conf_mid_ = env_->GetMethodID(hbaseMiniClusterClass, 
"getConfiguration",
+                                  "()Lorg/apache/hadoop/conf/Configuration;");
+
+    conf_class_ = env_->FindClass("org/apache/hadoop/conf/Configuration");
+    set_conf_mid_ = env_->GetMethodID(conf_class_, "set", 
"(Ljava/lang/String;Ljava/lang/String;)V");
+    if (set_conf_mid_ == NULL) {
+      LOG(INFO) << "Couldn't find method getConf in MiniHBaseCluster";
+      exit(-1);
+    }
+    conf_get_mid_ = env_->GetMethodID(conf_class_, "get", 
"(Ljava/lang/String;)Ljava/lang/String;");
+
+    jclass tableClass = 
env_->FindClass("org/apache/hadoop/hbase/client/Table");
+    put_mid_ = env_->GetMethodID(tableClass, "put", 
"(Lorg/apache/hadoop/hbase/client/Put;)V");
+    jclass connFactoryClass = 
env_->FindClass("org/apache/hadoop/hbase/client/ConnectionFactory");
+    create_conn_mid_ = env_->GetStaticMethodID(connFactoryClass, 
"createConnection",
+                                           
"()Lorg/apache/hadoop/hbase/client/Connection;");
+    if (create_conn_mid_ == NULL) {
+      LOG(INFO) << "Couldn't find createConnection";
+      exit(-1);
+    }
+    put_class_ = env_->FindClass("org/apache/hadoop/hbase/client/Put");
+    put_ctor_ = env_->GetMethodID(put_class_, "<init>", "([B)V");
+    add_col_mid_ =
+        env_->GetMethodID(put_class_, "addColumn", 
"([B[B[B)Lorg/apache/hadoop/hbase/client/Put;");
+    if (add_col_mid_ == NULL) {
+      LOG(INFO) << "Couldn't find method addColumn";
+      exit(-1);
+    }
+  }
+  pthread_mutex_unlock(&count_mutex_);
+}
+
+jobject MiniCluster::htu() {
+  Setup();
+  return htu_;
+}
+
+JNIEnv *MiniCluster::env() {
+  Setup();
+  return env_;
+}
+// converts C char* to Java byte[]
+jbyteArray MiniCluster::StrToByteChar(const std::string& str) {
+  char *p = const_cast<char*>(str.c_str());
+  int n = 0;
+  while (*p++) {
+    n++;
+  }
+  if (n == NULL) return NULL;
+  jbyteArray arr = env_->NewByteArray(n);
+  env_->SetByteArrayRegion(arr, 0, n, reinterpret_cast<const jbyte 
*>(str.c_str()));
+  return arr;
+}
+
+jobject MiniCluster::CreateTable(std::string tblNam, std::string familyName) {
+  jstring tblNameStr = env_->NewStringUTF(tblNam.c_str());
+  jobject tblName = env_->CallStaticObjectMethod(table_name_class_, 
tbl_name_value_of_mid_, tblNameStr);
+  jstring famStr = env_->NewStringUTF(familyName.c_str());
+  jobject tbl = env_->CallObjectMethod(htu_, create_table_mid_, tblName, 
famStr);
+  return tbl;
+}
+jobject MiniCluster::CreateTable(std::string tblNam, std::string familyName, 
std::string key1,
+        std::string key2) {
+  jstring tblNameStr = env_->NewStringUTF(tblNam.c_str());
+  jobject tblName = env_->CallStaticObjectMethod(table_name_class_, 
tbl_name_value_of_mid_, tblNameStr);
+  jclass arrayElemType = env_->FindClass("[B");
+
+  jobjectArray famArray = env_->NewObjectArray(1, arrayElemType, 
env_->NewByteArray(1));
+  env_->SetObjectArrayElement(famArray, 0, StrToByteChar(familyName));
+
+  int len = 2;
+  if (key2.empty()) len = 1;
+  jobjectArray keyArray = env_->NewObjectArray(len, arrayElemType, 
env_->NewByteArray(1));
+
+  env_->SetObjectArrayElement(keyArray, 0, StrToByteChar(key1));
+  if (!key2.empty()) {
+    env_->SetObjectArrayElement(keyArray, 1, StrToByteChar(key2));
+  }
+  jobject tbl = env_->CallObjectMethod(htu_, create_table_with_split_mid_, 
tblName, famArray, keyArray);
+  return tbl;
+}
+
+jobject MiniCluster::StopRegionServer(jobject cluster, int idx) {
+  env();
+  return env_->CallObjectMethod(cluster, stop_rs_mid_, (jint)idx);
+}
+
+// returns the Configuration for the cluster
+jobject MiniCluster::GetConf() {
+  env();
+  return env_->CallObjectMethod(cluster_, get_conf_mid_);
+}
+// return the Admin instance for the local cluster
+jobject MiniCluster::admin() {
+  env();
+  jobject conn = env_->CallObjectMethod(htu(), get_conn_mid_);
+  jobject admin = env_->CallObjectMethod(conn, get_admin_mid_);
+  return admin;
+}
+
+jobject MiniCluster::TablePut(const std::string table, const std::string row, 
const std::string fam,
+  const std::string col, const std::string value) {
+  env();
+  jobject conn = env_->CallObjectMethod(htu(), get_conn_mid_);
+  jobject put = env_->NewObject(put_class_, put_ctor_, StrToByteChar(row));
+  if (put == NULL) {
+    LOG(INFO) << "Couldn't create Put";
+    exit(-1);
+  }
+  env_->CallObjectMethod(put, add_col_mid_, StrToByteChar(fam), 
StrToByteChar(col),
+                        StrToByteChar(value));
+  jobject tblName =
+      env_->CallStaticObjectMethod(table_name_class_, tbl_name_value_of_mid_,
+              env_->NewStringUTF(table.c_str()));
+  jobject tableObj = env_->CallObjectMethod(conn, get_table_mid_, tblName);
+  env_->CallObjectMethod(tableObj, put_mid_, put);
+  return tableObj;
+}
+
+// moves region to server
+void MiniCluster::MoveRegion(std::string region, std::string server) {
+  jobject admin_ = admin();
+  env_->CallObjectMethod(admin_, move_mid_, StrToByteChar(region),
+          StrToByteChar(server));
+}
+
+jobject MiniCluster::StartCluster(int numRegionServers, std::string conf_path) 
{
+  env();
+  jmethodID mid = env_->GetMethodID(testing_util_class_, "startMiniCluster",
+                                   
"(I)Lorg/apache/hadoop/hbase/MiniHBaseCluster;");
+  if (mid == NULL) {
+    LOG(INFO) << "Couldn't find method startMiniCluster in the class 
HBaseTestingUtility";
+    exit(-1);
+  }
+  cluster_ = env_->CallObjectMethod(htu(), mid, (jint)numRegionServers);
+  jobject conf = GetConf();
+  jstring jport = (jstring)env_->CallObjectMethod(
+      conf, conf_get_mid_, 
env_->NewStringUTF("hbase.zookeeper.property.clientPort"));
+  const char *port = env_->GetStringUTFChars(jport, 0);
+  LOG(INFO) << "retrieved port " << port;
+  std::string quorum("localhost:");
+  env_->CallObjectMethod(conf, set_conf_mid_, 
env_->NewStringUTF("hbase.zookeeper.quorum"),
+                        env_->NewStringUTF((quorum + port).c_str()));
+  if (!conf_path.empty()) {
+    // Directory will be created if not present
+    if (!boost::filesystem::exists(conf_path)) {
+      boost::filesystem::create_directories(conf_path);
+    }
+    WriteConf(conf, conf_path + "/hbase-site.xml");
+  }
+  return cluster_;
+}
+
+void MiniCluster::StopCluster() {
+  env();
+  jmethodID mid = env_->GetMethodID(testing_util_class_, 
"shutdownMiniCluster", "()V");
+  env_->CallVoidMethod(htu(), mid);
+  if (jvm != NULL) {
+     jvm->DestroyJavaVM();
+     jvm = NULL;
+  }
+}
+
+const std::string MiniCluster::GetConfValue(std::string key) {
+  jobject conf = GetConf();
+  jstring jval = (jstring)env_->CallObjectMethod(conf, conf_get_mid_,
+          env_->NewStringUTF(key.c_str()));
+  const char *val = env_->GetStringUTFChars(jval, 0);
+  return val;
+}
diff --git a/hbase-native-client/test-util/mini-cluster.h 
b/hbase-native-client/test-util/mini-cluster.h
new file mode 100644
index 0000000..9b8ca92
--- /dev/null
+++ b/hbase-native-client/test-util/mini-cluster.h
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ *
+ */
+#pragma once
+
+#include <gtest/gtest.h>
+#include <string>
+#include "core/client.h"
+#include "core/configuration.h"
+#include "core/get.h"
+#include "core/hbase_configuration_loader.h"
+#include "core/result.h"
+#include "core/table.h"
+#include "jni.h"
+#include "serde/table-name.h"
+namespace hbase {
+class MiniCluster {
+ public:
+  jobject StartCluster(int numRegionServers, std::string conf_path);
+  void StopCluster();
+  jobject CreateTable(std::string tblNam, std::string familyName);
+  jobject CreateTable(std::string tblNam, std::string familyName, std::string 
key1, std::string k2);
+  jobject StopRegionServer(jobject cluster, int idx);
+
+  // moves region to server
+  void MoveRegion(std::string region, std::string server);
+  // returns the Configuration instance for the cluster
+  jobject GetConf();
+  // returns the value for config key retrieved from cluster
+  const std::string GetConfValue(std::string key);
+  // Does Put into table for family fam, qualifier col with value
+  jobject TablePut(const std::string table, const std::string row, const 
std::string fam,
+    const std::string col, const std::string value);
+
+ private:
+  JNIEnv *env_;
+  jclass testing_util_class_;
+  jclass table_name_class_;
+  jclass put_class_;
+  jclass conf_class_;
+  jmethodID stop_rs_mid_;
+  jmethodID get_conf_mid_;
+  jmethodID set_conf_mid_;
+  jmethodID tbl_name_value_of_mid_;
+  jmethodID create_table_mid_;
+  jmethodID create_table_with_split_mid_;
+  jmethodID put_mid_;
+  jmethodID put_ctor_;
+  jmethodID add_col_mid_;
+  jmethodID create_conn_mid_;
+  jmethodID get_conn_mid_;
+  jmethodID get_table_mid_;
+  jmethodID conf_get_mid_;
+  jmethodID get_admin_mid_;
+  jmethodID move_mid_;
+  jmethodID str_ctor_mid_;
+  jobject htu_;
+  jobject cluster_;
+  pthread_mutex_t count_mutex_;
+  JavaVM *jvm;
+  JNIEnv *CreateVM(JavaVM **jvm);
+  void WriteConf(jobject conf, const std::string& filepath);
+  void Setup();
+  jobject htu();
+  JNIEnv *env();
+  jbyteArray StrToByteChar(const std::string& str);
+  jobject admin();
+};
+} /*namespace hbase*/
diff --git a/hbase-native-client/test-util/test-util.cc 
b/hbase-native-client/test-util/test-util.cc
index e355bdf..13c4ec4 100644
--- a/hbase-native-client/test-util/test-util.cc
+++ b/hbase-native-client/test-util/test-util.cc
@@ -18,6 +18,7 @@
  */
 
 #include "test-util/test-util.h"
+#include <string.h>
 
 #include <folly/Format.h>
 
@@ -41,20 +42,33 @@ std::string TestUtil::RandString(int len) {
   return s;
 }
 
-TestUtil::TestUtil() : temp_dir_(TestUtil::RandString()) {
+TestUtil::TestUtil() : TestUtil::TestUtil(2, "") {}
+
+TestUtil::TestUtil(int servers, const std::string& confPath)
+    : temp_dir_(TestUtil::RandString()), numRegionServers(servers), 
conf_path(confPath) {
   auto p = temp_dir_.path().string();
-  auto cmd = std::string{"bin/start-local-hbase.sh " + p};
-  auto res_code = std::system(cmd.c_str());
-  CHECK_EQ(res_code, 0);
+  StartMiniCluster(2);
+  std::string quorum("localhost:");
+  const std::string port = 
mini->GetConfValue("hbase.zookeeper.property.clientPort");
+  conf()->Set("hbase.zookeeper.quorum", quorum + port);
 }
 
-TestUtil::~TestUtil() {
-  auto res_code = std::system("bin/stop-local-hbase.sh");
-  CHECK_EQ(res_code, 0);
+TestUtil::~TestUtil() { StopMiniCluster(); }
+
+void TestUtil::StartMiniCluster(int num_region_servers) {
+  mini = std::make_unique<MiniCluster>();
+  mini->StartCluster(num_region_servers, conf_path);
 }
+void TestUtil::StopMiniCluster() { mini->StopCluster(); }
 
-void TestUtil::RunShellCmd(const std::string &command) {
-  auto cmd_string = folly::sformat("echo \"{}\" | ../bin/hbase shell", 
command);
-  auto res_code = std::system(cmd_string.c_str());
-  CHECK_EQ(res_code, 0);
+void TestUtil::CreateTable(std::string tblNam, std::string familyName) {
+  mini->CreateTable(tblNam, familyName);
+}
+void TestUtil::CreateTable(std::string tblNam, std::string familyName, 
std::string key1,
+        std::string k2) {
+  mini->CreateTable(tblNam, familyName, key1, k2);
+}
+void TestUtil::TablePut(std::string table, std::string row, std::string fam, 
std::string col,
+        std::string value) {
+  mini->TablePut(table, row, fam, col, value);
 }
diff --git a/hbase-native-client/test-util/test-util.h 
b/hbase-native-client/test-util/test-util.h
index cc35511..1734870 100644
--- a/hbase-native-client/test-util/test-util.h
+++ b/hbase-native-client/test-util/test-util.h
@@ -22,9 +22,10 @@
 #include <folly/experimental/TestUtil.h>
 
 #include <cstdlib>
+#include <memory>
 #include <string>
-
 #include "core/configuration.h"
+#include "test-util/mini-cluster.h"
 
 namespace hbase {
 /**
@@ -36,20 +37,15 @@ class TestUtil {
    * Creating a TestUtil will spin up a cluster.
    */
   TestUtil();
-
   /**
-   * Destroying a TestUtil will spin down a cluster and remove the test dir.
+   * Creating a TestUtil will spin up a cluster with numRegionServers region 
servers.
    */
-  ~TestUtil();
+  TestUtil(int numRegionServers, const std::string& confPath);
 
   /**
-   * Run a command in the hbase shell. Command should not include any double
-   * quotes.
-   *
-   * This should only be used until there is a good Admin support from the
-   * native client
+   * Destroying a TestUtil will spin down a cluster and remove the test dir.
    */
-  void RunShellCmd(const std::string &command);
+  ~TestUtil();
 
   /**
    * Create a random string. This random string is all letters, as such it is
@@ -62,8 +58,22 @@ class TestUtil {
    */
   std::shared_ptr<Configuration> conf() const { return conf_; }
 
+  /**
+   * Starts mini hbase cluster with specified number of region servers
+   */
+  void StartMiniCluster(int num_region_servers);
+
+  void StopMiniCluster();
+  void CreateTable(std::string tblNam, std::string familyName);
+  void CreateTable(std::string tblNam, std::string familyName, std::string 
key1, std::string k2);
+  void TablePut(std::string table, std::string row, std::string fam, 
std::string col,
+          std::string value);
+
  private:
+  std::unique_ptr<MiniCluster> mini;
   folly::test::TemporaryDirectory temp_dir_;
+  int numRegionServers = 2;
+  std::string conf_path;
   std::shared_ptr<Configuration> conf_ = std::make_shared<Configuration>();
 };
 }  // namespace hbase
diff --git a/hbase-native-client/third-party/BUCK 
b/hbase-native-client/third-party/BUCK
index f37eb4e..a55a6fb 100644
--- a/hbase-native-client/third-party/BUCK
+++ b/hbase-native-client/third-party/BUCK
@@ -112,4 +112,6 @@ cxx_library(
         ('googletest/googlemock', 'src/*.cc'),
     ]),
     exported_deps=dynamic_rules,
-    visibility=['PUBLIC',],)
+    visibility=[
+        'PUBLIC',
+    ],)

Reply via email to