forked from OSchip/llvm-project
[flang] Add list input test to GTest suite
This commit is contained in:
parent
03375089f5
commit
ccef0adc59
|
@ -37,11 +37,6 @@ add_flang_nongtest_unittest(external-io
|
|||
FortranRuntime
|
||||
)
|
||||
|
||||
add_flang_nongtest_unittest(list-input
|
||||
RuntimeTesting
|
||||
FortranRuntime
|
||||
)
|
||||
|
||||
add_flang_nongtest_unittest(buffer
|
||||
RuntimeTesting
|
||||
FortranRuntime
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
// Basic sanity tests for list-directed input
|
||||
|
||||
#include "testing.h"
|
||||
#include "../../runtime/descriptor.h"
|
||||
#include "../../runtime/io-api.h"
|
||||
#include "../../runtime/io-error.h"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
using namespace Fortran::runtime;
|
||||
using namespace Fortran::runtime::io;
|
||||
|
||||
int main() {
|
||||
StartTests();
|
||||
|
||||
char buffer[4][32];
|
||||
int j{0};
|
||||
for (const char *p : {"1 2 2*3 ,", ",6,,8,1*",
|
||||
"2*'abcdefghijklmnopqrstuvwxyzABC", "DEFGHIJKLMNOPQRSTUVWXYZ'"}) {
|
||||
SetCharacter(buffer[j++], sizeof buffer[0], p);
|
||||
}
|
||||
for (; j < 4; ++j) {
|
||||
SetCharacter(buffer[j], sizeof buffer[0], "");
|
||||
}
|
||||
|
||||
StaticDescriptor<1> staticDescriptor;
|
||||
Descriptor &whole{staticDescriptor.descriptor()};
|
||||
SubscriptValue extent[]{4};
|
||||
whole.Establish(TypeCode{CFI_type_char}, sizeof buffer[0], &buffer, 1, extent,
|
||||
CFI_attribute_pointer);
|
||||
whole.Dump();
|
||||
whole.Check();
|
||||
|
||||
try {
|
||||
auto cookie{IONAME(BeginInternalArrayListInput)(whole)};
|
||||
std::int64_t n[9]{-1, -2, -3, -4, 5, -6, 7, -8, 9};
|
||||
std::int64_t want[9]{1, 2, 3, 3, 5, 6, 7, 8, 9};
|
||||
for (j = 0; j < 9; ++j) {
|
||||
IONAME(InputInteger)(cookie, n[j]);
|
||||
}
|
||||
char asc[2][54]{};
|
||||
IONAME(InputAscii)(cookie, asc[0], sizeof asc[0] - 1);
|
||||
IONAME(InputAscii)(cookie, asc[1], sizeof asc[1] - 1);
|
||||
if (auto status{IONAME(EndIoStatement)(cookie)}) {
|
||||
Fail() << "list-directed input failed, status "
|
||||
<< static_cast<int>(status) << '\n';
|
||||
} else {
|
||||
for (j = 0; j < 9; ++j) {
|
||||
if (n[j] != want[j]) {
|
||||
Fail() << "wanted n[" << j << "]==" << want[j] << ", got " << n[j]
|
||||
<< '\n';
|
||||
}
|
||||
}
|
||||
for (j = 0; j < 2; ++j) {
|
||||
if (std::strcmp(asc[j],
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ") != 0) {
|
||||
Fail() << "wanted asc[" << j << "]=alphabets, got '" << asc[j]
|
||||
<< "'\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::string &crash) {
|
||||
Fail() << "crash: " << crash << '\n';
|
||||
}
|
||||
|
||||
return EndTests();
|
||||
}
|
|
@ -36,11 +36,3 @@ int EndTests() {
|
|||
}
|
||||
return failures != 0;
|
||||
}
|
||||
|
||||
void SetCharacter(char *to, std::size_t n, const char *from) {
|
||||
auto len{std::strlen(from)};
|
||||
std::memcpy(to, from, std::min(len, n));
|
||||
if (len < n) {
|
||||
std::memset(to + len, ' ', n - len);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,4 @@ void StartTests();
|
|||
llvm::raw_ostream &Fail();
|
||||
int EndTests();
|
||||
|
||||
// Defines a CHARACTER object with padding when needed
|
||||
void SetCharacter(char *, std::size_t, const char *);
|
||||
|
||||
#endif // FORTRAN_TEST_RUNTIME_TESTING_H_
|
||||
|
|
|
@ -7,6 +7,7 @@ add_flang_unittest(FlangRuntimeTests
|
|||
Random.cpp
|
||||
Reduction.cpp
|
||||
RuntimeCrashTest.cpp
|
||||
ListInputTest.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(FlangRuntimeTests
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
//===-- flang/unittests/RuntimeGTest/ListInputTest.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 "CrashHandlerFixture.h"
|
||||
#include "../../runtime/descriptor.h"
|
||||
#include "../../runtime/io-api.h"
|
||||
#include "../../runtime/io-error.h"
|
||||
|
||||
using namespace Fortran::runtime;
|
||||
using namespace Fortran::runtime::io;
|
||||
|
||||
// Pads characters with whitespace when needed
|
||||
void SetCharacter(char *to, std::size_t n, const char *from) {
|
||||
auto len{std::strlen(from)};
|
||||
std::memcpy(to, from, std::min(len, n));
|
||||
if (len < n) {
|
||||
std::memset(to + len, ' ', n - len);
|
||||
}
|
||||
}
|
||||
|
||||
struct InputTest : CrashHandlerFixture {};
|
||||
|
||||
TEST(InputTest, TestListInputAlphabet) {
|
||||
constexpr int numInputBuffers{2};
|
||||
constexpr int maxInputBufferLength{32};
|
||||
char inputBuffers[numInputBuffers][maxInputBufferLength];
|
||||
const char expectedOutput[]{
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "};
|
||||
int j{0};
|
||||
|
||||
// Use _two_ input buffers and _three_ output buffers. Note the `3*` in the
|
||||
// _inputBuffers_.
|
||||
SetCharacter(inputBuffers[j++], maxInputBufferLength,
|
||||
"3*'abcdefghijklmnopqrstuvwxyzABC");
|
||||
SetCharacter(
|
||||
inputBuffers[j++], maxInputBufferLength, "DEFGHIJKLMNOPQRSTUVWXYZ'");
|
||||
|
||||
StaticDescriptor<1> staticDescriptor;
|
||||
Descriptor &whole{staticDescriptor.descriptor()};
|
||||
SubscriptValue extent[]{numInputBuffers};
|
||||
whole.Establish(TypeCode{CFI_type_char}, maxInputBufferLength, &inputBuffers,
|
||||
1, extent, CFI_attribute_pointer);
|
||||
whole.Check();
|
||||
auto *cookie{IONAME(BeginInternalArrayListInput)(whole)};
|
||||
|
||||
constexpr int numOutputBuffers{3};
|
||||
constexpr int outputBufferLength{54};
|
||||
char outputBuffers[numOutputBuffers][outputBufferLength]{};
|
||||
for (j = 0; j < numOutputBuffers; ++j) {
|
||||
IONAME(InputAscii)(cookie, outputBuffers[j], outputBufferLength - 1);
|
||||
}
|
||||
|
||||
const auto status{IONAME(EndIoStatement)(cookie)};
|
||||
ASSERT_EQ(status, 0) << "list-directed input failed, status "
|
||||
<< static_cast<int>(status) << '\n';
|
||||
|
||||
// Verify results that the _two_ ascii inputs result in _three_ alphabets
|
||||
for (j = 0; j < numOutputBuffers; ++j) {
|
||||
ASSERT_EQ(std::strcmp(outputBuffers[j], expectedOutput), 0)
|
||||
<< "wanted outputBuffers[" << j << "]=" << expectedOutput << ", got '"
|
||||
<< outputBuffers[j] << "'\n";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(InputTest, TestListInputIntegerList) {
|
||||
constexpr int numBuffers{2};
|
||||
constexpr int maxBufferLength{32};
|
||||
char buffer[numBuffers][maxBufferLength];
|
||||
int j{0};
|
||||
SetCharacter(buffer[j++], maxBufferLength, "1 2 2*3 ,");
|
||||
SetCharacter(buffer[j++], maxBufferLength, ",6,,8,1*");
|
||||
|
||||
StaticDescriptor<1> staticDescriptor;
|
||||
Descriptor &whole{staticDescriptor.descriptor()};
|
||||
SubscriptValue extent[]{numBuffers};
|
||||
whole.Establish(TypeCode{CFI_type_char}, maxBufferLength, &buffer, 1, extent,
|
||||
CFI_attribute_pointer);
|
||||
whole.Check();
|
||||
auto *cookie{IONAME(BeginInternalArrayListInput)(whole)};
|
||||
|
||||
constexpr int listInputLength{9};
|
||||
|
||||
// Negative numbers will be overwritten by _expectedOutput_, and positive
|
||||
// numbers will not be as their indices are "Null values" of the Fortran 2018
|
||||
// standard 13.10.3.2 in the format strings _buffer_
|
||||
std::int64_t actualOutput[listInputLength]{-1, -2, -3, -4, 5, -6, 7, -8, 9};
|
||||
const std::int64_t expectedOutput[listInputLength]{1, 2, 3, 3, 5, 6, 7, 8, 9};
|
||||
for (j = 0; j < listInputLength; ++j) {
|
||||
IONAME(InputInteger)(cookie, actualOutput[j]);
|
||||
}
|
||||
|
||||
const auto status{IONAME(EndIoStatement)(cookie)};
|
||||
ASSERT_EQ(status, 0) << "list-directed input failed, status "
|
||||
<< static_cast<int>(status) << '\n';
|
||||
|
||||
// Verify the calls to _InputInteger_ resulted in _expectedOutput_
|
||||
for (j = 0; j < listInputLength; ++j) {
|
||||
ASSERT_EQ(actualOutput[j], expectedOutput[j])
|
||||
<< "wanted actualOutput[" << j << "]==" << expectedOutput[j] << ", got "
|
||||
<< actualOutput[j] << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
TEST(InputTest, TestListInputInvalidFormatWithSingleSuccess) {
|
||||
std::string formatBuffer{"1, g"};
|
||||
constexpr int numBuffers{1};
|
||||
|
||||
StaticDescriptor<1> staticDescriptor;
|
||||
Descriptor &whole{staticDescriptor.descriptor()};
|
||||
SubscriptValue extent[]{numBuffers};
|
||||
whole.Establish(TypeCode{CFI_type_char}, formatBuffer.size(),
|
||||
formatBuffer.data(), 1, extent, CFI_attribute_pointer);
|
||||
whole.Check();
|
||||
|
||||
auto *cookie{IONAME(BeginInternalArrayListInput)(whole)};
|
||||
std::int64_t dummy;
|
||||
|
||||
// Perform _InputInteger_ once successfully
|
||||
IONAME(InputInteger)(cookie, dummy);
|
||||
|
||||
// Perform failing InputInteger
|
||||
ASSERT_DEATH(IONAME(InputInteger)(cookie, dummy),
|
||||
"Bad character 'g' in INTEGER input field");
|
||||
}
|
||||
|
||||
// Same test as _TestListInputInvalidFormatWithSingleSuccess_, however no
|
||||
// successful call to _InputInteger_ is performed first.
|
||||
TEST(InputTest, TestListInputInvalidFormat) {
|
||||
std::string formatBuffer{"g"};
|
||||
constexpr int numBuffers{1};
|
||||
|
||||
StaticDescriptor<1> staticDescriptor;
|
||||
Descriptor &whole{staticDescriptor.descriptor()};
|
||||
SubscriptValue extent[]{numBuffers};
|
||||
whole.Establish(TypeCode{CFI_type_char}, formatBuffer.size(),
|
||||
formatBuffer.data(), 1, extent, CFI_attribute_pointer);
|
||||
whole.Check();
|
||||
|
||||
auto *cookie{IONAME(BeginInternalArrayListInput)(whole)};
|
||||
std::int64_t dummy;
|
||||
|
||||
// Perform failing InputInteger
|
||||
ASSERT_DEATH(IONAME(InputInteger)(cookie, dummy),
|
||||
"Bad character 'g' in INTEGER input field");
|
||||
}
|
||||
|
||||
using ParamTy = std::tuple<std::string, std::vector<int>>;
|
||||
|
||||
struct SimpleListInputTest : testing::TestWithParam<ParamTy> {};
|
||||
|
||||
TEST_P(SimpleListInputTest, TestListInput) {
|
||||
auto [formatBuffer, expectedOutput] = GetParam();
|
||||
constexpr int numBuffers{1};
|
||||
|
||||
StaticDescriptor<1> staticDescriptor;
|
||||
Descriptor &whole{staticDescriptor.descriptor()};
|
||||
SubscriptValue extent[]{numBuffers};
|
||||
whole.Establish(TypeCode{CFI_type_char}, formatBuffer.size(),
|
||||
formatBuffer.data(), 1, extent, CFI_attribute_pointer);
|
||||
whole.Check();
|
||||
auto *cookie{IONAME(BeginInternalArrayListInput)(whole)};
|
||||
|
||||
const auto listInputLength{expectedOutput.size()};
|
||||
std::vector<std::int64_t> actualOutput(listInputLength);
|
||||
for (std::size_t j = 0; j < listInputLength; ++j) {
|
||||
IONAME(InputInteger)(cookie, actualOutput[j]);
|
||||
}
|
||||
|
||||
const auto status{IONAME(EndIoStatement)(cookie)};
|
||||
ASSERT_EQ(status, 0) << "list-directed input failed, status "
|
||||
<< static_cast<int>(status) << '\n';
|
||||
|
||||
// Verify the calls to _InputInteger_ resulted in _expectedOutput_
|
||||
for (std::size_t j = 0; j < listInputLength; ++j) {
|
||||
ASSERT_EQ(actualOutput[j], expectedOutput[j])
|
||||
<< "wanted actualOutput[" << j << "]==" << expectedOutput[j] << ", got "
|
||||
<< actualOutput[j] << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SimpleListInputTestInstantiation, SimpleListInputTest,
|
||||
testing::Values(std::make_tuple("", std::vector<int>{}),
|
||||
std::make_tuple("0", std::vector<int>{}),
|
||||
std::make_tuple("1", std::vector<int>{1}),
|
||||
std::make_tuple("1, 2", std::vector<int>{1, 2}),
|
||||
std::make_tuple("3*2", std::vector<int>{2, 2, 2})), );
|
Loading…
Reference in New Issue