forked from OSchip/llvm-project
[flang] Update output format test to use GTest
Better document each test in output formatting tests. Use GTest primitives and infrastructure in same spirit as [[ https://reviews.llvm.org/D97403 | D97403 ]]. [[ https://github.com/flang-compiler/f18/issues/995#issuecomment-790737912 | See legacy github issue linked here ]] for additional context. Reorganize long test cases to be more readable. Reviewed By: awarzynski, klausler Differential Revision: https://reviews.llvm.org/D98303
This commit is contained in:
parent
7d8b478ce1
commit
e8515ca847
|
@ -23,11 +23,6 @@ add_flang_nongtest_unittest(format
|
|||
FortranRuntime
|
||||
)
|
||||
|
||||
add_flang_nongtest_unittest(hello
|
||||
RuntimeTesting
|
||||
FortranRuntime
|
||||
)
|
||||
|
||||
# This test is not run by default as it requires input.
|
||||
add_executable(external-hello-world
|
||||
external-hello.cpp
|
||||
|
|
|
@ -1,526 +0,0 @@
|
|||
// Basic sanity tests of I/O API; exhaustive testing will be done in Fortran
|
||||
|
||||
#include "testing.h"
|
||||
#include "../../runtime/descriptor.h"
|
||||
#include "../../runtime/io-api.h"
|
||||
#include <cstring>
|
||||
|
||||
using namespace Fortran::runtime;
|
||||
using namespace Fortran::runtime::io;
|
||||
|
||||
static bool test(const char *format, const char *expect, std::string &&got) {
|
||||
std::string want{expect};
|
||||
want.resize(got.length(), ' ');
|
||||
if (got != want) {
|
||||
Fail() << '\'' << format << "' failed;\n got '" << got
|
||||
<< "',\nexpected '" << want << "'\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void hello() {
|
||||
char buffer[32];
|
||||
const char *format{"(6HHELLO,,A6,2X,I3,1X,'0x',Z8,1X,L1)"};
|
||||
auto cookie{IONAME(BeginInternalFormattedOutput)(
|
||||
buffer, sizeof buffer, format, std::strlen(format))};
|
||||
IONAME(OutputAscii)(cookie, "WORLD", 5);
|
||||
IONAME(OutputInteger64)(cookie, 678);
|
||||
IONAME(OutputInteger64)(cookie, 0xfeedface);
|
||||
IONAME(OutputLogical)(cookie, true);
|
||||
if (auto status{IONAME(EndIoStatement)(cookie)}) {
|
||||
Fail() << "hello: '" << format << "' failed, status "
|
||||
<< static_cast<int>(status) << '\n';
|
||||
} else {
|
||||
test(format, "HELLO, WORLD 678 0xFEEDFACE T",
|
||||
std::string{buffer, sizeof buffer});
|
||||
}
|
||||
}
|
||||
|
||||
static void multiline() {
|
||||
char buffer[5][32];
|
||||
StaticDescriptor<1> staticDescriptor[2];
|
||||
Descriptor &whole{staticDescriptor[0].descriptor()};
|
||||
SubscriptValue extent[]{5};
|
||||
whole.Establish(TypeCode{CFI_type_char}, sizeof buffer[0], &buffer, 1, extent,
|
||||
CFI_attribute_pointer);
|
||||
whole.Dump();
|
||||
whole.Check();
|
||||
Descriptor §ion{staticDescriptor[1].descriptor()};
|
||||
SubscriptValue lowers[]{0}, uppers[]{4}, strides[]{1};
|
||||
section.Establish(whole.type(), whole.ElementBytes(), nullptr, 1, extent,
|
||||
CFI_attribute_pointer);
|
||||
if (auto error{
|
||||
CFI_section(§ion.raw(), &whole.raw(), lowers, uppers, strides)}) {
|
||||
Fail() << "multiline: CFI_section failed: " << error << '\n';
|
||||
return;
|
||||
}
|
||||
section.Dump();
|
||||
section.Check();
|
||||
const char *format{
|
||||
"('?abcde,',T1,'>',T9,A,TL12,A,TR25,'<'//G0,17X,'abcd',1(2I4))"};
|
||||
auto cookie{IONAME(BeginInternalArrayFormattedOutput)(
|
||||
section, format, std::strlen(format))};
|
||||
IONAME(OutputAscii)(cookie, "WORLD", 5);
|
||||
IONAME(OutputAscii)(cookie, "HELLO", 5);
|
||||
IONAME(OutputInteger64)(cookie, 789);
|
||||
for (int j{666}; j <= 999; j += 111) {
|
||||
IONAME(OutputInteger64)(cookie, j);
|
||||
}
|
||||
if (auto status{IONAME(EndIoStatement)(cookie)}) {
|
||||
Fail() << "multiline: '" << format << "' failed, status "
|
||||
<< static_cast<int>(status) << '\n';
|
||||
} else {
|
||||
test(format,
|
||||
">HELLO, WORLD <"
|
||||
" "
|
||||
"789 abcd 666 777"
|
||||
" 888 999 "
|
||||
" ",
|
||||
std::string{buffer[0], sizeof buffer});
|
||||
}
|
||||
}
|
||||
|
||||
static void listInputTest() {
|
||||
static const char input[]{",1*,(5.,6..)"};
|
||||
auto cookie{IONAME(BeginInternalListInput)(input, sizeof input - 1)};
|
||||
float z[6];
|
||||
for (int j{0}; j < 6; ++j) {
|
||||
z[j] = -(j + 1);
|
||||
}
|
||||
for (int j{0}; j < 6; j += 2) {
|
||||
if (!IONAME(InputComplex32)(cookie, &z[j])) {
|
||||
Fail() << "InputComplex32 failed\n";
|
||||
}
|
||||
}
|
||||
auto status{IONAME(EndIoStatement)(cookie)};
|
||||
if (status) {
|
||||
Fail() << "Failed complex list-directed input, status "
|
||||
<< static_cast<int>(status) << '\n';
|
||||
} else {
|
||||
char output[33];
|
||||
output[32] = '\0';
|
||||
cookie = IONAME(BeginInternalListOutput)(output, 32);
|
||||
for (int j{0}; j < 6; j += 2) {
|
||||
if (!IONAME(OutputComplex32)(cookie, z[j], z[j + 1])) {
|
||||
Fail() << "OutputComplex32 failed\n";
|
||||
}
|
||||
}
|
||||
status = IONAME(EndIoStatement)(cookie);
|
||||
static const char expect[33]{" (-1.,-2.) (-3.,-4.) (5.,6.) "};
|
||||
if (status) {
|
||||
Fail() << "Failed complex list-directed output, status "
|
||||
<< static_cast<int>(status) << '\n';
|
||||
} else if (std::strncmp(output, expect, 33) != 0) {
|
||||
Fail() << "Failed complex list-directed output, expected '" << expect
|
||||
<< "', but got '" << output << "'\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void descrOutputTest() {
|
||||
char buffer[9];
|
||||
// Formatted
|
||||
const char *format{"(2A4)"};
|
||||
auto cookie{IONAME(BeginInternalFormattedOutput)(
|
||||
buffer, sizeof buffer, format, std::strlen(format))};
|
||||
StaticDescriptor<1> staticDescriptor;
|
||||
Descriptor &desc{staticDescriptor.descriptor()};
|
||||
SubscriptValue extent[]{2};
|
||||
char data[2][4];
|
||||
std::memcpy(data[0], "ABCD", 4);
|
||||
std::memcpy(data[1], "EFGH", 4);
|
||||
desc.Establish(TypeCode{CFI_type_char}, sizeof data[0], &data, 1, extent);
|
||||
desc.Dump();
|
||||
desc.Check();
|
||||
IONAME(OutputDescriptor)(cookie, desc);
|
||||
if (auto status{IONAME(EndIoStatement)(cookie)}) {
|
||||
Fail() << "descrOutputTest: '" << format << "' failed, status "
|
||||
<< static_cast<int>(status) << '\n';
|
||||
} else {
|
||||
test("descrOutputTest(formatted)", "ABCDEFGH ",
|
||||
std::string{buffer, sizeof buffer});
|
||||
}
|
||||
// List-directed
|
||||
cookie = IONAME(BeginInternalListOutput)(buffer, sizeof buffer);
|
||||
IONAME(OutputDescriptor)(cookie, desc);
|
||||
if (auto status{IONAME(EndIoStatement)(cookie)}) {
|
||||
Fail() << "descrOutputTest: list-directed failed, status "
|
||||
<< static_cast<int>(status) << '\n';
|
||||
} else {
|
||||
test("descrOutputTest(list)", " ABCDEFGH",
|
||||
std::string{buffer, sizeof buffer});
|
||||
}
|
||||
}
|
||||
|
||||
static void realTest(const char *format, double x, const char *expect) {
|
||||
char buffer[800];
|
||||
auto cookie{IONAME(BeginInternalFormattedOutput)(
|
||||
buffer, sizeof buffer, format, std::strlen(format))};
|
||||
IONAME(OutputReal64)(cookie, x);
|
||||
if (auto status{IONAME(EndIoStatement)(cookie)}) {
|
||||
Fail() << '\'' << format << "' failed, status " << static_cast<int>(status)
|
||||
<< '\n';
|
||||
} else {
|
||||
test(format, expect, std::string{buffer, sizeof buffer});
|
||||
}
|
||||
}
|
||||
|
||||
static void realInTest(
|
||||
const char *format, const char *data, std::uint64_t want) {
|
||||
auto cookie{IONAME(BeginInternalFormattedInput)(
|
||||
data, std::strlen(data), format, std::strlen(format))};
|
||||
union {
|
||||
double x;
|
||||
std::uint64_t raw;
|
||||
} u;
|
||||
u.raw = 0;
|
||||
IONAME(EnableHandlers)(cookie, true, true, true, true, true);
|
||||
IONAME(InputReal64)(cookie, u.x);
|
||||
char iomsg[65];
|
||||
iomsg[0] = '\0';
|
||||
iomsg[sizeof iomsg - 1] = '\0';
|
||||
IONAME(GetIoMsg)(cookie, iomsg, sizeof iomsg - 1);
|
||||
auto status{IONAME(EndIoStatement)(cookie)};
|
||||
if (status) {
|
||||
Fail() << '\'' << format << "' failed reading '" << data << "', status "
|
||||
<< static_cast<int>(status) << " iomsg '" << iomsg << "'\n";
|
||||
} else if (u.raw != want) {
|
||||
Fail() << '\'' << format << "' failed reading '" << data << "', want 0x";
|
||||
Fail().write_hex(want) << ", got 0x" << u.raw << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
StartTests();
|
||||
|
||||
hello();
|
||||
multiline();
|
||||
|
||||
static const char *zeroes[][2]{
|
||||
{"(E32.17,';')", " 0.00000000000000000E+00;"},
|
||||
{"(F32.17,';')", " 0.00000000000000000;"},
|
||||
{"(G32.17,';')", " 0.0000000000000000 ;"},
|
||||
{"(DC,E32.17,';')", " 0,00000000000000000E+00;"},
|
||||
{"(DC,F32.17,';')", " 0,00000000000000000;"},
|
||||
{"(DC,G32.17,';')", " 0,0000000000000000 ;"},
|
||||
{"(D32.17,';')", " 0.00000000000000000D+00;"},
|
||||
{"(E32.17E1,';')", " 0.00000000000000000E+0;"},
|
||||
{"(G32.17E1,';')", " 0.0000000000000000 ;"},
|
||||
{"(E32.17E0,';')", " 0.00000000000000000E+0;"},
|
||||
{"(G32.17E0,';')", " 0.0000000000000000 ;"},
|
||||
{"(1P,E32.17,';')", " 0.00000000000000000E+00;"},
|
||||
{"(1PE32.17,';')", " 0.00000000000000000E+00;"}, // no comma
|
||||
{"(1P,F32.17,';')", " 0.00000000000000000;"},
|
||||
{"(1P,G32.17,';')", " 0.0000000000000000 ;"},
|
||||
{"(2P,E32.17,';')", " 00.0000000000000000E+00;"},
|
||||
{"(-1P,E32.17,';')", " 0.00000000000000000E+00;"},
|
||||
{"(G0,';')", "0.;"}, {}};
|
||||
for (int j{0}; zeroes[j][0]; ++j) {
|
||||
realTest(zeroes[j][0], 0.0, zeroes[j][1]);
|
||||
}
|
||||
|
||||
static const char *ones[][2]{
|
||||
{"(E32.17,';')", " 0.10000000000000000E+01;"},
|
||||
{"(F32.17,';')", " 1.00000000000000000;"},
|
||||
{"(G32.17,';')", " 1.0000000000000000 ;"},
|
||||
{"(E32.17E1,';')", " 0.10000000000000000E+1;"},
|
||||
{"(G32.17E1,';')", " 1.0000000000000000 ;"},
|
||||
{"(E32.17E0,';')", " 0.10000000000000000E+1;"},
|
||||
{"(G32.17E0,';')", " 1.0000000000000000 ;"},
|
||||
{"(E32.17E4,';')", " 0.10000000000000000E+0001;"},
|
||||
{"(G32.17E4,';')", " 1.0000000000000000 ;"},
|
||||
{"(1P,E32.17,';')", " 1.00000000000000000E+00;"},
|
||||
{"(1PE32.17,';')", " 1.00000000000000000E+00;"}, // no comma
|
||||
{"(1P,F32.17,';')", " 10.00000000000000000;"},
|
||||
{"(1P,G32.17,';')", " 1.0000000000000000 ;"},
|
||||
{"(ES32.17,';')", " 1.00000000000000000E+00;"},
|
||||
{"(2P,E32.17,';')", " 10.0000000000000000E-01;"},
|
||||
{"(2P,G32.17,';')", " 1.0000000000000000 ;"},
|
||||
{"(-1P,E32.17,';')", " 0.01000000000000000E+02;"},
|
||||
{"(-1P,G32.17,';')", " 1.0000000000000000 ;"},
|
||||
{"(G0,';')", "1.;"}, {}};
|
||||
for (int j{0}; ones[j][0]; ++j) {
|
||||
realTest(ones[j][0], 1.0, ones[j][1]);
|
||||
}
|
||||
|
||||
realTest("(E32.17,';')", -1.0, " -0.10000000000000000E+01;");
|
||||
realTest("(F32.17,';')", -1.0, " -1.00000000000000000;");
|
||||
realTest("(G32.17,';')", -1.0, " -1.0000000000000000 ;");
|
||||
realTest("(G0,';')", -1.0, "-1.;");
|
||||
|
||||
volatile union {
|
||||
double d;
|
||||
std::uint64_t n;
|
||||
} u;
|
||||
u.n = 0x8000000000000000; // -0
|
||||
realTest("(E9.1,';')", u.d, " -0.0E+00;");
|
||||
realTest("(F4.0,';')", u.d, " -0.;");
|
||||
realTest("(G8.0,';')", u.d, "-0.0E+00;");
|
||||
realTest("(G8.1,';')", u.d, " -0. ;");
|
||||
realTest("(G0,';')", u.d, "-0.;");
|
||||
u.n = 0x7ff0000000000000; // +Inf
|
||||
realTest("(E9.1,';')", u.d, " Inf;");
|
||||
realTest("(F9.1,';')", u.d, " Inf;");
|
||||
realTest("(G9.1,';')", u.d, " Inf;");
|
||||
realTest("(SP,E9.1,';')", u.d, " +Inf;");
|
||||
realTest("(SP,F9.1,';')", u.d, " +Inf;");
|
||||
realTest("(SP,G9.1,';')", u.d, " +Inf;");
|
||||
realTest("(G0,';')", u.d, "Inf;");
|
||||
u.n = 0xfff0000000000000; // -Inf
|
||||
realTest("(E9.1,';')", u.d, " -Inf;");
|
||||
realTest("(F9.1,';')", u.d, " -Inf;");
|
||||
realTest("(G9.1,';')", u.d, " -Inf;");
|
||||
realTest("(G0,';')", u.d, "-Inf;");
|
||||
u.n = 0x7ff0000000000001; // NaN
|
||||
realTest("(E9.1,';')", u.d, " NaN;");
|
||||
realTest("(F9.1,';')", u.d, " NaN;");
|
||||
realTest("(G9.1,';')", u.d, " NaN;");
|
||||
realTest("(G0,';')", u.d, "NaN;");
|
||||
u.n = 0xfff0000000000001; // NaN (sign irrelevant)
|
||||
realTest("(E9.1,';')", u.d, " NaN;");
|
||||
realTest("(F9.1,';')", u.d, " NaN;");
|
||||
realTest("(G9.1,';')", u.d, " NaN;");
|
||||
realTest("(SP,E9.1,';')", u.d, " NaN;");
|
||||
realTest("(SP,F9.1,';')", u.d, " NaN;");
|
||||
realTest("(SP,G9.1,';')", u.d, " NaN;");
|
||||
realTest("(G0,';')", u.d, "NaN;");
|
||||
|
||||
u.n = 0x3fb999999999999a; // 0.1 rounded
|
||||
realTest("(E62.55,';')", u.d,
|
||||
" 0.1000000000000000055511151231257827021181583404541015625E+00;");
|
||||
realTest("(E0.0,';')", u.d, "0.E+00;");
|
||||
realTest("(E0.55,';')", u.d,
|
||||
"0.1000000000000000055511151231257827021181583404541015625E+00;");
|
||||
realTest("(E0,';')", u.d, ".1E+00;");
|
||||
realTest("(F58.55,';')", u.d,
|
||||
" 0.1000000000000000055511151231257827021181583404541015625;");
|
||||
realTest("(F0.0,';')", u.d, "0.;");
|
||||
realTest("(F0.55,';')", u.d,
|
||||
".1000000000000000055511151231257827021181583404541015625;");
|
||||
realTest("(F0,';')", u.d, ".1;");
|
||||
realTest("(G62.55,';')", u.d,
|
||||
" 0.1000000000000000055511151231257827021181583404541015625 ;");
|
||||
realTest("(G0.0,';')", u.d, "0.;");
|
||||
realTest("(G0.55,';')", u.d,
|
||||
".1000000000000000055511151231257827021181583404541015625;");
|
||||
realTest("(G0,';')", u.d, ".1;");
|
||||
|
||||
u.n = 0x3ff8000000000000; // 1.5
|
||||
realTest("(E9.2,';')", u.d, " 0.15E+01;");
|
||||
realTest("(F4.1,';')", u.d, " 1.5;");
|
||||
realTest("(G7.1,';')", u.d, " 2. ;");
|
||||
realTest("(RN,E8.1,';')", u.d, " 0.2E+01;");
|
||||
realTest("(RN,F3.0,';')", u.d, " 2.;");
|
||||
realTest("(RN,G7.0,';')", u.d, " 0.E+01;");
|
||||
realTest("(RN,G7.1,';')", u.d, " 2. ;");
|
||||
realTest("(RD,E8.1,';')", u.d, " 0.1E+01;");
|
||||
realTest("(RD,F3.0,';')", u.d, " 1.;");
|
||||
realTest("(RD,G7.0,';')", u.d, " 0.E+01;");
|
||||
realTest("(RD,G7.1,';')", u.d, " 1. ;");
|
||||
realTest("(RU,E8.1,';')", u.d, " 0.2E+01;");
|
||||
realTest("(RU,G7.0,';')", u.d, " 0.E+01;");
|
||||
realTest("(RU,G7.1,';')", u.d, " 2. ;");
|
||||
realTest("(RZ,E8.1,';')", u.d, " 0.1E+01;");
|
||||
realTest("(RZ,F3.0,';')", u.d, " 1.;");
|
||||
realTest("(RZ,G7.0,';')", u.d, " 0.E+01;");
|
||||
realTest("(RZ,G7.1,';')", u.d, " 1. ;");
|
||||
realTest("(RC,E8.1,';')", u.d, " 0.2E+01;");
|
||||
realTest("(RC,F3.0,';')", u.d, " 2.;");
|
||||
realTest("(RC,G7.0,';')", u.d, " 0.E+01;");
|
||||
realTest("(RC,G7.1,';')", u.d, " 2. ;");
|
||||
|
||||
// TODO continue F and G editing tests on these data
|
||||
|
||||
u.n = 0xbff8000000000000; // -1.5
|
||||
realTest("(E9.2,';')", u.d, "-0.15E+01;");
|
||||
realTest("(RN,E8.1,';')", u.d, "-0.2E+01;");
|
||||
realTest("(RD,E8.1,';')", u.d, "-0.2E+01;");
|
||||
realTest("(RU,E8.1,';')", u.d, "-0.1E+01;");
|
||||
realTest("(RZ,E8.1,';')", u.d, "-0.1E+01;");
|
||||
realTest("(RC,E8.1,';')", u.d, "-0.2E+01;");
|
||||
|
||||
u.n = 0x4004000000000000; // 2.5
|
||||
realTest("(E9.2,';')", u.d, " 0.25E+01;");
|
||||
realTest("(RN,E8.1,';')", u.d, " 0.2E+01;");
|
||||
realTest("(RD,E8.1,';')", u.d, " 0.2E+01;");
|
||||
realTest("(RU,E8.1,';')", u.d, " 0.3E+01;");
|
||||
realTest("(RZ,E8.1,';')", u.d, " 0.2E+01;");
|
||||
realTest("(RC,E8.1,';')", u.d, " 0.3E+01;");
|
||||
|
||||
u.n = 0xc004000000000000; // -2.5
|
||||
realTest("(E9.2,';')", u.d, "-0.25E+01;");
|
||||
realTest("(RN,E8.1,';')", u.d, "-0.2E+01;");
|
||||
realTest("(RD,E8.1,';')", u.d, "-0.3E+01;");
|
||||
realTest("(RU,E8.1,';')", u.d, "-0.2E+01;");
|
||||
realTest("(RZ,E8.1,';')", u.d, "-0.2E+01;");
|
||||
realTest("(RC,E8.1,';')", u.d, "-0.3E+01;");
|
||||
|
||||
u.n = 1; // least positive nonzero subnormal
|
||||
realTest("(E32.17,';')", u.d, " 0.49406564584124654-323;");
|
||||
realTest("(ES32.17,';')", u.d, " 4.94065645841246544-324;");
|
||||
realTest("(EN32.17,';')", u.d, " 4.94065645841246544-324;");
|
||||
realTest("(E759.752,';')", u.d,
|
||||
" 0."
|
||||
"494065645841246544176568792868221372365059802614324764425585682500675507"
|
||||
"270208751865299836361635992379796564695445717730926656710355939796398774"
|
||||
"796010781878126300713190311404527845817167848982103688718636056998730723"
|
||||
"050006387409153564984387312473397273169615140031715385398074126238565591"
|
||||
"171026658556686768187039560310624931945271591492455329305456544401127480"
|
||||
"129709999541931989409080416563324524757147869014726780159355238611550134"
|
||||
"803526493472019379026810710749170333222684475333572083243193609238289345"
|
||||
"836806010601150616980975307834227731832924790498252473077637592724787465"
|
||||
"608477820373446969953364701797267771758512566055119913150489110145103786"
|
||||
"273816725095583738973359899366480994116420570263709027924276754456522908"
|
||||
"75386825064197182655334472656250-323;");
|
||||
realTest("(G0,';')", u.d, ".5-323;");
|
||||
realTest("(E757.750,';')", u.d,
|
||||
" 0."
|
||||
"494065645841246544176568792868221372365059802614324764425585682500675507"
|
||||
"270208751865299836361635992379796564695445717730926656710355939796398774"
|
||||
"796010781878126300713190311404527845817167848982103688718636056998730723"
|
||||
"050006387409153564984387312473397273169615140031715385398074126238565591"
|
||||
"171026658556686768187039560310624931945271591492455329305456544401127480"
|
||||
"129709999541931989409080416563324524757147869014726780159355238611550134"
|
||||
"803526493472019379026810710749170333222684475333572083243193609238289345"
|
||||
"836806010601150616980975307834227731832924790498252473077637592724787465"
|
||||
"608477820373446969953364701797267771758512566055119913150489110145103786"
|
||||
"273816725095583738973359899366480994116420570263709027924276754456522908"
|
||||
"753868250641971826553344726562-323;");
|
||||
realTest("(RN,E757.750,';')", u.d,
|
||||
" 0."
|
||||
"494065645841246544176568792868221372365059802614324764425585682500675507"
|
||||
"270208751865299836361635992379796564695445717730926656710355939796398774"
|
||||
"796010781878126300713190311404527845817167848982103688718636056998730723"
|
||||
"050006387409153564984387312473397273169615140031715385398074126238565591"
|
||||
"171026658556686768187039560310624931945271591492455329305456544401127480"
|
||||
"129709999541931989409080416563324524757147869014726780159355238611550134"
|
||||
"803526493472019379026810710749170333222684475333572083243193609238289345"
|
||||
"836806010601150616980975307834227731832924790498252473077637592724787465"
|
||||
"608477820373446969953364701797267771758512566055119913150489110145103786"
|
||||
"273816725095583738973359899366480994116420570263709027924276754456522908"
|
||||
"753868250641971826553344726562-323;");
|
||||
realTest("(RD,E757.750,';')", u.d,
|
||||
" 0."
|
||||
"494065645841246544176568792868221372365059802614324764425585682500675507"
|
||||
"270208751865299836361635992379796564695445717730926656710355939796398774"
|
||||
"796010781878126300713190311404527845817167848982103688718636056998730723"
|
||||
"050006387409153564984387312473397273169615140031715385398074126238565591"
|
||||
"171026658556686768187039560310624931945271591492455329305456544401127480"
|
||||
"129709999541931989409080416563324524757147869014726780159355238611550134"
|
||||
"803526493472019379026810710749170333222684475333572083243193609238289345"
|
||||
"836806010601150616980975307834227731832924790498252473077637592724787465"
|
||||
"608477820373446969953364701797267771758512566055119913150489110145103786"
|
||||
"273816725095583738973359899366480994116420570263709027924276754456522908"
|
||||
"753868250641971826553344726562-323;");
|
||||
realTest("(RU,E757.750,';')", u.d,
|
||||
" 0."
|
||||
"494065645841246544176568792868221372365059802614324764425585682500675507"
|
||||
"270208751865299836361635992379796564695445717730926656710355939796398774"
|
||||
"796010781878126300713190311404527845817167848982103688718636056998730723"
|
||||
"050006387409153564984387312473397273169615140031715385398074126238565591"
|
||||
"171026658556686768187039560310624931945271591492455329305456544401127480"
|
||||
"129709999541931989409080416563324524757147869014726780159355238611550134"
|
||||
"803526493472019379026810710749170333222684475333572083243193609238289345"
|
||||
"836806010601150616980975307834227731832924790498252473077637592724787465"
|
||||
"608477820373446969953364701797267771758512566055119913150489110145103786"
|
||||
"273816725095583738973359899366480994116420570263709027924276754456522908"
|
||||
"753868250641971826553344726563-323;");
|
||||
realTest("(RC,E757.750,';')", u.d,
|
||||
" 0."
|
||||
"494065645841246544176568792868221372365059802614324764425585682500675507"
|
||||
"270208751865299836361635992379796564695445717730926656710355939796398774"
|
||||
"796010781878126300713190311404527845817167848982103688718636056998730723"
|
||||
"050006387409153564984387312473397273169615140031715385398074126238565591"
|
||||
"171026658556686768187039560310624931945271591492455329305456544401127480"
|
||||
"129709999541931989409080416563324524757147869014726780159355238611550134"
|
||||
"803526493472019379026810710749170333222684475333572083243193609238289345"
|
||||
"836806010601150616980975307834227731832924790498252473077637592724787465"
|
||||
"608477820373446969953364701797267771758512566055119913150489110145103786"
|
||||
"273816725095583738973359899366480994116420570263709027924276754456522908"
|
||||
"753868250641971826553344726563-323;");
|
||||
|
||||
u.n = 0x10000000000000; // least positive nonzero normal
|
||||
realTest("(E723.716,';')", u.d,
|
||||
" 0."
|
||||
"222507385850720138309023271733240406421921598046233183055332741688720443"
|
||||
"481391819585428315901251102056406733973103581100515243416155346010885601"
|
||||
"238537771882113077799353200233047961014744258363607192156504694250373420"
|
||||
"837525080665061665815894872049117996859163964850063590877011830487479978"
|
||||
"088775374994945158045160505091539985658247081864511353793580499211598108"
|
||||
"576605199243335211435239014879569960959128889160299264151106346631339366"
|
||||
"347758651302937176204732563178148566435087212282863764204484681140761391"
|
||||
"147706280168985324411002416144742161856716615054015428508471675290190316"
|
||||
"132277889672970737312333408698898317506783884692609277397797285865965494"
|
||||
"10913690954061364675687023986783152906809846172109246253967285156250-"
|
||||
"307;");
|
||||
realTest("(G0,';')", u.d, ".22250738585072014-307;");
|
||||
|
||||
u.n = 0x7fefffffffffffffuLL; // greatest finite
|
||||
realTest("(E32.17,';')", u.d, " 0.17976931348623157+309;");
|
||||
realTest("(E317.310,';')", u.d,
|
||||
" 0."
|
||||
"179769313486231570814527423731704356798070567525844996598917476803157260"
|
||||
"780028538760589558632766878171540458953514382464234321326889464182768467"
|
||||
"546703537516986049910576551282076245490090389328944075868508455133942304"
|
||||
"583236903222948165808559332123348274797826204144723168738177180919299881"
|
||||
"2504040261841248583680+309;");
|
||||
realTest("(ES317.310,';')", u.d,
|
||||
" 1."
|
||||
"797693134862315708145274237317043567980705675258449965989174768031572607"
|
||||
"800285387605895586327668781715404589535143824642343213268894641827684675"
|
||||
"467035375169860499105765512820762454900903893289440758685084551339423045"
|
||||
"832369032229481658085593321233482747978262041447231687381771809192998812"
|
||||
"5040402618412485836800+308;");
|
||||
realTest("(EN319.310,';')", u.d,
|
||||
" 179."
|
||||
"769313486231570814527423731704356798070567525844996598917476803157260780"
|
||||
"028538760589558632766878171540458953514382464234321326889464182768467546"
|
||||
"703537516986049910576551282076245490090389328944075868508455133942304583"
|
||||
"236903222948165808559332123348274797826204144723168738177180919299881250"
|
||||
"4040261841248583680000+306;");
|
||||
realTest("(G0,';')", u.d, ".17976931348623157+309;");
|
||||
|
||||
realTest("(F5.3,';')", 25., "*****;");
|
||||
realTest("(F5.3,';')", 2.5, "2.500;");
|
||||
realTest("(F5.3,';')", 0.25, "0.250;");
|
||||
realTest("(F5.3,';')", 0.025, "0.025;");
|
||||
realTest("(F5.3,';')", 0.0025, "0.003;");
|
||||
realTest("(F5.3,';')", 0.00025, "0.000;");
|
||||
realTest("(F5.3,';')", 0.000025, "0.000;");
|
||||
realTest("(F5.3,';')", -25., "*****;");
|
||||
realTest("(F5.3,';')", -2.5, "*****;");
|
||||
realTest("(F5.3,';')", -0.25, "-.250;");
|
||||
realTest("(F5.3,';')", -0.025, "-.025;");
|
||||
realTest("(F5.3,';')", -0.0025, "-.003;");
|
||||
realTest("(F5.3,';')", -0.00025, "-.000;");
|
||||
realTest("(F5.3,';')", -0.000025, "-.000;");
|
||||
|
||||
realInTest("(F18.0)", " 0", 0x0);
|
||||
realInTest("(F18.0)", " ", 0x0);
|
||||
realInTest("(F18.0)", " -0", 0x8000000000000000);
|
||||
realInTest("(F18.0)", " 01", 0x3ff0000000000000);
|
||||
realInTest("(F18.0)", " 1", 0x3ff0000000000000);
|
||||
realInTest("(F18.0)", " 125.", 0x405f400000000000);
|
||||
realInTest("(F18.0)", " 12.5", 0x4029000000000000);
|
||||
realInTest("(F18.0)", " 1.25", 0x3ff4000000000000);
|
||||
realInTest("(F18.0)", " 01.25", 0x3ff4000000000000);
|
||||
realInTest("(F18.0)", " .125", 0x3fc0000000000000);
|
||||
realInTest("(F18.0)", " 0.125", 0x3fc0000000000000);
|
||||
realInTest("(F18.0)", " .0625", 0x3fb0000000000000);
|
||||
realInTest("(F18.0)", " 0.0625", 0x3fb0000000000000);
|
||||
realInTest("(F18.0)", " 125", 0x405f400000000000);
|
||||
realInTest("(F18.1)", " 125", 0x4029000000000000);
|
||||
realInTest("(F18.2)", " 125", 0x3ff4000000000000);
|
||||
realInTest("(F18.3)", " 125", 0x3fc0000000000000);
|
||||
realInTest("(-1P,F18.0)", " 125", 0x4093880000000000); // 1250
|
||||
realInTest("(1P,F18.0)", " 125", 0x4029000000000000); // 12.5
|
||||
realInTest("(BZ,F18.0)", " 125 ", 0x4093880000000000); // 1250
|
||||
realInTest("(BZ,F18.0)", " 125 . e +1 ", 0x42a6bcc41e900000); // 1.25e13
|
||||
realInTest("(DC,F18.0)", " 12,5", 0x4029000000000000);
|
||||
|
||||
listInputTest();
|
||||
descrOutputTest();
|
||||
|
||||
return EndTests();
|
||||
}
|
|
@ -2,6 +2,9 @@ add_flang_unittest(FlangRuntimeTests
|
|||
CharacterTest.cpp
|
||||
RuntimeCrashTest.cpp
|
||||
CrashHandlerFixture.cpp
|
||||
NumericalFormatTest.cpp
|
||||
RuntimeCrashTest.cpp
|
||||
CrashHandlerFixture.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(FlangRuntimeTests
|
||||
|
|
|
@ -0,0 +1,694 @@
|
|||
//===-- flang/unittests/RuntimeGTest/NumericalFormatTest.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 <algorithm>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <gtest/gtest.h>
|
||||
#include <tuple>
|
||||
|
||||
using namespace Fortran::runtime;
|
||||
using namespace Fortran::runtime::io;
|
||||
|
||||
static bool CompareFormattedStrings(
|
||||
const std::string &expect, const std::string &&got) {
|
||||
std::string want{expect};
|
||||
want.resize(got.size(), ' ');
|
||||
return want == got;
|
||||
}
|
||||
|
||||
static bool CompareFormattedStrings(
|
||||
const char *expect, const std::string &&got) {
|
||||
return CompareFormattedStrings(std::string(expect), std::move(got));
|
||||
}
|
||||
|
||||
// Perform format and compare the result with expected value
|
||||
static bool CompareFormatReal(
|
||||
const char *format, double x, const char *expect) {
|
||||
char buffer[800];
|
||||
auto *cookie{IONAME(BeginInternalFormattedOutput)(
|
||||
buffer, sizeof buffer, format, std::strlen(format))};
|
||||
IONAME(OutputReal64)(cookie, x);
|
||||
auto status{IONAME(EndIoStatement)(cookie)};
|
||||
|
||||
EXPECT_EQ(status, 0);
|
||||
return CompareFormattedStrings(expect, std::string{buffer, sizeof buffer});
|
||||
}
|
||||
|
||||
// Convert raw uint64 into double, perform format, and compare with expected
|
||||
static bool CompareFormatReal(
|
||||
const char *format, std::uint64_t xInt, const char *expect) {
|
||||
double x;
|
||||
static_assert(sizeof(double) == sizeof(std::uint64_t),
|
||||
"Size of double != size of uint64_t!");
|
||||
std::memcpy(&x, &xInt, sizeof xInt);
|
||||
return CompareFormatReal(format, x, expect);
|
||||
}
|
||||
|
||||
struct IOApiTests : CrashHandlerFixture {};
|
||||
|
||||
TEST(IOApiTests, HelloWorldOutputTest) {
|
||||
static constexpr int bufferSize{32};
|
||||
char buffer[bufferSize];
|
||||
|
||||
// Create format for all types and values to be written
|
||||
const char *format{"(6HHELLO,,A6,2X,I3,1X,'0x',Z8,1X,L1)"};
|
||||
auto *cookie{IONAME(BeginInternalFormattedOutput)(
|
||||
buffer, bufferSize, format, std::strlen(format))};
|
||||
|
||||
// Write string, integer, and logical values to buffer
|
||||
IONAME(OutputAscii)(cookie, "WORLD", 5);
|
||||
IONAME(OutputInteger64)(cookie, 678);
|
||||
IONAME(OutputInteger64)(cookie, 0xfeedface);
|
||||
IONAME(OutputLogical)(cookie, true);
|
||||
|
||||
// Ensure IO succeeded
|
||||
auto status{IONAME(EndIoStatement)(cookie)};
|
||||
ASSERT_EQ(status, 0) << "hello: '" << format << "' failed, status "
|
||||
<< static_cast<int>(status);
|
||||
|
||||
// Ensure final buffer matches expected string output
|
||||
static const std::string expect{"HELLO, WORLD 678 0xFEEDFACE T"};
|
||||
ASSERT_TRUE(
|
||||
CompareFormattedStrings(expect, std::string{buffer, sizeof buffer}))
|
||||
<< "Expected '" << expect << "', got " << buffer;
|
||||
}
|
||||
|
||||
TEST(IOApiTests, MultilineOutputTest) {
|
||||
// Allocate buffer for multiline output
|
||||
static constexpr int numLines{5};
|
||||
static constexpr int lineLength{32};
|
||||
static char buffer[numLines][lineLength];
|
||||
|
||||
// Create descriptor for entire buffer
|
||||
static constexpr int staticDescriptorMaxRank{1};
|
||||
static StaticDescriptor<staticDescriptorMaxRank> wholeStaticDescriptor;
|
||||
static Descriptor &whole{wholeStaticDescriptor.descriptor()};
|
||||
static SubscriptValue extent[]{numLines};
|
||||
whole.Establish(TypeCode{CFI_type_char}, /*elementBytes=*/lineLength, &buffer,
|
||||
staticDescriptorMaxRank, extent, CFI_attribute_pointer);
|
||||
whole.Dump(stderr);
|
||||
whole.Check();
|
||||
|
||||
// Create descriptor for buffer section
|
||||
static StaticDescriptor<staticDescriptorMaxRank> sectionStaticDescriptor;
|
||||
static Descriptor §ion{sectionStaticDescriptor.descriptor()};
|
||||
static const SubscriptValue lowers[]{0}, uppers[]{4}, strides[]{1};
|
||||
section.Establish(whole.type(), /*elementBytes=*/whole.ElementBytes(),
|
||||
nullptr, /*maxRank=*/staticDescriptorMaxRank, extent,
|
||||
CFI_attribute_pointer);
|
||||
|
||||
// Ensure C descriptor address `section.raw()` is updated without error
|
||||
const auto error{
|
||||
CFI_section(§ion.raw(), &whole.raw(), lowers, uppers, strides)};
|
||||
ASSERT_EQ(error, 0) << "multiline: CFI_section failed: " << error;
|
||||
section.Dump(stderr);
|
||||
section.Check();
|
||||
|
||||
// Create format string and initialize IO operation
|
||||
const char *format{
|
||||
"('?abcde,',T1,'>',T9,A,TL12,A,TR25,'<'//G0,17X,'abcd',1(2I4))"};
|
||||
static auto *cookie{IONAME(BeginInternalArrayFormattedOutput)(
|
||||
section, format, std::strlen(format))};
|
||||
|
||||
// Write data to buffer
|
||||
IONAME(OutputAscii)(cookie, "WORLD", 5);
|
||||
IONAME(OutputAscii)(cookie, "HELLO", 5);
|
||||
IONAME(OutputInteger64)(cookie, 789);
|
||||
for (int j{666}; j <= 999; j += 111) {
|
||||
IONAME(OutputInteger64)(cookie, j);
|
||||
}
|
||||
|
||||
// Ensure no errors occured in write operations above
|
||||
const auto status{IONAME(EndIoStatement)(cookie)};
|
||||
ASSERT_EQ(status, 0) << "multiline: '" << format << "' failed, status "
|
||||
<< static_cast<int>(status);
|
||||
|
||||
static const std::string expect{">HELLO, WORLD <"
|
||||
" "
|
||||
"789 abcd 666 777"
|
||||
" 888 999 "
|
||||
" "};
|
||||
// Ensure formatted string matches expected output
|
||||
ASSERT_TRUE(
|
||||
CompareFormattedStrings(expect, std::string{buffer[0], sizeof buffer}))
|
||||
<< "Expected " << expect << " but got " << buffer;
|
||||
}
|
||||
|
||||
TEST(IOApiTests, ListInputTest) {
|
||||
static const char input[]{",1*,(5.,6..)"};
|
||||
static auto *cookie{IONAME(BeginInternalListInput)(input, sizeof input - 1)};
|
||||
|
||||
// Create real values for IO tests
|
||||
static constexpr int numRealValues{6};
|
||||
static float z[numRealValues];
|
||||
for (int j{0}; j < numRealValues; ++j) {
|
||||
z[j] = -(j + 1);
|
||||
}
|
||||
|
||||
// Ensure reading complex values to floats does not result in an error
|
||||
for (int j{0}; j < numRealValues; j += 2) {
|
||||
ASSERT_TRUE(IONAME(InputComplex32)(cookie, &z[j]))
|
||||
<< "InputComplex32 failed with value " << z[j];
|
||||
}
|
||||
|
||||
// Ensure no IO errors occured during IO operations above
|
||||
static auto status{IONAME(EndIoStatement)(cookie)};
|
||||
ASSERT_EQ(status, 0) << "Failed complex list-directed input, status "
|
||||
<< static_cast<int>(status);
|
||||
|
||||
// Ensure writing complex values from floats does not result in an error
|
||||
static constexpr int bufferSize{33};
|
||||
static char output[bufferSize];
|
||||
output[bufferSize - 1] = '\0';
|
||||
cookie = IONAME(BeginInternalListOutput)(output, bufferSize - 1);
|
||||
for (int j{0}; j < numRealValues; j += 2) {
|
||||
ASSERT_TRUE(IONAME(OutputComplex32)(cookie, z[j], z[j + 1]))
|
||||
<< "OutputComplex32 failed when outputting value " << z[j] << ", "
|
||||
<< z[j + 1];
|
||||
}
|
||||
|
||||
// Ensure no IO errors occured during IO operations above
|
||||
status = IONAME(EndIoStatement)(cookie);
|
||||
ASSERT_EQ(status, 0) << "Failed complex list-directed output, status "
|
||||
<< static_cast<int>(status);
|
||||
|
||||
// Verify output buffer against expected value
|
||||
static const char expect[bufferSize]{" (-1.,-2.) (-3.,-4.) (5.,6.) "};
|
||||
ASSERT_EQ(std::strncmp(output, expect, bufferSize), 0)
|
||||
<< "Failed complex list-directed output, expected '" << expect
|
||||
<< "', but got '" << output << "'";
|
||||
}
|
||||
|
||||
TEST(IOApiTests, DescriptorOutputTest) {
|
||||
static constexpr int bufferSize{9};
|
||||
static char buffer[bufferSize];
|
||||
static const char *format{"(2A4)"};
|
||||
static auto *cookie{IONAME(BeginInternalFormattedOutput)(
|
||||
buffer, bufferSize, format, std::strlen(format))};
|
||||
|
||||
// Create descriptor for output
|
||||
static constexpr int staticDescriptorMaxRank{1};
|
||||
static StaticDescriptor<staticDescriptorMaxRank> staticDescriptor;
|
||||
static Descriptor &desc{staticDescriptor.descriptor()};
|
||||
static constexpr int subscriptExtent{2};
|
||||
static const SubscriptValue extent[]{subscriptExtent};
|
||||
|
||||
// Manually write to descriptor buffer
|
||||
static constexpr int dataLength{4};
|
||||
static char data[subscriptExtent][dataLength];
|
||||
std::memcpy(data[0], "ABCD", dataLength);
|
||||
std::memcpy(data[1], "EFGH", dataLength);
|
||||
desc.Establish(TypeCode{CFI_type_char}, dataLength, &data,
|
||||
staticDescriptorMaxRank, extent);
|
||||
desc.Dump(stderr);
|
||||
desc.Check();
|
||||
IONAME(OutputDescriptor)(cookie, desc);
|
||||
|
||||
// Ensure no errors were encountered in initializing the cookie and descriptor
|
||||
static auto formatStatus{IONAME(EndIoStatement)(cookie)};
|
||||
ASSERT_EQ(formatStatus, 0)
|
||||
<< "descrOutputTest: '" << format << "' failed, status "
|
||||
<< static_cast<int>(formatStatus);
|
||||
|
||||
// Ensure buffer matches expected output
|
||||
ASSERT_TRUE(
|
||||
CompareFormattedStrings("ABCDEFGH ", std::string{buffer, sizeof buffer}));
|
||||
|
||||
// Begin list-directed output on cookie by descriptor
|
||||
cookie = IONAME(BeginInternalListOutput)(buffer, sizeof buffer);
|
||||
IONAME(OutputDescriptor)(cookie, desc);
|
||||
|
||||
// Ensure list-directed output does not result in an IO error
|
||||
static auto listDirectedStatus{IONAME(EndIoStatement)(cookie)};
|
||||
ASSERT_EQ(listDirectedStatus, 0)
|
||||
<< "descrOutputTest: list-directed failed, status "
|
||||
<< static_cast<int>(listDirectedStatus);
|
||||
|
||||
// Ensure buffer matches expected output
|
||||
ASSERT_TRUE(
|
||||
CompareFormattedStrings(" ABCDEFGH", std::string{buffer, sizeof buffer}));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Tests for output formatting real values
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
TEST(IOApiTests, FormatZeroes) {
|
||||
static constexpr std::pair<const char *, const char *> zeroes[]{
|
||||
{"(E32.17,';')", " 0.00000000000000000E+00;"},
|
||||
{"(F32.17,';')", " 0.00000000000000000;"},
|
||||
{"(G32.17,';')", " 0.0000000000000000 ;"},
|
||||
{"(DC,E32.17,';')", " 0,00000000000000000E+00;"},
|
||||
{"(DC,F32.17,';')", " 0,00000000000000000;"},
|
||||
{"(DC,G32.17,';')", " 0,0000000000000000 ;"},
|
||||
{"(D32.17,';')", " 0.00000000000000000D+00;"},
|
||||
{"(E32.17E1,';')", " 0.00000000000000000E+0;"},
|
||||
{"(G32.17E1,';')", " 0.0000000000000000 ;"},
|
||||
{"(E32.17E0,';')", " 0.00000000000000000E+0;"},
|
||||
{"(G32.17E0,';')", " 0.0000000000000000 ;"},
|
||||
{"(1P,E32.17,';')", " 0.00000000000000000E+00;"},
|
||||
{"(1PE32.17,';')", " 0.00000000000000000E+00;"}, // no comma
|
||||
{"(1P,F32.17,';')", " 0.00000000000000000;"},
|
||||
{"(1P,G32.17,';')", " 0.0000000000000000 ;"},
|
||||
{"(2P,E32.17,';')", " 00.0000000000000000E+00;"},
|
||||
{"(-1P,E32.17,';')", " 0.00000000000000000E+00;"},
|
||||
{"(G0,';')", "0.;"},
|
||||
};
|
||||
|
||||
for (auto const &[format, expect] : zeroes) {
|
||||
ASSERT_TRUE(CompareFormatReal(format, 0.0, expect))
|
||||
<< "Failed to format " << format << ", expected " << expect;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(IOApiTests, FormatOnes) {
|
||||
static constexpr std::pair<const char *, const char *> ones[]{
|
||||
{"(E32.17,';')", " 0.10000000000000000E+01;"},
|
||||
{"(F32.17,';')", " 1.00000000000000000;"},
|
||||
{"(G32.17,';')", " 1.0000000000000000 ;"},
|
||||
{"(E32.17E1,';')", " 0.10000000000000000E+1;"},
|
||||
{"(G32.17E1,';')", " 1.0000000000000000 ;"},
|
||||
{"(E32.17E0,';')", " 0.10000000000000000E+1;"},
|
||||
{"(G32.17E0,';')", " 1.0000000000000000 ;"},
|
||||
{"(E32.17E4,';')", " 0.10000000000000000E+0001;"},
|
||||
{"(G32.17E4,';')", " 1.0000000000000000 ;"},
|
||||
{"(1P,E32.17,';')", " 1.00000000000000000E+00;"},
|
||||
{"(1PE32.17,';')", " 1.00000000000000000E+00;"}, // no comma
|
||||
{"(1P,F32.17,';')", " 10.00000000000000000;"},
|
||||
{"(1P,G32.17,';')", " 1.0000000000000000 ;"},
|
||||
{"(ES32.17,';')", " 1.00000000000000000E+00;"},
|
||||
{"(2P,E32.17,';')", " 10.0000000000000000E-01;"},
|
||||
{"(2P,G32.17,';')", " 1.0000000000000000 ;"},
|
||||
{"(-1P,E32.17,';')", " 0.01000000000000000E+02;"},
|
||||
{"(-1P,G32.17,';')", " 1.0000000000000000 ;"},
|
||||
{"(G0,';')", "1.;"},
|
||||
};
|
||||
|
||||
for (auto const &[format, expect] : ones) {
|
||||
ASSERT_TRUE(CompareFormatReal(format, 1.0, expect))
|
||||
<< "Failed to format " << format << ", expected " << expect;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(IOApiTests, FormatNegativeOnes) {
|
||||
static constexpr std::tuple<const char *, const char *> negOnes[]{
|
||||
{"(E32.17,';')", " -0.10000000000000000E+01;"},
|
||||
{"(F32.17,';')", " -1.00000000000000000;"},
|
||||
{"(G32.17,';')", " -1.0000000000000000 ;"},
|
||||
{"(G0,';')", "-1.;"},
|
||||
};
|
||||
for (auto const &[format, expect] : negOnes) {
|
||||
ASSERT_TRUE(CompareFormatReal(format, -1.0, expect))
|
||||
<< "Failed to format " << format << ", expected " << expect;
|
||||
}
|
||||
}
|
||||
|
||||
// Each test case contains a raw uint64, a format string for a real value, and
|
||||
// the expected resulting string from formatting the raw uint64. The double
|
||||
// representation of the uint64 is commented above each test case.
|
||||
TEST(IOApiTests, FormatDoubleValues) {
|
||||
|
||||
using TestCaseTy = std::tuple<std::uint64_t,
|
||||
std::vector<std::tuple<const char *, const char *>>>;
|
||||
static const std::vector<TestCaseTy> testCases{
|
||||
{// -0
|
||||
0x8000000000000000,
|
||||
{
|
||||
{"(E9.1,';')", " -0.0E+00;"},
|
||||
{"(F4.0,';')", " -0.;"},
|
||||
{"(G8.0,';')", "-0.0E+00;"},
|
||||
{"(G8.1,';')", " -0. ;"},
|
||||
{"(G0,';')", "-0.;"},
|
||||
{"(E9.1,';')", " -0.0E+00;"},
|
||||
}},
|
||||
{// +Inf
|
||||
0x7ff0000000000000,
|
||||
{
|
||||
{"(E9.1,';')", " Inf;"},
|
||||
{"(F9.1,';')", " Inf;"},
|
||||
{"(G9.1,';')", " Inf;"},
|
||||
{"(SP,E9.1,';')", " +Inf;"},
|
||||
{"(SP,F9.1,';')", " +Inf;"},
|
||||
{"(SP,G9.1,';')", " +Inf;"},
|
||||
{"(G0,';')", "Inf;"},
|
||||
}},
|
||||
{// -Inf
|
||||
0xfff0000000000000,
|
||||
{
|
||||
{"(E9.1,';')", " -Inf;"},
|
||||
{"(F9.1,';')", " -Inf;"},
|
||||
{"(G9.1,';')", " -Inf;"},
|
||||
{"(G0,';')", "-Inf;"},
|
||||
}},
|
||||
{// NaN
|
||||
0x7ff0000000000001,
|
||||
{
|
||||
{"(E9.1,';')", " NaN;"},
|
||||
{"(F9.1,';')", " NaN;"},
|
||||
{"(G9.1,';')", " NaN;"},
|
||||
{"(G0,';')", "NaN;"},
|
||||
}},
|
||||
{// NaN (sign irrelevant)
|
||||
0xfff0000000000001,
|
||||
{
|
||||
{"(E9.1,';')", " NaN;"},
|
||||
{"(F9.1,';')", " NaN;"},
|
||||
{"(G9.1,';')", " NaN;"},
|
||||
{"(SP,E9.1,';')", " NaN;"},
|
||||
{"(SP,F9.1,';')", " NaN;"},
|
||||
{"(SP,G9.1,';')", " NaN;"},
|
||||
{"(G0,';')", "NaN;"},
|
||||
}},
|
||||
{// 0.1 rounded
|
||||
0x3fb999999999999a,
|
||||
{
|
||||
{"(E62.55,';')",
|
||||
" 0.1000000000000000055511151231257827021181583404541015625E+"
|
||||
"00;"},
|
||||
{"(E0.0,';')", "0.E+00;"},
|
||||
{"(E0.55,';')",
|
||||
"0.1000000000000000055511151231257827021181583404541015625E+"
|
||||
"00;"},
|
||||
{"(E0,';')", ".1E+00;"},
|
||||
{"(F58.55,';')",
|
||||
" 0."
|
||||
"1000000000000000055511151231257827021181583404541015625;"},
|
||||
{"(F0.0,';')", "0.;"},
|
||||
{"(F0.55,';')",
|
||||
".1000000000000000055511151231257827021181583404541015625;"},
|
||||
{"(F0,';')", ".1;"},
|
||||
{"(G62.55,';')",
|
||||
" 0.1000000000000000055511151231257827021181583404541015625 "
|
||||
" ;"},
|
||||
{"(G0.0,';')", "0.;"},
|
||||
{"(G0.55,';')",
|
||||
".1000000000000000055511151231257827021181583404541015625;"},
|
||||
{"(G0,';')", ".1;"},
|
||||
}},
|
||||
{// 1.5
|
||||
0x3ff8000000000000,
|
||||
{
|
||||
{"(E9.2,';')", " 0.15E+01;"},
|
||||
{"(F4.1,';')", " 1.5;"},
|
||||
{"(G7.1,';')", " 2. ;"},
|
||||
{"(RN,E8.1,';')", " 0.2E+01;"},
|
||||
{"(RN,F3.0,';')", " 2.;"},
|
||||
{"(RN,G7.0,';')", " 0.E+01;"},
|
||||
{"(RN,G7.1,';')", " 2. ;"},
|
||||
{"(RD,E8.1,';')", " 0.1E+01;"},
|
||||
{"(RD,F3.0,';')", " 1.;"},
|
||||
{"(RD,G7.0,';')", " 0.E+01;"},
|
||||
{"(RD,G7.1,';')", " 1. ;"},
|
||||
{"(RU,E8.1,';')", " 0.2E+01;"},
|
||||
{"(RU,G7.0,';')", " 0.E+01;"},
|
||||
{"(RU,G7.1,';')", " 2. ;"},
|
||||
{"(RZ,E8.1,';')", " 0.1E+01;"},
|
||||
{"(RZ,F3.0,';')", " 1.;"},
|
||||
{"(RZ,G7.0,';')", " 0.E+01;"},
|
||||
{"(RZ,G7.1,';')", " 1. ;"},
|
||||
{"(RC,E8.1,';')", " 0.2E+01;"},
|
||||
{"(RC,F3.0,';')", " 2.;"},
|
||||
{"(RC,G7.0,';')", " 0.E+01;"},
|
||||
{"(RC,G7.1,';')", " 2. ;"},
|
||||
}},
|
||||
{// -1.5
|
||||
0xbff8000000000000,
|
||||
{
|
||||
{"(E9.2,';')", "-0.15E+01;"},
|
||||
{"(RN,E8.1,';')", "-0.2E+01;"},
|
||||
{"(RD,E8.1,';')", "-0.2E+01;"},
|
||||
{"(RU,E8.1,';')", "-0.1E+01;"},
|
||||
{"(RZ,E8.1,';')", "-0.1E+01;"},
|
||||
{"(RC,E8.1,';')", "-0.2E+01;"},
|
||||
}},
|
||||
{// 2.5
|
||||
0x4004000000000000,
|
||||
{
|
||||
{"(E9.2,';')", " 0.25E+01;"},
|
||||
{"(RN,E8.1,';')", " 0.2E+01;"},
|
||||
{"(RD,E8.1,';')", " 0.2E+01;"},
|
||||
{"(RU,E8.1,';')", " 0.3E+01;"},
|
||||
{"(RZ,E8.1,';')", " 0.2E+01;"},
|
||||
{"(RC,E8.1,';')", " 0.3E+01;"},
|
||||
}},
|
||||
{// -2.5
|
||||
0xc004000000000000,
|
||||
{
|
||||
{"(E9.2,';')", "-0.25E+01;"},
|
||||
{"(RN,E8.1,';')", "-0.2E+01;"},
|
||||
{"(RD,E8.1,';')", "-0.3E+01;"},
|
||||
{"(RU,E8.1,';')", "-0.2E+01;"},
|
||||
{"(RZ,E8.1,';')", "-0.2E+01;"},
|
||||
{"(RC,E8.1,';')", "-0.3E+01;"},
|
||||
}},
|
||||
{// least positive nonzero subnormal
|
||||
1,
|
||||
{
|
||||
{"(E32.17,';')", " 0.49406564584124654-323;"},
|
||||
{"(ES32.17,';')", " 4.94065645841246544-324;"},
|
||||
{"(EN32.17,';')", " 4.94065645841246544-324;"},
|
||||
{"(E759.752,';')",
|
||||
" 0."
|
||||
"494065645841246544176568792868221372365059802614324764425585"
|
||||
"682500675507270208751865299836361635992379796564695445717730"
|
||||
"926656710355939796398774796010781878126300713190311404527845"
|
||||
"817167848982103688718636056998730723050006387409153564984387"
|
||||
"312473397273169615140031715385398074126238565591171026658556"
|
||||
"686768187039560310624931945271591492455329305456544401127480"
|
||||
"129709999541931989409080416563324524757147869014726780159355"
|
||||
"238611550134803526493472019379026810710749170333222684475333"
|
||||
"572083243193609238289345836806010601150616980975307834227731"
|
||||
"832924790498252473077637592724787465608477820373446969953364"
|
||||
"701797267771758512566055119913150489110145103786273816725095"
|
||||
"583738973359899366480994116420570263709027924276754456522908"
|
||||
"75386825064197182655334472656250-323;"},
|
||||
{"(G0,';')", ".5-323;"},
|
||||
{"(E757.750,';')",
|
||||
" 0."
|
||||
"494065645841246544176568792868221372365059802614324764425585"
|
||||
"682500675507270208751865299836361635992379796564695445717730"
|
||||
"926656710355939796398774796010781878126300713190311404527845"
|
||||
"817167848982103688718636056998730723050006387409153564984387"
|
||||
"312473397273169615140031715385398074126238565591171026658556"
|
||||
"686768187039560310624931945271591492455329305456544401127480"
|
||||
"129709999541931989409080416563324524757147869014726780159355"
|
||||
"238611550134803526493472019379026810710749170333222684475333"
|
||||
"572083243193609238289345836806010601150616980975307834227731"
|
||||
"832924790498252473077637592724787465608477820373446969953364"
|
||||
"701797267771758512566055119913150489110145103786273816725095"
|
||||
"583738973359899366480994116420570263709027924276754456522908"
|
||||
"753868250641971826553344726562-323;"},
|
||||
{"(RN,E757.750,';')",
|
||||
" 0."
|
||||
"494065645841246544176568792868221372365059802614324764425585"
|
||||
"682500675507270208751865299836361635992379796564695445717730"
|
||||
"926656710355939796398774796010781878126300713190311404527845"
|
||||
"817167848982103688718636056998730723050006387409153564984387"
|
||||
"312473397273169615140031715385398074126238565591171026658556"
|
||||
"686768187039560310624931945271591492455329305456544401127480"
|
||||
"129709999541931989409080416563324524757147869014726780159355"
|
||||
"238611550134803526493472019379026810710749170333222684475333"
|
||||
"572083243193609238289345836806010601150616980975307834227731"
|
||||
"832924790498252473077637592724787465608477820373446969953364"
|
||||
"701797267771758512566055119913150489110145103786273816725095"
|
||||
"583738973359899366480994116420570263709027924276754456522908"
|
||||
"753868250641971826553344726562-323;"},
|
||||
{"(RD,E757.750,';')",
|
||||
" 0."
|
||||
"494065645841246544176568792868221372365059802614324764425585"
|
||||
"682500675507270208751865299836361635992379796564695445717730"
|
||||
"926656710355939796398774796010781878126300713190311404527845"
|
||||
"817167848982103688718636056998730723050006387409153564984387"
|
||||
"312473397273169615140031715385398074126238565591171026658556"
|
||||
"686768187039560310624931945271591492455329305456544401127480"
|
||||
"129709999541931989409080416563324524757147869014726780159355"
|
||||
"238611550134803526493472019379026810710749170333222684475333"
|
||||
"572083243193609238289345836806010601150616980975307834227731"
|
||||
"832924790498252473077637592724787465608477820373446969953364"
|
||||
"701797267771758512566055119913150489110145103786273816725095"
|
||||
"583738973359899366480994116420570263709027924276754456522908"
|
||||
"753868250641971826553344726562-323;"},
|
||||
{"(RU,E757.750,';')",
|
||||
" 0."
|
||||
"494065645841246544176568792868221372365059802614324764425585"
|
||||
"682500675507270208751865299836361635992379796564695445717730"
|
||||
"926656710355939796398774796010781878126300713190311404527845"
|
||||
"817167848982103688718636056998730723050006387409153564984387"
|
||||
"312473397273169615140031715385398074126238565591171026658556"
|
||||
"686768187039560310624931945271591492455329305456544401127480"
|
||||
"129709999541931989409080416563324524757147869014726780159355"
|
||||
"238611550134803526493472019379026810710749170333222684475333"
|
||||
"572083243193609238289345836806010601150616980975307834227731"
|
||||
"832924790498252473077637592724787465608477820373446969953364"
|
||||
"701797267771758512566055119913150489110145103786273816725095"
|
||||
"583738973359899366480994116420570263709027924276754456522908"
|
||||
"753868250641971826553344726563-323;"},
|
||||
{"(RC,E757.750,';')",
|
||||
" 0."
|
||||
"494065645841246544176568792868221372365059802614324764425585"
|
||||
"682500675507270208751865299836361635992379796564695445717730"
|
||||
"926656710355939796398774796010781878126300713190311404527845"
|
||||
"817167848982103688718636056998730723050006387409153564984387"
|
||||
"312473397273169615140031715385398074126238565591171026658556"
|
||||
"686768187039560310624931945271591492455329305456544401127480"
|
||||
"129709999541931989409080416563324524757147869014726780159355"
|
||||
"238611550134803526493472019379026810710749170333222684475333"
|
||||
"572083243193609238289345836806010601150616980975307834227731"
|
||||
"832924790498252473077637592724787465608477820373446969953364"
|
||||
"701797267771758512566055119913150489110145103786273816725095"
|
||||
"583738973359899366480994116420570263709027924276754456522908"
|
||||
"753868250641971826553344726563-323;"},
|
||||
}},
|
||||
{// least positive nonzero normal
|
||||
0x10000000000000,
|
||||
{
|
||||
{"(E723.716,';')",
|
||||
" 0."
|
||||
"222507385850720138309023271733240406421921598046233183055332"
|
||||
"741688720443481391819585428315901251102056406733973103581100"
|
||||
"515243416155346010885601238537771882113077799353200233047961"
|
||||
"014744258363607192156504694250373420837525080665061665815894"
|
||||
"872049117996859163964850063590877011830487479978088775374994"
|
||||
"945158045160505091539985658247081864511353793580499211598108"
|
||||
"576605199243335211435239014879569960959128889160299264151106"
|
||||
"346631339366347758651302937176204732563178148566435087212282"
|
||||
"863764204484681140761391147706280168985324411002416144742161"
|
||||
"856716615054015428508471675290190316132277889672970737312333"
|
||||
"408698898317506783884692609277397797285865965494109136909540"
|
||||
"61364675687023986783152906809846172109246253967285156250-"
|
||||
"307;"},
|
||||
{"(G0,';')", ".22250738585072014-307;"},
|
||||
}},
|
||||
{// greatest finite
|
||||
0x7fefffffffffffffuLL,
|
||||
{
|
||||
{"(E32.17,';')", " 0.17976931348623157+309;"},
|
||||
{"(E317.310,';')",
|
||||
" 0."
|
||||
"179769313486231570814527423731704356798070567525844996598917"
|
||||
"476803157260780028538760589558632766878171540458953514382464"
|
||||
"234321326889464182768467546703537516986049910576551282076245"
|
||||
"490090389328944075868508455133942304583236903222948165808559"
|
||||
"332123348274797826204144723168738177180919299881250404026184"
|
||||
"1248583680+309;"},
|
||||
{"(ES317.310,';')",
|
||||
" 1."
|
||||
"797693134862315708145274237317043567980705675258449965989174"
|
||||
"768031572607800285387605895586327668781715404589535143824642"
|
||||
"343213268894641827684675467035375169860499105765512820762454"
|
||||
"900903893289440758685084551339423045832369032229481658085593"
|
||||
"321233482747978262041447231687381771809192998812504040261841"
|
||||
"2485836800+308;"},
|
||||
{"(EN319.310,';')",
|
||||
" 179."
|
||||
"769313486231570814527423731704356798070567525844996598917476"
|
||||
"803157260780028538760589558632766878171540458953514382464234"
|
||||
"321326889464182768467546703537516986049910576551282076245490"
|
||||
"090389328944075868508455133942304583236903222948165808559332"
|
||||
"123348274797826204144723168738177180919299881250404026184124"
|
||||
"8583680000+306;"},
|
||||
{"(G0,';')", ".17976931348623157+309;"},
|
||||
}},
|
||||
};
|
||||
|
||||
for (auto const &[value, cases] : testCases) {
|
||||
for (auto const &[format, expect] : cases) {
|
||||
ASSERT_TRUE(CompareFormatReal(format, value, expect))
|
||||
<< "Failed to format " << format << ", expected " << expect;
|
||||
}
|
||||
}
|
||||
|
||||
using IndividualTestCaseTy = std::tuple<const char *, double, const char *>;
|
||||
static std::vector<IndividualTestCaseTy> individualTestCases{
|
||||
{"(F5.3,';')", 25., "*****;"},
|
||||
{"(F5.3,';')", 2.5, "2.500;"},
|
||||
{"(F5.3,';')", 0.25, "0.250;"},
|
||||
{"(F5.3,';')", 0.025, "0.025;"},
|
||||
{"(F5.3,';')", 0.0025, "0.003;"},
|
||||
{"(F5.3,';')", 0.00025, "0.000;"},
|
||||
{"(F5.3,';')", 0.000025, "0.000;"},
|
||||
{"(F5.3,';')", -25., "*****;"},
|
||||
{"(F5.3,';')", -2.5, "*****;"},
|
||||
{"(F5.3,';')", -0.25, "-.250;"},
|
||||
{"(F5.3,';')", -0.025, "-.025;"},
|
||||
{"(F5.3,';')", -0.0025, "-.003;"},
|
||||
{"(F5.3,';')", -0.00025, "-.000;"},
|
||||
{"(F5.3,';')", -0.000025, "-.000;"},
|
||||
};
|
||||
|
||||
for (auto const &[format, value, expect] : individualTestCases) {
|
||||
ASSERT_TRUE(CompareFormatReal(format, value, expect))
|
||||
<< "Failed to format " << format << ", expected " << expect;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Tests for input formatting real values
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Ensure double input values correctly map to raw uint64 values
|
||||
TEST(IOApiTests, FormatDoubleInputValues) {
|
||||
using TestCaseTy = std::tuple<const char *, const char *, std::uint64_t>;
|
||||
static std::vector<TestCaseTy> testCases{
|
||||
{"(F18.0)", " 0", 0x0},
|
||||
{"(F18.0)", " ", 0x0},
|
||||
{"(F18.0)", " -0", 0x8000000000000000},
|
||||
{"(F18.0)", " 01", 0x3ff0000000000000},
|
||||
{"(F18.0)", " 1", 0x3ff0000000000000},
|
||||
{"(F18.0)", " 125.", 0x405f400000000000},
|
||||
{"(F18.0)", " 12.5", 0x4029000000000000},
|
||||
{"(F18.0)", " 1.25", 0x3ff4000000000000},
|
||||
{"(F18.0)", " 01.25", 0x3ff4000000000000},
|
||||
{"(F18.0)", " .125", 0x3fc0000000000000},
|
||||
{"(F18.0)", " 0.125", 0x3fc0000000000000},
|
||||
{"(F18.0)", " .0625", 0x3fb0000000000000},
|
||||
{"(F18.0)", " 0.0625", 0x3fb0000000000000},
|
||||
{"(F18.0)", " 125", 0x405f400000000000},
|
||||
{"(F18.1)", " 125", 0x4029000000000000},
|
||||
{"(F18.2)", " 125", 0x3ff4000000000000},
|
||||
{"(F18.3)", " 125", 0x3fc0000000000000},
|
||||
{"(-1P,F18.0)", " 125", 0x4093880000000000}, // 1250
|
||||
{"(1P,F18.0)", " 125", 0x4029000000000000}, // 12.5
|
||||
{"(BZ,F18.0)", " 125 ", 0x4093880000000000}, // 1250
|
||||
{"(BZ,F18.0)", " 125 . e +1 ", 0x42a6bcc41e900000}, // 1.25e13
|
||||
{"(DC,F18.0)", " 12,5", 0x4029000000000000},
|
||||
};
|
||||
for (auto const &[format, data, want] : testCases) {
|
||||
auto *cookie{IONAME(BeginInternalFormattedInput)(
|
||||
data, std::strlen(data), format, std::strlen(format))};
|
||||
union {
|
||||
double x;
|
||||
std::uint64_t raw;
|
||||
} u;
|
||||
u.raw = 0;
|
||||
|
||||
// Read buffer into union value
|
||||
IONAME(EnableHandlers)(cookie, true, true, true, true, true);
|
||||
IONAME(InputReal64)(cookie, u.x);
|
||||
|
||||
static constexpr int bufferSize{65};
|
||||
static char iomsg[bufferSize];
|
||||
std::memset(iomsg, '\0', bufferSize - 1);
|
||||
|
||||
// Ensure no errors were encountered reading input buffer into union value
|
||||
IONAME(GetIoMsg)(cookie, iomsg, bufferSize - 1);
|
||||
static auto status{IONAME(EndIoStatement)(cookie)};
|
||||
ASSERT_EQ(status, 0) << '\'' << format << "' failed reading '" << data
|
||||
<< "', status " << static_cast<int>(status)
|
||||
<< " iomsg '" << iomsg << "'";
|
||||
|
||||
// Ensure raw uint64 value matches expected conversion from double
|
||||
ASSERT_EQ(u.raw, want) << '\'' << format << "' failed reading '" << data
|
||||
<< "', want 0x" << std::hex << want << ", got 0x"
|
||||
<< u.raw;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue