This is an automated email from the ASF dual-hosted git repository.

bneradt pushed a commit to branch doc-lexicon
in repository https://gitbox.apache.org/repos/asf/trafficserver-libswoc.git

commit 0472985c417790f4e3aa903d2b4396a0cedbeccb
Author: Alan M. Carroll <[email protected]>
AuthorDate: Tue May 19 12:28:06 2020 -0500

    CMake: load on Win32.
---
 code/CMakeLists.txt       |   4 +-
 example/CMakeLists.txt    |   9 ++-
 unit_tests/CMakeLists.txt |   4 +-
 unit_tests/ex_Lexicon.cc  | 200 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 213 insertions(+), 4 deletions(-)

diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt
index 60a3916..2220c81 100644
--- a/code/CMakeLists.txt
+++ b/code/CMakeLists.txt
@@ -45,7 +45,9 @@ set(CC_FILES
     )
 
 add_library(libswoc STATIC ${CC_FILES})
-target_compile_options(libswoc PRIVATE -Wall -Wextra -Werror 
-Wnon-virtual-dtor -Wpedantic)
+if (CMAKE_COMPILER_IS_GNUCXX)
+    target_compile_options(libswoc PRIVATE -Wall -Wextra -Werror 
-Wnon-virtual-dtor -Wpedantic)
+endif()
 
 # Not quite sure how this works, but I think it generates one of two paths 
depending on the context.
 # That is, the generator functions return non-empty stri ngs only in the 
corresponding context.
diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt
index 4150aa5..c29ac05 100644
--- a/example/CMakeLists.txt
+++ b/example/CMakeLists.txt
@@ -5,8 +5,13 @@ set(CMAKE_CXX_STANDARD 17)
 add_executable(ex_netdb ex_netdb.cc)
 target_link_libraries(ex_netdb PUBLIC libswoc)
 set_target_properties(ex_netdb PROPERTIES CLANG_FORMAT_DIRS 
${CMAKE_CURRENT_SOURCE_DIR})
-target_compile_options(ex_netdb PRIVATE -Wall -Wextra -Werror)
+
+if (CMAKE_COMPILER_IS_GNUCXX)
+    target_compile_options(ex_netdb PRIVATE -Wall -Wextra -Werror)
+endif()
 
 add_executable(ex_netcompact ex_netcompact.cc)
 target_link_libraries(ex_netcompact PUBLIC libswoc)
-target_compile_options(ex_netcompact PRIVATE -Wall -Wextra -Werror)
+if (CMAKE_COMPILER_IS_GNUCXX)
+    target_compile_options(ex_netcompact PRIVATE -Wall -Wextra -Werror)
+endif()
diff --git a/unit_tests/CMakeLists.txt b/unit_tests/CMakeLists.txt
index a4295be..56d6fed 100644
--- a/unit_tests/CMakeLists.txt
+++ b/unit_tests/CMakeLists.txt
@@ -29,5 +29,7 @@ add_executable(test_libswoc
 
 target_link_libraries(test_libswoc PUBLIC libswoc)
 set_target_properties(test_libswoc PROPERTIES CLANG_FORMAT_DIRS 
${CMAKE_CURRENT_SOURCE_DIR})
-target_compile_options(test_libswoc PRIVATE -Wall -Wextra -Werror 
-Wno-unused-parameter -Wno-format-truncation -Wno-stringop-overflow 
-Wno-invalid-offsetof)
+if (CMAKE_COMPILER_IS_GNUCXX)
+    target_compile_options(test_libswoc PRIVATE -Wall -Wextra -Werror 
-Wno-unused-parameter -Wno-format-truncation -Wno-stringop-overflow 
-Wno-invalid-offsetof)
+endif()
 #add_definitions(-DVERBOSE_EXAMPLE_OUTPUT=1)
diff --git a/unit_tests/ex_Lexicon.cc b/unit_tests/ex_Lexicon.cc
new file mode 100644
index 0000000..e2df5cc
--- /dev/null
+++ b/unit_tests/ex_Lexicon.cc
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright Verizon Media 2020
+/** @file
+
+    Lexicon unit tests.
+*/
+
+#include "swoc/Lexicon.h"
+#include "catch.hpp"
+
+// Example code for documentatoin
+// ---
+
+enum class Example { INVALID, Value_0, Value_1, Value_2, Value_3 };
+
+using ExampleNames = swoc::Lexicon<Example>;
+
+namespace
+{
+[[maybe_unused]] ExampleNames Static_Names {
+  {Example::Value_0, {"zero", "0"}}, {Example::Value_1, {"one", "1"}}, 
{Example::Value_2, {"two", "2"}},
+    {Example::Value_3, {"three", "3"}},
+  {
+    Example::INVALID, { "INVALID" }
+  }
+};
+}
+
+TEST_CASE("Lexicon Example", "[libts][Lexicon]")
+{
+  ExampleNames exnames{{Example::Value_0, {"zero", "0"}},
+                       {Example::Value_1, {"one", "1"}},
+                       {Example::Value_2, {"two", "2"}},
+                       {Example::Value_3, {"three", "3"}},
+                       {Example::INVALID, {"INVALID"}}};
+
+  ExampleNames exnames2{{Example::Value_0, "zero"},
+                        {Example::Value_1, "one"},
+                        {Example::Value_2, "two"},
+                        {Example::Value_3, "three"},
+                        {Example::INVALID, "INVALID"}};
+
+  // Check constructing with just defaults.
+  ExampleNames def_names_1 { Example::INVALID };
+  ExampleNames def_names_2 { "INVALID" };
+  ExampleNames def_names_3 { Example::INVALID, "INVALID" };
+
+  exnames.set_default(Example::INVALID).set_default("INVALID");
+
+  REQUIRE(exnames[Example::INVALID] == "INVALID");
+  REQUIRE(exnames[Example::Value_0] == "zero");
+  REQUIRE(exnames["zero"] == Example::Value_0);
+  REQUIRE(exnames["Zero"] == Example::Value_0);
+  REQUIRE(exnames["ZERO"] == Example::Value_0);
+  REQUIRE(exnames["one"] == Example::Value_1);
+  REQUIRE(exnames["1"] == Example::Value_1);
+  REQUIRE(exnames["Evil Dave"] == Example::INVALID);
+  REQUIRE(exnames[static_cast<Example>(0xBADD00D)] == "INVALID");
+  REQUIRE(exnames[exnames[static_cast<Example>(0xBADD00D)]] == 
Example::INVALID);
+
+  REQUIRE(def_names_1["zero"] == Example::INVALID);
+  REQUIRE(def_names_2[Example::Value_0] == "INVALID");
+  REQUIRE(def_names_3["zero"] == Example::INVALID);
+  REQUIRE(def_names_3[Example::Value_0] == "INVALID");
+
+  enum class Radio { INVALID, ALPHA, BRAVO, CHARLIE, DELTA };
+  using Lex = swoc::Lexicon<Radio>;
+  Lex lex({{Radio::INVALID, {"Invalid"}},
+           {Radio::ALPHA, {"Alpha"}},
+           {Radio::BRAVO, {"Bravo", "Beta"}},
+           {Radio::CHARLIE, {"Charlie"}},
+           {Radio::DELTA, {"Delta"}}});
+
+  // test structured binding for iteration.
+  for ([[maybe_unused]] auto const &[key, name] : lex) {
+  }
+};
+
+// ---
+// End example code.
+
+enum Values { NoValue, LowValue, HighValue, Priceless };
+enum Hex { A, B, C, D, E, F, INVALID };
+
+using ValueLexicon = swoc::Lexicon<Values>;
+using HexLexicon   = swoc::Lexicon<Hex>;
+
+TEST_CASE("Lexicon Constructor", "[libts][Lexicon]")
+{
+  // Construct with a secondary name for NoValue
+  ValueLexicon vl{{NoValue, {"NoValue", "garbage"}}, {LowValue, {"LowValue"}}};
+
+  REQUIRE("LowValue" == vl[LowValue]);                 // Primary name
+  REQUIRE(NoValue == vl["NoValue"]);                   // Primary name
+  REQUIRE(NoValue == vl["garbage"]);                   // Secondary name
+  REQUIRE_THROWS_AS(vl["monkeys"], std::domain_error); // No default, so throw.
+  vl.set_default(NoValue);                             // Put in a default.
+  REQUIRE(NoValue == vl["monkeys"]);                   // Returns default 
instead of throw
+  REQUIRE(LowValue == vl["lowVALUE"]);                 // Check case 
insensitivity.
+
+  REQUIRE(NoValue == vl["HighValue"]);               // Not defined yet.
+  vl.define(HighValue, {"HighValue", "High_Value"}); // Add it.
+  REQUIRE(HighValue == vl["HighValue"]);             // Verify it's there and 
is case insensitive.
+  REQUIRE(HighValue == vl["highVALUE"]);
+  REQUIRE(HighValue == vl["HIGH_VALUE"]);
+  REQUIRE("HighValue" == vl[HighValue]); // Verify value -> primary name.
+
+  // A few more checks on primary/secondary.
+  REQUIRE(NoValue == vl["Priceless"]);
+  REQUIRE(NoValue == vl["unique"]);
+  vl.define(Priceless, "Priceless", "Unique");
+  REQUIRE("Priceless" == vl[Priceless]);
+  REQUIRE(Priceless == vl["unique"]);
+
+  // Check default handlers.
+  using LL         = swoc::Lexicon<Hex>;
+  bool bad_value_p = false;
+  LL ll_1({{A, "A"}, {B, "B"}, {C, "C"}, {E, "E"}});
+  ll_1.set_default([&bad_value_p](std::string_view name) mutable -> Hex {
+    bad_value_p = true;
+    return INVALID;
+  });
+  ll_1.set_default([&bad_value_p](Hex value) mutable -> std::string_view {
+    bad_value_p = true;
+    return "INVALID";
+  });
+  REQUIRE(bad_value_p == false);
+  REQUIRE(INVALID == ll_1["F"]);
+  REQUIRE(bad_value_p == true);
+  bad_value_p = false;
+  REQUIRE("INVALID" == ll_1[F]);
+  REQUIRE(bad_value_p == true);
+  bad_value_p = false;
+  // Verify that INVALID / "INVALID" are equal because of the default handlers.
+  REQUIRE("INVALID" == ll_1[INVALID]);
+  REQUIRE(INVALID == ll_1["INVALID"]);
+  REQUIRE(bad_value_p == true);
+  // Define the value/name, verify the handlers are *not* invoked.
+  ll_1.define(INVALID, "INVALID");
+  bad_value_p = false;
+  REQUIRE("INVALID" == ll_1[INVALID]);
+  REQUIRE(INVALID == ll_1["INVALID"]);
+  REQUIRE(bad_value_p == false);
+
+  ll_1.define({D, "D"});          // Pair style
+  ll_1.define({F, {"F", "0xf"}}); // Definition style
+  REQUIRE(ll_1[D] == "D");
+  REQUIRE(ll_1["0XF"] == F);
+
+  // iteration
+  std::bitset<INVALID + 1> mark;
+  for (auto [value, name] : ll_1) {
+    if (mark[value]) {
+      std::cerr << "Lexicon: " << name << ':' << value << " double iterated" 
<< std::endl;
+      mark.reset();
+      break;
+    }
+    mark[value] = true;
+  }
+  REQUIRE(mark.all());
+
+  ValueLexicon v2(std::move(vl));
+  REQUIRE(vl.count() == 0);
+
+  REQUIRE("LowValue" == v2[LowValue]);                 // Primary name
+  REQUIRE(NoValue == v2["NoValue"]);                   // Primary name
+  REQUIRE(NoValue == v2["garbage"]);                   // Secondary name
+
+  REQUIRE(HighValue == v2["highVALUE"]);
+  REQUIRE(HighValue == v2["HIGH_VALUE"]);
+  REQUIRE("HighValue" == v2[HighValue]); // Verify value -> primary name.
+
+  // A few more checks on primary/secondary.
+  REQUIRE("Priceless" == v2[Priceless]);
+  REQUIRE(Priceless == v2["unique"]);
+
+};
+
+TEST_CASE("Lexicon Constructor 2", "[libts][Lexicon]")
+{
+  // Check the various construction cases
+  // No defaults, value default, name default, both, both the other way.
+  const HexLexicon v1({{A, {"A", "ten"}}, {B, {"B", "eleven"}}});
+
+  const HexLexicon v2({{A, {"A", "ten"}}, {B, {"B", "eleven"}}}, INVALID);
+
+  const HexLexicon v3({{A, {"A", "ten"}}, {B, {"B", "eleven"}}}, "Invalid");
+
+  const HexLexicon v4({{A, {"A", "ten"}}, {B, {"B", "eleven"}}}, "Invalid", 
INVALID);
+
+  const HexLexicon v5{{{A, {"A", "ten"}}, {B, {"B", "eleven"}}}, INVALID, 
"Invalid"};
+
+  REQUIRE(v1["a"] == A);
+  REQUIRE(v2["q"] == INVALID);
+  REQUIRE(v3[C] == "Invalid");
+  REQUIRE(v4["q"] == INVALID);
+  REQUIRE(v4[C] == "Invalid");
+  REQUIRE(v5["q"] == INVALID);
+  REQUIRE(v5[C] == "Invalid");
+}

Reply via email to