diff options
-rw-r--r-- | absl/base/BUILD.bazel | 2 | ||||
-rw-r--r-- | absl/base/CMakeLists.txt | 2 | ||||
-rw-r--r-- | absl/base/log_severity.h | 17 | ||||
-rw-r--r-- | absl/base/log_severity_test.cc | 158 | ||||
-rw-r--r-- | absl/base/macros.h | 9 | ||||
-rw-r--r-- | absl/flags/BUILD.bazel | 2 | ||||
-rw-r--r-- | absl/flags/marshalling.cc | 40 | ||||
-rw-r--r-- | absl/flags/marshalling.h | 12 | ||||
-rw-r--r-- | absl/random/internal/named_generator.cc | 30 |
9 files changed, 234 insertions, 38 deletions
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index a2e510f8..57caa065 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -575,6 +575,8 @@ cc_test( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":log_severity", + "//absl/flags:marshalling", + "//absl/strings", "@com_google_googletest//:gtest_main", ], ) diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index 15a92f5f..2f11ef86 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -529,7 +529,9 @@ absl_cc_test( SRCS "log_severity_test.cc" DEPS + absl::flags_marshalling absl::log_severity + absl::strings gmock gtest_main ) diff --git a/absl/base/log_severity.h b/absl/base/log_severity.h index 5a1d5576..f5dc7d26 100644 --- a/absl/base/log_severity.h +++ b/absl/base/log_severity.h @@ -25,6 +25,19 @@ namespace absl { // Four severity levels are defined. Logging APIs should terminate the program // when a message is logged at severity `kFatal`; the other levels have no // special semantics. +// +// Abseil flags may be defined with type `LogSeverity`. Dependency layering +// constraints require that the `AbslParseFlag` overload be declared and defined +// in the flags module rather than here. The `AbslUnparseFlag` overload is +// defined there too for consistency. +// +// The parser accepts arbitrary integers (as if the type were `int`). It also +// accepts each named enumerator, without regard for case, with or without the +// leading 'k'. For example: "kInfo", "INFO", and "info" all parse to the value +// `absl::LogSeverity::kInfo`. +// +// Unparsing a flag produces the same result as `absl::LogSeverityName()` for +// the standard levels and a base-ten integer otherwise. enum class LogSeverity : int { kInfo = 0, kWarning = 1, @@ -40,7 +53,7 @@ constexpr std::array<absl::LogSeverity, 4> LogSeverities() { } // Returns the all-caps string representation (e.g. "INFO") of the specified -// severity level if it is one of the normal levels and "UNKNOWN" otherwise. +// severity level if it is one of the standard levels and "UNKNOWN" otherwise. constexpr const char* LogSeverityName(absl::LogSeverity s) { return s == absl::LogSeverity::kInfo ? "INFO" @@ -59,7 +72,7 @@ constexpr absl::LogSeverity NormalizeLogSeverity(absl::LogSeverity s) { : s > absl::LogSeverity::kFatal ? absl::LogSeverity::kError : s; } constexpr absl::LogSeverity NormalizeLogSeverity(int s) { - return NormalizeLogSeverity(static_cast<absl::LogSeverity>(s)); + return absl::NormalizeLogSeverity(static_cast<absl::LogSeverity>(s)); } // The exact representation of a streamed `absl::LogSeverity` is deliberately diff --git a/absl/base/log_severity_test.cc b/absl/base/log_severity_test.cc index 1de2d101..1e3aafa5 100644 --- a/absl/base/log_severity_test.cc +++ b/absl/base/log_severity_test.cc @@ -14,14 +14,25 @@ #include "absl/base/log_severity.h" +#include <cstdint> +#include <ios> +#include <limits> +#include <ostream> #include <sstream> #include <string> +#include <tuple> #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/flags/marshalling.h" +#include "absl/strings/str_cat.h" namespace { -using testing::Eq; +using ::testing::Eq; +using ::testing::IsFalse; +using ::testing::IsTrue; +using ::testing::TestWithParam; +using ::testing::Values; std::string StreamHelper(absl::LogSeverity value) { std::ostringstream stream; @@ -40,4 +51,149 @@ TEST(StreamTest, Works) { Eq("absl::LogSeverity(4)")); } +using ParseFlagFromOutOfRangeIntegerTest = TestWithParam<int64_t>; +INSTANTIATE_TEST_SUITE_P( + Instantiation, ParseFlagFromOutOfRangeIntegerTest, + Values(static_cast<int64_t>(std::numeric_limits<int>::min()) - 1, + static_cast<int64_t>(std::numeric_limits<int>::max()) + 1)); +TEST_P(ParseFlagFromOutOfRangeIntegerTest, ReturnsError) { + const std::string to_parse = absl::StrCat(GetParam()); + absl::LogSeverity value; + std::string error; + EXPECT_THAT(absl::ParseFlag(to_parse, &value, &error), IsFalse()) << value; +} + +using ParseFlagFromAlmostOutOfRangeIntegerTest = TestWithParam<int>; +INSTANTIATE_TEST_SUITE_P(Instantiation, + ParseFlagFromAlmostOutOfRangeIntegerTest, + Values(std::numeric_limits<int>::min(), + std::numeric_limits<int>::max())); +TEST_P(ParseFlagFromAlmostOutOfRangeIntegerTest, YieldsExpectedValue) { + const auto expected = static_cast<absl::LogSeverity>(GetParam()); + const std::string to_parse = absl::StrCat(GetParam()); + absl::LogSeverity value; + std::string error; + ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error; + EXPECT_THAT(value, Eq(expected)); +} + +using ParseFlagFromIntegerMatchingEnumeratorTest = + TestWithParam<std::tuple<absl::string_view, absl::LogSeverity>>; +INSTANTIATE_TEST_SUITE_P( + Instantiation, ParseFlagFromIntegerMatchingEnumeratorTest, + Values(std::make_tuple("0", absl::LogSeverity::kInfo), + std::make_tuple(" 0", absl::LogSeverity::kInfo), + std::make_tuple("-0", absl::LogSeverity::kInfo), + std::make_tuple("+0", absl::LogSeverity::kInfo), + std::make_tuple("00", absl::LogSeverity::kInfo), + std::make_tuple("0 ", absl::LogSeverity::kInfo), + std::make_tuple("0x0", absl::LogSeverity::kInfo), + std::make_tuple("1", absl::LogSeverity::kWarning), + std::make_tuple("+1", absl::LogSeverity::kWarning), + std::make_tuple("2", absl::LogSeverity::kError), + std::make_tuple("3", absl::LogSeverity::kFatal))); +TEST_P(ParseFlagFromIntegerMatchingEnumeratorTest, YieldsExpectedValue) { + const absl::string_view to_parse = std::get<0>(GetParam()); + const absl::LogSeverity expected = std::get<1>(GetParam()); + absl::LogSeverity value; + std::string error; + ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error; + EXPECT_THAT(value, Eq(expected)); +} + +using ParseFlagFromOtherIntegerTest = + TestWithParam<std::tuple<absl::string_view, int>>; +INSTANTIATE_TEST_SUITE_P(Instantiation, ParseFlagFromOtherIntegerTest, + Values(std::make_tuple("-1", -1), + std::make_tuple("4", 4), + std::make_tuple("010", 10), + std::make_tuple("0x10", 16))); +TEST_P(ParseFlagFromOtherIntegerTest, YieldsExpectedValue) { + const absl::string_view to_parse = std::get<0>(GetParam()); + const auto expected = static_cast<absl::LogSeverity>(std::get<1>(GetParam())); + absl::LogSeverity value; + std::string error; + ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error; + EXPECT_THAT(value, Eq(expected)); +} + +using ParseFlagFromEnumeratorTest = + TestWithParam<std::tuple<absl::string_view, absl::LogSeverity>>; +INSTANTIATE_TEST_SUITE_P( + Instantiation, ParseFlagFromEnumeratorTest, + Values(std::make_tuple("INFO", absl::LogSeverity::kInfo), + std::make_tuple("info", absl::LogSeverity::kInfo), + std::make_tuple("kInfo", absl::LogSeverity::kInfo), + std::make_tuple("iNfO", absl::LogSeverity::kInfo), + std::make_tuple("kInFo", absl::LogSeverity::kInfo), + std::make_tuple("WARNING", absl::LogSeverity::kWarning), + std::make_tuple("warning", absl::LogSeverity::kWarning), + std::make_tuple("kWarning", absl::LogSeverity::kWarning), + std::make_tuple("WaRnInG", absl::LogSeverity::kWarning), + std::make_tuple("KwArNiNg", absl::LogSeverity::kWarning), + std::make_tuple("ERROR", absl::LogSeverity::kError), + std::make_tuple("error", absl::LogSeverity::kError), + std::make_tuple("kError", absl::LogSeverity::kError), + std::make_tuple("eRrOr", absl::LogSeverity::kError), + std::make_tuple("kErRoR", absl::LogSeverity::kError), + std::make_tuple("FATAL", absl::LogSeverity::kFatal), + std::make_tuple("fatal", absl::LogSeverity::kFatal), + std::make_tuple("kFatal", absl::LogSeverity::kFatal), + std::make_tuple("FaTaL", absl::LogSeverity::kFatal), + std::make_tuple("KfAtAl", absl::LogSeverity::kFatal))); +TEST_P(ParseFlagFromEnumeratorTest, YieldsExpectedValue) { + const absl::string_view to_parse = std::get<0>(GetParam()); + const absl::LogSeverity expected = std::get<1>(GetParam()); + absl::LogSeverity value; + std::string error; + ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error; + EXPECT_THAT(value, Eq(expected)); +} + +using ParseFlagFromGarbageTest = TestWithParam<absl::string_view>; +INSTANTIATE_TEST_SUITE_P(Instantiation, ParseFlagFromGarbageTest, + Values("", "\0", " ", "garbage", "kkinfo", "I")); +TEST_P(ParseFlagFromGarbageTest, ReturnsError) { + const absl::string_view to_parse = GetParam(); + absl::LogSeverity value; + std::string error; + EXPECT_THAT(absl::ParseFlag(to_parse, &value, &error), IsFalse()) << value; +} + +using UnparseFlagToEnumeratorTest = + TestWithParam<std::tuple<absl::LogSeverity, absl::string_view>>; +INSTANTIATE_TEST_SUITE_P( + Instantiation, UnparseFlagToEnumeratorTest, + Values(std::make_tuple(absl::LogSeverity::kInfo, "INFO"), + std::make_tuple(absl::LogSeverity::kWarning, "WARNING"), + std::make_tuple(absl::LogSeverity::kError, "ERROR"), + std::make_tuple(absl::LogSeverity::kFatal, "FATAL"))); +TEST_P(UnparseFlagToEnumeratorTest, ReturnsExpectedValueAndRoundTrips) { + const absl::LogSeverity to_unparse = std::get<0>(GetParam()); + const absl::string_view expected = std::get<1>(GetParam()); + const std::string stringified_value = absl::UnparseFlag(to_unparse); + EXPECT_THAT(stringified_value, Eq(expected)); + absl::LogSeverity reparsed_value; + std::string error; + EXPECT_THAT(absl::ParseFlag(stringified_value, &reparsed_value, &error), + IsTrue()); + EXPECT_THAT(reparsed_value, Eq(to_unparse)); +} + +using UnparseFlagToOtherIntegerTest = TestWithParam<int>; +INSTANTIATE_TEST_SUITE_P(Instantiation, UnparseFlagToOtherIntegerTest, + Values(std::numeric_limits<int>::min(), -1, 4, + std::numeric_limits<int>::max())); +TEST_P(UnparseFlagToOtherIntegerTest, ReturnsExpectedValueAndRoundTrips) { + const absl::LogSeverity to_unparse = + static_cast<absl::LogSeverity>(GetParam()); + const std::string expected = absl::StrCat(GetParam()); + const std::string stringified_value = absl::UnparseFlag(to_unparse); + EXPECT_THAT(stringified_value, Eq(expected)); + absl::LogSeverity reparsed_value; + std::string error; + EXPECT_THAT(absl::ParseFlag(stringified_value, &reparsed_value, &error), + IsTrue()); + EXPECT_THAT(reparsed_value, Eq(to_unparse)); +} } // namespace diff --git a/absl/base/macros.h b/absl/base/macros.h index 606a90ac..d481288f 100644 --- a/absl/base/macros.h +++ b/absl/base/macros.h @@ -137,10 +137,15 @@ enum LinkerInitialized { // declarations. The macro argument is used as a custom diagnostic message (e.g. // suggestion of a better alternative). // -// Example: +// Examples: // // class ABSL_DEPRECATED("Use Bar instead") Foo {...}; -// ABSL_DEPRECATED("Use Baz instead") void Bar() {...} +// +// ABSL_DEPRECATED("Use Baz() instead") void Bar() {...} +// +// template <typename T> +// ABSL_DEPRECATED("Use DoThat() instead") +// void DoThis(); // // Every usage of a deprecated entity will trigger a warning when compiled with // clang's `-Wdeprecated-declarations` option. This option is turned off by diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel index fe59ec84..2bf562f8 100644 --- a/absl/flags/BUILD.bazel +++ b/absl/flags/BUILD.bazel @@ -251,7 +251,7 @@ cc_library( ) ############################################################################ -# Unit tests in alpahabetical order. +# Unit tests in alphabetical order. cc_test( name = "commandlineflag_test", diff --git a/absl/flags/marshalling.cc b/absl/flags/marshalling.cc index f025ae7e..f4ebe0e3 100644 --- a/absl/flags/marshalling.cc +++ b/absl/flags/marshalling.cc @@ -16,6 +16,7 @@ #include "absl/flags/marshalling.h" #include <limits> +#include <type_traits> #include "absl/base/macros.h" #include "absl/strings/match.h" @@ -186,4 +187,43 @@ std::string AbslUnparseFlag(const std::vector<std::string>& v) { } } // namespace flags_internal + +bool AbslParseFlag(absl::string_view text, absl::LogSeverity* dst, + std::string* err) { + text = absl::StripAsciiWhitespace(text); + if (text.empty()) { + *err = "no value provided"; + return false; + } + if (text.front() == 'k' || text.front() == 'K') text.remove_prefix(1); + if (absl::EqualsIgnoreCase(text, "info")) { + *dst = absl::LogSeverity::kInfo; + return true; + } + if (absl::EqualsIgnoreCase(text, "warning")) { + *dst = absl::LogSeverity::kWarning; + return true; + } + if (absl::EqualsIgnoreCase(text, "error")) { + *dst = absl::LogSeverity::kError; + return true; + } + if (absl::EqualsIgnoreCase(text, "fatal")) { + *dst = absl::LogSeverity::kFatal; + return true; + } + std::underlying_type<absl::LogSeverity>::type numeric_value; + if (absl::ParseFlag(text, &numeric_value, err)) { + *dst = static_cast<absl::LogSeverity>(numeric_value); + return true; + } + *err = "only integers and absl::LogSeverity enumerators are accepted"; + return false; +} + +std::string AbslUnparseFlag(absl::LogSeverity v) { + if (v == absl::NormalizeLogSeverity(v)) return absl::LogSeverityName(v); + return absl::UnparseFlag(static_cast<int>(v)); +} + } // namespace absl diff --git a/absl/flags/marshalling.h b/absl/flags/marshalling.h index f9e29594..6d391804 100644 --- a/absl/flags/marshalling.h +++ b/absl/flags/marshalling.h @@ -33,6 +33,7 @@ // * `double` // * `std::string` // * `std::vector<std::string>` +// * `absl::LogSeverity` (provided here due to dependency ordering) // // Note that support for integral types is implemented using overloads for // variable-width fundamental types (`short`, `int`, `long`, etc.). However, @@ -178,8 +179,8 @@ bool AbslParseFlag(absl::string_view, unsigned int*, std::string*); // NOLINT bool AbslParseFlag(absl::string_view, long*, std::string*); // NOLINT bool AbslParseFlag(absl::string_view, unsigned long*, std::string*); // NOLINT bool AbslParseFlag(absl::string_view, long long*, std::string*); // NOLINT -bool AbslParseFlag(absl::string_view, unsigned long long*, - std::string*); // NOLINT +bool AbslParseFlag(absl::string_view, unsigned long long*, // NOLINT + std::string*); bool AbslParseFlag(absl::string_view, float*, std::string*); bool AbslParseFlag(absl::string_view, double*, std::string*); bool AbslParseFlag(absl::string_view, std::string*, std::string*); @@ -248,6 +249,13 @@ inline std::string UnparseFlag(const T& v) { return flags_internal::Unparse(v); } +// Overloads for `absl::LogSeverity` can't (easily) appear alongside that type's +// definition because it is layered below flags. See proper documentation in +// base/log_severity.h. +enum class LogSeverity : int; +bool AbslParseFlag(absl::string_view, absl::LogSeverity*, std::string*); +std::string AbslUnparseFlag(absl::LogSeverity); + } // namespace absl #endif // ABSL_FLAGS_MARSHALLING_H_ diff --git a/absl/random/internal/named_generator.cc b/absl/random/internal/named_generator.cc deleted file mode 100644 index b168a25b..00000000 --- a/absl/random/internal/named_generator.cc +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2018 The Abseil Authors. -// -// Licensed 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 -// -// https://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 <cstddef> -#include <iostream> - -#include "absl/random/random.h" - -// This program is used in integration tests. - -int main() { - auto seed_seq = absl::MakeTaggedSeedSeq("TEST_GENERATOR", std::cerr); - absl::BitGen rng(seed_seq); - constexpr size_t kSequenceLength = 8; - for (size_t i = 0; i < kSequenceLength; i++) { - std::cout << rng() << "\n"; - } - return 0; -} |