1ffc67bb3SDavid Spickett //===-- flang/unittests/RuntimeGTest/ExternalIOTest.cpp ---------*- C++ -*-===// 2ffc67bb3SDavid Spickett // 3ffc67bb3SDavid Spickett // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ffc67bb3SDavid Spickett // See https://llvm.org/LICENSE.txt for license information. 5ffc67bb3SDavid Spickett // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ffc67bb3SDavid Spickett // 7ffc67bb3SDavid Spickett //===----------------------------------------------------------------------===// 8ffc67bb3SDavid Spickett // 9ffc67bb3SDavid Spickett // Sanity test for all external I/O modes 10ffc67bb3SDavid Spickett // 11ffc67bb3SDavid Spickett //===----------------------------------------------------------------------===// 12ffc67bb3SDavid Spickett 13ffc67bb3SDavid Spickett #include "CrashHandlerFixture.h" 14ffc67bb3SDavid Spickett #include "gtest/gtest.h" 15ffc67bb3SDavid Spickett #include "flang/Runtime/descriptor.h" 16*c91ba043SMichael Kruse #include "flang/Runtime/io-api-consts.h" 17ffc67bb3SDavid Spickett #include "flang/Runtime/main.h" 18ffc67bb3SDavid Spickett #include "flang/Runtime/stop.h" 19ffc67bb3SDavid Spickett #include "llvm/Support/raw_ostream.h" 20ffc67bb3SDavid Spickett #include <cstring> 21ffc67bb3SDavid Spickett #include <string_view> 22ffc67bb3SDavid Spickett 23ffc67bb3SDavid Spickett using namespace Fortran::runtime; 24ffc67bb3SDavid Spickett using namespace Fortran::runtime::io; 25ffc67bb3SDavid Spickett 26ffc67bb3SDavid Spickett struct ExternalIOTests : public CrashHandlerFixture {}; 27ffc67bb3SDavid Spickett 28ffc67bb3SDavid Spickett TEST(ExternalIOTests, TestDirectUnformatted) { 29ffc67bb3SDavid Spickett // OPEN(NEWUNIT=unit,ACCESS='DIRECT',ACTION='READWRITE',& 30ffc67bb3SDavid Spickett // FORM='UNFORMATTED',RECL=8,STATUS='SCRATCH') 31ffc67bb3SDavid Spickett Cookie io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)}; 32ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAccess)(io, "DIRECT", 6)) << "SetAccess(DIRECT)"; 33ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)"; 34ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetForm)(io, "UNFORMATTED", 11)) << "SetForm(UNFORMATTED)"; 35ffc67bb3SDavid Spickett 36ffc67bb3SDavid Spickett std::int64_t buffer; 37ffc67bb3SDavid Spickett static constexpr std::size_t recl{sizeof buffer}; 38ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetRecl)(io, recl)) << "SetRecl()"; 39ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)"; 40ffc67bb3SDavid Spickett 41ffc67bb3SDavid Spickett int unit{-1}; 42ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()"; 43ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 44ffc67bb3SDavid Spickett << "EndIoStatement() for OpenNewUnit"; 45ffc67bb3SDavid Spickett 468cf6e940Skkwli StaticDescriptor<0> staticDescriptor; 478cf6e940Skkwli Descriptor &desc{staticDescriptor.descriptor()}; 488cf6e940Skkwli desc.Establish(TypeCode{CFI_type_int8_t}, recl, &buffer, 0); 498cf6e940Skkwli desc.Check(); 508cf6e940Skkwli 51ffc67bb3SDavid Spickett // INQUIRE(IOLENGTH=) j 52ffc67bb3SDavid Spickett io = IONAME(BeginInquireIoLength)(__FILE__, __LINE__); 538cf6e940Skkwli ASSERT_TRUE(IONAME(OutputDescriptor)(io, desc)) 548cf6e940Skkwli << "OutputDescriptor() for InquireIoLength"; 55ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(GetIoLength)(io), recl) << "GetIoLength"; 56ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 57ffc67bb3SDavid Spickett << "EndIoStatement() for InquireIoLength"; 58ffc67bb3SDavid Spickett 59ffc67bb3SDavid Spickett static constexpr int records{10}; 60ffc67bb3SDavid Spickett for (int j{1}; j <= records; ++j) { 61ffc67bb3SDavid Spickett // WRITE(UNIT=unit,REC=j) j 62ffc67bb3SDavid Spickett io = IONAME(BeginUnformattedOutput)(unit, __FILE__, __LINE__); 63ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')'; 64ffc67bb3SDavid Spickett 65ffc67bb3SDavid Spickett buffer = j; 668cf6e940Skkwli ASSERT_TRUE(IONAME(OutputDescriptor)(io, desc)) 678cf6e940Skkwli << "OutputDescriptor() for Write"; 68ffc67bb3SDavid Spickett 69ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 708cf6e940Skkwli << "EndIoStatement() for Write"; 71ffc67bb3SDavid Spickett } 72ffc67bb3SDavid Spickett 73ffc67bb3SDavid Spickett for (int j{records}; j >= 1; --j) { 748cf6e940Skkwli buffer = -1; 75ffc67bb3SDavid Spickett // READ(UNIT=unit,REC=j) n 76ffc67bb3SDavid Spickett io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__); 77ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')'; 788cf6e940Skkwli ASSERT_TRUE(IONAME(InputDescriptor)(io, desc)) 798cf6e940Skkwli << "InputDescriptor() for Read"; 80ffc67bb3SDavid Spickett 81ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 828cf6e940Skkwli << "EndIoStatement() for Read"; 83ffc67bb3SDavid Spickett 84ffc67bb3SDavid Spickett ASSERT_EQ(buffer, j) << "Read back " << buffer 85ffc67bb3SDavid Spickett << " from direct unformatted record " << j 86ffc67bb3SDavid Spickett << ", expected " << j << '\n'; 87ffc67bb3SDavid Spickett } 88ffc67bb3SDavid Spickett // CLOSE(UNIT=unit,STATUS='DELETE') 89ffc67bb3SDavid Spickett io = IONAME(BeginClose)(unit, __FILE__, __LINE__); 90ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)"; 91ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 92ffc67bb3SDavid Spickett << "EndIoStatement() for Close"; 93ffc67bb3SDavid Spickett } 94ffc67bb3SDavid Spickett 95ffc67bb3SDavid Spickett TEST(ExternalIOTests, TestDirectUnformattedSwapped) { 96ffc67bb3SDavid Spickett // OPEN(NEWUNIT=unit,ACCESS='DIRECT',ACTION='READWRITE',& 97ffc67bb3SDavid Spickett // FORM='UNFORMATTED',RECL=8,STATUS='SCRATCH',CONVERT='NATIVE') 98ffc67bb3SDavid Spickett auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)}; 99ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAccess)(io, "DIRECT", 6)) << "SetAccess(DIRECT)"; 100ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)"; 101ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetForm)(io, "UNFORMATTED", 11)) << "SetForm(UNFORMATTED)"; 102ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetConvert)(io, "NATIVE", 6)) << "SetConvert(NATIVE)"; 103ffc67bb3SDavid Spickett 104ffc67bb3SDavid Spickett std::int64_t buffer; 105ffc67bb3SDavid Spickett static constexpr std::size_t recl{sizeof buffer}; 106ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetRecl)(io, recl)) << "SetRecl()"; 107ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)"; 108ffc67bb3SDavid Spickett 109ffc67bb3SDavid Spickett int unit{-1}; 110ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()"; 111ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 112ffc67bb3SDavid Spickett << "EndIoStatement() for OpenNewUnit"; 113ffc67bb3SDavid Spickett 1148cf6e940Skkwli StaticDescriptor<0> staticDescriptor; 1158cf6e940Skkwli Descriptor &desc{staticDescriptor.descriptor()}; 1168cf6e940Skkwli desc.Establish(TypeCode{CFI_type_int64_t}, recl, &buffer, 0); 1178cf6e940Skkwli desc.Check(); 1188cf6e940Skkwli 119ffc67bb3SDavid Spickett static constexpr int records{10}; 120ffc67bb3SDavid Spickett for (int j{1}; j <= records; ++j) { 121ffc67bb3SDavid Spickett // WRITE(UNIT=unit,REC=j) j 122ffc67bb3SDavid Spickett io = IONAME(BeginUnformattedOutput)(unit, __FILE__, __LINE__); 123ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')'; 124ffc67bb3SDavid Spickett buffer = j; 1258cf6e940Skkwli ASSERT_TRUE(IONAME(OutputDescriptor)(io, desc)) 1268cf6e940Skkwli << "OutputDescriptor() for Write"; 127ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 1288cf6e940Skkwli << "EndIoStatement() for Write"; 129ffc67bb3SDavid Spickett } 130ffc67bb3SDavid Spickett 131ffc67bb3SDavid Spickett // OPEN(UNIT=unit,STATUS='OLD',CONVERT='SWAP') 132ffc67bb3SDavid Spickett io = IONAME(BeginOpenUnit)(unit, __FILE__, __LINE__); 133ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "OLD", 3)) << "SetStatus(OLD)"; 134ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetConvert)(io, "SWAP", 4)) << "SetConvert(SWAP)"; 135ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 136ffc67bb3SDavid Spickett << "EndIoStatement() for OpenUnit"; 137ffc67bb3SDavid Spickett 138ffc67bb3SDavid Spickett for (int j{records}; j >= 1; --j) { 139ffc67bb3SDavid Spickett // READ(UNIT=unit,REC=j) n 140ffc67bb3SDavid Spickett io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__); 141ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')'; 1428cf6e940Skkwli ASSERT_TRUE(IONAME(InputDescriptor)(io, desc)) 1438cf6e940Skkwli << "InputDescriptor() for Read"; 144ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 1458cf6e940Skkwli << "EndIoStatement() for Read"; 146ffc67bb3SDavid Spickett ASSERT_EQ(buffer >> 56, j) 147ffc67bb3SDavid Spickett << "Read back " << (buffer >> 56) << " from direct unformatted record " 148ffc67bb3SDavid Spickett << j << ", expected " << j << '\n'; 149ffc67bb3SDavid Spickett } 150ffc67bb3SDavid Spickett 151ffc67bb3SDavid Spickett // CLOSE(UNIT=unit,STATUS='DELETE') 152ffc67bb3SDavid Spickett io = IONAME(BeginClose)(unit, __FILE__, __LINE__); 153ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)"; 154ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 155ffc67bb3SDavid Spickett << "EndIoStatement() for Close"; 156ffc67bb3SDavid Spickett } 157ffc67bb3SDavid Spickett 158ffc67bb3SDavid Spickett TEST(ExternalIOTests, TestSequentialFixedUnformatted) { 159ffc67bb3SDavid Spickett // OPEN(NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',& 160ffc67bb3SDavid Spickett // FORM='UNFORMATTED',RECL=8,STATUS='SCRATCH') 161ffc67bb3SDavid Spickett auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)}; 162ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAccess)(io, "SEQUENTIAL", 10)) 163ffc67bb3SDavid Spickett << "SetAccess(SEQUENTIAL)"; 164ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)"; 165ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetForm)(io, "UNFORMATTED", 11)) << "SetForm(UNFORMATTED)"; 166ffc67bb3SDavid Spickett 167ffc67bb3SDavid Spickett std::int64_t buffer; 168ffc67bb3SDavid Spickett static constexpr std::size_t recl{sizeof buffer}; 169ffc67bb3SDavid Spickett 170ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetRecl)(io, recl)) << "SetRecl()"; 171ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)"; 172ffc67bb3SDavid Spickett 173ffc67bb3SDavid Spickett int unit{-1}; 174ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()"; 175ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 176ffc67bb3SDavid Spickett << "EndIoStatement() for OpenNewUnit"; 177ffc67bb3SDavid Spickett 178ffc67bb3SDavid Spickett // INQUIRE(IOLENGTH=) j, ... 179ffc67bb3SDavid Spickett StaticDescriptor<0> staticDescriptor; 180ffc67bb3SDavid Spickett Descriptor &desc{staticDescriptor.descriptor()}; 181ffc67bb3SDavid Spickett desc.Establish(TypeCode{CFI_type_int64_t}, recl, &buffer, 0); 182ffc67bb3SDavid Spickett desc.Dump(stderr); 183ffc67bb3SDavid Spickett desc.Check(); 184ffc67bb3SDavid Spickett io = IONAME(BeginInquireIoLength)(__FILE__, __LINE__); 185ffc67bb3SDavid Spickett for (int j{1}; j <= 3; ++j) { 186ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(OutputDescriptor)(io, desc)) 187ffc67bb3SDavid Spickett << "OutputDescriptor() for InquireIoLength"; 188ffc67bb3SDavid Spickett } 189ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(GetIoLength)(io), 3 * recl) << "GetIoLength"; 190ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 191ffc67bb3SDavid Spickett << "EndIoStatement() for InquireIoLength"; 192ffc67bb3SDavid Spickett 193ffc67bb3SDavid Spickett static const int records{10}; 194ffc67bb3SDavid Spickett for (int j{1}; j <= records; ++j) { 195ffc67bb3SDavid Spickett // DO J=1,RECORDS; WRITE(UNIT=unit) j; END DO 196ffc67bb3SDavid Spickett io = IONAME(BeginUnformattedOutput)(unit, __FILE__, __LINE__); 197ffc67bb3SDavid Spickett buffer = j; 1988cf6e940Skkwli ASSERT_TRUE(IONAME(OutputDescriptor)(io, desc)) 1998cf6e940Skkwli << "OutputDescriptor() for Write"; 200ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 2018cf6e940Skkwli << "EndIoStatement() for WRITE"; 202ffc67bb3SDavid Spickett } 203ffc67bb3SDavid Spickett 204ffc67bb3SDavid Spickett // REWIND(UNIT=unit) 205ffc67bb3SDavid Spickett io = IONAME(BeginRewind)(unit, __FILE__, __LINE__); 206ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 207ffc67bb3SDavid Spickett << "EndIoStatement() for Rewind"; 208ffc67bb3SDavid Spickett 209ffc67bb3SDavid Spickett for (int j{1}; j <= records; ++j) { 210ffc67bb3SDavid Spickett // DO J=1,RECORDS; READ(UNIT=unit) n; check n; END DO 211ffc67bb3SDavid Spickett io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__); 2128cf6e940Skkwli ASSERT_TRUE(IONAME(InputDescriptor)(io, desc)) 2138cf6e940Skkwli << "InputDescriptor() for Read"; 214ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 2158cf6e940Skkwli << "EndIoStatement() for Read"; 216ffc67bb3SDavid Spickett ASSERT_EQ(buffer, j) << "Read back " << buffer 217ffc67bb3SDavid Spickett << " from sequential fixed unformatted record " << j 218ffc67bb3SDavid Spickett << ", expected " << j << '\n'; 219ffc67bb3SDavid Spickett } 220ffc67bb3SDavid Spickett 221ffc67bb3SDavid Spickett for (int j{records}; j >= 1; --j) { 222ffc67bb3SDavid Spickett // BACKSPACE(UNIT=unit) 223ffc67bb3SDavid Spickett io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__); 224ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 225ffc67bb3SDavid Spickett << "EndIoStatement() for Backspace (before read)"; 226ffc67bb3SDavid Spickett // READ(UNIT=unit) n 227ffc67bb3SDavid Spickett io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__); 2288cf6e940Skkwli ASSERT_TRUE(IONAME(InputDescriptor)(io, desc)) 2298cf6e940Skkwli << "InputDescriptor() for Read"; 230ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 2318cf6e940Skkwli << "EndIoStatement() for Read"; 232ffc67bb3SDavid Spickett ASSERT_EQ(buffer, j) << "Read back " << buffer 233ffc67bb3SDavid Spickett << " from sequential fixed unformatted record " << j 234ffc67bb3SDavid Spickett << " after backspacing, expected " << j << '\n'; 235ffc67bb3SDavid Spickett // BACKSPACE(UNIT=unit) 236ffc67bb3SDavid Spickett io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__); 237ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 238ffc67bb3SDavid Spickett << "EndIoStatement() for Backspace (after read)"; 239ffc67bb3SDavid Spickett } 240ffc67bb3SDavid Spickett 241ffc67bb3SDavid Spickett // CLOSE(UNIT=unit,STATUS='DELETE') 242ffc67bb3SDavid Spickett io = IONAME(BeginClose)(unit, __FILE__, __LINE__); 243ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)"; 244ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 245ffc67bb3SDavid Spickett << "EndIoStatement() for Close"; 246ffc67bb3SDavid Spickett } 247ffc67bb3SDavid Spickett 248ffc67bb3SDavid Spickett TEST(ExternalIOTests, TestSequentialVariableUnformatted) { 249ffc67bb3SDavid Spickett // OPEN(NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',& 250ffc67bb3SDavid Spickett // FORM='UNFORMATTED',STATUS='SCRATCH') 251ffc67bb3SDavid Spickett auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)}; 252ffc67bb3SDavid Spickett 253ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAccess)(io, "SEQUENTIAL", 10)) 254ffc67bb3SDavid Spickett << "SetAccess(SEQUENTIAL)"; 255ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)"; 256ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetForm)(io, "UNFORMATTED", 11)) << "SetForm(UNFORMATTED)"; 257ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)"; 258ffc67bb3SDavid Spickett 259ffc67bb3SDavid Spickett int unit{-1}; 260ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()"; 261ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 262ffc67bb3SDavid Spickett << "EndIoStatement() for OpenNewUnit"; 263ffc67bb3SDavid Spickett 264ffc67bb3SDavid Spickett static const int records{10}; 265ffc67bb3SDavid Spickett std::int64_t buffer[records]; // INTEGER*8 :: BUFFER(0:9) = [(j,j=0,9)] 266ffc67bb3SDavid Spickett for (int j{0}; j < records; ++j) { 267ffc67bb3SDavid Spickett buffer[j] = j; 268ffc67bb3SDavid Spickett } 269ffc67bb3SDavid Spickett 2708cf6e940Skkwli StaticDescriptor<0> staticDescriptor; 2718cf6e940Skkwli Descriptor &desc{staticDescriptor.descriptor()}; 2728cf6e940Skkwli 273ffc67bb3SDavid Spickett for (int j{1}; j <= records; ++j) { 274ffc67bb3SDavid Spickett // DO J=1,RECORDS; WRITE(UNIT=unit) BUFFER(0:j); END DO 275ffc67bb3SDavid Spickett io = IONAME(BeginUnformattedOutput)(unit, __FILE__, __LINE__); 2768cf6e940Skkwli desc.Establish(TypeCode{sizeof *buffer}, j * sizeof *buffer, buffer, 0); 2778cf6e940Skkwli desc.Check(); 2788cf6e940Skkwli ASSERT_TRUE(IONAME(OutputDescriptor)(io, desc)) 2798cf6e940Skkwli << "OutputDescriptor() for Write"; 280ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 2818cf6e940Skkwli << "EndIoStatement() for Write"; 282ffc67bb3SDavid Spickett } 283ffc67bb3SDavid Spickett 284ffc67bb3SDavid Spickett // REWIND(UNIT=unit) 285ffc67bb3SDavid Spickett io = IONAME(BeginRewind)(unit, __FILE__, __LINE__); 286ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 287ffc67bb3SDavid Spickett << "EndIoStatement() for Rewind"; 288ffc67bb3SDavid Spickett for (int j{1}; j <= records; ++j) { 289ffc67bb3SDavid Spickett // DO J=1,RECORDS; READ(UNIT=unit) n; check n; END DO 290ffc67bb3SDavid Spickett io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__); 2918cf6e940Skkwli desc.Establish(TypeCode{sizeof *buffer}, j * sizeof *buffer, buffer, 0); 2928cf6e940Skkwli desc.Check(); 2938cf6e940Skkwli ASSERT_TRUE(IONAME(InputDescriptor)(io, desc)) 2948cf6e940Skkwli << "InputDescriptor() for Read"; 295ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 2968cf6e940Skkwli << "EndIoStatement() for Read"; 297ffc67bb3SDavid Spickett for (int k{0}; k < j; ++k) { 298ffc67bb3SDavid Spickett ASSERT_EQ(buffer[k], k) << "Read back [" << k << "]=" << buffer[k] 299ffc67bb3SDavid Spickett << " from direct unformatted record " << j 300ffc67bb3SDavid Spickett << ", expected " << k << '\n'; 301ffc67bb3SDavid Spickett } 302ffc67bb3SDavid Spickett } 303ffc67bb3SDavid Spickett 304ffc67bb3SDavid Spickett for (int j{records}; j >= 1; --j) { 305ffc67bb3SDavid Spickett // BACKSPACE(unit) 306ffc67bb3SDavid Spickett io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__); 307ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 308ffc67bb3SDavid Spickett << "EndIoStatement() for Backspace (before read)"; 309ffc67bb3SDavid Spickett // READ(unit=unit) n; check 310ffc67bb3SDavid Spickett io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__); 3118cf6e940Skkwli desc.Establish(TypeCode{sizeof *buffer}, j * sizeof *buffer, buffer, 0); 3128cf6e940Skkwli desc.Check(); 3138cf6e940Skkwli ASSERT_TRUE(IONAME(InputDescriptor)(io, desc)) << "InputDescriptor()"; 314ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 315ffc67bb3SDavid Spickett << "EndIoStatement() for InputUnformattedBlock"; 316ffc67bb3SDavid Spickett for (int k{0}; k < j; ++k) { 317ffc67bb3SDavid Spickett ASSERT_EQ(buffer[k], k) << "Read back [" << k << "]=" << buffer[k] 318ffc67bb3SDavid Spickett << " from sequential variable unformatted record " 319ffc67bb3SDavid Spickett << j << ", expected " << k << '\n'; 320ffc67bb3SDavid Spickett } 321ffc67bb3SDavid Spickett // BACKSPACE(unit) 322ffc67bb3SDavid Spickett io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__); 323ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 324ffc67bb3SDavid Spickett << "EndIoStatement() for Backspace (after read)"; 325ffc67bb3SDavid Spickett } 326ffc67bb3SDavid Spickett 327ffc67bb3SDavid Spickett // CLOSE(UNIT=unit,STATUS='DELETE') 328ffc67bb3SDavid Spickett io = IONAME(BeginClose)(unit, __FILE__, __LINE__); 329ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)"; 330ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 331ffc67bb3SDavid Spickett << "EndIoStatement() for Close"; 332ffc67bb3SDavid Spickett } 333ffc67bb3SDavid Spickett 334ffc67bb3SDavid Spickett TEST(ExternalIOTests, TestDirectFormatted) { 335ffc67bb3SDavid Spickett // OPEN(NEWUNIT=unit,ACCESS='DIRECT',ACTION='READWRITE',& 336ffc67bb3SDavid Spickett // FORM='FORMATTED',RECL=8,STATUS='SCRATCH') 337ffc67bb3SDavid Spickett auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)}; 338ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAccess)(io, "DIRECT", 6)) << "SetAccess(DIRECT)"; 339ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)"; 340ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetForm)(io, "FORMATTED", 9)) << "SetForm(FORMATTED)"; 341ffc67bb3SDavid Spickett 342ffc67bb3SDavid Spickett static constexpr std::size_t recl{8}; 343ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetRecl)(io, recl)) << "SetRecl()"; 344ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)"; 345ffc67bb3SDavid Spickett 346ffc67bb3SDavid Spickett int unit{-1}; 347ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()"; 348ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 349ffc67bb3SDavid Spickett << "EndIoStatement() for OpenNewUnit"; 350ffc67bb3SDavid Spickett 351ffc67bb3SDavid Spickett static constexpr int records{10}; 352ffc67bb3SDavid Spickett static const char fmt[]{"(I4)"}; 353ffc67bb3SDavid Spickett for (int j{1}; j <= records; ++j) { 354ffc67bb3SDavid Spickett // WRITE(UNIT=unit,FMT=fmt,REC=j) j 355ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedOutput)( 356ffc67bb3SDavid Spickett fmt, sizeof fmt - 1, nullptr, unit, __FILE__, __LINE__); 357ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')'; 358ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(OutputInteger64)(io, j)) << "OutputInteger64()"; 359ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 360ffc67bb3SDavid Spickett << "EndIoStatement() for OutputInteger64"; 361ffc67bb3SDavid Spickett } 362ffc67bb3SDavid Spickett 363ffc67bb3SDavid Spickett for (int j{records}; j >= 1; --j) { 364ffc67bb3SDavid Spickett // READ(UNIT=unit,FMT=fmt,REC=j) n 365ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedInput)( 366ffc67bb3SDavid Spickett fmt, sizeof fmt - 1, nullptr, unit, __FILE__, __LINE__); 367ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')'; 368ffc67bb3SDavid Spickett std::int64_t buffer; 369ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(InputInteger)(io, buffer)) << "InputInteger()"; 370ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 371ffc67bb3SDavid Spickett << "EndIoStatement() for InputInteger"; 372ffc67bb3SDavid Spickett 373ffc67bb3SDavid Spickett ASSERT_EQ(buffer, j) << "Read back " << buffer 374ffc67bb3SDavid Spickett << " from direct formatted record " << j 375ffc67bb3SDavid Spickett << ", expected " << j << '\n'; 376ffc67bb3SDavid Spickett } 377ffc67bb3SDavid Spickett 378ffc67bb3SDavid Spickett // CLOSE(UNIT=unit,STATUS='DELETE') 379ffc67bb3SDavid Spickett io = IONAME(BeginClose)(unit, __FILE__, __LINE__); 380ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)"; 381ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 382ffc67bb3SDavid Spickett << "EndIoStatement() for Close"; 383ffc67bb3SDavid Spickett } 384ffc67bb3SDavid Spickett 385ffc67bb3SDavid Spickett TEST(ExternalIOTests, TestSequentialVariableFormatted) { 386ffc67bb3SDavid Spickett // OPEN(NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',& 387ffc67bb3SDavid Spickett // FORM='FORMATTED',STATUS='SCRATCH') 388ffc67bb3SDavid Spickett auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)}; 389ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAccess)(io, "SEQUENTIAL", 10)) 390ffc67bb3SDavid Spickett << "SetAccess(SEQUENTIAL)"; 391ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)"; 392ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetForm)(io, "FORMATTED", 9)) << "SetForm(FORMATTED)"; 393ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)"; 394ffc67bb3SDavid Spickett 395ffc67bb3SDavid Spickett int unit{-1}; 396ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()"; 397ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 398ffc67bb3SDavid Spickett << "EndIoStatement() for OpenNewUnit"; 399ffc67bb3SDavid Spickett 400ffc67bb3SDavid Spickett static const int records{10}; 401ffc67bb3SDavid Spickett std::int64_t buffer[records]; // INTEGER*8 :: BUFFER(0:9) = [(j,j=0,9)] 402ffc67bb3SDavid Spickett for (int j{0}; j < records; ++j) { 403ffc67bb3SDavid Spickett buffer[j] = j; 404ffc67bb3SDavid Spickett } 405ffc67bb3SDavid Spickett 406ffc67bb3SDavid Spickett char fmt[32]; 407ffc67bb3SDavid Spickett for (int j{1}; j <= records; ++j) { 408ffc67bb3SDavid Spickett std::snprintf(fmt, sizeof fmt, "(%dI4)", j); 409ffc67bb3SDavid Spickett // DO J=1,RECORDS; WRITE(UNIT=unit,FMT=fmt) BUFFER(0:j); END DO 410ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedOutput)( 411ffc67bb3SDavid Spickett fmt, std::strlen(fmt), nullptr, unit, __FILE__, __LINE__); 412ffc67bb3SDavid Spickett for (int k{0}; k < j; ++k) { 413ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(OutputInteger64)(io, buffer[k])) 414ffc67bb3SDavid Spickett << "OutputInteger64()"; 415ffc67bb3SDavid Spickett } 416ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 417ffc67bb3SDavid Spickett << "EndIoStatement() for OutputInteger64"; 418ffc67bb3SDavid Spickett } 419ffc67bb3SDavid Spickett 420ffc67bb3SDavid Spickett // REWIND(UNIT=unit) 421ffc67bb3SDavid Spickett io = IONAME(BeginRewind)(unit, __FILE__, __LINE__); 422ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 423ffc67bb3SDavid Spickett << "EndIoStatement() for Rewind"; 424ffc67bb3SDavid Spickett 425ffc67bb3SDavid Spickett for (int j{1}; j <= records; ++j) { 426ffc67bb3SDavid Spickett std::snprintf(fmt, sizeof fmt, "(%dI4)", j); 427ffc67bb3SDavid Spickett // DO J=1,RECORDS; READ(UNIT=unit,FMT=fmt) n; check n; END DO 428ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedInput)( 429ffc67bb3SDavid Spickett fmt, std::strlen(fmt), nullptr, unit, __FILE__, __LINE__); 430ffc67bb3SDavid Spickett 431ffc67bb3SDavid Spickett std::int64_t check[records]; 432ffc67bb3SDavid Spickett for (int k{0}; k < j; ++k) { 433ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(InputInteger)(io, check[k])) << "InputInteger()"; 434ffc67bb3SDavid Spickett } 435ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 436ffc67bb3SDavid Spickett << "EndIoStatement() for InputInteger"; 437ffc67bb3SDavid Spickett 438ffc67bb3SDavid Spickett for (int k{0}; k < j; ++k) { 439ffc67bb3SDavid Spickett ASSERT_EQ(buffer[k], check[k]) 440ffc67bb3SDavid Spickett << "Read back [" << k << "]=" << check[k] 441ffc67bb3SDavid Spickett << " from sequential variable formatted record " << j << ", expected " 442ffc67bb3SDavid Spickett << buffer[k] << '\n'; 443ffc67bb3SDavid Spickett } 444ffc67bb3SDavid Spickett } 445ffc67bb3SDavid Spickett 446ffc67bb3SDavid Spickett for (int j{records}; j >= 1; --j) { 447ffc67bb3SDavid Spickett // BACKSPACE(unit) 448ffc67bb3SDavid Spickett io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__); 449ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 450ffc67bb3SDavid Spickett << "EndIoStatement() for Backspace (before read)"; 451ffc67bb3SDavid Spickett 452ffc67bb3SDavid Spickett std::snprintf(fmt, sizeof fmt, "(%dI4)", j); 453ffc67bb3SDavid Spickett // READ(UNIT=unit,FMT=fmt,SIZE=chars) n; check 454ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedInput)( 455ffc67bb3SDavid Spickett fmt, std::strlen(fmt), nullptr, unit, __FILE__, __LINE__); 456ffc67bb3SDavid Spickett 457ffc67bb3SDavid Spickett std::int64_t check[records]; 458ffc67bb3SDavid Spickett for (int k{0}; k < j; ++k) { 459ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(InputInteger)(io, check[k])) << "InputInteger()"; 460ffc67bb3SDavid Spickett } 461ffc67bb3SDavid Spickett 462ffc67bb3SDavid Spickett std::size_t chars{IONAME(GetSize)(io)}; 463ffc67bb3SDavid Spickett ASSERT_EQ(chars, j * 4u) 464ffc67bb3SDavid Spickett << "GetSize()=" << chars << ", expected " << (j * 4u) << '\n'; 465ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 466ffc67bb3SDavid Spickett << "EndIoStatement() for InputInteger"; 467ffc67bb3SDavid Spickett for (int k{0}; k < j; ++k) { 468ffc67bb3SDavid Spickett ASSERT_EQ(buffer[k], check[k]) 469ffc67bb3SDavid Spickett << "Read back [" << k << "]=" << buffer[k] 470ffc67bb3SDavid Spickett << " from sequential variable formatted record " << j << ", expected " 471ffc67bb3SDavid Spickett << buffer[k] << '\n'; 472ffc67bb3SDavid Spickett } 473ffc67bb3SDavid Spickett 474ffc67bb3SDavid Spickett // BACKSPACE(unit) 475ffc67bb3SDavid Spickett io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__); 476ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 477ffc67bb3SDavid Spickett << "EndIoStatement() for Backspace (after read)"; 478ffc67bb3SDavid Spickett } 479ffc67bb3SDavid Spickett 480ffc67bb3SDavid Spickett // CLOSE(UNIT=unit,STATUS='DELETE') 481ffc67bb3SDavid Spickett io = IONAME(BeginClose)(unit, __FILE__, __LINE__); 482ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)"; 483ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 484ffc67bb3SDavid Spickett << "EndIoStatement() for Close"; 485ffc67bb3SDavid Spickett } 486ffc67bb3SDavid Spickett 487ffc67bb3SDavid Spickett TEST(ExternalIOTests, TestNonAvancingInput) { 488ffc67bb3SDavid Spickett // OPEN(NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',& 489ffc67bb3SDavid Spickett // FORM='FORMATTED',STATUS='SCRATCH') 490ffc67bb3SDavid Spickett auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)}; 491ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAccess)(io, "SEQUENTIAL", 10)) 492ffc67bb3SDavid Spickett << "SetAccess(SEQUENTIAL)"; 493ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)"; 494ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetForm)(io, "FORMATTED", 9)) << "SetForm(FORMATTED)"; 495ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)"; 496ffc67bb3SDavid Spickett 497ffc67bb3SDavid Spickett int unit{-1}; 498ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()"; 499ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 500ffc67bb3SDavid Spickett << "EndIoStatement() for OpenNewUnit"; 501ffc67bb3SDavid Spickett 502ffc67bb3SDavid Spickett // Write the file to be used for the input test. 503ffc67bb3SDavid Spickett static constexpr std::string_view records[] = { 504ffc67bb3SDavid Spickett "ABCDEFGH", "IJKLMNOP", "QRSTUVWX"}; 505ffc67bb3SDavid Spickett static constexpr std::string_view fmt{"(A)"}; 506ffc67bb3SDavid Spickett for (const auto &record : records) { 507ffc67bb3SDavid Spickett // WRITE(UNIT=unit,FMT=fmt) record 508ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedOutput)( 509ffc67bb3SDavid Spickett fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__); 510ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(OutputAscii)(io, record.data(), record.length())) 511ffc67bb3SDavid Spickett << "OutputAscii()"; 512ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 513ffc67bb3SDavid Spickett << "EndIoStatement() for OutputAscii"; 514ffc67bb3SDavid Spickett } 515ffc67bb3SDavid Spickett 516ffc67bb3SDavid Spickett // REWIND(UNIT=unit) 517ffc67bb3SDavid Spickett io = IONAME(BeginRewind)(unit, __FILE__, __LINE__); 518ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 519ffc67bb3SDavid Spickett << "EndIoStatement() for Rewind"; 520ffc67bb3SDavid Spickett 521ffc67bb3SDavid Spickett struct TestItems { 522ffc67bb3SDavid Spickett std::string item; 523ffc67bb3SDavid Spickett int expectedIoStat; 524ffc67bb3SDavid Spickett std::string expectedItemValue[2]; 525ffc67bb3SDavid Spickett }; 526ffc67bb3SDavid Spickett // Actual non advancing input IO test 527ffc67bb3SDavid Spickett TestItems inputItems[]{ 528ffc67bb3SDavid Spickett {std::string(4, '+'), IostatOk, {"ABCD", "ABCD"}}, 529ffc67bb3SDavid Spickett {std::string(4, '+'), IostatOk, {"EFGH", "EFGH"}}, 530ffc67bb3SDavid Spickett {std::string(4, '+'), IostatEor, {"++++", " "}}, 531ffc67bb3SDavid Spickett {std::string(2, '+'), IostatOk, {"IJ", "IJ"}}, 532ffc67bb3SDavid Spickett {std::string(8, '+'), IostatEor, {"++++++++", "KLMNOP "}}, 533ffc67bb3SDavid Spickett {std::string(10, '+'), IostatEor, {"++++++++++", "QRSTUVWX "}}, 534ffc67bb3SDavid Spickett }; 535ffc67bb3SDavid Spickett 536ffc67bb3SDavid Spickett // Test with PAD='NO' 537ffc67bb3SDavid Spickett int j{0}; 538ffc67bb3SDavid Spickett for (auto &inputItem : inputItems) { 539ffc67bb3SDavid Spickett // READ(UNIT=unit, FMT=fmt, ADVANCE='NO', PAD='NO', IOSTAT=iostat) inputItem 540ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedInput)( 541ffc67bb3SDavid Spickett fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__); 542ffc67bb3SDavid Spickett IONAME(EnableHandlers)(io, true, false, false, false, false); 543ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAdvance)(io, "NO", 2)) << "SetAdvance(NO)" << j; 544ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetPad)(io, "NO", 2)) << "SetPad(NO)" << j; 545ffc67bb3SDavid Spickett bool result{ 546ffc67bb3SDavid Spickett IONAME(InputAscii)(io, inputItem.item.data(), inputItem.item.length())}; 547ffc67bb3SDavid Spickett ASSERT_EQ(result, inputItem.expectedIoStat == IostatOk) 548ffc67bb3SDavid Spickett << "InputAscii() " << j; 549ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), inputItem.expectedIoStat) 550ffc67bb3SDavid Spickett << "EndIoStatement() for Read " << j; 551ffc67bb3SDavid Spickett ASSERT_EQ(inputItem.item, inputItem.expectedItemValue[0]) 552ffc67bb3SDavid Spickett << "Input-item value after non advancing read " << j; 553ffc67bb3SDavid Spickett j++; 554ffc67bb3SDavid Spickett } 555ffc67bb3SDavid Spickett 556ffc67bb3SDavid Spickett // REWIND(UNIT=unit) 557ffc67bb3SDavid Spickett io = IONAME(BeginRewind)(unit, __FILE__, __LINE__); 558ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 559ffc67bb3SDavid Spickett << "EndIoStatement() for Rewind"; 560ffc67bb3SDavid Spickett 561ffc67bb3SDavid Spickett // Test again with PAD='YES' 562ffc67bb3SDavid Spickett j = 0; 563ffc67bb3SDavid Spickett for (auto &inputItem : inputItems) { 564ffc67bb3SDavid Spickett // READ(UNIT=unit, FMT=fmt, ADVANCE='NO', PAD='YES', IOSTAT=iostat) 565ffc67bb3SDavid Spickett // inputItem 566ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedInput)( 567ffc67bb3SDavid Spickett fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__); 568ffc67bb3SDavid Spickett IONAME(EnableHandlers)(io, true, false, false, false, false); 569ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAdvance)(io, "NO", 2)) << "SetAdvance(NO)" << j; 570ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetPad)(io, "YES", 3)) << "SetPad(YES)" << j; 571ffc67bb3SDavid Spickett bool result{ 572ffc67bb3SDavid Spickett IONAME(InputAscii)(io, inputItem.item.data(), inputItem.item.length())}; 573ffc67bb3SDavid Spickett ASSERT_EQ(result, inputItem.expectedIoStat == IostatOk) 574ffc67bb3SDavid Spickett << "InputAscii() " << j; 575ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), inputItem.expectedIoStat) 576ffc67bb3SDavid Spickett << "EndIoStatement() for Read " << j; 577ffc67bb3SDavid Spickett ASSERT_EQ(inputItem.item, inputItem.expectedItemValue[1]) 578ffc67bb3SDavid Spickett << "Input-item value after non advancing read " << j; 579ffc67bb3SDavid Spickett j++; 580ffc67bb3SDavid Spickett } 581ffc67bb3SDavid Spickett 582ffc67bb3SDavid Spickett // CLOSE(UNIT=unit) 583ffc67bb3SDavid Spickett io = IONAME(BeginClose)(unit, __FILE__, __LINE__); 584ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 585ffc67bb3SDavid Spickett << "EndIoStatement() for Close"; 586ffc67bb3SDavid Spickett } 587ffc67bb3SDavid Spickett 588ffc67bb3SDavid Spickett TEST(ExternalIOTests, TestWriteAfterNonAvancingInput) { 589ffc67bb3SDavid Spickett // OPEN(NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',& 590ffc67bb3SDavid Spickett // FORM='FORMATTED',STATUS='SCRATCH') 591ffc67bb3SDavid Spickett auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)}; 592ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAccess)(io, "SEQUENTIAL", 10)) 593ffc67bb3SDavid Spickett << "SetAccess(SEQUENTIAL)"; 594ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)"; 595ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetForm)(io, "FORMATTED", 9)) << "SetForm(FORMATTED)"; 596ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)"; 597ffc67bb3SDavid Spickett 598ffc67bb3SDavid Spickett int unit{-1}; 599ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()"; 600ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 601ffc67bb3SDavid Spickett << "EndIoStatement() for OpenNewUnit"; 602ffc67bb3SDavid Spickett 603ffc67bb3SDavid Spickett // Write the file to be used for the input test. 604ffc67bb3SDavid Spickett static constexpr std::string_view records[] = {"ABCDEFGHIJKLMNOPQRST"}; 605ffc67bb3SDavid Spickett static constexpr std::string_view fmt{"(A)"}; 606ffc67bb3SDavid Spickett for (const auto &record : records) { 607ffc67bb3SDavid Spickett // WRITE(UNIT=unit,FMT=fmt) record 608ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedOutput)( 609ffc67bb3SDavid Spickett fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__); 610ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(OutputAscii)(io, record.data(), record.length())) 611ffc67bb3SDavid Spickett << "OutputAscii()"; 612ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 613ffc67bb3SDavid Spickett << "EndIoStatement() for OutputAscii"; 614ffc67bb3SDavid Spickett } 615ffc67bb3SDavid Spickett 616ffc67bb3SDavid Spickett // REWIND(UNIT=unit) 617ffc67bb3SDavid Spickett io = IONAME(BeginRewind)(unit, __FILE__, __LINE__); 618ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 619ffc67bb3SDavid Spickett << "EndIoStatement() for Rewind"; 620ffc67bb3SDavid Spickett 621ffc67bb3SDavid Spickett struct TestItems { 622ffc67bb3SDavid Spickett std::string item; 623ffc67bb3SDavid Spickett int expectedIoStat; 624ffc67bb3SDavid Spickett std::string expectedItemValue; 625ffc67bb3SDavid Spickett }; 626ffc67bb3SDavid Spickett // Actual non advancing input IO test 627ffc67bb3SDavid Spickett TestItems inputItems[]{ 628ffc67bb3SDavid Spickett {std::string(4, '+'), IostatOk, "ABCD"}, 629ffc67bb3SDavid Spickett {std::string(4, '+'), IostatOk, "EFGH"}, 630ffc67bb3SDavid Spickett }; 631ffc67bb3SDavid Spickett 632ffc67bb3SDavid Spickett int j{0}; 633ffc67bb3SDavid Spickett for (auto &inputItem : inputItems) { 634ffc67bb3SDavid Spickett // READ(UNIT=unit, FMT=fmt, ADVANCE='NO', IOSTAT=iostat) inputItem 635ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedInput)( 636ffc67bb3SDavid Spickett fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__); 637ffc67bb3SDavid Spickett IONAME(EnableHandlers)(io, true, false, false, false, false); 638ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAdvance)(io, "NO", 2)) << "SetAdvance(NO)" << j; 639ffc67bb3SDavid Spickett ASSERT_TRUE( 640ffc67bb3SDavid Spickett IONAME(InputAscii)(io, inputItem.item.data(), inputItem.item.length())) 641ffc67bb3SDavid Spickett << "InputAscii() " << j; 642ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), inputItem.expectedIoStat) 643ffc67bb3SDavid Spickett << "EndIoStatement() for Read " << j; 644ffc67bb3SDavid Spickett ASSERT_EQ(inputItem.item, inputItem.expectedItemValue) 645ffc67bb3SDavid Spickett << "Input-item value after non advancing read " << j; 646ffc67bb3SDavid Spickett j++; 647ffc67bb3SDavid Spickett } 648ffc67bb3SDavid Spickett 649ffc67bb3SDavid Spickett // WRITE(UNIT=unit, FMT=fmt, IOSTAT=iostat) outputItem. 650ffc67bb3SDavid Spickett static constexpr std::string_view outputItem{"XYZ"}; 651ffc67bb3SDavid Spickett // WRITE(UNIT=unit,FMT=fmt) record 652ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedOutput)( 653ffc67bb3SDavid Spickett fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__); 654ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(OutputAscii)(io, outputItem.data(), outputItem.length())) 655ffc67bb3SDavid Spickett << "OutputAscii()"; 656ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 657ffc67bb3SDavid Spickett << "EndIoStatement() for OutputAscii"; 658ffc67bb3SDavid Spickett 659ffc67bb3SDavid Spickett // Verify that the output was written in the record read in non advancing 660ffc67bb3SDavid Spickett // mode, after the read part, and that the end was truncated. 661ffc67bb3SDavid Spickett 662ffc67bb3SDavid Spickett // REWIND(UNIT=unit) 663ffc67bb3SDavid Spickett io = IONAME(BeginRewind)(unit, __FILE__, __LINE__); 664ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 665ffc67bb3SDavid Spickett << "EndIoStatement() for Rewind"; 666ffc67bb3SDavid Spickett 667ffc67bb3SDavid Spickett std::string resultRecord(20, '+'); 668ffc67bb3SDavid Spickett std::string expectedRecord{"ABCDEFGHXYZ "}; 669ffc67bb3SDavid Spickett // READ(UNIT=unit, FMT=fmt, IOSTAT=iostat) result 670ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedInput)( 671ffc67bb3SDavid Spickett fmt.data(), fmt.length(), nullptr, unit, __FILE__, __LINE__); 672ffc67bb3SDavid Spickett IONAME(EnableHandlers)(io, true, false, false, false, false); 673ffc67bb3SDavid Spickett ASSERT_TRUE( 674ffc67bb3SDavid Spickett IONAME(InputAscii)(io, resultRecord.data(), resultRecord.length())) 675ffc67bb3SDavid Spickett << "InputAscii() "; 676ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 677ffc67bb3SDavid Spickett << "EndIoStatement() for Read "; 678ffc67bb3SDavid Spickett ASSERT_EQ(resultRecord, expectedRecord) 679ffc67bb3SDavid Spickett << "Record after non advancing read followed by write"; 680ffc67bb3SDavid Spickett // CLOSE(UNIT=unit) 681ffc67bb3SDavid Spickett io = IONAME(BeginClose)(unit, __FILE__, __LINE__); 682ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 683ffc67bb3SDavid Spickett << "EndIoStatement() for Close"; 684ffc67bb3SDavid Spickett } 685ffc67bb3SDavid Spickett 686ffc67bb3SDavid Spickett TEST(ExternalIOTests, TestWriteAfterEndfile) { 687ffc67bb3SDavid Spickett // OPEN(NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',& 688ffc67bb3SDavid Spickett // FORM='FORMATTED',STATUS='SCRATCH') 689ffc67bb3SDavid Spickett auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)}; 690ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAccess)(io, "SEQUENTIAL", 10)) 691ffc67bb3SDavid Spickett << "SetAccess(SEQUENTIAL)"; 692ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)"; 693ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetForm)(io, "FORMATTED", 9)) << "SetForm(FORMATTED)"; 694ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)"; 695ffc67bb3SDavid Spickett int unit{-1}; 696ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()"; 697ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 698ffc67bb3SDavid Spickett << "EndIoStatement() for OpenNewUnit"; 699ffc67bb3SDavid Spickett // WRITE(unit,"(I8)") 1234 700ffc67bb3SDavid Spickett static constexpr std::string_view format{"(I8)"}; 701ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedOutput)( 702ffc67bb3SDavid Spickett format.data(), format.length(), nullptr, unit, __FILE__, __LINE__); 703ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(OutputInteger64)(io, 1234)) << "OutputInteger64()"; 704ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 705ffc67bb3SDavid Spickett << "EndIoStatement for WRITE before ENDFILE"; 706ffc67bb3SDavid Spickett // ENDFILE(unit) 707ffc67bb3SDavid Spickett io = IONAME(BeginEndfile)(unit, __FILE__, __LINE__); 708ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 709ffc67bb3SDavid Spickett << "EndIoStatement for ENDFILE"; 710ffc67bb3SDavid Spickett // WRITE(unit,"(I8)",iostat=iostat) 5678 711ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedOutput)( 712ffc67bb3SDavid Spickett format.data(), format.length(), nullptr, unit, __FILE__, __LINE__); 713ffc67bb3SDavid Spickett IONAME(EnableHandlers)(io, true /*IOSTAT=*/); 714ffc67bb3SDavid Spickett ASSERT_FALSE(IONAME(OutputInteger64)(io, 5678)) << "OutputInteger64()"; 715ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatWriteAfterEndfile) 716ffc67bb3SDavid Spickett << "EndIoStatement for WRITE after ENDFILE"; 717ffc67bb3SDavid Spickett // BACKSPACE(unit) 718ffc67bb3SDavid Spickett io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__); 719ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 720ffc67bb3SDavid Spickett << "EndIoStatement for BACKSPACE"; 721ffc67bb3SDavid Spickett // WRITE(unit,"(I8)") 3456 722ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedOutput)( 723ffc67bb3SDavid Spickett format.data(), format.length(), nullptr, unit, __FILE__, __LINE__); 724ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(OutputInteger64)(io, 3456)) << "OutputInteger64()"; 725ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 726ffc67bb3SDavid Spickett << "EndIoStatement for WRITE after BACKSPACE"; 727ffc67bb3SDavid Spickett // REWIND(unit) 728ffc67bb3SDavid Spickett io = IONAME(BeginRewind)(unit, __FILE__, __LINE__); 729ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 730ffc67bb3SDavid Spickett << "EndIoStatement for REWIND"; 731ffc67bb3SDavid Spickett // READ(unit,"(I8)",END=) j, k 732ffc67bb3SDavid Spickett std::int64_t j{-1}, k{-1}, eof{-1}; 733ffc67bb3SDavid Spickett io = IONAME(BeginExternalFormattedInput)( 734ffc67bb3SDavid Spickett format.data(), format.length(), nullptr, unit, __FILE__, __LINE__); 735ffc67bb3SDavid Spickett IONAME(EnableHandlers)(io, false, false, true /*END=*/); 736ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(InputInteger)(io, j)) << "InputInteger(j)"; 737ffc67bb3SDavid Spickett ASSERT_EQ(j, 1234) << "READ(j)"; 738ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(InputInteger)(io, k)) << "InputInteger(k)"; 739ffc67bb3SDavid Spickett ASSERT_EQ(k, 3456) << "READ(k)"; 740ffc67bb3SDavid Spickett ASSERT_FALSE(IONAME(InputInteger)(io, eof)) << "InputInteger(eof)"; 741ffc67bb3SDavid Spickett ASSERT_EQ(eof, -1) << "READ(eof)"; 742ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatEnd) << "EndIoStatement for READ"; 743ffc67bb3SDavid Spickett // CLOSE(UNIT=unit) 744ffc67bb3SDavid Spickett io = IONAME(BeginClose)(unit, __FILE__, __LINE__); 745ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 746ffc67bb3SDavid Spickett << "EndIoStatement() for Close"; 747ffc67bb3SDavid Spickett } 748ffc67bb3SDavid Spickett 749ffc67bb3SDavid Spickett TEST(ExternalIOTests, TestUTF8Encoding) { 750ffc67bb3SDavid Spickett // OPEN(FILE="utf8test",NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',& 751ffc67bb3SDavid Spickett // FORM='FORMATTED',STATUS='REPLACE',ENCODING='UTF-8') 752ffc67bb3SDavid Spickett auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)}; 753ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAccess)(io, "SEQUENTIAL", 10)) 754ffc67bb3SDavid Spickett << "SetAccess(SEQUENTIAL)"; 755ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)"; 756ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetFile)(io, "utf8test", 8)) << "SetFile(utf8test)"; 757ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetForm)(io, "FORMATTED", 9)) << "SetForm(FORMATTED)"; 758ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "REPLACE", 7)) << "SetStatus(REPLACE)"; 759ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetEncoding)(io, "UTF-8", 5)) << "SetEncoding(UTF-8)"; 760ffc67bb3SDavid Spickett int unit{-1}; 761ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()"; 762ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 763ffc67bb3SDavid Spickett << "EndIoStatement() for first OPEN"; 764ffc67bb3SDavid Spickett char buffer[12]; 765ffc67bb3SDavid Spickett std::memcpy(buffer, 766ffc67bb3SDavid Spickett "abc\x80\xff" 767ffc67bb3SDavid Spickett "de\0\0\0\0\0", 768ffc67bb3SDavid Spickett 12); 769ffc67bb3SDavid Spickett // WRITE(unit, *) buffer 770ffc67bb3SDavid Spickett io = IONAME(BeginExternalListOutput)(unit, __FILE__, __LINE__); 771ffc67bb3SDavid Spickett StaticDescriptor<0> staticDescriptor; 772ffc67bb3SDavid Spickett Descriptor &desc{staticDescriptor.descriptor()}; 773ffc67bb3SDavid Spickett desc.Establish(TypeCode{CFI_type_char}, 7, buffer, 0); 774ffc67bb3SDavid Spickett desc.Check(); 775ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(OutputDescriptor)(io, desc)); 776ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 777ffc67bb3SDavid Spickett << "EndIoStatement() for WRITE"; 778ffc67bb3SDavid Spickett // REWIND(unit) 779ffc67bb3SDavid Spickett io = IONAME(BeginRewind)(unit, __FILE__, __LINE__); 780ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 781ffc67bb3SDavid Spickett << "EndIoStatement for REWIND"; 782ffc67bb3SDavid Spickett // READ(unit, *) buffer 783ffc67bb3SDavid Spickett desc.Establish(TypeCode(CFI_type_char), sizeof buffer, buffer, 0); 784ffc67bb3SDavid Spickett desc.Check(); 785ffc67bb3SDavid Spickett io = IONAME(BeginExternalListInput)(unit, __FILE__, __LINE__); 786ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(InputDescriptor)(io, desc)); 787ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 788ffc67bb3SDavid Spickett << "EndIoStatement() for first READ"; 789ffc67bb3SDavid Spickett ASSERT_EQ(std::memcmp(buffer, 790ffc67bb3SDavid Spickett "abc\x80\xff" 791ffc67bb3SDavid Spickett "de ", 792ffc67bb3SDavid Spickett 12), 793ffc67bb3SDavid Spickett 0); 794ffc67bb3SDavid Spickett // CLOSE(UNIT=unit,STATUS='KEEP') 795ffc67bb3SDavid Spickett io = IONAME(BeginClose)(unit, __FILE__, __LINE__); 796ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "KEEP", 4)) << "SetStatus(KEEP)"; 797ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 798ffc67bb3SDavid Spickett << "EndIoStatement() for first CLOSE"; 799ffc67bb3SDavid Spickett // OPEN(FILE="utf8test",NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',& 800ffc67bb3SDavid Spickett // FORM='FORMATTED',STATUS='OLD') 801ffc67bb3SDavid Spickett io = IONAME(BeginOpenNewUnit)(__FILE__, __LINE__); 802ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAccess)(io, "SEQUENTIAL", 10)) 803ffc67bb3SDavid Spickett << "SetAccess(SEQUENTIAL)"; 804ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)"; 805ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetFile)(io, "utf8test", 8)) << "SetFile(utf8test)"; 806ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetForm)(io, "FORMATTED", 9)) << "SetForm(FORMATTED)"; 807ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "OLD", 3)) << "SetStatus(OLD)"; 808ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()"; 809ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 810ffc67bb3SDavid Spickett << "EndIoStatement() for second OPEN"; 811ffc67bb3SDavid Spickett // READ(unit, *) buffer 812ffc67bb3SDavid Spickett io = IONAME(BeginExternalListInput)(unit, __FILE__, __LINE__); 813ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(InputDescriptor)(io, desc)); 814ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 815ffc67bb3SDavid Spickett << "EndIoStatement() for second READ"; 816ffc67bb3SDavid Spickett ASSERT_EQ(std::memcmp(buffer, 817ffc67bb3SDavid Spickett "abc\xc2\x80\xc3\xbf" 818ffc67bb3SDavid Spickett "de ", 819ffc67bb3SDavid Spickett 12), 820ffc67bb3SDavid Spickett 0); 821ffc67bb3SDavid Spickett // CLOSE(UNIT=unit,STATUS='DELETE') 822ffc67bb3SDavid Spickett io = IONAME(BeginClose)(unit, __FILE__, __LINE__); 823ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)"; 824ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 825ffc67bb3SDavid Spickett << "EndIoStatement() for second CLOSE"; 826ffc67bb3SDavid Spickett } 827ffc67bb3SDavid Spickett 828ffc67bb3SDavid Spickett TEST(ExternalIOTests, TestUCS) { 829ffc67bb3SDavid Spickett // OPEN(FILE="ucstest',NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',& 830ffc67bb3SDavid Spickett // FORM='FORMATTED',STATUS='REPLACE',ENCODING='UTF-8') 831ffc67bb3SDavid Spickett auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)}; 832ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAccess)(io, "SEQUENTIAL", 10)) 833ffc67bb3SDavid Spickett << "SetAccess(SEQUENTIAL)"; 834ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)"; 835ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetFile)(io, "ucstest", 7)) << "SetAction(ucstest)"; 836ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetForm)(io, "FORMATTED", 9)) << "SetForm(FORMATTED)"; 837ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "REPLACE", 7)) << "SetStatus(REPLACE)"; 838ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetEncoding)(io, "UTF-8", 5)) << "SetEncoding(UTF-8)"; 839ffc67bb3SDavid Spickett int unit{-1}; 840ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()"; 841ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 842ffc67bb3SDavid Spickett << "EndIoStatement() for first OPEN"; 843ffc67bb3SDavid Spickett char32_t wbuffer[8]{U"abc\u0080\uffff" 844ffc67bb3SDavid Spickett "de"}; 845ffc67bb3SDavid Spickett // WRITE(unit, *) wbuffec 846ffc67bb3SDavid Spickett io = IONAME(BeginExternalListOutput)(unit, __FILE__, __LINE__); 847ffc67bb3SDavid Spickett StaticDescriptor<0> staticDescriptor; 848ffc67bb3SDavid Spickett Descriptor &desc{staticDescriptor.descriptor()}; 849ffc67bb3SDavid Spickett desc.Establish(TypeCode{CFI_type_char32_t}, sizeof wbuffer - sizeof(char32_t), 850ffc67bb3SDavid Spickett wbuffer, 0); 851ffc67bb3SDavid Spickett desc.Check(); 852ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(OutputDescriptor)(io, desc)); 853ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 854ffc67bb3SDavid Spickett << "EndIoStatement() for WRITE"; 855ffc67bb3SDavid Spickett // REWIND(unit) 856ffc67bb3SDavid Spickett io = IONAME(BeginRewind)(unit, __FILE__, __LINE__); 857ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 858ffc67bb3SDavid Spickett << "EndIoStatement for REWIND"; 859ffc67bb3SDavid Spickett // READ(unit, *) buffer 860ffc67bb3SDavid Spickett io = IONAME(BeginExternalListInput)(unit, __FILE__, __LINE__); 861ffc67bb3SDavid Spickett desc.Establish(TypeCode{CFI_type_char32_t}, sizeof wbuffer, wbuffer, 0); 862ffc67bb3SDavid Spickett desc.Check(); 863ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(InputDescriptor)(io, desc)); 864ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 865ffc67bb3SDavid Spickett << "EndIoStatement() for first READ"; 866ffc67bb3SDavid Spickett char dump[80]; 867ffc67bb3SDavid Spickett dump[0] = '\0'; 868ffc67bb3SDavid Spickett for (int j{0}; j < 8; ++j) { 869ffc67bb3SDavid Spickett std::size_t dumpLen{std::strlen(dump)}; 870ffc67bb3SDavid Spickett std::snprintf( 871ffc67bb3SDavid Spickett dump + dumpLen, sizeof dump - dumpLen, " %x", (unsigned)wbuffer[j]); 872ffc67bb3SDavid Spickett } 873ffc67bb3SDavid Spickett EXPECT_EQ(wbuffer[0], U'a') << dump; 874ffc67bb3SDavid Spickett EXPECT_EQ(wbuffer[1], U'b') << dump; 875ffc67bb3SDavid Spickett EXPECT_EQ(wbuffer[2], U'c') << dump; 876ffc67bb3SDavid Spickett EXPECT_EQ(wbuffer[3], U'\u0080') << dump; 877ffc67bb3SDavid Spickett EXPECT_EQ(wbuffer[4], U'\uffff') << dump; 878ffc67bb3SDavid Spickett EXPECT_EQ(wbuffer[5], U'd') << dump; 879ffc67bb3SDavid Spickett EXPECT_EQ(wbuffer[6], U'e') << dump; 880ffc67bb3SDavid Spickett EXPECT_EQ(wbuffer[7], U' ') << dump; 881ffc67bb3SDavid Spickett // CLOSE(UNIT=unit,STATUS='KEEP') 882ffc67bb3SDavid Spickett io = IONAME(BeginClose)(unit, __FILE__, __LINE__); 883ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "KEEP", 4)) << "SetStatus(KEEP)"; 884ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 885ffc67bb3SDavid Spickett << "EndIoStatement() for first CLOSE"; 886ffc67bb3SDavid Spickett // OPEN(FILE="ucstest",NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',& 887ffc67bb3SDavid Spickett // FORM='FORMATTED',STATUS='OLD') 888ffc67bb3SDavid Spickett io = IONAME(BeginOpenNewUnit)(__FILE__, __LINE__); 889ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAccess)(io, "SEQUENTIAL", 10)) 890ffc67bb3SDavid Spickett << "SetAccess(SEQUENTIAL)"; 891ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)"; 892ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetFile)(io, "ucstest", 7)) << "SetFile(ucstest)"; 893ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetForm)(io, "FORMATTED", 9)) << "SetForm(FORMATTED)"; 894ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "OLD", 3)) << "SetStatus(OLD)"; 895ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()"; 896ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 897ffc67bb3SDavid Spickett << "EndIoStatement() for second OPEN"; 898ffc67bb3SDavid Spickett char buffer[12]; 899ffc67bb3SDavid Spickett // READ(unit, *) buffer 900ffc67bb3SDavid Spickett io = IONAME(BeginExternalListInput)(unit, __FILE__, __LINE__); 901ffc67bb3SDavid Spickett desc.Establish(TypeCode{CFI_type_char}, sizeof buffer, buffer, 0); 902ffc67bb3SDavid Spickett desc.Check(); 903ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(InputDescriptor)(io, desc)); 904ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 905ffc67bb3SDavid Spickett << "EndIoStatement() for second READ"; 906ffc67bb3SDavid Spickett dump[0] = '\0'; 907ffc67bb3SDavid Spickett for (int j{0}; j < 12; ++j) { 908ffc67bb3SDavid Spickett std::size_t dumpLen{std::strlen(dump)}; 909ffc67bb3SDavid Spickett std::snprintf(dump + dumpLen, sizeof dump - dumpLen, " %x", 910ffc67bb3SDavid Spickett (unsigned)(unsigned char)buffer[j]); 911ffc67bb3SDavid Spickett } 912ffc67bb3SDavid Spickett EXPECT_EQ(std::memcmp(buffer, 913ffc67bb3SDavid Spickett "abc\xc2\x80\xef\xbf\xbf" 914ffc67bb3SDavid Spickett "de ", 915ffc67bb3SDavid Spickett 12), 916ffc67bb3SDavid Spickett 0) 917ffc67bb3SDavid Spickett << dump; 918ffc67bb3SDavid Spickett // CLOSE(UNIT=unit,STATUS='DELETE') 919ffc67bb3SDavid Spickett io = IONAME(BeginClose)(unit, __FILE__, __LINE__); 920ffc67bb3SDavid Spickett ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)"; 921ffc67bb3SDavid Spickett ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk) 922ffc67bb3SDavid Spickett << "EndIoStatement() for second CLOSE"; 923ffc67bb3SDavid Spickett } 924ffc67bb3SDavid Spickett 925ffc67bb3SDavid Spickett TEST(ExternalIOTests, BigUnitNumbers) { 926ffc67bb3SDavid Spickett if (std::numeric_limits<ExternalUnit>::max() < 927ffc67bb3SDavid Spickett std::numeric_limits<std::int64_t>::max()) { 928ffc67bb3SDavid Spickett std::int64_t unit64Ok = std::numeric_limits<ExternalUnit>::max(); 929ffc67bb3SDavid Spickett std::int64_t unit64Bad = unit64Ok + 1; 930ffc67bb3SDavid Spickett std::int64_t unit64Bad2 = 931ffc67bb3SDavid Spickett static_cast<std::int64_t>(std::numeric_limits<ExternalUnit>::min()) - 1; 932ffc67bb3SDavid Spickett EXPECT_EQ(IONAME(CheckUnitNumberInRange64)(unit64Ok, true), IostatOk); 933ffc67bb3SDavid Spickett EXPECT_EQ(IONAME(CheckUnitNumberInRange64)(unit64Ok, false), IostatOk); 934ffc67bb3SDavid Spickett EXPECT_EQ( 935ffc67bb3SDavid Spickett IONAME(CheckUnitNumberInRange64)(unit64Bad, true), IostatUnitOverflow); 936ffc67bb3SDavid Spickett EXPECT_EQ( 937ffc67bb3SDavid Spickett IONAME(CheckUnitNumberInRange64)(unit64Bad2, true), IostatUnitOverflow); 938ffc67bb3SDavid Spickett constexpr std::size_t n{80}; 939ffc67bb3SDavid Spickett char expectedMsg[n + 1]; 940ffc67bb3SDavid Spickett expectedMsg[n] = '\0'; 941ffc67bb3SDavid Spickett std::snprintf(expectedMsg, n, "UNIT number %jd is out of range", 942ffc67bb3SDavid Spickett static_cast<std::intmax_t>(unit64Bad)); 943ffc67bb3SDavid Spickett EXPECT_DEATH( 94467782d2dSSiHuaN IONAME(CheckUnitNumberInRange64)(unit64Bad, false), expectedMsg); 945ffc67bb3SDavid Spickett for (auto i{std::strlen(expectedMsg)}; i < n; ++i) { 946ffc67bb3SDavid Spickett expectedMsg[i] = ' '; 947ffc67bb3SDavid Spickett } 948ffc67bb3SDavid Spickett char msg[n + 1]; 949ffc67bb3SDavid Spickett msg[n] = '\0'; 950ffc67bb3SDavid Spickett EXPECT_EQ(IONAME(CheckUnitNumberInRange64)(unit64Bad, true, msg, n), 951ffc67bb3SDavid Spickett IostatUnitOverflow); 952ffc67bb3SDavid Spickett EXPECT_EQ(std::strncmp(msg, expectedMsg, n), 0); 953ffc67bb3SDavid Spickett } 954ffc67bb3SDavid Spickett } 955