brintos

brintos / llvm-project-archived public Read only

0
0
Text · 45.0 KiB · 033002c Raw
1021 lines · cpp
1//===-- unittests/Runtime/NumericalFormatTest.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/Runtime/io-api.h"12#include <algorithm>13#include <array>14#include <cstring>15#include <gtest/gtest.h>16#include <tuple>17 18using namespace Fortran::runtime;19using namespace Fortran::runtime::io;20 21static bool CompareFormattedStrings(22    const std::string &expect, const std::string &got) {23  std::string want{expect};24  want.resize(got.size(), ' ');25  return want == got;26}27 28static bool CompareFormattedStrings(29    const char *expect, const std::string &&got) {30  return CompareFormattedStrings(std::string(expect), std::move(got));31}32 33// Perform format and compare the result with expected value34static bool CompareFormatReal(35    const char *format, double x, const char *expect, std::string &got) {36  char buffer[800];37  auto cookie{IONAME(BeginInternalFormattedOutput)(38      buffer, sizeof buffer, format, std::strlen(format))};39  EXPECT_TRUE(IONAME(OutputReal64)(cookie, x));40  auto status{IONAME(EndIoStatement)(cookie)};41  EXPECT_EQ(status, 0);42  got = std::string{buffer, sizeof buffer};43  auto lastNonBlank{got.find_last_not_of(" ")};44  if (lastNonBlank != std::string::npos) {45    got.resize(lastNonBlank + 1);46  }47  return CompareFormattedStrings(expect, got);48}49 50// Convert raw uint64 into double, perform format, and compare with expected51static bool CompareFormatReal(const char *format, std::uint64_t xInt,52    const char *expect, std::string &got) {53  double x;54  static_assert(sizeof(double) == sizeof(std::uint64_t),55      "Size of double != size of uint64_t!");56  std::memcpy(&x, &xInt, sizeof xInt);57  return CompareFormatReal(format, x, expect, got);58}59 60static bool CompareFormatInteger(61    const char *format, std::int64_t x, const char *expect, std::string &got) {62  char buffer[800];63  auto cookie{IONAME(BeginInternalFormattedOutput)(64      buffer, sizeof buffer, format, std::strlen(format))};65  EXPECT_TRUE(IONAME(OutputInteger64)(cookie, x));66  auto status{IONAME(EndIoStatement)(cookie)};67  EXPECT_EQ(status, 0);68  got = std::string{buffer, sizeof buffer};69  auto lastNonBlank{got.find_last_not_of(" ")};70  if (lastNonBlank != std::string::npos) {71    got.resize(lastNonBlank + 1);72  }73  return CompareFormattedStrings(expect, got);74}75 76struct IOApiTests : CrashHandlerFixture {};77 78TEST(IOApiTests, HelloWorldOutputTest) {79  static constexpr int bufferSize{32};80  char buffer[bufferSize];81 82  // Create format for all types and values to be written83  const char *format{"(6HHELLO,,A6,2X,I3,1X,'0x',Z8,1X,L1)"};84  auto cookie{IONAME(BeginInternalFormattedOutput)(85      buffer, bufferSize, format, std::strlen(format))};86 87  // Write string, integer, and logical values to buffer88  IONAME(OutputAscii)(cookie, "WORLD", 5);89  IONAME(OutputInteger64)(cookie, 678);90  IONAME(OutputInteger32)(cookie, 0xfeedface);91  IONAME(OutputLogical)(cookie, true);92 93  // Ensure IO succeeded94  auto status{IONAME(EndIoStatement)(cookie)};95  ASSERT_EQ(status, 0) << "hello: '" << format << "' failed, status "96                       << static_cast<int>(status);97 98  // Ensure final buffer matches expected string output99  static const std::string expect{"HELLO, WORLD  678 0xFEEDFACE T"};100  ASSERT_TRUE(101      CompareFormattedStrings(expect, std::string{buffer, sizeof buffer}))102      << "Expected '" << expect << "', got " << buffer;103}104 105TEST(IOApiTests, MultilineOutputTest) {106  // Allocate buffer for multiline output107  static constexpr int numLines{5};108  static constexpr int lineLength{32};109  char buffer[numLines][lineLength];110 111  // Create descriptor for entire buffer112  static constexpr int staticDescriptorMaxRank{1};113  StaticDescriptor<staticDescriptorMaxRank> wholeStaticDescriptor;114  Descriptor &whole{wholeStaticDescriptor.descriptor()};115  static const SubscriptValue extent[]{numLines};116  whole.Establish(TypeCode{CFI_type_char}, /*elementBytes=*/lineLength, &buffer,117      staticDescriptorMaxRank, extent, CFI_attribute_pointer);118  whole.Dump(stderr);119  whole.Check();120 121  // Create descriptor for buffer section122  StaticDescriptor<staticDescriptorMaxRank> sectionStaticDescriptor;123  Descriptor &section{sectionStaticDescriptor.descriptor()};124  static const SubscriptValue lowers[]{0}, uppers[]{4}, strides[]{1};125  section.Establish(whole.type(), /*elementBytes=*/whole.ElementBytes(),126      nullptr, /*maxRank=*/staticDescriptorMaxRank, extent,127      CFI_attribute_pointer);128 129  // Ensure C descriptor address `section.raw()` is updated without error130  const auto error{131      CFI_section(&section.raw(), &whole.raw(), lowers, uppers, strides)};132  ASSERT_EQ(error, 0) << "multiline: CFI_section failed: " << error;133  section.Dump(stderr);134  section.Check();135 136  // Create format string and initialize IO operation137  const char *format{138      "('?abcde,',T1,'>',T9,A,TL12,A,TR25,'<'//G0,17X,'abcd',1(2I4))"};139  auto cookie{IONAME(BeginInternalArrayFormattedOutput)(140      section, format, std::strlen(format))};141 142  // Fill last line with periods143  std::memset(buffer[numLines - 1], '.', lineLength);144 145  // Write data to buffer146  IONAME(OutputAscii)(cookie, "WORLD", 5);147  IONAME(OutputAscii)(cookie, "HELLO", 5);148  IONAME(OutputInteger64)(cookie, 789);149  for (int j{666}; j <= 999; j += 111) {150    IONAME(OutputInteger64)(cookie, j);151  }152 153  // Ensure no errors occured in write operations above154  const auto status{IONAME(EndIoStatement)(cookie)};155  ASSERT_EQ(status, 0) << "multiline: '" << format << "' failed, status "156                       << static_cast<int>(status);157 158  static const std::string expect{">HELLO, WORLD                  <"159                                  "                                "160                                  "789                 abcd 666 777"161                                  " 888 999                        "162                                  "................................"};163  // Ensure formatted string matches expected output164  EXPECT_TRUE(165      CompareFormattedStrings(expect, std::string{buffer[0], sizeof buffer}))166      << "Expected '" << expect << "' but got '"167      << std::string{buffer[0], sizeof buffer} << "'";168}169 170TEST(IOApiTests, ListInputTest) {171  static const char input[]{",1*,(5.,6.),(7.0,8.0)"};172  auto cookie{IONAME(BeginInternalListInput)(input, sizeof input - 1)};173 174  // Create real values for IO tests175  static constexpr int numRealValues{8};176  float z[numRealValues];177  for (int j{0}; j < numRealValues; ++j) {178    z[j] = -(j + 1);179  }180 181  // Ensure reading complex values to floats does not result in an error182  for (int j{0}; j < numRealValues; j += 2) {183    ASSERT_TRUE(IONAME(InputComplex32)(cookie, &z[j]))184        << "InputComplex32 failed with value " << z[j];185  }186 187  // Ensure no IO errors occured during IO operations above188  auto status{IONAME(EndIoStatement)(cookie)};189  ASSERT_EQ(status, 0) << "Failed complex list-directed input, status "190                       << static_cast<int>(status);191 192  // Ensure writing complex values from floats does not result in an error193  static constexpr int bufferSize{39};194  char output[bufferSize];195  output[bufferSize - 1] = '\0';196  cookie = IONAME(BeginInternalListOutput)(output, bufferSize - 1);197  for (int j{0}; j < numRealValues; j += 2) {198    ASSERT_TRUE(IONAME(OutputComplex32)(cookie, z[j], z[j + 1]))199        << "OutputComplex32 failed when outputting value " << z[j] << ", "200        << z[j + 1];201  }202 203  // Ensure no IO errors occured during IO operations above204  status = IONAME(EndIoStatement)(cookie);205  ASSERT_EQ(status, 0) << "Failed complex list-directed output, status "206                       << static_cast<int>(status);207 208  // Verify output buffer against expected value209  static const char expect[bufferSize]{210      " (-1.,-2.) (-3.,-4.) (5.,6.) (7.,8.)  "};211  ASSERT_EQ(std::strncmp(output, expect, bufferSize), 0)212      << "Failed complex list-directed output, expected '" << expect213      << "', but got '" << output << "'";214}215 216TEST(IOApiTests, ListInputComplexRegressionTest) {217  static const char input[]{"(1,;2, );(3,;4,)"};218  auto cookie{IONAME(BeginInternalListInput)(input, sizeof input - 1)};219  static constexpr int numRealValues{4};220  float z[numRealValues];221  ASSERT_TRUE(IONAME(SetDecimal)(cookie, "COMMA", 5));222  for (int j{0}; j < numRealValues; j += 2) {223    ASSERT_TRUE(IONAME(InputComplex32)(cookie, &z[j]))224        << "InputComplex32 failed with value " << z[j];225  }226  auto status{IONAME(EndIoStatement)(cookie)};227  ASSERT_EQ(status, 0) << "Failed complex list-directed input, status "228                       << static_cast<int>(status);229  static constexpr int bufferSize{18};230  char output[bufferSize];231  output[bufferSize - 1] = '\0';232  cookie = IONAME(BeginInternalListOutput)(output, bufferSize - 1);233  for (int j{0}; j < numRealValues; j += 2) {234    ASSERT_TRUE(IONAME(OutputComplex32)(cookie, z[j], z[j + 1]))235        << "OutputComplex32 failed when outputting value " << z[j] << ", "236        << z[j + 1];237  }238  status = IONAME(EndIoStatement)(cookie);239  ASSERT_EQ(status, 0) << "Failed complex list-directed output, status "240                       << static_cast<int>(status);241  static const char expect[bufferSize]{" (1.,2.) (3.,4.) "};242  ASSERT_EQ(std::strncmp(output, expect, bufferSize), 0)243      << "Failed complex list-directed output, expected '" << expect244      << "', but got '" << output << "'";245}246 247TEST(IOApiTests, DescriptorOutputTest) {248  static constexpr int bufferSize{10};249  char buffer[bufferSize];250  const char *format{"(2A4)"};251  auto cookie{IONAME(BeginInternalFormattedOutput)(252      buffer, bufferSize, format, std::strlen(format))};253 254  // Create descriptor for output255  static constexpr int staticDescriptorMaxRank{1};256  StaticDescriptor<staticDescriptorMaxRank> staticDescriptor;257  Descriptor &desc{staticDescriptor.descriptor()};258  static constexpr int subscriptExtent{2};259  static const SubscriptValue extent[]{subscriptExtent};260 261  // Manually write to descriptor buffer262  static constexpr int dataLength{4};263  char data[subscriptExtent][dataLength];264  std::memcpy(data[0], "ABCD", dataLength);265  std::memcpy(data[1], "EFGH", dataLength);266  desc.Establish(TypeCode{CFI_type_char}, dataLength, &data,267      staticDescriptorMaxRank, extent);268  desc.Dump(stderr);269  desc.Check();270  IONAME(OutputDescriptor)(cookie, desc);271 272  // Ensure no errors were encountered in initializing the cookie and descriptor273  auto formatStatus{IONAME(EndIoStatement)(cookie)};274  ASSERT_EQ(formatStatus, 0)275      << "descrOutputTest: '" << format << "' failed, status "276      << static_cast<int>(formatStatus);277 278  // Ensure buffer matches expected output279  EXPECT_TRUE(280      CompareFormattedStrings("ABCDEFGH  ", std::string{buffer, sizeof buffer}))281      << "descrOutputTest: formatted: got '"282      << std::string{buffer, sizeof buffer} << "'";283 284  // Begin list-directed output on cookie by descriptor285  cookie = IONAME(BeginInternalListOutput)(buffer, sizeof buffer);286  IONAME(OutputDescriptor)(cookie, desc);287 288  // Ensure list-directed output does not result in an IO error289  auto listDirectedStatus{IONAME(EndIoStatement)(cookie)};290  ASSERT_EQ(listDirectedStatus, 0)291      << "descrOutputTest: list-directed failed, status "292      << static_cast<int>(listDirectedStatus);293 294  // Ensure buffer matches expected output295  EXPECT_TRUE(296      CompareFormattedStrings(" ABCDEFGH ", std::string{buffer, sizeof buffer}))297      << "descrOutputTest: list-directed: got '"298      << std::string{buffer, sizeof buffer} << "'";299}300 301//------------------------------------------------------------------------------302/// Tests for output formatting real values303//------------------------------------------------------------------------------304 305TEST(IOApiTests, FormatZeroes) {306  static constexpr std::pair<const char *, const char *> zeroes[]{307      {"(E32.17,';')", "         0.00000000000000000E+00;"},308      {"(F32.17,';')", "             0.00000000000000000;"},309      {"(G32.17,';')", "          0.0000000000000000    ;"},310      {"(DC,E32.17,';')", "         0,00000000000000000E+00;"},311      {"(DC,F32.17,';')", "             0,00000000000000000;"},312      {"(DC,G32.17,';')", "          0,0000000000000000    ;"},313      {"(D32.17,';')", "         0.00000000000000000D+00;"},314      {"(E32.17E1,';')", "          0.00000000000000000E+0;"},315      {"(G32.17E1,';')", "           0.0000000000000000   ;"},316      {"(E32.17E0,';')", "          0.00000000000000000E+0;"},317      {"(G32.17E0,';')", "          0.0000000000000000    ;"},318      {"(1P,E32.17,';')", "         0.00000000000000000E+00;"},319      {"(1PE32.17,';')", "         0.00000000000000000E+00;"}, // no comma320      {"(1P,F32.17,';')", "             0.00000000000000000;"},321      {"(1P,G32.17,';')", "          0.0000000000000000    ;"},322      {"(2P,E32.17,';')", "         00.0000000000000000E+00;"},323      {"(-1P,E32.17,';')", "         0.00000000000000000E+00;"},324      {"(EX32.17,';')", "        0X0.00000000000000000P+0;"},325      {"(DC,EX32.17,';')", "        0X0,00000000000000000P+0;"},326      {"(G0,';')", "0.;"},327  };328 329  for (auto const &[format, expect] : zeroes) {330    std::string got;331    ASSERT_TRUE(CompareFormatReal(format, 0.0, expect, got))332        << "Failed to format " << format << ", expected '" << expect333        << "', got '" << got << "'";334  }335}336 337TEST(IOApiTests, FormatOnes) {338  static constexpr std::pair<const char *, const char *> ones[]{339      {"(E32.17,';')", "         0.10000000000000000E+01;"},340      {"(F32.17,';')", "             1.00000000000000000;"},341      {"(G32.17,';')", "          1.0000000000000000    ;"},342      {"(E32.17E1,';')", "          0.10000000000000000E+1;"},343      {"(G32.17E1,';')", "           1.0000000000000000   ;"},344      {"(E32.17E0,';')", "          0.10000000000000000E+1;"},345      {"(G32.17E0,';')", "          1.0000000000000000    ;"},346      {"(E32.17E4,';')", "       0.10000000000000000E+0001;"},347      {"(G32.17E4,';')", "        1.0000000000000000      ;"},348      {"(1P,E32.17,';')", "         1.00000000000000000E+00;"},349      {"(1PE32.17,';')", "         1.00000000000000000E+00;"}, // no comma350      {"(1P,F32.17,';')", "            10.00000000000000000;"},351      {"(1P,G32.17,';')", "          1.0000000000000000    ;"},352      {"(ES32.17,';')", "         1.00000000000000000E+00;"},353      {"(2P,E32.17,';')", "         10.0000000000000000E-01;"},354      {"(2P,G32.17,';')", "          1.0000000000000000    ;"},355      {"(-1P,E32.17,';')", "         0.01000000000000000E+02;"},356      {"(-1P,G32.17,';')", "          1.0000000000000000    ;"},357      {"(EX32.17,';')", "        0X8.00000000000000000P-3;"},358      {"(DC,EX32.17,';')", "        0X8,00000000000000000P-3;"},359      {"(G0,';')", "1.;"},360  };361 362  for (auto const &[format, expect] : ones) {363    std::string got;364    ASSERT_TRUE(CompareFormatReal(format, 1.0, expect, got))365        << "Failed to format " << format << ", expected '" << expect366        << "', got '" << got << "'";367  }368}369 370TEST(IOApiTests, FormatNegativeOnes) {371  static constexpr std::tuple<const char *, const char *> negOnes[]{372      {"(E32.17,';')", "        -0.10000000000000000E+01;"},373      {"(F32.17,';')", "            -1.00000000000000000;"},374      {"(G32.17,';')", "         -1.0000000000000000    ;"},375      {"(EX32.17,';')", "       -0X8.00000000000000000P-3;"},376      {"(G0,';')", "-1.;"},377  };378  for (auto const &[format, expect] : negOnes) {379    std::string got;380    ASSERT_TRUE(CompareFormatReal(format, -1.0, expect, got))381        << "Failed to format " << format << ", expected '" << expect382        << "', got '" << got << "'";383  }384}385 386// Each test case contains a raw uint64, a format string for a real value, and387// the expected resulting string from formatting the raw uint64. The double388// representation of the uint64 is commented above each test case.389TEST(IOApiTests, FormatDoubleValues) {390 391  using TestCaseTy = std::tuple<std::uint64_t,392      std::vector<std::tuple<const char *, const char *>>>;393  static const std::vector<TestCaseTy> testCases{394      {// -0395          0x8000000000000000,396          {397              {"(E9.1,';')", " -0.0E+00;"},398              {"(F4.0,';')", " -0.;"},399              {"(F0.1,';')", "-.0;"},400              {"(G8.0,';')", "-0.0E+00;"},401              {"(G8.1,';')", " -0.    ;"},402              {"(G0,';')", "-0.;"},403              {"(E9.1,';')", " -0.0E+00;"},404              {"(EX9.1,';')", "-0X0.0P+0;"},405          }},406      {// +Inf407          0x7ff0000000000000,408          {409              {"(E9.1,';')", "      Inf;"},410              {"(F9.1,';')", "      Inf;"},411              {"(G9.1,';')", "      Inf;"},412              {"(EX9.1,';')", "      Inf;"},413              {"(SP,E9.1,';')", "     +Inf;"},414              {"(SP,F9.1,';')", "     +Inf;"},415              {"(SP,G9.1,';')", "     +Inf;"},416              {"(SP,EX9.1,';')", "     +Inf;"},417              {"(G0,';')", "Inf;"},418          }},419      {// -Inf420          0xfff0000000000000,421          {422              {"(E9.1,';')", "     -Inf;"},423              {"(F9.1,';')", "     -Inf;"},424              {"(G9.1,';')", "     -Inf;"},425              {"(EX9.1,';')", "     -Inf;"},426              {"(G0,';')", "-Inf;"},427          }},428      {// NaN429          0x7ff0000000000001,430          {431              {"(E9.1,';')", "      NaN;"},432              {"(F9.1,';')", "      NaN;"},433              {"(G9.1,';')", "      NaN;"},434              {"(EX9.1,';')", "      NaN;"},435              {"(G0,';')", "NaN;"},436          }},437      {// NaN (sign irrelevant)438          0xfff0000000000001,439          {440              {"(E9.1,';')", "      NaN;"},441              {"(F9.1,';')", "      NaN;"},442              {"(G9.1,';')", "      NaN;"},443              {"(SP,E9.1,';')", "      NaN;"},444              {"(SP,F9.1,';')", "      NaN;"},445              {"(SP,G9.1,';')", "      NaN;"},446              {"(SP,EX9.1,';')", "      NaN;"},447              {"(G0,';')", "NaN;"},448          }},449      {// 0.1 rounded450          0x3fb999999999999a,451          {452              {"(E62.55,';')",453                  " 0.1000000000000000055511151231257827021181583404541015625E+"454                  "00;"},455              {"(E0.1,';')", ".1E+00;"},456              {"(E0.55,';')",457                  ".1000000000000000055511151231257827021181583404541015625E+"458                  "00;"},459              {"(E0,';')", ".1E+00;"},460              {"(F58.55,';')",461                  " 0."462                  "1000000000000000055511151231257827021181583404541015625;"},463              {"(F0.0,';')", "0.;"},464              {"(F0.55,';')",465                  ".1000000000000000055511151231257827021181583404541015625;"},466              {"(F0,';')", ".1;"},467              {"(G62.55,';')",468                  " 0.1000000000000000055511151231257827021181583404541015625  "469                  "  ;"},470              {"(G0.0,';')", "0.;"},471              {"(G0.55,';')",472                  ".1000000000000000055511151231257827021181583404541015625;"},473              {"(G0,';')", ".1;"},474              {"(EX20.12,';')", " 0XC.CCCCCCCCCCCDP-7;"},475          }},476      {// 1.5477          0x3ff8000000000000,478          {479              {"(E9.2,';')", " 0.15E+01;"},480              {"(F4.1,';')", " 1.5;"},481              {"(G7.1,';')", " 2.    ;"},482              {"(EX9.1,';')", " 0XC.0P-3;"},483              {"(RN,E8.1,';')", " 0.2E+01;"},484              {"(RN,F3.0,';')", " 2.;"},485              {"(RN,G7.0,';')", " 0.E+01;"},486              {"(RN,G7.1,';')", " 2.    ;"},487              {"(RD,E8.1,';')", " 0.1E+01;"},488              {"(RD,F3.0,';')", " 1.;"},489              {"(RD,G7.0,';')", " 0.E+01;"},490              {"(RD,G7.1,';')", " 1.    ;"},491              {"(RU,E8.1,';')", " 0.2E+01;"},492              {"(RU,G7.0,';')", " 0.E+01;"},493              {"(RU,G7.1,';')", " 2.    ;"},494              {"(RZ,E8.1,';')", " 0.1E+01;"},495              {"(RZ,F3.0,';')", " 1.;"},496              {"(RZ,G7.0,';')", " 0.E+01;"},497              {"(RZ,G7.1,';')", " 1.    ;"},498              {"(RC,E8.1,';')", " 0.2E+01;"},499              {"(RC,F3.0,';')", " 2.;"},500              {"(RC,G7.0,';')", " 0.E+01;"},501              {"(RC,G7.1,';')", " 2.    ;"},502          }},503      {// -1.5504          0xbff8000000000000,505          {506              {"(E9.2,';')", "-0.15E+01;"},507              {"(RN,E8.1,';')", "-0.2E+01;"},508              {"(RD,E8.1,';')", "-0.2E+01;"},509              {"(RU,E8.1,';')", "-0.1E+01;"},510              {"(RZ,E8.1,';')", "-0.1E+01;"},511              {"(RC,E8.1,';')", "-0.2E+01;"},512              {"(EX9.1,';')", "-0XC.0P-3;"},513          }},514      {// 2.5515          0x4004000000000000,516          {517              {"(E9.2,';')", " 0.25E+01;"},518              {"(RN,E8.1,';')", " 0.2E+01;"},519              {"(RD,E8.1,';')", " 0.2E+01;"},520              {"(RU,E8.1,';')", " 0.3E+01;"},521              {"(RZ,E8.1,';')", " 0.2E+01;"},522              {"(RC,E8.1,';')", " 0.3E+01;"},523              {"(EX9.1,';')", " 0XA.0P-2;"},524          }},525      {// -2.5526          0xc004000000000000,527          {528              {"(E9.2,';')", "-0.25E+01;"},529              {"(RN,E8.1,';')", "-0.2E+01;"},530              {"(RD,E8.1,';')", "-0.3E+01;"},531              {"(RU,E8.1,';')", "-0.2E+01;"},532              {"(RZ,E8.1,';')", "-0.2E+01;"},533              {"(RC,E8.1,';')", "-0.3E+01;"},534              {"(EX9.1,';')", "-0XA.0P-2;"},535          }},536      {// least positive nonzero subnormal537          1,538          {539              {"(E32.17,';')", "         0.49406564584124654-323;"},540              {"(ES32.17,';')", "         4.94065645841246544-324;"},541              {"(EN32.17,';')", "         4.94065645841246544-324;"},542              {"(E759.752,';')",543                  " 0."544                  "494065645841246544176568792868221372365059802614324764425585"545                  "682500675507270208751865299836361635992379796564695445717730"546                  "926656710355939796398774796010781878126300713190311404527845"547                  "817167848982103688718636056998730723050006387409153564984387"548                  "312473397273169615140031715385398074126238565591171026658556"549                  "686768187039560310624931945271591492455329305456544401127480"550                  "129709999541931989409080416563324524757147869014726780159355"551                  "238611550134803526493472019379026810710749170333222684475333"552                  "572083243193609238289345836806010601150616980975307834227731"553                  "832924790498252473077637592724787465608477820373446969953364"554                  "701797267771758512566055119913150489110145103786273816725095"555                  "583738973359899366480994116420570263709027924276754456522908"556                  "75386825064197182655334472656250-323;"},557              {"(G0,';')", ".5E-323;"},558              {"(E757.750,';')",559                  " 0."560                  "494065645841246544176568792868221372365059802614324764425585"561                  "682500675507270208751865299836361635992379796564695445717730"562                  "926656710355939796398774796010781878126300713190311404527845"563                  "817167848982103688718636056998730723050006387409153564984387"564                  "312473397273169615140031715385398074126238565591171026658556"565                  "686768187039560310624931945271591492455329305456544401127480"566                  "129709999541931989409080416563324524757147869014726780159355"567                  "238611550134803526493472019379026810710749170333222684475333"568                  "572083243193609238289345836806010601150616980975307834227731"569                  "832924790498252473077637592724787465608477820373446969953364"570                  "701797267771758512566055119913150489110145103786273816725095"571                  "583738973359899366480994116420570263709027924276754456522908"572                  "753868250641971826553344726562-323;"},573              {"(RN,E757.750,';')",574                  " 0."575                  "494065645841246544176568792868221372365059802614324764425585"576                  "682500675507270208751865299836361635992379796564695445717730"577                  "926656710355939796398774796010781878126300713190311404527845"578                  "817167848982103688718636056998730723050006387409153564984387"579                  "312473397273169615140031715385398074126238565591171026658556"580                  "686768187039560310624931945271591492455329305456544401127480"581                  "129709999541931989409080416563324524757147869014726780159355"582                  "238611550134803526493472019379026810710749170333222684475333"583                  "572083243193609238289345836806010601150616980975307834227731"584                  "832924790498252473077637592724787465608477820373446969953364"585                  "701797267771758512566055119913150489110145103786273816725095"586                  "583738973359899366480994116420570263709027924276754456522908"587                  "753868250641971826553344726562-323;"},588              {"(RD,E757.750,';')",589                  " 0."590                  "494065645841246544176568792868221372365059802614324764425585"591                  "682500675507270208751865299836361635992379796564695445717730"592                  "926656710355939796398774796010781878126300713190311404527845"593                  "817167848982103688718636056998730723050006387409153564984387"594                  "312473397273169615140031715385398074126238565591171026658556"595                  "686768187039560310624931945271591492455329305456544401127480"596                  "129709999541931989409080416563324524757147869014726780159355"597                  "238611550134803526493472019379026810710749170333222684475333"598                  "572083243193609238289345836806010601150616980975307834227731"599                  "832924790498252473077637592724787465608477820373446969953364"600                  "701797267771758512566055119913150489110145103786273816725095"601                  "583738973359899366480994116420570263709027924276754456522908"602                  "753868250641971826553344726562-323;"},603              {"(RU,E757.750,';')",604                  " 0."605                  "494065645841246544176568792868221372365059802614324764425585"606                  "682500675507270208751865299836361635992379796564695445717730"607                  "926656710355939796398774796010781878126300713190311404527845"608                  "817167848982103688718636056998730723050006387409153564984387"609                  "312473397273169615140031715385398074126238565591171026658556"610                  "686768187039560310624931945271591492455329305456544401127480"611                  "129709999541931989409080416563324524757147869014726780159355"612                  "238611550134803526493472019379026810710749170333222684475333"613                  "572083243193609238289345836806010601150616980975307834227731"614                  "832924790498252473077637592724787465608477820373446969953364"615                  "701797267771758512566055119913150489110145103786273816725095"616                  "583738973359899366480994116420570263709027924276754456522908"617                  "753868250641971826553344726563-323;"},618              {"(RC,E757.750,';')",619                  " 0."620                  "494065645841246544176568792868221372365059802614324764425585"621                  "682500675507270208751865299836361635992379796564695445717730"622                  "926656710355939796398774796010781878126300713190311404527845"623                  "817167848982103688718636056998730723050006387409153564984387"624                  "312473397273169615140031715385398074126238565591171026658556"625                  "686768187039560310624931945271591492455329305456544401127480"626                  "129709999541931989409080416563324524757147869014726780159355"627                  "238611550134803526493472019379026810710749170333222684475333"628                  "572083243193609238289345836806010601150616980975307834227731"629                  "832924790498252473077637592724787465608477820373446969953364"630                  "701797267771758512566055119913150489110145103786273816725095"631                  "583738973359899366480994116420570263709027924276754456522908"632                  "753868250641971826553344726563-323;"},633              {"(EX24.13,';')", " 0X8.0000000000000P-1077;"},634          }},635      {// least positive nonzero normal636          0x10000000000000,637          {638              {"(E723.716,';')",639                  " 0."640                  "222507385850720138309023271733240406421921598046233183055332"641                  "741688720443481391819585428315901251102056406733973103581100"642                  "515243416155346010885601238537771882113077799353200233047961"643                  "014744258363607192156504694250373420837525080665061665815894"644                  "872049117996859163964850063590877011830487479978088775374994"645                  "945158045160505091539985658247081864511353793580499211598108"646                  "576605199243335211435239014879569960959128889160299264151106"647                  "346631339366347758651302937176204732563178148566435087212282"648                  "863764204484681140761391147706280168985324411002416144742161"649                  "856716615054015428508471675290190316132277889672970737312333"650                  "408698898317506783884692609277397797285865965494109136909540"651                  "61364675687023986783152906809846172109246253967285156250-"652                  "307;"},653              {"(G0,';')", ".22250738585072014E-307;"},654              {"(EX24.13,';')", " 0X8.0000000000000P-1025;"},655          }},656      {// greatest finite657          0x7fefffffffffffffuLL,658          {659              {"(E32.17,';')", "         0.17976931348623157+309;"},660              {"(E317.310,';')",661                  " 0."662                  "179769313486231570814527423731704356798070567525844996598917"663                  "476803157260780028538760589558632766878171540458953514382464"664                  "234321326889464182768467546703537516986049910576551282076245"665                  "490090389328944075868508455133942304583236903222948165808559"666                  "332123348274797826204144723168738177180919299881250404026184"667                  "1248583680+309;"},668              {"(ES317.310,';')",669                  " 1."670                  "797693134862315708145274237317043567980705675258449965989174"671                  "768031572607800285387605895586327668781715404589535143824642"672                  "343213268894641827684675467035375169860499105765512820762454"673                  "900903893289440758685084551339423045832369032229481658085593"674                  "321233482747978262041447231687381771809192998812504040261841"675                  "2485836800+308;"},676              {"(EN319.310,';')",677                  " 179."678                  "769313486231570814527423731704356798070567525844996598917476"679                  "803157260780028538760589558632766878171540458953514382464234"680                  "321326889464182768467546703537516986049910576551282076245490"681                  "090389328944075868508455133942304583236903222948165808559332"682                  "123348274797826204144723168738177180919299881250404026184124"683                  "8583680000+306;"},684              {"(G0,';')", ".17976931348623157E+309;"},685              {"(EX24.13,';')", " 0XF.FFFFFFFFFFFF8P+1020;"},686          }},687      {// EX rounding688          0x3ff0100000000000uLL,689          {690              {"(F11.8,';')", " 1.00390625;"},691              {"(EX10.2,';')", " 0X8.08P-3;"},692              {"(EX10.1,';')", "  0X8.0P-3;"},693              {"(EX10.0,';')", " 0X8.08P-3;"},694              {"(EX0.0,';')", "0X8.08P-3;"},695              {"(EX0,';')", "0X8.08P-3;"},696              {"(RN,EX10.1,';')", "  0X8.0P-3;"},697              {"(RU,EX10.1,';')", "  0X8.1P-3;"},698              {"(RD,EX10.1,';')", "  0X8.0P-3;"},699              {"(RZ,EX10.1,';')", "  0X8.0P-3;"},700              {"(RC,EX10.1,';')", "  0X8.1P-3;"},701              {"(RN,EX10.0,';')", " 0X8.08P-3;"},702              {"(RU,EX10.0,';')", " 0X8.08P-3;"},703              {"(RD,EX10.0,';')", " 0X8.08P-3;"},704              {"(RZ,EX10.0,';')", " 0X8.08P-3;"},705              {"(RC,EX10.0,';')", " 0X8.08P-3;"},706          }},707      {// EX rounding708          0xbff0100000000000uLL,709          {710              {"(F11.8,';')", "-1.00390625;"},711              {"(EX10.2,';')", "-0X8.08P-3;"},712              {"(EX10.1,';')", " -0X8.0P-3;"},713              {"(EX10.0,';')", "-0X8.08P-3;"},714              {"(EX0.0,';')", "-0X8.08P-3;"},715              {"(EX0,';')", "-0X8.08P-3;"},716              {"(RN,EX10.1,';')", " -0X8.0P-3;"},717              {"(RU,EX10.1,';')", " -0X8.0P-3;"},718              {"(RD,EX10.1,';')", " -0X8.1P-3;"},719              {"(RZ,EX10.1,';')", " -0X8.0P-3;"},720              {"(RC,EX10.1,';')", " -0X8.1P-3;"},721              {"(RN,EX10.0,';')", "-0X8.08P-3;"},722              {"(RU,EX10.0,';')", "-0X8.08P-3;"},723              {"(RD,EX10.0,';')", "-0X8.08P-3;"},724              {"(RZ,EX10.0,';')", "-0X8.08P-3;"},725              {"(RC,EX10.0,';')", "-0X8.08P-3;"},726          }},727  };728 729  for (auto const &[value, cases] : testCases) {730    for (auto const &[format, expect] : cases) {731      std::string got;732      ASSERT_TRUE(CompareFormatReal(format, value, expect, got))733          << "Failed to format " << format << ", expected '" << expect734          << "', got '" << got << "'";735    }736  }737 738  using IndividualTestCaseTy = std::tuple<const char *, double, const char *>;739  static const std::vector<IndividualTestCaseTy> individualTestCases{740      {"(F5.3,';')", 25., "*****;"},741      {"(F5.3,';')", 2.5, "2.500;"},742      {"(F5.3,';')", 0.25, "0.250;"},743      {"(F5.3,';')", 0.025, "0.025;"},744      {"(F5.3,';')", 0.0025, "0.003;"},745      {"(F5.3,';')", 0.00025, "0.000;"},746      {"(F5.3,';')", 0.000025, "0.000;"},747      {"(F5.3,';')", -25., "*****;"},748      {"(F5.3,';')", -2.5, "*****;"},749      {"(F5.3,';')", -0.25, "-.250;"},750      {"(F5.3,';')", -0.025, "-.025;"},751      {"(F5.3,';')", -0.0025, "-.003;"},752      {"(F5.3,';')", -0.00025, "-.000;"},753      {"(F5.3,';')", -0.000025, "-.000;"},754      {"(F5.3,';')", 99.999, "*****;"},755      {"(F5.3,';')", 9.9999, "*****;"},756      {"(F5.3,';')", 0.99999, "1.000;"},757      {"(F5.3,';')", 0.099999, "0.100;"},758      {"(F5.3,';')", 0.0099999, "0.010;"},759      {"(F5.3,';')", 0.00099999, "0.001;"},760      {"(F5.3,';')",761          0.0005000000000000000104083408558608425664715468883514404296875,762          "0.001;"},763      {"(F5.3,';')",764          0.000499999999999999901988123607310399165726266801357269287109375,765          "0.000;"},766      {"(F5.3,';')", 0.000099999, "0.000;"},767      {"(F5.3,';')", -99.999, "*****;"},768      {"(F5.3,';')", -9.9999, "*****;"},769      {"(F5.3,';')", -0.99999, "*****;"},770      {"(F5.3,';')", -0.099999, "-.100;"},771      {"(F5.3,';')", -0.0099999, "-.010;"},772      {"(F5.3,';')", -0.00099999, "-.001;"},773      {"(F5.3,';')",774          -0.0005000000000000000104083408558608425664715468883514404296875,775          "-.001;"},776      {"(F5.3,';')",777          -0.000499999999999999901988123607310399165726266801357269287109375,778          "-.000;"},779      {"(F5.3,';')", -0.000099999, "-.000;"},780      {"(F0.1,';')", 0.0, ".0;"},781      {"(F5.0,';')", -0.5000000000000001, "  -1.;"},782      {"(F5.0,';')", -0.5, "  -0.;"},783      {"(F5.0,';')", -0.49999999999999994, "  -0.;"},784      {"(F5.0,';')", 0.49999999999999994, "   0.;"},785      {"(F5.0,';')", 0.5, "   0.;"},786      {"(F5.0,';')", 0.5000000000000001, "   1.;"},787      {"(ES0.0E0,';')", 0.666, "7.E-1;"},788      {"(EN0.0E0,';')", 0.666, "666.E-3;"},789  };790 791  for (auto const &[format, value, expect] : individualTestCases) {792    std::string got;793    char hex[17];794    std::snprintf(hex, sizeof hex, "%016llx",795        *reinterpret_cast<const unsigned long long *>(&value));796    ASSERT_TRUE(CompareFormatReal(format, value, expect, got))797        << "Failed to format " << value << " 0x" << hex << " with format "798        << format << ", expected '" << expect << "', got '" << got << "'";799  }800 801  // Problematic EN formatting edge cases with rounding802  using IndividualENTestCaseTy = std::tuple<std::uint64_t, const char *>;803  static const std::vector<IndividualENTestCaseTy> individualENTestCases{804      {0x3E11183197785F8C, " 995.0E-12"}, // 0.9950312500000000115852E-09805      {0x3E11180E68455D30, " 995.0E-12"}, // 0.9949999999999999761502E-09806      {0x3E112BD8F4F6B0D7, " 999.5E-12"}, // 0.9994999999999999089118E-09807      {0x3E45794883CA8782, "  10.0E-09"}, // 0.9999499999999999642266E-08808      {0x3F506218230C7482, " 999.9E-06"}, // 0.9999499999999998840761E-03809      {0x3FB99652BD3C3612, " 100.0E-03"}, // 0.9999500000000000055067E+00810      {0x4023E66666666667, "  10.0E+00"}, // 0.9950000000000001065814E+01811  };812 813  for (auto const &[value, expect] : individualENTestCases) {814    std::string got;815    ASSERT_TRUE(CompareFormatReal("(EN10.1)", value, expect, got))816        << "Failed to format EN10.1, expected '" << expect << "', got '" << got817        << "'";818  }819}820 821TEST(IOApiTests, FormatIntegerValues) {822  using IntTestCaseTy = std::tuple<const char *, std::int64_t, const char *>;823  static const std::vector<IntTestCaseTy> intTestCases{824      {"(I4)", 0, "   0"},825      {"(I4)", 1, "   1"},826      {"(I4)", 9999, "9999"},827      {"(SP,I4)", 1, "  +1"},828      {"(SP,I4)", 9999, "****"},829      {"(SP,I4)", 999, "+999"},830      {"(I4)", -1, "  -1"},831      {"(I4)", -9999, "****"},832      {"(I4)", -999, "-999"},833      {"(I4.2)", 1, "  01"},834      {"(I4.2)", -1, " -01"},835      {"(I4.2)", 999, " 999"},836      {"(I4.4)", 999, "0999"},837      {"(I0)", 0, "0"},838      {"(I0)", 1, "1"},839      {"(I0)", 9999, "9999"},840      {"(SP,I0)", 1, "+1"},841      {"(SP,I0)", 9999, "+9999"},842      {"(SP,I0)", 999, "+999"},843      {"(I0)", -1, "-1"},844      {"(I0)", -9999, "-9999"},845      {"(I0)", -999, "-999"},846      {"(I0.2)", 1, "01"},847      {"(I0.2)", -1, "-01"},848      {"(I0.2)", 999, "999"},849      {"(I0.4)", 999, "0999"},850      {"(G4)", 0, "   0"},851      {"(G4)", 1, "   1"},852      {"(G4)", 9999, "9999"},853      {"(SP,G4)", 1, "  +1"},854      {"(SP,G4)", 9999, "****"},855      {"(SP,G4)", 999, "+999"},856      {"(G4)", -1, "  -1"},857      {"(G4)", -9999, "****"},858      {"(G4)", -999, "-999"},859      {"(G4.2)", 1, "   1"},860      {"(G4.2)", -1, "  -1"},861      {"(G4.2)", 999, " 999"},862      {"(G4.4)", 999, " 999"},863      {"(G0)", 0, "0"},864      {"(G0)", 1, "1"},865      {"(G0)", 9999, "9999"},866      {"(SP,G0)", 1, "+1"},867      {"(SP,G0)", 9999, "+9999"},868      {"(SP,G0)", 999, "+999"},869      {"(G0)", -1, "-1"},870      {"(G0)", -9999, "-9999"},871      {"(G0)", -999, "-999"},872      {"(G0.2)", 1, "1"},873      {"(G0.2)", -1, "-1"},874      {"(G0.2)", 999, "999"},875      {"(G0.4)", 999, "999"},876      {"(I)", 999, "999"},877      {"(G)", 999, "999"},878      {"('x',I)", 999, "x 999"},879      {"('x',G)", 999, "x 999"},880  };881 882  for (auto const &[fmt, value, expect] : intTestCases) {883    std::string got;884    ASSERT_TRUE(CompareFormatInteger(fmt, value, expect, got))885        << "Failed to format " << fmt << ", expected '" << expect << "', got '"886        << got << "'";887  }888}889 890//------------------------------------------------------------------------------891/// Tests for input editing real values892//------------------------------------------------------------------------------893 894// Ensure double input values correctly map to raw uint64 values895TEST(IOApiTests, EditDoubleInputValues) {896  using TestCaseTy = std::tuple<const char *, const char *, std::uint64_t, int>;897  int ovf{IostatRealInputOverflow};898  static const std::vector<TestCaseTy> testCases{899      {"(F18.0)", "                 0", 0x0, 0},900      {"(F18.0)", "                  ", 0x0, 0},901      {"(F18.0)", "                -0", 0x8000000000000000, 0},902      {"(F18.0)", "                01", 0x3ff0000000000000, 0},903      {"(F18.0)", "                 1", 0x3ff0000000000000, 0},904      {"(F18.0)", "              125.", 0x405f400000000000, 0},905      {"(F18.0)", "              12.5", 0x4029000000000000, 0},906      {"(F18.0)", "              1.25", 0x3ff4000000000000, 0},907      {"(F18.0)", "             01.25", 0x3ff4000000000000, 0},908      {"(F18.0)", "              .125", 0x3fc0000000000000, 0},909      {"(F18.0)", "             0.125", 0x3fc0000000000000, 0},910      {"(F18.0)", "             .0625", 0x3fb0000000000000, 0},911      {"(F18.0)", "            0.0625", 0x3fb0000000000000, 0},912      {"(F18.0)", "               125", 0x405f400000000000, 0},913      {"(F18.1)", "               125", 0x4029000000000000, 0},914      {"(F18.2)", "               125", 0x3ff4000000000000, 0},915      {"(F18.3)", "               125", 0x3fc0000000000000, 0},916      {"('str',F3.0)", "xxx125", 0x405f400000000000, 0},917      {"(-1P,F18.0)", "               125", 0x4093880000000000, 0}, // 1250918      {"(1P,F18.0)", "               125", 0x4029000000000000, 0}, // 12.5919      {"(BZ,F18.0)", "              125 ", 0x4093880000000000, 0}, // 1250920      {"(BZ,F18.0)", "       125 . e +1 ", 0x42a6bcc41e900000, 0}, // 1.25e13921      {"(BZ,F18.0)", "           .      ", 0x0, 0},922      {"(BZ,F18.0)", "           . e +1 ", 0x0, 0},923      {"(DC,F18.0)", "              12,5", 0x4029000000000000, 0},924      {"(DC,F18.0)", "             12,5;", 0x4029000000000000, 0},925      {"(EX22.0)", "0X0P0                 ", 0x0, 0}, // +0.926      {"(EX22.0)", "-0X0P0                ", 0x8000000000000000, 0}, // -0.927      {"(EX22.0)", "0X.8P1                ", 0x3ff0000000000000, 0}, // 1.0928      {"(EX22.0)", "0X8.P-3               ", 0x3ff0000000000000, 0}, // 1.0929      {"(EX22.0)", "0X.1P4                ", 0x3ff0000000000000, 0}, // 1.0930      {"(EX22.0)", "0X10.P-4              ", 0x3ff0000000000000, 0}, // 1.0931      {"(EX22.0)", "0X8.00P-3             ", 0x3ff0000000000000, 0}, // 1.0932      {"(EX22.0)", "0X80.0P-6             ", 0x4000000000000000, 0}, // 2.0933      {"(EX22.0)", "0XC.CCCCCCCCCCCDP-7   ", 0x3fb999999999999a, 0}, // 0.1934      {"(EX22.0)", "0X.8P-1021            ", 0x0010000000000000,935          0}, // min normal936      {"(EX22.0)", "0X.8P-1022            ", 0x0008000000000000,937          0}, // subnormal938      {"(EX22.0)", "0X.8P-1073            ", 0x0000000000000001,939          0}, // min subn.940      {"(EX22.0)", "0X.FFFFFFFFFFFFF8P1024", 0x7fefffffffffffff,941          0}, // max finite942      {"(EX22.0)", "0X.8P1025             ", 0x7ff0000000000000, ovf}, // +Inf943      {"(EX22.0)", "-0X.8P1025            ", 0xfff0000000000000, ovf}, // -Inf944      {"(RC,EX22.0)", "0X1.0000000000000P0   ", 0x3ff0000000000000, 0},945      {"(RC,EX22.0)", "0X1.00000000000008P0  ", 0x3ff0000000000001, 0},946      {"(RC,EX22.0)", "0X1.000000000000008P0 ", 0x3ff0000000000000, 0},947      {"(RC,EX22.0)", "0X1.00000000000004P0  ", 0x3ff0000000000000, 0},948      {"(RC,EX22.0)", "0X.80000000000000P1   ", 0x3ff0000000000000, 0},949      {"(RC,EX22.0)", "0X.80000000000004P1   ", 0x3ff0000000000001, 0},950      {"(RC,EX22.0)", "0X.800000000000004P1  ", 0x3ff0000000000000, 0},951      {"(RC,EX22.0)", "0X.80000000000002P1   ", 0x3ff0000000000000, 0},952      {"(RZ,F7.0)", " 2.e308", 0x7fefffffffffffff, 0}, // +HUGE()953      {"(RD,F7.0)", " 2.e308", 0x7fefffffffffffff, 0}, // +HUGE()954      {"(RU,F7.0)", " 2.e308", 0x7ff0000000000000, ovf}, // +Inf955      {"(RZ,F7.0)", "-2.e308", 0xffefffffffffffff, 0}, // -HUGE()956      {"(RD,F7.0)", "-2.e308", 0xfff0000000000000, ovf}, // -Inf957      {"(RU,F7.0)", "-2.e308", 0xffefffffffffffff, 0}, // -HUGE()958      {"(RZ,F7.0)", " 1.e999", 0x7fefffffffffffff, 0}, // +HUGE()959      {"(RD,F7.0)", " 1.e999", 0x7fefffffffffffff, 0}, // +HUGE()960      {"(RU,F7.0)", " 1.e999", 0x7ff0000000000000, ovf}, // +Inf961      {"(RZ,F7.0)", "-1.e999", 0xffefffffffffffff, 0}, // -HUGE()962      {"(RD,F7.0)", "-1.e999", 0xfff0000000000000, ovf}, // -Inf963      {"(RU,F7.0)", "-1.e999", 0xffefffffffffffff, 0}, // -HUGE()964      {"(E9.1)", " 1.0E-325", 0x0, 0},965      {"(RU,E9.1)", " 1.0E-325", 0x1, 0},966      {"(E9.1)", "-1.0E-325", 0x8000000000000000, 0},967      {"(RD,E9.1)", "-1.0E-325", 0x8000000000000001, 0},968      {"(F7.0)", "+NaN(q)", 0x7ff8000000000000, 0},969      {"(G)", "D", 0, IostatBadRealInput},970      {"(G0)", "D", 0, IostatErrorInFormat},971      {"(G1.0)", "D", 0, 0},972  };973  for (auto const &[format, data, want, iostat] : testCases) {974    auto cookie{IONAME(BeginInternalFormattedInput)(975        data, std::strlen(data), format, std::strlen(format))};976    union {977      double x;978      std::uint64_t raw;979    } u;980    u.raw = 0;981 982    // Read buffer into union value983    IONAME(EnableHandlers)(cookie, true, true, true, true, true);984    IONAME(InputReal64)(cookie, u.x);985 986    static constexpr int bufferSize{65};987    char iomsg[bufferSize];988    std::memset(iomsg, '\0', bufferSize - 1);989 990    // Ensure no unexpected errors were encountered reading input buffer into991    // union value992    IONAME(GetIoMsg)(cookie, iomsg, bufferSize - 1);993    auto status{IONAME(EndIoStatement)(cookie)};994    EXPECT_EQ(status, iostat)995        << '\'' << format << "' failed reading '" << data << "', status "996        << static_cast<int>(status) << " != expected " << iostat << " iomsg '"997        << iomsg << "'";998 999    // Ensure raw uint64 value matches expected conversion from double1000    EXPECT_EQ(u.raw, want) << '\'' << format << "' failed reading '" << data1001                           << "', want " << want << ", got " << u.raw;1002  }1003}1004 1005// regression test for confusing digit minimization1006TEST(IOApiTests, ConfusingMinimization) {1007  char buffer[8]{};1008  auto cookie{IONAME(BeginInternalListOutput)(buffer, sizeof buffer)};1009  StaticDescriptor<0> staticDescriptor;1010  Descriptor &desc{staticDescriptor.descriptor()};1011  std::uint16_t x{0x7bff}; // HUGE(0._2)1012  desc.Establish(TypeCode{CFI_type_half_float}, sizeof x, &x, 0, nullptr);1013  desc.Check();1014  EXPECT_TRUE(IONAME(OutputDescriptor)(cookie, desc));1015  auto status{IONAME(EndIoStatement)(cookie)};1016  EXPECT_EQ(status, 0);1017  std::string got{std::string{buffer, sizeof buffer}};1018  EXPECT_TRUE(CompareFormattedStrings(" 65504. ", got))1019      << "expected ' 65504. ', got '" << got << '\''; // not 65500.!1020}1021