brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.1 KiB · a8f0d45 Raw
194 lines · cpp
1//===-- unittests/Runtime/ListInputTest.cpp ---------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "CrashHandlerFixture.h"10#include "flang-rt/runtime/descriptor.h"11#include "flang-rt/runtime/io-error.h"12#include "flang/Runtime/io-api.h"13 14using namespace Fortran::runtime;15using namespace Fortran::runtime::io;16 17// Pads characters with whitespace when needed18void SetCharacter(char *to, std::size_t n, const char *from) {19  auto len{std::strlen(from)};20  std::memcpy(to, from, std::min(len, n));21  if (len < n) {22    std::memset(to + len, ' ', n - len);23  }24}25 26struct InputTest : CrashHandlerFixture {};27 28TEST(InputTest, TestListInputAlphabet) {29  constexpr int numInputBuffers{2};30  constexpr int maxInputBufferLength{32};31  char inputBuffers[numInputBuffers][maxInputBufferLength];32  const char expectedOutput[]{33      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "};34  int j{0};35 36  // Use _two_ input buffers and _three_ output buffers. Note the `3*` in the37  // _inputBuffers_.38  SetCharacter(inputBuffers[j++], maxInputBufferLength,39      "3*'abcdefghijklmnopqrstuvwxyzABC");40  SetCharacter(41      inputBuffers[j++], maxInputBufferLength, "DEFGHIJKLMNOPQRSTUVWXYZ'");42 43  StaticDescriptor<1> staticDescriptor;44  Descriptor &whole{staticDescriptor.descriptor()};45  SubscriptValue extent[]{numInputBuffers};46  whole.Establish(TypeCode{CFI_type_char}, maxInputBufferLength, &inputBuffers,47      1, extent, CFI_attribute_pointer);48  whole.Check();49  auto *cookie{IONAME(BeginInternalArrayListInput)(whole)};50 51  constexpr int numOutputBuffers{3};52  constexpr int outputBufferLength{54};53  char outputBuffers[numOutputBuffers][outputBufferLength]{};54  for (j = 0; j < numOutputBuffers; ++j) {55    IONAME(InputAscii)(cookie, outputBuffers[j], outputBufferLength - 1);56  }57 58  const auto status{IONAME(EndIoStatement)(cookie)};59  ASSERT_EQ(status, 0) << "list-directed input failed, status "60                       << static_cast<int>(status) << '\n';61 62  // Verify results that the _two_ ascii inputs result in _three_ alphabets63  for (j = 0; j < numOutputBuffers; ++j) {64    ASSERT_EQ(std::strcmp(outputBuffers[j], expectedOutput), 0)65        << "wanted outputBuffers[" << j << "]=" << expectedOutput << ", got '"66        << outputBuffers[j] << "'\n";67  }68}69 70TEST(InputTest, TestListInputIntegerList) {71  constexpr int numBuffers{2};72  constexpr int maxBufferLength{32};73  char buffer[numBuffers][maxBufferLength];74  int j{0};75  SetCharacter(buffer[j++], maxBufferLength, "1 2 2*3  ,");76  SetCharacter(buffer[j++], maxBufferLength, ",6,,8,2*");77 78  StaticDescriptor<1> staticDescriptor;79  Descriptor &whole{staticDescriptor.descriptor()};80  SubscriptValue extent[]{numBuffers};81  whole.Establish(TypeCode{CFI_type_char}, maxBufferLength, &buffer, 1, extent,82      CFI_attribute_pointer);83  whole.Check();84  auto *cookie{IONAME(BeginInternalArrayListInput)(whole)};85 86  constexpr int listInputLength{10};87 88  // Negative numbers will be overwritten by _expectedOutput_, and positive89  // numbers will not be as their indices are "Null values" of the Fortran 201890  // standard 13.10.3.2 in the format strings _buffer_91  std::int64_t actualOutput[listInputLength]{92      -1, -2, -3, -4, 5, -6, 7, -8, 9, 10};93  const std::int64_t expectedOutput[listInputLength]{94      1, 2, 3, 3, 5, 6, 7, 8, 9, 10};95  for (j = 0; j < listInputLength; ++j) {96    IONAME(InputInteger)(cookie, actualOutput[j]);97  }98 99  const auto status{IONAME(EndIoStatement)(cookie)};100  ASSERT_EQ(status, 0) << "list-directed input failed, status "101                       << static_cast<int>(status) << '\n';102 103  // Verify the calls to _InputInteger_ resulted in _expectedOutput_104  for (j = 0; j < listInputLength; ++j) {105    ASSERT_EQ(actualOutput[j], expectedOutput[j])106        << "wanted actualOutput[" << j << "]==" << expectedOutput[j] << ", got "107        << actualOutput[j] << '\n';108  }109}110 111TEST(InputTest, TestListInputInvalidFormatWithSingleSuccess) {112  std::string formatBuffer{"1, g"};113  constexpr int numBuffers{1};114 115  StaticDescriptor<1> staticDescriptor;116  Descriptor &whole{staticDescriptor.descriptor()};117  SubscriptValue extent[]{numBuffers};118  whole.Establish(TypeCode{CFI_type_char}, formatBuffer.size(),119      formatBuffer.data(), 1, extent, CFI_attribute_pointer);120  whole.Check();121 122  auto *cookie{IONAME(BeginInternalArrayListInput)(whole)};123  std::int64_t dummy;124 125  // Perform _InputInteger_ once successfully126  IONAME(InputInteger)(cookie, dummy);127 128  // Perform failing InputInteger129  ASSERT_DEATH(IONAME(InputInteger)(cookie, dummy),130      "Bad character 'g' in INTEGER input field");131}132 133// Same test as _TestListInputInvalidFormatWithSingleSuccess_, however no134// successful call to _InputInteger_ is performed first.135TEST(InputTest, TestListInputInvalidFormat) {136  std::string formatBuffer{"g"};137  constexpr int numBuffers{1};138 139  StaticDescriptor<1> staticDescriptor;140  Descriptor &whole{staticDescriptor.descriptor()};141  SubscriptValue extent[]{numBuffers};142  whole.Establish(TypeCode{CFI_type_char}, formatBuffer.size(),143      formatBuffer.data(), 1, extent, CFI_attribute_pointer);144  whole.Check();145 146  auto *cookie{IONAME(BeginInternalArrayListInput)(whole)};147  std::int64_t dummy;148 149  // Perform failing InputInteger150  ASSERT_DEATH(IONAME(InputInteger)(cookie, dummy),151      "Bad character 'g' in INTEGER input field");152}153 154using ParamTy = std::tuple<std::string, std::vector<int>>;155 156struct SimpleListInputTest : testing::TestWithParam<ParamTy> {};157 158TEST_P(SimpleListInputTest, TestListInput) {159  auto [formatBuffer, expectedOutput] = GetParam();160  constexpr int numBuffers{1};161 162  StaticDescriptor<1> staticDescriptor;163  Descriptor &whole{staticDescriptor.descriptor()};164  SubscriptValue extent[]{numBuffers};165  whole.Establish(TypeCode{CFI_type_char}, formatBuffer.size(),166      formatBuffer.data(), 1, extent, CFI_attribute_pointer);167  whole.Check();168  auto *cookie{IONAME(BeginInternalArrayListInput)(whole)};169 170  const auto listInputLength{expectedOutput.size()};171  std::vector<std::int64_t> actualOutput(listInputLength);172  for (std::size_t j = 0; j < listInputLength; ++j) {173    IONAME(InputInteger)(cookie, actualOutput[j]);174  }175 176  const auto status{IONAME(EndIoStatement)(cookie)};177  ASSERT_EQ(status, 0) << "list-directed input failed, status "178                       << static_cast<int>(status) << '\n';179 180  // Verify the calls to _InputInteger_ resulted in _expectedOutput_181  for (std::size_t j = 0; j < listInputLength; ++j) {182    ASSERT_EQ(actualOutput[j], expectedOutput[j])183        << "wanted actualOutput[" << j << "]==" << expectedOutput[j] << ", got "184        << actualOutput[j] << '\n';185  }186}187 188INSTANTIATE_TEST_SUITE_P(SimpleListInputTestInstantiation, SimpleListInputTest,189    testing::Values(std::make_tuple("", std::vector<int>{}),190        std::make_tuple("0", std::vector<int>{}),191        std::make_tuple("1", std::vector<int>{1}),192        std::make_tuple("1, 2", std::vector<int>{1, 2}),193        std::make_tuple("3*2", std::vector<int>{2, 2, 2})));194