[flang-commits] [flang] 95193ac - [flang] update character tests to use gtest

Andrzej Warzynski via flang-commits flang-commits at lists.llvm.org
Tue Mar 9 00:53:23 PST 2021


Author: Asher Mancinelli
Date: 2021-03-09T08:31:20Z
New Revision: 95193ac5ba60b5ffd1af43bc561ce2b745437f94

URL: https://github.com/llvm/llvm-project/commit/95193ac5ba60b5ffd1af43bc561ce2b745437f94
DIFF: https://github.com/llvm/llvm-project/commit/95193ac5ba60b5ffd1af43bc561ce2b745437f94.diff

LOG: [flang] update character tests to use gtest

Move character tests to gtest, according to reviews from revision
D97349. Create a new temporary directory parallel to old runtime
unittests directory to facilitate the transition. Once patches for all
tests have been accepted using GTest, the old directory may be removed.
The new directory is required because LLVM's CMake unit test
infrastructure requires that the test depends on all source files in
the `CMAKE_CURRENT_SOURCE_DIR` directory.

Reviewed By: awarzynski

Differential Revision: https://reviews.llvm.org/D97403

Added: 
    flang/unittests/RuntimeGTest/CMakeLists.txt
    flang/unittests/RuntimeGTest/CharacterTest.cpp

Modified: 
    flang/unittests/CMakeLists.txt
    flang/unittests/Runtime/CMakeLists.txt

Removed: 
    flang/unittests/Runtime/character.cpp


################################################################################
diff  --git a/flang/unittests/CMakeLists.txt b/flang/unittests/CMakeLists.txt
index 54af3aff21d6..dd4ee4f37a72 100644
--- a/flang/unittests/CMakeLists.txt
+++ b/flang/unittests/CMakeLists.txt
@@ -40,6 +40,7 @@ add_subdirectory(Optimizer)
 add_subdirectory(Decimal)
 add_subdirectory(Evaluate)
 add_subdirectory(Runtime)
+add_subdirectory(RuntimeGTest)
 
 if (FLANG_BUILD_NEW_DRIVER)
   add_subdirectory(Frontend)

diff  --git a/flang/unittests/Runtime/CMakeLists.txt b/flang/unittests/Runtime/CMakeLists.txt
index b9bfeab2d08a..b80eceac7446 100644
--- a/flang/unittests/Runtime/CMakeLists.txt
+++ b/flang/unittests/Runtime/CMakeLists.txt
@@ -46,8 +46,3 @@ add_flang_nongtest_unittest(list-input
   RuntimeTesting
   FortranRuntime
 )
-
-add_flang_nongtest_unittest(character
-  RuntimeTesting
-  FortranRuntime
-)

diff  --git a/flang/unittests/Runtime/character.cpp b/flang/unittests/Runtime/character.cpp
deleted file mode 100644
index 486f79b4052c..000000000000
--- a/flang/unittests/Runtime/character.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-// Basic sanity tests of CHARACTER API; exhaustive testing will be done
-// in Fortran.
-
-#include "../../runtime/character.h"
-#include "testing.h"
-#include <cstring>
-
-using namespace Fortran::runtime;
-
-static void AppendAndPad(std::size_t limit) {
-  char x[8];
-  std::size_t xLen{0};
-  std::memset(x, 0, sizeof x);
-  xLen = RTNAME(CharacterAppend1)(x, limit, xLen, "abc", 3);
-  xLen = RTNAME(CharacterAppend1)(x, limit, xLen, "DE", 2);
-  RTNAME(CharacterPad1)(x, limit, xLen);
-  if (xLen > limit) {
-    Fail() << "xLen " << xLen << ">" << limit << '\n';
-  }
-  if (x[limit]) {
-    Fail() << "x[" << limit << "]='" << x[limit] << "'\n";
-    x[limit] = '\0';
-  }
-  if (std::memcmp(x, "abcDE   ", limit)) {
-    Fail() << "x = '" << x << "'\n";
-  }
-}
-
-static void TestCharCompare(const char *x, const char *y, std::size_t xBytes,
-    std::size_t yBytes, int expect) {
-  int cmp{RTNAME(CharacterCompareScalar1)(x, y, xBytes, yBytes)};
-  if (cmp != expect) {
-    char buf[2][8];
-    std::memset(buf, 0, sizeof buf);
-    std::memcpy(buf[0], x, xBytes);
-    std::memcpy(buf[1], y, yBytes);
-    Fail() << "compare '" << buf[0] << "'(" << xBytes << ") to '" << buf[1]
-           << "'(" << yBytes << "), got " << cmp << ", should be " << expect
-           << '\n';
-  }
-}
-
-static void Compare(const char *x, const char *y, std::size_t xBytes,
-    std::size_t yBytes, int expect) {
-  TestCharCompare(x, y, xBytes, yBytes, expect);
-  TestCharCompare(y, x, yBytes, xBytes, -expect);
-}
-
-static void Scan(
-    const char *str, const char *set, bool back, std::size_t expect) {
-  auto res{RTNAME(Scan1)(str, std::strlen(str), set, std::strlen(set), back)};
-  if (res != expect) {
-    Fail() << "Scan(" << str << ',' << set << ",back=" << back << "): got "
-           << res << ", should be " << expect << '\n';
-  }
-}
-
-static void Verify(
-    const char *str, const char *set, bool back, std::size_t expect) {
-  auto res{RTNAME(Verify1)(str, std::strlen(str), set, std::strlen(set), back)};
-  if (res != expect) {
-    Fail() << "Verify(" << str << ',' << set << ",back=" << back << "): got "
-           << res << ", should be " << expect << '\n';
-  }
-}
-
-int main() {
-  StartTests();
-  for (std::size_t j{0}; j < 8; ++j) {
-    AppendAndPad(j);
-  }
-  Compare("abc", "abc", 3, 3, 0);
-  Compare("abc", "def", 3, 3, -1);
-  Compare("ab ", "abc", 3, 2, 0);
-  Compare("abc", "abc", 2, 3, -1);
-  Scan("abc", "abc", false, 1);
-  Scan("abc", "abc", true, 3);
-  Scan("abc", "cde", false, 3);
-  Scan("abc", "cde", true, 3);
-  Scan("abc", "x", false, 0);
-  Scan("", "x", false, 0);
-  Verify("abc", "abc", false, 0);
-  Verify("abc", "abc", true, 0);
-  Verify("abc", "cde", false, 1);
-  Verify("abc", "cde", true, 2);
-  Verify("abc", "x", false, 1);
-  Verify("", "x", false, 0);
-  return EndTests();
-}

diff  --git a/flang/unittests/RuntimeGTest/CMakeLists.txt b/flang/unittests/RuntimeGTest/CMakeLists.txt
new file mode 100644
index 000000000000..77aff3069f14
--- /dev/null
+++ b/flang/unittests/RuntimeGTest/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_flang_unittest(FlangRuntimeTests
+  CharacterTest.cpp
+)
+
+target_link_libraries(FlangRuntimeTests
+  PRIVATE
+  FortranRuntime
+)

diff  --git a/flang/unittests/RuntimeGTest/CharacterTest.cpp b/flang/unittests/RuntimeGTest/CharacterTest.cpp
new file mode 100644
index 000000000000..a025429035f8
--- /dev/null
+++ b/flang/unittests/RuntimeGTest/CharacterTest.cpp
@@ -0,0 +1,282 @@
+//===-- flang/unittests/RuntimeGTest/CharacterTest.cpp ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "../../runtime/character.h"
+#include "gtest/gtest.h"
+#include <cstring>
+#include <functional>
+#include <tuple>
+#include <vector>
+
+using namespace Fortran::runtime;
+
+TEST(CharacterTests, AppendAndPad) {
+  static constexpr int limitMax{8};
+  static char buffer[limitMax];
+  static std::size_t offset{0};
+  for (std::size_t limit{0}; limit < limitMax; ++limit, offset = 0) {
+    std::memset(buffer, 0, sizeof buffer);
+
+    // Ensure appending characters does not overrun the limit
+    offset = RTNAME(CharacterAppend1)(buffer, limit, offset, "abc", 3);
+    offset = RTNAME(CharacterAppend1)(buffer, limit, offset, "DE", 2);
+    ASSERT_LE(offset, limit) << "offset " << offset << ">" << limit;
+
+    // Ensure whitespace padding does not overrun limit, the string is still
+    // null-terminated, and string matches the expected value up to the limit.
+    RTNAME(CharacterPad1)(buffer, limit, offset);
+    EXPECT_EQ(buffer[limit], '\0')
+        << "buffer[" << limit << "]='" << buffer[limit] << "'";
+    buffer[limit] = buffer[limit] ? '\0' : buffer[limit];
+    ASSERT_EQ(std::memcmp(buffer, "abcDE   ", limit), 0)
+        << "buffer = '" << buffer << "'";
+  }
+}
+
+TEST(CharacterTests, CharacterAppend1Overrun) {
+  static constexpr int bufferSize{4};
+  static constexpr std::size_t limit{2};
+  static char buffer[bufferSize];
+  static std::size_t offset{0};
+  std::memset(buffer, 0, sizeof buffer);
+  offset = RTNAME(CharacterAppend1)(buffer, limit, offset, "1234", bufferSize);
+  ASSERT_EQ(offset, limit) << "CharacterAppend1 did not halt at limit = "
+                           << limit << ", but at offset = " << offset;
+}
+
+//------------------------------------------------------------------------------
+/// Tests and infrastructure for character comparison functions
+//------------------------------------------------------------------------------
+
+template <typename CHAR>
+using ComparisonFuncTy =
+    std::function<int(const CHAR *, const CHAR *, std::size_t, std::size_t)>;
+
+using ComparisonFuncsTy = std::tuple<ComparisonFuncTy<char>,
+    ComparisonFuncTy<char16_t>, ComparisonFuncTy<char32_t>>;
+
+// These comparison functions are the systems under test in the
+// CharacterComparisonTests test cases.
+static ComparisonFuncsTy comparisonFuncs{
+    RTNAME(CharacterCompareScalar1),
+    RTNAME(CharacterCompareScalar2),
+    RTNAME(CharacterCompareScalar4),
+};
+
+// Types of _values_ over which comparison tests are parameterized
+template <typename CHAR>
+using ComparisonParametersTy =
+    std::vector<std::tuple<const CHAR *, const CHAR *, int, int, int>>;
+
+using ComparisonTestCasesTy = std::tuple<ComparisonParametersTy<char>,
+    ComparisonParametersTy<char16_t>, ComparisonParametersTy<char32_t>>;
+
+static ComparisonTestCasesTy comparisonTestCases{
+    {
+        std::make_tuple("abc", "abc", 3, 3, 0),
+        std::make_tuple("abc", "def", 3, 3, -1),
+        std::make_tuple("ab ", "abc", 3, 2, 0),
+        std::make_tuple("abc", "abc", 2, 3, -1),
+    },
+    {
+        std::make_tuple(u"abc", u"abc", 3, 3, 0),
+        std::make_tuple(u"abc", u"def", 3, 3, -1),
+        std::make_tuple(u"ab ", u"abc", 3, 2, 0),
+        std::make_tuple(u"abc", u"abc", 2, 3, -1),
+    },
+    {
+        std::make_tuple(U"abc", U"abc", 3, 3, 0),
+        std::make_tuple(U"abc", U"def", 3, 3, -1),
+        std::make_tuple(U"ab ", U"abc", 3, 2, 0),
+        std::make_tuple(U"abc", U"abc", 2, 3, -1),
+    }};
+
+template <typename CHAR>
+struct CharacterComparisonTests : public ::testing::Test {
+  CharacterComparisonTests()
+      : parameters{std::get<ComparisonParametersTy<CHAR>>(comparisonTestCases)},
+        characterComparisonFunc{
+            std::get<ComparisonFuncTy<CHAR>>(comparisonFuncs)} {}
+  ComparisonParametersTy<CHAR> parameters;
+  ComparisonFuncTy<CHAR> characterComparisonFunc;
+};
+
+using CharacterTypes = ::testing::Types<char, char16_t, char32_t>;
+TYPED_TEST_CASE(CharacterComparisonTests, CharacterTypes);
+
+TYPED_TEST(CharacterComparisonTests, CompareCharacters) {
+  for (auto &[x, y, xBytes, yBytes, expect] : this->parameters) {
+    int cmp{this->characterComparisonFunc(x, y, xBytes, yBytes)};
+    TypeParam buf[2][8];
+    std::memset(buf, 0, sizeof buf);
+    std::memcpy(buf[0], x, xBytes);
+    std::memcpy(buf[1], y, yBytes);
+    ASSERT_EQ(cmp, expect) << "compare '" << x << "'(" << xBytes << ") to '"
+                           << y << "'(" << yBytes << "), got " << cmp
+                           << ", should be " << expect << '\n';
+
+    // Perform the same test with the parameters reversed and the 
diff erence
+    // negated
+    std::swap(x, y);
+    std::swap(xBytes, yBytes);
+    expect = -expect;
+
+    cmp = this->characterComparisonFunc(x, y, xBytes, yBytes);
+    std::memset(buf, 0, sizeof buf);
+    std::memcpy(buf[0], x, xBytes);
+    std::memcpy(buf[1], y, yBytes);
+    ASSERT_EQ(cmp, expect) << "compare '" << x << "'(" << xBytes << ") to '"
+                           << y << "'(" << yBytes << "), got " << cmp
+                           << ", should be " << expect << '\n';
+  }
+}
+
+//------------------------------------------------------------------------------
+/// Tests and infrastructure for Scan functions
+//------------------------------------------------------------------------------
+
+template <typename CHAR>
+using ScanFuncTy = std::function<int(
+    const CHAR *, std::size_t, const CHAR *, std::size_t, bool)>;
+
+using ScanFuncsTy =
+    std::tuple<ScanFuncTy<char>, ScanFuncTy<char16_t>, ScanFuncTy<char32_t>>;
+
+// These functions are the systems under test in CharacterScanTests test cases.
+static ScanFuncsTy scanFuncs{
+    RTNAME(Scan1),
+    RTNAME(Scan2),
+    RTNAME(Scan4),
+};
+
+// Types of _values_ over which tests are parameterized
+template <typename CHAR>
+using ScanParametersTy =
+    std::vector<std::tuple<const CHAR *, const CHAR *, bool, int>>;
+
+using ScanTestCasesTy = std::tuple<ScanParametersTy<char>,
+    ScanParametersTy<char16_t>, ScanParametersTy<char32_t>>;
+
+static ScanTestCasesTy scanTestCases{
+    {
+        std::make_tuple("abc", "abc", false, 1),
+        std::make_tuple("abc", "abc", true, 3),
+        std::make_tuple("abc", "cde", false, 3),
+        std::make_tuple("abc", "cde", true, 3),
+        std::make_tuple("abc", "x", false, 0),
+        std::make_tuple("", "x", false, 0),
+    },
+    {
+        std::make_tuple(u"abc", u"abc", false, 1),
+        std::make_tuple(u"abc", u"abc", true, 3),
+        std::make_tuple(u"abc", u"cde", false, 3),
+        std::make_tuple(u"abc", u"cde", true, 3),
+        std::make_tuple(u"abc", u"x", false, 0),
+        std::make_tuple(u"", u"x", false, 0),
+    },
+    {
+        std::make_tuple(U"abc", U"abc", false, 1),
+        std::make_tuple(U"abc", U"abc", true, 3),
+        std::make_tuple(U"abc", U"cde", false, 3),
+        std::make_tuple(U"abc", U"cde", true, 3),
+        std::make_tuple(U"abc", U"x", false, 0),
+        std::make_tuple(U"", U"x", false, 0),
+    }};
+
+template <typename CHAR> struct CharacterScanTests : public ::testing::Test {
+  CharacterScanTests()
+      : parameters{std::get<ScanParametersTy<CHAR>>(scanTestCases)},
+        characterScanFunc{std::get<ScanFuncTy<CHAR>>(scanFuncs)} {}
+  ScanParametersTy<CHAR> parameters;
+  ScanFuncTy<CHAR> characterScanFunc;
+};
+
+// Type-parameterized over the same character types as CharacterComparisonTests
+TYPED_TEST_CASE(CharacterScanTests, CharacterTypes);
+
+TYPED_TEST(CharacterScanTests, ScanCharacters) {
+  for (auto const &[str, set, back, expect] : this->parameters) {
+    auto res{
+        this->characterScanFunc(str, std::char_traits<TypeParam>::length(str),
+            set, std::char_traits<TypeParam>::length(set), back)};
+    ASSERT_EQ(res, expect) << "Scan(" << str << ',' << set << ",back=" << back
+                           << "): got " << res << ", should be " << expect;
+  }
+}
+
+//------------------------------------------------------------------------------
+/// Tests and infrastructure for Verify functions
+//------------------------------------------------------------------------------
+template <typename CHAR>
+using VerifyFuncTy = std::function<int(
+    const CHAR *, std::size_t, const CHAR *, std::size_t, bool)>;
+
+using VerifyFuncsTy = std::tuple<VerifyFuncTy<char>, VerifyFuncTy<char16_t>,
+    VerifyFuncTy<char32_t>>;
+
+// These functions are the systems under test in CharacterVerifyTests test cases
+static VerifyFuncsTy verifyFuncs{
+    RTNAME(Verify1),
+    RTNAME(Verify2),
+    RTNAME(Verify4),
+};
+
+// Types of _values_ over which tests are parameterized
+template <typename CHAR>
+using VerifyParametersTy =
+    std::vector<std::tuple<const CHAR *, const CHAR *, bool, int>>;
+
+using VerifyTestCasesTy = std::tuple<VerifyParametersTy<char>,
+    VerifyParametersTy<char16_t>, VerifyParametersTy<char32_t>>;
+
+static VerifyTestCasesTy verifyTestCases{
+    {
+        std::make_tuple("abc", "abc", false, 0),
+        std::make_tuple("abc", "abc", true, 0),
+        std::make_tuple("abc", "cde", false, 1),
+        std::make_tuple("abc", "cde", true, 2),
+        std::make_tuple("abc", "x", false, 1),
+        std::make_tuple("", "x", false, 0),
+    },
+    {
+        std::make_tuple(u"abc", u"abc", false, 0),
+        std::make_tuple(u"abc", u"abc", true, 0),
+        std::make_tuple(u"abc", u"cde", false, 1),
+        std::make_tuple(u"abc", u"cde", true, 2),
+        std::make_tuple(u"abc", u"x", false, 1),
+        std::make_tuple(u"", u"x", false, 0),
+    },
+    {
+        std::make_tuple(U"abc", U"abc", false, 0),
+        std::make_tuple(U"abc", U"abc", true, 0),
+        std::make_tuple(U"abc", U"cde", false, 1),
+        std::make_tuple(U"abc", U"cde", true, 2),
+        std::make_tuple(U"abc", U"x", false, 1),
+        std::make_tuple(U"", U"x", false, 0),
+    }};
+
+template <typename CHAR> struct CharacterVerifyTests : public ::testing::Test {
+  CharacterVerifyTests()
+      : parameters{std::get<VerifyParametersTy<CHAR>>(verifyTestCases)},
+        characterVerifyFunc{std::get<VerifyFuncTy<CHAR>>(verifyFuncs)} {}
+  VerifyParametersTy<CHAR> parameters;
+  VerifyFuncTy<CHAR> characterVerifyFunc;
+};
+
+// Type-parameterized over the same character types as CharacterComparisonTests
+TYPED_TEST_CASE(CharacterVerifyTests, CharacterTypes);
+
+TYPED_TEST(CharacterVerifyTests, VerifyCharacters) {
+  for (auto const &[str, set, back, expect] : this->parameters) {
+    auto res{
+        this->characterVerifyFunc(str, std::char_traits<TypeParam>::length(str),
+            set, std::char_traits<TypeParam>::length(set), back)};
+    ASSERT_EQ(res, expect) << "Verify(" << str << ',' << set << ",back=" << back
+                           << "): got " << res << ", should be " << expect;
+  }
+}


        


More information about the flang-commits mailing list