forked from OSchip/llvm-project
[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
This commit is contained in:
parent
4289a7f1d7
commit
95193ac5ba
|
@ -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)
|
||||
|
|
|
@ -46,8 +46,3 @@ add_flang_nongtest_unittest(list-input
|
|||
RuntimeTesting
|
||||
FortranRuntime
|
||||
)
|
||||
|
||||
add_flang_nongtest_unittest(character
|
||||
RuntimeTesting
|
||||
FortranRuntime
|
||||
)
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
add_flang_unittest(FlangRuntimeTests
|
||||
CharacterTest.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(FlangRuntimeTests
|
||||
PRIVATE
|
||||
FortranRuntime
|
||||
)
|
|
@ -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 difference
|
||||
// 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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue