about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--absl/base/BUILD.bazel2
-rw-r--r--absl/base/CMakeLists.txt2
-rw-r--r--absl/base/log_severity.h17
-rw-r--r--absl/base/log_severity_test.cc158
-rw-r--r--absl/base/macros.h9
-rw-r--r--absl/flags/BUILD.bazel2
-rw-r--r--absl/flags/marshalling.cc40
-rw-r--r--absl/flags/marshalling.h12
-rw-r--r--absl/random/internal/named_generator.cc30
9 files changed, 234 insertions, 38 deletions
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index a2e510f8d32e..57caa0656e59 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 15a92f5fbd2e..2f11ef86556f 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 5a1d5576ce7b..f5dc7d266120 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 1de2d101bfa8..1e3aafa56619 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 606a90ac0cca..d481288f35f9 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 fe59ec848e84..2bf562f898c7 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 f025ae7e86c4..f4ebe0e34330 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 f9e2959437a1..6d3918043704 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 b168a25be2e7..000000000000
--- 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;
-}