aboutsummaryrefslogtreecommitdiff
path: root/flang
diff options
context:
space:
mode:
authorAsher Mancinelli <asher.mancinelli@pnnl.gov>2021-03-30 11:16:23 -0700
committerAsher Mancinelli <asher.mancinelli@pnnl.gov>2021-04-15 09:27:43 -0700
commitccef0adc59680cf307fcb3334f15d4e2cba62de7 (patch)
treeb008a218abc1922d7facc256677c685ecf16ee67 /flang
parent[libc] Add index operator[] to StringView (diff)
downloadllvm-project-ccef0adc59680cf307fcb3334f15d4e2cba62de7.tar.gz
llvm-project-ccef0adc59680cf307fcb3334f15d4e2cba62de7.tar.bz2
llvm-project-ccef0adc59680cf307fcb3334f15d4e2cba62de7.zip
[flang] Add list input test to GTest suite
Diffstat (limited to 'flang')
-rw-r--r--flang/unittests/Runtime/CMakeLists.txt5
-rw-r--r--flang/unittests/Runtime/list-input.cpp67
-rw-r--r--flang/unittests/Runtime/testing.cpp8
-rw-r--r--flang/unittests/Runtime/testing.h3
-rw-r--r--flang/unittests/RuntimeGTest/CMakeLists.txt1
-rw-r--r--flang/unittests/RuntimeGTest/ListInputTest.cpp191
6 files changed, 192 insertions, 83 deletions
diff --git a/flang/unittests/Runtime/CMakeLists.txt b/flang/unittests/Runtime/CMakeLists.txt
index cc7ac7277183..03998fa55d14 100644
--- a/flang/unittests/Runtime/CMakeLists.txt
+++ b/flang/unittests/Runtime/CMakeLists.txt
@@ -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
diff --git a/flang/unittests/Runtime/list-input.cpp b/flang/unittests/Runtime/list-input.cpp
deleted file mode 100644
index 9ec77080203a..000000000000
--- a/flang/unittests/Runtime/list-input.cpp
+++ /dev/null
@@ -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();
-}
diff --git a/flang/unittests/Runtime/testing.cpp b/flang/unittests/Runtime/testing.cpp
index 546a1e1da51d..ab2b5c25bcb9 100644
--- a/flang/unittests/Runtime/testing.cpp
+++ b/flang/unittests/Runtime/testing.cpp
@@ -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);
- }
-}
diff --git a/flang/unittests/Runtime/testing.h b/flang/unittests/Runtime/testing.h
index d3551ba5ef07..21c2acd9b0aa 100644
--- a/flang/unittests/Runtime/testing.h
+++ b/flang/unittests/Runtime/testing.h
@@ -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_
diff --git a/flang/unittests/RuntimeGTest/CMakeLists.txt b/flang/unittests/RuntimeGTest/CMakeLists.txt
index 80314c124831..38a577d5add0 100644
--- a/flang/unittests/RuntimeGTest/CMakeLists.txt
+++ b/flang/unittests/RuntimeGTest/CMakeLists.txt
@@ -7,6 +7,7 @@ add_flang_unittest(FlangRuntimeTests
Random.cpp
Reduction.cpp
RuntimeCrashTest.cpp
+ ListInputTest.cpp
)
target_link_libraries(FlangRuntimeTests
diff --git a/flang/unittests/RuntimeGTest/ListInputTest.cpp b/flang/unittests/RuntimeGTest/ListInputTest.cpp
new file mode 100644
index 000000000000..9654048f20bb
--- /dev/null
+++ b/flang/unittests/RuntimeGTest/ListInputTest.cpp
@@ -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})), );