Return-Path: X-Original-To: apmail-hadoop-common-commits-archive@www.apache.org Delivered-To: apmail-hadoop-common-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 6DBFC18C35 for ; Wed, 25 Nov 2015 17:10:24 +0000 (UTC) Received: (qmail 43538 invoked by uid 500); 25 Nov 2015 17:10:24 -0000 Delivered-To: apmail-hadoop-common-commits-archive@hadoop.apache.org Received: (qmail 43470 invoked by uid 500); 25 Nov 2015 17:10:23 -0000 Mailing-List: contact common-commits-help@hadoop.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: common-dev@hadoop.apache.org Delivered-To: mailing list common-commits@hadoop.apache.org Received: (qmail 43461 invoked by uid 99); 25 Nov 2015 17:10:23 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 25 Nov 2015 17:10:23 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 9DEBBE0019; Wed, 25 Nov 2015 17:10:23 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: jhc@apache.org To: common-commits@hadoop.apache.org Message-Id: <9946666e7f7b476cab46ae1d4af7dc0f@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: hadoop git commit: HDFS-9117. Config file reader / options classes for libhdfs++. Contributed by Bob Hansen. Date: Wed, 25 Nov 2015 17:10:23 +0000 (UTC) Repository: hadoop Updated Branches: refs/heads/HDFS-8707 8b7769557 -> 8c6a84fdd HDFS-9117. Config file reader / options classes for libhdfs++. Contributed by Bob Hansen. Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/8c6a84fd Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/8c6a84fd Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/8c6a84fd Branch: refs/heads/HDFS-8707 Commit: 8c6a84fdd55350791268bb4624b1f2b3163bc90b Parents: 8b77695 Author: James Authored: Wed Nov 25 12:09:13 2015 -0500 Committer: James Committed: Wed Nov 25 12:09:13 2015 -0500 ---------------------------------------------------------------------- .../src/main/native/libhdfspp/CMakeLists.txt | 2 + .../native/libhdfspp/lib/common/CMakeLists.txt | 2 +- .../libhdfspp/lib/common/configuration.cc | 231 ++++++++++++ .../native/libhdfspp/lib/common/configuration.h | 94 +++++ .../main/native/libhdfspp/tests/CMakeLists.txt | 4 + .../libhdfspp/tests/configuration_test.cc | 363 +++++++++++++++++++ .../native/libhdfspp/tests/configuration_test.h | 73 ++++ 7 files changed, 768 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hadoop/blob/8c6a84fd/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/CMakeLists.txt b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/CMakeLists.txt index 18e4cb0..d1b60be 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/CMakeLists.txt +++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/CMakeLists.txt @@ -49,7 +49,9 @@ include_directories( lib ${PROJECT_BINARY_DIR}/lib/proto third_party/asio-1.10.2/include + third_party/rapidxml-1.13 third_party/gmock-1.7.0 + third_party/tr2 ${OPENSSL_INCLUDE_DIR} ../libhdfs/include ) http://git-wip-us.apache.org/repos/asf/hadoop/blob/8c6a84fd/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/common/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/common/CMakeLists.txt b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/common/CMakeLists.txt index b03f00b..8dbcd03 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/common/CMakeLists.txt +++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/common/CMakeLists.txt @@ -1 +1 @@ -add_library(common base64.cc options.cc status.cc sasl_digest_md5.cc hdfs_public_api.cc) +add_library(common base64.cc status.cc sasl_digest_md5.cc hdfs_public_api.cc options.cc configuration.cc) http://git-wip-us.apache.org/repos/asf/hadoop/blob/8c6a84fd/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/common/configuration.cc ---------------------------------------------------------------------- diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/common/configuration.cc b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/common/configuration.cc new file mode 100644 index 0000000..2baf84b --- /dev/null +++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/common/configuration.cc @@ -0,0 +1,231 @@ +/** + * 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. + */ + +/* + * The following features are not currently implemented + * - Deprecated values + * - Make filename and config file contents unicode-safe + * - Config redirection/environment substitution + * + * - getInts (comma separated)) + * - getStrings (comma separated)) + * - getIntegerRange + * - getSocketAddr + * - getTimeDuration + * - getBytes (e.g. 1M or 1G) + * - hex values + */ + +#include "configuration.h" + +#include +#include +#include +#include +#include + +namespace hdfs { + +/* + * Configuration class + */ + +Configuration::Configuration() {} + +bool is_valid_bool(const std::string& raw) { + if (!strcasecmp(raw.c_str(), "true")) { + return true; + } + if (!strcasecmp(raw.c_str(), "false")) { + return true; + } + return false; +} + +bool str_to_bool(const std::string& raw) { + if (!strcasecmp(raw.c_str(), "true")) { + return true; + } + + return false; +} + +optional Configuration::Load(const std::string& xmlData) { + Configuration result; + return result.OverlayResourceString(xmlData); +} + +optional Configuration::OverlayResourceString( + const std::string& xmlData) const { + if (xmlData.size() == 0) { + return optional(); + } + + int length = xmlData.size(); + std::vector raw_bytes; + raw_bytes.reserve(length + 1); + std::copy(xmlData.begin(), xmlData.end(), std::back_inserter(raw_bytes)); + raw_bytes.push_back('\0'); + + ConfigMap map(raw_values_); + bool success = UpdateMapWithResource(map, raw_bytes); + + if (success) { + return optional(Configuration(map)); + } else { + return optional(); + } +} + +bool Configuration::UpdateMapWithResource(ConfigMap& map, + std::vector& raw_bytes) { + rapidxml::xml_document<> dom; + dom.parse(&raw_bytes[0]); + + /* File must contain a single stanza */ + auto config_node = dom.first_node("configuration", 0, false); + if (!config_node) { + return false; + } + + /* Walk all of the nodes, ignoring the rest */ + for (auto property_node = config_node->first_node("property", 0, false); + property_node; + property_node = property_node->next_sibling("property", 0, false)) { + auto name_node = property_node->first_node("name", 0, false); + auto value_node = property_node->first_node("value", 0, false); + + if (name_node && value_node) { + auto mapValue = map.find(name_node->value()); + if (mapValue != map.end() && mapValue->second.final) { + continue; + } + + map[name_node->value()] = value_node->value(); + auto final_node = property_node->first_node("final", 0, false); + if (final_node && is_valid_bool(final_node->value())) { + map[name_node->value()].final = str_to_bool(final_node->value()); + } + } + + auto name_attr = property_node->first_attribute("name", 0, false); + auto value_attr = property_node->first_attribute("value", 0, false); + + if (name_attr && value_attr) { + auto mapValue = map.find(name_attr->value()); + if (mapValue != map.end() && mapValue->second.final) { + continue; + } + + map[name_attr->value()] = value_attr->value(); + auto final_attr = property_node->first_attribute("final", 0, false); + if (final_attr && is_valid_bool(final_attr->value())) { + map[name_attr->value()].final = str_to_bool(final_attr->value()); + } + } + } + + return true; +} + +optional Configuration::Get(const std::string& key) const { + auto found = raw_values_.find(key); + if (found != raw_values_.end()) { + return std::experimental::make_optional(found->second.value); + } else { + return optional(); + } +} + +std::string Configuration::GetWithDefault( + const std::string& key, const std::string& default_value) const { + return Get(key).value_or(default_value); +} + +optional Configuration::GetInt(const std::string& key) const { + auto raw = Get(key); + if (raw) { + errno = 0; + char* end = nullptr; + auto result = + std::experimental::make_optional(strtol(raw->c_str(), &end, 10)); + if (end == raw->c_str()) { + /* strtoll will set end to input if no conversion was done */ + return optional(); + } + if (errno == ERANGE) { + return optional(); + } + + return result; + } else { + return optional(); + } +} + +int64_t Configuration::GetIntWithDefault(const std::string& key, + int64_t default_value) const { + return GetInt(key).value_or(default_value); +} + +optional Configuration::GetDouble(const std::string& key) const { + auto raw = Get(key); + if (raw) { + errno = 0; + char* end = nullptr; + auto result = std::experimental::make_optional(strtod(raw->c_str(), &end)); + if (end == raw->c_str()) { + /* strtod will set end to input if no conversion was done */ + return optional(); + } + if (errno == ERANGE) { + return optional(); + } + + return result; + } else { + return optional(); + } +} + +double Configuration::GetDoubleWithDefault(const std::string& key, + double default_value) const { + return GetDouble(key).value_or(default_value); +} + +optional Configuration::GetBool(const std::string& key) const { + auto raw = Get(key); + if (!raw) { + return optional(); + } + + if (!strcasecmp(raw->c_str(), "true")) { + return std::experimental::make_optional(true); + } + if (!strcasecmp(raw->c_str(), "false")) { + return std::experimental::make_optional(false); + } + + return optional(); +} + +bool Configuration::GetBoolWithDefault(const std::string& key, + bool default_value) const { + return GetBool(key).value_or(default_value); +} +} http://git-wip-us.apache.org/repos/asf/hadoop/blob/8c6a84fd/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/common/configuration.h ---------------------------------------------------------------------- diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/common/configuration.h b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/common/configuration.h new file mode 100644 index 0000000..54ada94 --- /dev/null +++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/common/configuration.h @@ -0,0 +1,94 @@ +/** + * 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. + */ + +#ifndef COMMON_CONFIGURATION_H_ +#define COMMON_CONFIGURATION_H_ + +#include +#include +#include +#include +#include +#include +#include + +namespace hdfs { + +template +using optional = std::experimental::optional; + +/** + * Configuration class that parses XML. + * + * Files should be an XML file of the form + * + * + * Name + * Value + * + * + * + * This class is not thread-safe. + */ +class Configuration { + public: + /* Creates a new Configuration from input xml */ + static optional Load(const std::string &xml_data); + + /* Constructs a configuration with no resources loaded */ + Configuration(); + + /* Loads resources from a file or a stream */ + optional OverlayResourceString( + const std::string &xml_data) const; + + // Gets values + std::string GetWithDefault(const std::string &key, + const std::string &default_value) const; + optional Get(const std::string &key) const; + int64_t GetIntWithDefault(const std::string &key, int64_t default_value) const; + optional GetInt(const std::string &key) const; + double GetDoubleWithDefault(const std::string &key, + double default_value) const; + optional GetDouble(const std::string &key) const; + bool GetBoolWithDefault(const std::string &key, bool default_value) const; + optional GetBool(const std::string &key) const; + + private: + /* Transparent data holder for property values */ + struct ConfigData { + std::string value; + bool final; + ConfigData() : final(false){}; + ConfigData(const std::string &value) : value(value), final(false) {} + void operator=(const std::string &new_value) { + value = new_value; + final = false; + } + }; + typedef std::map ConfigMap; + + Configuration(ConfigMap &src_map) : raw_values_(src_map){}; + static bool UpdateMapWithResource(ConfigMap &map, + std::vector &raw_bytes); + + const ConfigMap raw_values_; +}; +} + +#endif http://git-wip-us.apache.org/repos/asf/hadoop/blob/8c6a84fd/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/CMakeLists.txt b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/CMakeLists.txt index abd3858..7d06141 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/CMakeLists.txt +++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/CMakeLists.txt @@ -68,6 +68,10 @@ add_executable(node_exclusion_test node_exclusion_test.cc) target_link_libraries(node_exclusion_test fs gmock_main common ${PROTOBUF_LIBRARIES} ${OPENSSL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) add_test(node_exclusion node_exclusion_test) +add_executable(configuration_test configuration_test.cc) +target_link_libraries(configuration_test common gmock_main ${CMAKE_THREAD_LIBS_INIT}) +add_test(configuration configuration_test) + build_libhdfs_test(libhdfs_threaded hdfspp_test_shim_static expect.c test_libhdfs_threaded.c ${OS_DIR}/thread.c) link_libhdfs_test(libhdfs_threaded hdfspp_test_shim_static fs reader rpc proto common ${PROTOBUF_LIBRARIES} ${OPENSSL_LIBRARIES} native_mini_dfs ${JAVA_JVM_LIBRARY}) add_libhdfs_test(libhdfs_threaded hdfspp_test_shim_static) http://git-wip-us.apache.org/repos/asf/hadoop/blob/8c6a84fd/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/configuration_test.cc ---------------------------------------------------------------------- diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/configuration_test.cc b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/configuration_test.cc new file mode 100644 index 0000000..067fb8f --- /dev/null +++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/configuration_test.cc @@ -0,0 +1,363 @@ +/** + * 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 "configuration_test.h" +#include "common/configuration.h" +#include +#include +#include + +using ::testing::_; + +using namespace hdfs; + +namespace hdfs { + +TEST(ConfigurationTest, TestDegenerateInputs) { + /* Completely empty stream */ + { + std::stringstream stream; + optional config = Configuration::Load(""); + EXPECT_FALSE(config && "Empty stream"); + } + + /* No values */ + { + std::string data = ""; + optional config = Configuration::Load(data); + EXPECT_TRUE(config && "Blank config"); + } + + /* Extraneous values */ + { + std::string data = ""; + optional config = Configuration::Load(data); + EXPECT_TRUE(config && "Extraneous values"); + } +} + +TEST(ConfigurationTest, TestBasicOperations) { + /* Single value */ + { + std::stringstream stream; + simpleConfigStream(stream, "key1", "value1"); + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Parse single value"); + EXPECT_EQ("value1", config->GetWithDefault("key1", "")); + } + + /* Multiple values */ + { + optional config = + simpleConfig("key1", "value1", "key2", "value2"); + EXPECT_EQ("value1", config->GetWithDefault("key1", "")); + EXPECT_EQ("value2", config->GetWithDefault("key2", "")); + } + + /* No defaults */ + { + std::stringstream stream; + simpleConfigStream(stream, "key1", "value1"); + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Parse single value"); + optional value = config->Get("key1"); + EXPECT_TRUE((bool)value); + EXPECT_EQ("value1", *value); + EXPECT_FALSE(config->Get("key2")); + } +} + +TEST(ConfigurationTest, TestCompactValues) { + { + std::stringstream stream; + stream << ""; + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Compact value parse"); + EXPECT_EQ("value1", config->GetWithDefault("key1", "")); + } +} + +TEST(ConfigurationTest, TestMultipleResources) { + /* Single value */ + { + std::stringstream stream; + simpleConfigStream(stream, "key1", "value1"); + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Parse first stream"); + EXPECT_EQ("value1", config->GetWithDefault("key1", "")); + + std::stringstream stream2; + simpleConfigStream(stream2, "key2", "value2"); + optional config2 = + config->OverlayResourceString(stream2.str()); + EXPECT_TRUE(config2 && "Parse second stream"); + EXPECT_EQ("value1", config2->GetWithDefault("key1", "")); + EXPECT_EQ("value2", config2->GetWithDefault("key2", "")); + } +} + +TEST(ConfigurationTest, TestStringResource) { + /* Single value */ + { + std::stringstream stream; + simpleConfigStream(stream, "key1", "value1"); + std::string str = stream.str(); + + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Parse single value"); + EXPECT_EQ("value1", config->GetWithDefault("key1", "")); + } +} + +TEST(ConfigurationTest, TestFinal) { + { + /* Explicitly non-final non-compact value */ + std::stringstream stream; + stream << "key1value1false"; + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Parse first stream"); + EXPECT_EQ("value1", config->GetWithDefault("key1", "")); + + std::stringstream stream2; + simpleConfigStream(stream2, "key1", "value2"); + optional config2 = + config->OverlayResourceString(stream2.str()); + EXPECT_TRUE(config2 && "Parse second stream"); + EXPECT_EQ("value2", config2->GetWithDefault("key1", "")); + } + { + /* Explicitly final non-compact value */ + std::stringstream stream; + stream << "key1value1true"; + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Parse first stream"); + EXPECT_EQ("value1", config->GetWithDefault("key1", "")); + + std::stringstream stream2; + simpleConfigStream(stream2, "key1", "value2"); + optional config2 = + config->OverlayResourceString(stream2.str()); + EXPECT_TRUE(config2 && "Parse second stream"); + EXPECT_EQ("value1", config2->GetWithDefault("key1", "")); + } + { + /* Explicitly non-final compact value */ + std::stringstream stream; + stream << ""; + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Parse first stream"); + EXPECT_EQ("value1", config->GetWithDefault("key1", "")); + + std::stringstream stream2; + simpleConfigStream(stream2, "key1", "value2"); + optional config2 = + config->OverlayResourceString(stream2.str()); + EXPECT_TRUE(config2 && "Parse second stream"); + EXPECT_EQ("value2", config2->GetWithDefault("key1", "")); + } + { + /* Explicitly final compact value */ + std::stringstream stream; + stream << ""; + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Parse first stream"); + EXPECT_EQ("value1", config->GetWithDefault("key1", "")); + + std::stringstream stream2; + simpleConfigStream(stream2, "key1", "value2"); + optional config2 = + config->OverlayResourceString(stream2.str()); + EXPECT_TRUE(config2 && "Parse second stream"); + EXPECT_EQ("value1", config2->GetWithDefault("key1", "")); + } + { + /* Bogus final value */ + std::stringstream stream; + stream << "key1value1spam"; + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Parse first stream"); + EXPECT_EQ("value1", config->GetWithDefault("key1", "")); + + std::stringstream stream2; + simpleConfigStream(stream2, "key1", "value2"); + optional config2 = + config->OverlayResourceString(stream2.str()); + EXPECT_TRUE(config2 && "Parse second stream"); + EXPECT_EQ("value2", config2->GetWithDefault("key1", "")); + } + { + /* Blank final value */ + std::stringstream stream; + stream << "key1value1"; + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Parse first stream"); + EXPECT_EQ("value1", config->GetWithDefault("key1", "")); + + std::stringstream stream2; + simpleConfigStream(stream2, "key1", "value2"); + optional config2 = + config->OverlayResourceString(stream2.str()); + EXPECT_TRUE(config2 && "Parse second stream"); + EXPECT_EQ("value2", config2->GetWithDefault("key1", "")); + } +} +TEST(ConfigurationTest, TestIntConversions) { + /* No defaults */ + { + std::stringstream stream; + simpleConfigStream(stream, "key1", "1"); + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Parse single value"); + optional value = config->GetInt("key1"); + EXPECT_TRUE((bool)value); + EXPECT_EQ(1, *value); + EXPECT_FALSE(config->GetInt("key2")); + } + + { + optional config = simpleConfig("key1", "1"); + EXPECT_EQ(1, config->GetIntWithDefault("key1", -1)); + } + { + optional config = simpleConfig("key1", "-100"); + EXPECT_EQ(-100, config->GetIntWithDefault("key1", -1)); + } + { + optional config = simpleConfig("key1", " 1 "); + EXPECT_EQ(1, config->GetIntWithDefault("key1", -1)); + } + { + optional config = simpleConfig("key1", ""); + EXPECT_EQ(-1, config->GetIntWithDefault("key1", -1)); + } + { + optional config = simpleConfig("key1", "spam"); + EXPECT_EQ(-1, config->GetIntWithDefault("key1", -1)); + } + { + optional config = simpleConfig("key2", ""); + EXPECT_EQ(-1, config->GetIntWithDefault("key1", -1)); + } +} + +TEST(ConfigurationTest, TestDoubleConversions) { + /* No defaults */ + { + std::stringstream stream; + simpleConfigStream(stream, "key1", "1"); + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Parse single value"); + optional value = config->GetDouble("key1"); + EXPECT_TRUE((bool)value); + EXPECT_EQ(1, *value); + EXPECT_FALSE(config->GetDouble("key2")); + } + + { + optional config = simpleConfig("key1", "1"); + EXPECT_EQ(1, config->GetDoubleWithDefault("key1", -1)); + } + { + optional config = simpleConfig("key1", "-100"); + EXPECT_EQ(-100, config->GetDoubleWithDefault("key1", -1)); + } + { + optional config = simpleConfig("key1", " 1 "); + EXPECT_EQ(1, config->GetDoubleWithDefault("key1", -1)); + } + { + optional config = simpleConfig("key1", ""); + EXPECT_EQ(-1, config->GetDoubleWithDefault("key1", -1)); + } + { + optional config = simpleConfig("key1", "spam"); + EXPECT_EQ(-1, config->GetDoubleWithDefault("key1", -1)); + } + { + optional config = simpleConfig("key2", ""); + EXPECT_EQ(-1, config->GetDoubleWithDefault("key1", -1)); + } + { /* Out of range */ + optional config = simpleConfig("key2", "1e9999"); + EXPECT_EQ(-1, config->GetDoubleWithDefault("key1", -1)); + } +} + +TEST(ConfigurationTest, TestBoolConversions) { + /* No defaults */ + { + std::stringstream stream; + simpleConfigStream(stream, "key1", "true"); + optional config = Configuration::Load(stream.str()); + EXPECT_TRUE(config && "Parse single value"); + optional value = config->GetBool("key1"); + EXPECT_TRUE((bool)value); + EXPECT_EQ(true, *value); + EXPECT_FALSE(config->GetBool("key2")); + } + + { + optional config = simpleConfig("key1", "true"); + EXPECT_EQ(true, config->GetBoolWithDefault("key1", false)); + } + { + optional config = simpleConfig("key1", "tRuE"); + EXPECT_EQ(true, config->GetBoolWithDefault("key1", false)); + } + { + optional config = simpleConfig("key1", "false"); + EXPECT_FALSE(config->GetBoolWithDefault("key1", true)); + } + { + optional config = simpleConfig("key1", "FaLsE"); + EXPECT_FALSE(config->GetBoolWithDefault("key1", true)); + } + { + optional config = simpleConfig("key1", " FaLsE "); + EXPECT_FALSE(config->GetBoolWithDefault("key1", true)); + } + { + optional config = simpleConfig("key1", ""); + EXPECT_EQ(true, config->GetBoolWithDefault("key1", true)); + } + { + optional config = simpleConfig("key1", "spam"); + EXPECT_EQ(true, config->GetBoolWithDefault("key1", true)); + } + { + optional config = simpleConfig("key1", ""); + EXPECT_EQ(true, config->GetBoolWithDefault("key2", true)); + } +} + +int main(int argc, char *argv[]) { + /* + * The following line must be executed to initialize Google Mock + * (and Google Test) before running the tests. + */ + ::testing::InitGoogleMock(&argc, argv); + return RUN_ALL_TESTS(); +} +} http://git-wip-us.apache.org/repos/asf/hadoop/blob/8c6a84fd/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/configuration_test.h ---------------------------------------------------------------------- diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/configuration_test.h b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/configuration_test.h new file mode 100644 index 0000000..ec04ca4 --- /dev/null +++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/configuration_test.h @@ -0,0 +1,73 @@ +/** + * 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. + */ +#ifndef TESTS_CONFIGURATION_H_ +#define TESTS_CONFIGURATION_H_ + +#include "common/configuration.h" +#include +#include +#include +#include + +namespace hdfs { + +template +void simpleConfigStreamProperty(std::stringstream& out, T key, U value) { + out << "" + << "" << key << "" + << "" << value << "" + << ""; +} + +template +void simpleConfigStreamProperty(std::stringstream& out, T key, U value, + Args... args) { + simpleConfigStreamProperty(out, key, value); + simpleConfigStreamProperty(out, args...); +} + +template +void simpleConfigStream(std::stringstream& out, Args... args) { + out << ""; + simpleConfigStreamProperty(out, args...); + out << ""; +} + +template +optional simpleConfig(Args... args) { + Configuration result; + std::stringstream stream; + simpleConfigStream(stream, args...); + optional parse = result.Load(stream.str()); + EXPECT_TRUE((bool)parse); + + return parse; +} + +template +void writeSimpleConfig(const std::string& filename, Args... args) { + std::stringstream stream; + simpleConfigStream(stream, args...); + + std::ofstream out; + out.open(filename); + out << stream.rdbuf(); +} +} + +#endif