HBASE-15792 Add on a test for locating a region Summary: Add on a TestUtil class that will start a cluster. Add on the ability to run a shell command in a cluster. Throw an exception if the table isn't the correct table when looking up a region. Add a test to test that getting a region throws when the table doesn't exist. Add a test to make sure that getting a region location works when the table does exist.
Test Plan: Added unit tests. Changed unit tests. Differential Revision: https://reviews.facebook.net/D57891 Project: http://git-wip-us.apache.org/repos/asf/hbase/repo Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/eb4cde49 Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/eb4cde49 Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/eb4cde49 Branch: refs/heads/HBASE-14850 Commit: eb4cde498f0fed8fd1e7ff35b71c69cabe09768d Parents: d3a6efd Author: Elliott Clark <ecl...@apache.org> Authored: Mon May 9 12:06:54 2016 -0700 Committer: Elliott Clark <ecl...@apache.org> Committed: Mon Jul 11 16:47:26 2016 -0700 ---------------------------------------------------------------------- hbase-native-client/bin/start-local-hbase.sh | 5 +- .../connection/client-handler.cc | 3 +- hbase-native-client/core/BUCK | 4 +- hbase-native-client/core/client.cc | 1 + hbase-native-client/core/location-cache-test.cc | 29 ++++++++++- hbase-native-client/core/location-cache.cc | 10 +++- hbase-native-client/core/location-cache.h | 10 +++- hbase-native-client/core/test-env.cc | 45 ---------------- hbase-native-client/test-util/BUCK | 29 +++++++++++ hbase-native-client/test-util/test-util.cc | 54 ++++++++++++++++++++ hbase-native-client/test-util/test-util.h | 51 ++++++++++++++++++ 11 files changed, 187 insertions(+), 54 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hbase/blob/eb4cde49/hbase-native-client/bin/start-local-hbase.sh ---------------------------------------------------------------------- diff --git a/hbase-native-client/bin/start-local-hbase.sh b/hbase-native-client/bin/start-local-hbase.sh index cfc71f9..49637d6 100755 --- a/hbase-native-client/bin/start-local-hbase.sh +++ b/hbase-native-client/bin/start-local-hbase.sh @@ -21,7 +21,8 @@ rm -rf /tmp/hbase-* # Start the master/regionservers. -$PWD/../bin/start-hbase.sh +T_DIR=${1:-"/tmp/hbase-testing"} +$PWD/../bin/start-hbase.sh -Dhbase.tmp.dir="${T_DIR}" until [ $(curl -s -o /dev/null -I -w "%{http_code}" http://localhost:16010/jmx) == "200" ] do @@ -30,4 +31,4 @@ do done # This sucks, but master can easily be up and meta not be assigned yet. -sleep 30 +sleep 10 http://git-wip-us.apache.org/repos/asf/hbase/blob/eb4cde49/hbase-native-client/connection/client-handler.cc ---------------------------------------------------------------------- diff --git a/hbase-native-client/connection/client-handler.cc b/hbase-native-client/connection/client-handler.cc index 2e3fcd3..3409b80 100644 --- a/hbase-native-client/connection/client-handler.cc +++ b/hbase-native-client/connection/client-handler.cc @@ -37,7 +37,8 @@ using hbase::pb::GetResponse; using google::protobuf::Message; ClientHandler::ClientHandler(std::string user_name) - : user_name_(user_name), serde_(), once_flag_(std::make_unique<std::once_flag>()), + : user_name_(user_name), serde_(), + once_flag_(std::make_unique<std::once_flag>()), resp_msgs_( make_unique<folly::AtomicHashMap< uint32_t, std::shared_ptr<google::protobuf::Message>>>(5000)) {} http://git-wip-us.apache.org/repos/asf/hbase/blob/eb4cde49/hbase-native-client/core/BUCK ---------------------------------------------------------------------- diff --git a/hbase-native-client/core/BUCK b/hbase-native-client/core/BUCK index 485f9ba..1c926e3 100644 --- a/hbase-native-client/core/BUCK +++ b/hbase-native-client/core/BUCK @@ -46,10 +46,10 @@ cxx_library( ], ) cxx_test(name="location-cache-test", srcs=[ - "test-env.cc", "location-cache-test.cc", ], - deps=[":core", ], + deps=[":core", + "//test-util:test-util", ], run_test_separately=True, ) cxx_binary(name="simple-client", srcs=["simple-client.cc", ], http://git-wip-us.apache.org/repos/asf/hbase/blob/eb4cde49/hbase-native-client/core/client.cc ---------------------------------------------------------------------- diff --git a/hbase-native-client/core/client.cc b/hbase-native-client/core/client.cc index 1e80998..82ecd22 100644 --- a/hbase-native-client/core/client.cc +++ b/hbase-native-client/core/client.cc @@ -22,6 +22,7 @@ #include <glog/logging.h> #include <string> +#include <unistd.h> using namespace folly; using namespace std; http://git-wip-us.apache.org/repos/asf/hbase/blob/eb4cde49/hbase-native-client/core/location-cache-test.cc ---------------------------------------------------------------------- diff --git a/hbase-native-client/core/location-cache-test.cc b/hbase-native-client/core/location-cache-test.cc index 8bc6383..53db6fc 100644 --- a/hbase-native-client/core/location-cache-test.cc +++ b/hbase-native-client/core/location-cache-test.cc @@ -16,14 +16,22 @@ * limitations under the License. * */ +#include "core/location-cache.h" + #include <folly/Memory.h> #include <gtest/gtest.h> -#include "location-cache.h" +#include <chrono> + +#include "if/HBase.pb.h" +#include "serde/table-name.h" +#include "test-util/test-util.h" using namespace hbase; +using namespace std::chrono; TEST(LocationCacheTest, TestGetMetaNodeContents) { - // TODO(elliott): need to make a test utility for this. + TestUtil test_util{}; + auto cpu = std::make_shared<wangle::CPUThreadPoolExecutor>(4); auto io = std::make_shared<wangle::IOThreadPoolExecutor>(4); LocationCache cache{"localhost:2181", cpu, io}; @@ -33,3 +41,20 @@ TEST(LocationCacheTest, TestGetMetaNodeContents) { ASSERT_TRUE(result.has_port()); ASSERT_TRUE(result.has_host_name()); } + +TEST(LocationCacheTest, TestGetRegionLocation) { + TestUtil test_util{}; + auto cpu = std::make_shared<wangle::CPUThreadPoolExecutor>(4); + auto io = std::make_shared<wangle::IOThreadPoolExecutor>(4); + LocationCache cache{"localhost:2181", cpu, io}; + + // 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'"); + auto loc = cache.LocateFromMeta(tn, row).get(milliseconds(1000)); + ASSERT_TRUE(loc != nullptr); + cpu->stop(); + io->stop(); +} http://git-wip-us.apache.org/repos/asf/hbase/blob/eb4cde49/hbase-native-client/core/location-cache.cc ---------------------------------------------------------------------- diff --git a/hbase-native-client/core/location-cache.cc b/hbase-native-client/core/location-cache.cc index 6c018f9..9f2a0ef 100644 --- a/hbase-native-client/core/location-cache.cc +++ b/hbase-native-client/core/location-cache.cc @@ -116,7 +116,7 @@ LocationCache::LocateFromMeta(const TableName &tn, const string &row) { return this->LocateMeta() .via(cpu_executor_.get()) .then([this](ServerName sn) { return this->cp_.get(sn); }) - .then([&](std::shared_ptr<HBaseService> service) { + .then([tn, row, this](std::shared_ptr<HBaseService> service) { return (*service)(std::move(meta_util_.MetaRequest(tn, row))); }) .then([this](Response resp) { @@ -124,6 +124,14 @@ LocationCache::LocateFromMeta(const TableName &tn, const string &row) { // a region location. return this->CreateLocation(std::move(resp)); }) + .then([tn, this](std::shared_ptr<RegionLocation> rl) { + // Make sure that the correct location was found. + if (rl->region_info().table_name().namespace_() != tn.namespace_() || + rl->region_info().table_name().qualifier() != tn.qualifier()) { + throw std::runtime_error("Doesn't look like table exists."); + } + return rl; + }) .then([this](std::shared_ptr<RegionLocation> rl) { // Now fill out the connection. rl->set_service(cp_.get(rl->server_name())); http://git-wip-us.apache.org/repos/asf/hbase/blob/eb4cde49/hbase-native-client/core/location-cache.h ---------------------------------------------------------------------- diff --git a/hbase-native-client/core/location-cache.h b/hbase-native-client/core/location-cache.h index e077750..d435530 100644 --- a/hbase-native-client/core/location-cache.h +++ b/hbase-native-client/core/location-cache.h @@ -50,7 +50,9 @@ public: /** * Constructor. * @param quorum_spec Where to connect for Zookeeper. - * @param executor The cpu executor to run on. + * @param cpu_executor executor used to run non network IO based + * continuations. + * @param io_executor executor used to talk to the network */ LocationCache(std::string quorum_spec, std::shared_ptr<wangle::CPUThreadPoolExecutor> cpu_exector, @@ -70,6 +72,12 @@ public: /** * Go read meta and find out where a region is located. + * + * @param tn Table name of the table to look up. This object must live until + * after the future is returned + * + * @param row of the table to look up. This object must live until after the + * future is returned */ folly::Future<std::shared_ptr<RegionLocation>> LocateFromMeta(const hbase::pb::TableName &tn, const std::string &row); http://git-wip-us.apache.org/repos/asf/hbase/blob/eb4cde49/hbase-native-client/core/test-env.cc ---------------------------------------------------------------------- diff --git a/hbase-native-client/core/test-env.cc b/hbase-native-client/core/test-env.cc deleted file mode 100644 index 277abd9..0000000 --- a/hbase-native-client/core/test-env.cc +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 <gtest/gtest.h> - -namespace { - -class NativeClientTestEnv : public ::testing::Environment { -public: - void SetUp() override { - // start local HBase cluster to be reused by all tests - auto result = system("bin/start-local-hbase.sh"); - ASSERT_EQ(0, result); - } - - void TearDown() override { - // shutdown local HBase cluster - auto result = system("bin/stop-local-hbase.sh"); - ASSERT_EQ(0, result); - } -}; - -} // anonymous - -int main(int argc, char **argv) { - testing::InitGoogleTest(&argc, argv); - ::testing::AddGlobalTestEnvironment(new NativeClientTestEnv()); - return RUN_ALL_TESTS(); -} http://git-wip-us.apache.org/repos/asf/hbase/blob/eb4cde49/hbase-native-client/test-util/BUCK ---------------------------------------------------------------------- diff --git a/hbase-native-client/test-util/BUCK b/hbase-native-client/test-util/BUCK new file mode 100644 index 0000000..e5e6ea2 --- /dev/null +++ b/hbase-native-client/test-util/BUCK @@ -0,0 +1,29 @@ +## +# 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. + +cxx_library(name="test-util", + exported_headers=[ + "test-util.h", + ], + srcs=["test-util.cc"], + deps=[ + "//third-party:folly", + ], + visibility=[ + 'PUBLIC', + ], + ) \ No newline at end of file http://git-wip-us.apache.org/repos/asf/hbase/blob/eb4cde49/hbase-native-client/test-util/test-util.cc ---------------------------------------------------------------------- diff --git a/hbase-native-client/test-util/test-util.cc b/hbase-native-client/test-util/test-util.cc new file mode 100644 index 0000000..e5fba48 --- /dev/null +++ b/hbase-native-client/test-util/test-util.cc @@ -0,0 +1,54 @@ +/* + * 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/test-util.h" + +#include <folly/Format.h> + +using hbase::TestUtil; +using folly::Random; + +const static int STR_LEN = 32; + +std::string TestUtil::RandString() { + auto s = std::string(STR_LEN, 'z'); + + for (int i = 0; i < STR_LEN; i++) { + auto r = Random::rand32('a', 'z'); + s[i] = static_cast<char>(r); + } + return s; +} + +TestUtil::TestUtil() : temp_dir_(TestUtil::RandString()) { + 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(res_code == 0); +} +TestUtil::~TestUtil() { + auto res_code = std::system("bin/stop-local-hbase.sh"); + CHECK(res_code == 0); +} + +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(res_code == 0); +} http://git-wip-us.apache.org/repos/asf/hbase/blob/eb4cde49/hbase-native-client/test-util/test-util.h ---------------------------------------------------------------------- diff --git a/hbase-native-client/test-util/test-util.h b/hbase-native-client/test-util/test-util.h new file mode 100644 index 0000000..395b157 --- /dev/null +++ b/hbase-native-client/test-util/test-util.h @@ -0,0 +1,51 @@ +/* + * 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 <folly/experimental/TestUtil.h> +#include <folly/Random.h> + +#include <cstdlib> +#include <string> + +namespace hbase { +/** + * @brief Class to deal with a local instance cluster for testing. + */ +class TestUtil { +public: + + /** + * Creating a TestUtil will spin up a cluster. + */ + TestUtil(); + /** + * Destroying a TestUtil will spin down a cluster. + */ + ~TestUtil(); + /** + * Run a command in the hbase shell. + */ + void RunShellCmd(const std::string& command); + static std::string RandString(); + +private: + folly::test::TemporaryDirectory temp_dir_; +}; +} // namespace hbase