add a config FieldConvertor for parsing nanoseconds

Summary:
Add a `FieldConvertor` implementation allowing a config field to be parsed
into a `std::chrono::nanoseconds` value.

Reviewed By: strager

Differential Revision: D15428932

fbshipit-source-id: d3ace45a2986717c798897534e7b3015eda35fa9
This commit is contained in:
Adam Simpkins 2019-06-11 12:59:03 -07:00 committed by Facebook Github Bot
parent 60ef2759fe
commit 0c63605e75
3 changed files with 51 additions and 1 deletions

View File

@ -9,6 +9,8 @@
*/
#include "eden/fs/config/FieldConverter.h"
#include "eden/fs/utils/ChronoParse.h"
using folly::Expected;
using std::string;
@ -80,5 +82,21 @@ Expected<string, string> FieldConverter<string>::fromString(
return folly::makeExpected<string, string>(value.toString());
}
Expected<std::chrono::nanoseconds, string>
FieldConverter<std::chrono::nanoseconds>::fromString(
folly::StringPiece value,
const std::map<string, string>& /* unused */) const {
auto result = stringToDuration(value);
if (result.hasValue()) {
return result.value();
}
return folly::makeUnexpected(chronoParseErrorToString(result.error()).str());
}
std::string FieldConverter<std::chrono::nanoseconds>::toDebugString(
std::chrono::nanoseconds value) const {
return durationToString(value);
}
} // namespace eden
} // namespace facebook

View File

@ -9,6 +9,7 @@
*/
#pragma once
#include <chrono>
#include <map>
#include <string>
#include <type_traits>
@ -90,5 +91,23 @@ class FieldConverter<
}
};
/*
* FieldConverter implementation for nanoseconds.
*
* We could fairly easily implement this for other duration types, but we would
* have to decide what to do if the config specifies a more granular input
* value. e.g., if we wanted to parse a config field as `std::chrono::minutes`
* what should we do if the value in the config file was "10s"?
*/
template <>
class FieldConverter<std::chrono::nanoseconds> {
public:
folly::Expected<std::chrono::nanoseconds, std::string> fromString(
folly::StringPiece value,
const std::map<std::string, std::string>& convData) const;
std::string toDebugString(std::chrono::nanoseconds value) const;
};
} // namespace eden
} // namespace facebook

View File

@ -19,6 +19,7 @@ using folly::StringPiece;
using namespace facebook::eden;
using namespace folly::string_piece_literals;
using namespace std::chrono_literals;
TEST(ConfigSettingTest, initStateCheck) {
AbsolutePath defaultDir{"/DEFAULT_DIR"};
@ -285,7 +286,7 @@ void checkSet(
auto setResult =
setting.setStringValue(str, attrMap, ConfigSource::UserConfig);
ASSERT_FALSE(setResult.hasError()) << setResult.error();
if (std::is_floating_point<T>::value) {
if constexpr (std::is_floating_point<T>::value) {
EXPECT_FLOAT_EQ(expected, setting.getValue());
} else {
EXPECT_EQ(expected, setting.getValue());
@ -361,3 +362,15 @@ TEST(ConfigSettingTest, setArithmetic) {
"Non-whitespace character found after end of conversion: \"0.001.9\"",
"0.001.9");
}
TEST(ConfigSettingTest, setDuration) {
ConfigSetting<std::chrono::nanoseconds> setting{"test:value", 5ms, nullptr};
EXPECT_EQ(5ms, setting.getValue());
checkSet(setting, 90s, "1m30s");
checkSet(setting, -90s, "-1m30s");
checkSet(setting, 42ns, "42ns");
checkSet(setting, 300s, "5m");
checkSetError(setting, "empty input string", "");
checkSetError(setting, "unknown duration unit specifier", "90");
checkSetError(setting, "non-digit character found", "bogus");
}