Port external-io test to use GTest. Remove Runtime tests directory.
Rename RuntimeGTest directory to Runtime.
This is the last in a series of patches which ported tests from the old
flang/unittests/Runtime test directory to use GTest in a temporary
unittest directory under flang/unittests/RuntimeGTest. Now that all the
tests in the old directory have been ported to use GTest, the old
directory has been removed and the GTest directory has been renamed to
flang/unittests/Runtime.
Differential Revision: https://reviews.llvm.org/D105315
Reviewed by: Meinersbur, awarzynski
add_subdirectory(Decimal)
add_subdirectory(Evaluate)
add_subdirectory(Runtime)
-add_subdirectory(RuntimeGTest)
if (FLANG_BUILD_NEW_DRIVER)
add_subdirectory(Frontend)
-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
-
-# RuntimeTesting needs exceptions enabled
-set(LLVM_REQUIRES_EH ON)
-set(LLVM_REQUIRES_RTTI ON)
-add_library(RuntimeTesting
- testing.cpp
-)
-llvm_update_compile_flags(RuntimeTesting)
-
-if (LLVM_LINK_LLVM_DYLIB)
- set(llvm_libs LLVM)
-else()
- llvm_map_components_to_libnames(llvm_libs Support)
-endif()
-target_link_libraries(RuntimeTesting
- FortranRuntime
- ${llvm_libs}
+add_flang_unittest(FlangRuntimeTests
+ BufferTest.cpp
+ CharacterTest.cpp
+ CrashHandlerFixture.cpp
+ ExternalIOTest.cpp
+ Format.cpp
+ ListInputTest.cpp
+ Matmul.cpp
+ MiscIntrinsic.cpp
+ Namelist.cpp
+ Numeric.cpp
+ NumericalFormatTest.cpp
+ Random.cpp
+ Reduction.cpp
+ RuntimeCrashTest.cpp
+ Time.cpp
+ Transformational.cpp
)
-add_flang_nongtest_unittest(external-io
- RuntimeTesting
+target_link_libraries(FlangRuntimeTests
+ PRIVATE
FortranRuntime
)
// in Fortran.
#include "../../runtime/character.h"
-#include "../../runtime/descriptor.h"
#include "gtest/gtest.h"
+#include "../../runtime/descriptor.h"
#include <cstring>
#include <functional>
#include <tuple>
TYPED_TEST_SUITE(ExtremumTests, CharacterTypes, );
TYPED_TEST(ExtremumTests, MinTests) {
- static std::vector<ExtremumTestCase> tests{
- {{}, {"a"}, {"z"}, {"a"}},
+ static std::vector<ExtremumTestCase> tests{{{}, {"a"}, {"z"}, {"a"}},
{{1}, {"zaaa"}, {"aa"}, {"aa "}},
{{1, 1}, {"aaz"}, {"aaaaa"}, {"aaaaa"}},
- {
- { 2, 3 },
- { "a", "b", "c", "d", "E", "f" },
- { "xa", "ya", "az", "dd", "Sz", "cc"},
- { "a ", "b ", "az", "d ", "E ", "cc"}
- }
- };
+ {{2, 3}, {"a", "b", "c", "d", "E", "f"},
+ {"xa", "ya", "az", "dd", "Sz", "cc"},
+ {"a ", "b ", "az", "d ", "E ", "cc"}}};
RunExtremumTests<TypeParam>("MIN", RTNAME(CharacterMin), tests);
}
--- /dev/null
+//===-- flang/unittests/RuntimeGTest/ExternalIOTest.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
+//
+//===----------------------------------------------------------------------===//
+//
+// Sanity test for all external I/O modes
+//
+//===----------------------------------------------------------------------===//
+
+#include "CrashHandlerFixture.h"
+#include "gtest/gtest.h"
+#include "../../runtime/io-api.h"
+#include "../../runtime/main.h"
+#include "../../runtime/stop.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstring>
+
+using namespace Fortran::runtime::io;
+
+struct ExternalIOTests : public CrashHandlerFixture {};
+
+TEST(ExternalIOTests, TestDirectUnformatted) {
+ // OPEN(NEWUNIT=unit,ACCESS='DIRECT',ACTION='READWRITE',&
+ // FORM='UNFORMATTED',RECL=8,STATUS='SCRATCH')
+ Cookie io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)};
+ ASSERT_TRUE(IONAME(SetAccess)(io, "DIRECT", 6)) << "SetAccess(DIRECT)";
+ ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)";
+ ASSERT_TRUE(IONAME(SetForm)(io, "UNFORMATTED", 11)) << "SetForm(UNFORMATTED)";
+
+ std::int64_t buffer;
+ static constexpr std::size_t recl{sizeof buffer};
+ ASSERT_TRUE(IONAME(SetRecl)(io, recl)) << "SetRecl()";
+ ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)";
+
+ int unit{-1};
+ ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for OpenNewUnit";
+
+ static constexpr int records{10};
+ for (int j{1}; j <= records; ++j) {
+ // WRITE(UNIT=unit,REC=j) j
+ io = IONAME(BeginUnformattedOutput)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')';
+
+ buffer = j;
+ ASSERT_TRUE(IONAME(OutputUnformattedBlock)(
+ io, reinterpret_cast<const char *>(&buffer), recl, recl))
+ << "OutputUnformattedBlock()";
+
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for OutputUnformattedBlock";
+ }
+
+ for (int j{records}; j >= 1; --j) {
+ // READ(UNIT=unit,REC=j) n
+ io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')';
+ ASSERT_TRUE(IONAME(InputUnformattedBlock)(
+ io, reinterpret_cast<char *>(&buffer), recl, recl))
+ << "InputUnformattedBlock()";
+
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for InputUnformattedBlock";
+
+ ASSERT_EQ(buffer, j) << "Read back " << buffer
+ << " from direct unformatted record " << j
+ << ", expected " << j << '\n';
+ }
+ // CLOSE(UNIT=unit,STATUS='DELETE')
+ io = IONAME(BeginClose)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Close";
+}
+
+TEST(ExternalIOTests, TestDirectUnformattedSwapped) {
+ // OPEN(NEWUNIT=unit,ACCESS='DIRECT',ACTION='READWRITE',&
+ // FORM='UNFORMATTED',RECL=8,STATUS='SCRATCH',CONVERT='NATIVE')
+ auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)};
+ ASSERT_TRUE(IONAME(SetAccess)(io, "DIRECT", 6)) << "SetAccess(DIRECT)";
+ ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)";
+ ASSERT_TRUE(IONAME(SetForm)(io, "UNFORMATTED", 11)) << "SetForm(UNFORMATTED)";
+ ASSERT_TRUE(IONAME(SetConvert)(io, "NATIVE", 6)) << "SetConvert(NATIVE)";
+
+ std::int64_t buffer;
+ static constexpr std::size_t recl{sizeof buffer};
+ ASSERT_TRUE(IONAME(SetRecl)(io, recl)) << "SetRecl()";
+ ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)";
+
+ int unit{-1};
+ ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for OpenNewUnit";
+
+ static constexpr int records{10};
+ for (int j{1}; j <= records; ++j) {
+ // WRITE(UNIT=unit,REC=j) j
+ io = IONAME(BeginUnformattedOutput)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')';
+ buffer = j;
+ ASSERT_TRUE(IONAME(OutputUnformattedBlock)(
+ io, reinterpret_cast<const char *>(&buffer), recl, recl))
+ << "OutputUnformattedBlock()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for OutputUnformattedBlock";
+ }
+
+ // OPEN(UNIT=unit,STATUS='OLD',CONVERT='SWAP')
+ io = IONAME(BeginOpenUnit)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(SetStatus)(io, "OLD", 3)) << "SetStatus(OLD)";
+ ASSERT_TRUE(IONAME(SetConvert)(io, "SWAP", 4)) << "SetConvert(SWAP)";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for OpenUnit";
+
+ for (int j{records}; j >= 1; --j) {
+ // READ(UNIT=unit,REC=j) n
+ io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')';
+ ASSERT_TRUE(IONAME(InputUnformattedBlock)(
+ io, reinterpret_cast<char *>(&buffer), recl, recl))
+ << "InputUnformattedBlock()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for InputUnformattedBlock";
+ ASSERT_EQ(buffer >> 56, j)
+ << "Read back " << (buffer >> 56) << " from direct unformatted record "
+ << j << ", expected " << j << '\n';
+ }
+
+ // CLOSE(UNIT=unit,STATUS='DELETE')
+ io = IONAME(BeginClose)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Close";
+}
+
+TEST(ExternalIOTests, TestSequentialFixedUnformatted) {
+ // OPEN(NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',&
+ // FORM='UNFORMATTED',RECL=8,STATUS='SCRATCH')
+ auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)};
+ ASSERT_TRUE(IONAME(SetAccess)(io, "SEQUENTIAL", 10))
+ << "SetAccess(SEQUENTIAL)";
+ ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)";
+ ASSERT_TRUE(IONAME(SetForm)(io, "UNFORMATTED", 11)) << "SetForm(UNFORMATTED)";
+
+ std::int64_t buffer;
+ static constexpr std::size_t recl{sizeof buffer};
+
+ ASSERT_TRUE(IONAME(SetRecl)(io, recl)) << "SetRecl()";
+ ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)";
+
+ int unit{-1};
+ ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for OpenNewUnit";
+
+ static const int records{10};
+ for (int j{1}; j <= records; ++j) {
+ // DO J=1,RECORDS; WRITE(UNIT=unit) j; END DO
+ io = IONAME(BeginUnformattedOutput)(unit, __FILE__, __LINE__);
+ buffer = j;
+ ASSERT_TRUE(IONAME(OutputUnformattedBlock)(
+ io, reinterpret_cast<const char *>(&buffer), recl, recl))
+ << "OutputUnformattedBlock()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for OutputUnformattedBlock";
+ }
+
+ // REWIND(UNIT=unit)
+ io = IONAME(BeginRewind)(unit, __FILE__, __LINE__);
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Rewind";
+
+ for (int j{1}; j <= records; ++j) {
+ // DO J=1,RECORDS; READ(UNIT=unit) n; check n; END DO
+ io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(InputUnformattedBlock)(
+ io, reinterpret_cast<char *>(&buffer), recl, recl))
+ << "InputUnformattedBlock()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for InputUnformattedBlock";
+ ASSERT_EQ(buffer, j) << "Read back " << buffer
+ << " from sequential fixed unformatted record " << j
+ << ", expected " << j << '\n';
+ }
+
+ for (int j{records}; j >= 1; --j) {
+ // BACKSPACE(UNIT=unit)
+ io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__);
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Backspace (before read)";
+ // READ(UNIT=unit) n
+ io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(InputUnformattedBlock)(
+ io, reinterpret_cast<char *>(&buffer), recl, recl))
+ << "InputUnformattedBlock()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for InputUnformattedBlock";
+ ASSERT_EQ(buffer, j) << "Read back " << buffer
+ << " from sequential fixed unformatted record " << j
+ << " after backspacing, expected " << j << '\n';
+ // BACKSPACE(UNIT=unit)
+ io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__);
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Backspace (after read)";
+ }
+
+ // CLOSE(UNIT=unit,STATUS='DELETE')
+ io = IONAME(BeginClose)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Close";
+}
+
+TEST(ExternalIOTests, TestSequentialVariableUnformatted) {
+ // OPEN(NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',&
+ // FORM='UNFORMATTED',STATUS='SCRATCH')
+ auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)};
+
+ ASSERT_TRUE(IONAME(SetAccess)(io, "SEQUENTIAL", 10))
+ << "SetAccess(SEQUENTIAL)";
+ ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)";
+ ASSERT_TRUE(IONAME(SetForm)(io, "UNFORMATTED", 11)) << "SetForm(UNFORMATTED)";
+ ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)";
+
+ int unit{-1};
+ ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for OpenNewUnit";
+
+ static const int records{10};
+ std::int64_t buffer[records]; // INTEGER*8 :: BUFFER(0:9) = [(j,j=0,9)]
+ for (int j{0}; j < records; ++j) {
+ buffer[j] = j;
+ }
+
+ for (int j{1}; j <= records; ++j) {
+ // DO J=1,RECORDS; WRITE(UNIT=unit) BUFFER(0:j); END DO
+ io = IONAME(BeginUnformattedOutput)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(OutputUnformattedBlock)(io,
+ reinterpret_cast<const char *>(&buffer), j * sizeof *buffer,
+ sizeof *buffer))
+ << "OutputUnformattedBlock()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for OutputUnformattedBlock";
+ }
+
+ // REWIND(UNIT=unit)
+ io = IONAME(BeginRewind)(unit, __FILE__, __LINE__);
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Rewind";
+ for (int j{1}; j <= records; ++j) {
+ // DO J=1,RECORDS; READ(UNIT=unit) n; check n; END DO
+ io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(InputUnformattedBlock)(io,
+ reinterpret_cast<char *>(&buffer), j * sizeof *buffer, sizeof *buffer))
+ << "InputUnformattedBlock()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for InputUnformattedBlock";
+ for (int k{0}; k < j; ++k) {
+ ASSERT_EQ(buffer[k], k) << "Read back [" << k << "]=" << buffer[k]
+ << " from direct unformatted record " << j
+ << ", expected " << k << '\n';
+ }
+ }
+
+ for (int j{records}; j >= 1; --j) {
+ // BACKSPACE(unit)
+ io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__);
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Backspace (before read)";
+ // READ(unit=unit) n; check
+ io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(InputUnformattedBlock)(io,
+ reinterpret_cast<char *>(&buffer), j * sizeof *buffer, sizeof *buffer))
+ << "InputUnformattedBlock()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for InputUnformattedBlock";
+ for (int k{0}; k < j; ++k) {
+ ASSERT_EQ(buffer[k], k) << "Read back [" << k << "]=" << buffer[k]
+ << " from sequential variable unformatted record "
+ << j << ", expected " << k << '\n';
+ }
+ // BACKSPACE(unit)
+ io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__);
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Backspace (after read)";
+ }
+
+ // CLOSE(UNIT=unit,STATUS='DELETE')
+ io = IONAME(BeginClose)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Close";
+}
+
+TEST(ExternalIOTests, TestDirectFormatted) {
+ // OPEN(NEWUNIT=unit,ACCESS='DIRECT',ACTION='READWRITE',&
+ // FORM='FORMATTED',RECL=8,STATUS='SCRATCH')
+ auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)};
+ ASSERT_TRUE(IONAME(SetAccess)(io, "DIRECT", 6)) << "SetAccess(DIRECT)";
+ ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)";
+ ASSERT_TRUE(IONAME(SetForm)(io, "FORMATTED", 9)) << "SetForm(FORMATTED)";
+
+ static constexpr std::size_t recl{8};
+ ASSERT_TRUE(IONAME(SetRecl)(io, recl)) << "SetRecl()";
+ ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)";
+
+ int unit{-1};
+ ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for OpenNewUnit";
+
+ static constexpr int records{10};
+ static const char fmt[]{"(I4)"};
+ for (int j{1}; j <= records; ++j) {
+ // WRITE(UNIT=unit,FMT=fmt,REC=j) j
+ io = IONAME(BeginExternalFormattedOutput)(
+ fmt, sizeof fmt - 1, unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')';
+ ASSERT_TRUE(IONAME(OutputInteger64)(io, j)) << "OutputInteger64()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for OutputInteger64";
+ }
+
+ for (int j{records}; j >= 1; --j) {
+ // READ(UNIT=unit,FMT=fmt,REC=j) n
+ io = IONAME(BeginExternalFormattedInput)(
+ fmt, sizeof fmt - 1, unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(SetRec)(io, j)) << "SetRec(" << j << ')';
+ std::int64_t buffer;
+ ASSERT_TRUE(IONAME(InputInteger)(io, buffer)) << "InputInteger()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for InputInteger";
+
+ ASSERT_EQ(buffer, j) << "Read back " << buffer
+ << " from direct formatted record " << j
+ << ", expected " << j << '\n';
+ }
+
+ // CLOSE(UNIT=unit,STATUS='DELETE')
+ io = IONAME(BeginClose)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Close";
+}
+
+TEST(ExternalIOTests, TestSequentialVariableFormatted) {
+ // OPEN(NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',&
+ // FORM='FORMATTED',STATUS='SCRATCH')
+ auto *io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)};
+ ASSERT_TRUE(IONAME(SetAccess)(io, "SEQUENTIAL", 10))
+ << "SetAccess(SEQUENTIAL)";
+ ASSERT_TRUE(IONAME(SetAction)(io, "READWRITE", 9)) << "SetAction(READWRITE)";
+ ASSERT_TRUE(IONAME(SetForm)(io, "FORMATTED", 9)) << "SetForm(FORMATTED)";
+ ASSERT_TRUE(IONAME(SetStatus)(io, "SCRATCH", 7)) << "SetStatus(SCRATCH)";
+
+ int unit{-1};
+ ASSERT_TRUE(IONAME(GetNewUnit)(io, unit)) << "GetNewUnit()";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for OpenNewUnit";
+
+ static const int records{10};
+ std::int64_t buffer[records]; // INTEGER*8 :: BUFFER(0:9) = [(j,j=0,9)]
+ for (int j{0}; j < records; ++j) {
+ buffer[j] = j;
+ }
+
+ char fmt[32];
+ for (int j{1}; j <= records; ++j) {
+ std::snprintf(fmt, sizeof fmt, "(%dI4)", j);
+ // DO J=1,RECORDS; WRITE(UNIT=unit,FMT=fmt) BUFFER(0:j); END DO
+ io = IONAME(BeginExternalFormattedOutput)(
+ fmt, std::strlen(fmt), unit, __FILE__, __LINE__);
+ for (int k{0}; k < j; ++k) {
+ ASSERT_TRUE(IONAME(OutputInteger64)(io, buffer[k]))
+ << "OutputInteger64()";
+ }
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for OutputInteger64";
+ }
+
+ // REWIND(UNIT=unit)
+ io = IONAME(BeginRewind)(unit, __FILE__, __LINE__);
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Rewind";
+
+ for (int j{1}; j <= records; ++j) {
+ std::snprintf(fmt, sizeof fmt, "(%dI4)", j);
+ // DO J=1,RECORDS; READ(UNIT=unit,FMT=fmt) n; check n; END DO
+ io = IONAME(BeginExternalFormattedInput)(
+ fmt, std::strlen(fmt), unit, __FILE__, __LINE__);
+
+ std::int64_t check[records];
+ for (int k{0}; k < j; ++k) {
+ ASSERT_TRUE(IONAME(InputInteger)(io, check[k])) << "InputInteger()";
+ }
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for InputInteger";
+
+ for (int k{0}; k < j; ++k) {
+ ASSERT_EQ(buffer[k], check[k])
+ << "Read back [" << k << "]=" << check[k]
+ << " from sequential variable formatted record " << j << ", expected "
+ << buffer[k] << '\n';
+ }
+ }
+
+ for (int j{records}; j >= 1; --j) {
+ // BACKSPACE(unit)
+ io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__);
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Backspace (before read)";
+
+ std::snprintf(fmt, sizeof fmt, "(%dI4)", j);
+ // READ(UNIT=unit,FMT=fmt) n; check
+ io = IONAME(BeginExternalFormattedInput)(
+ fmt, std::strlen(fmt), unit, __FILE__, __LINE__);
+
+ std::int64_t check[records];
+ for (int k{0}; k < j; ++k) {
+ ASSERT_TRUE(IONAME(InputInteger)(io, check[k])) << "InputInteger()";
+ }
+
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for InputInteger";
+ for (int k{0}; k < j; ++k) {
+ ASSERT_EQ(buffer[k], check[k])
+ << "Read back [" << k << "]=" << buffer[k]
+ << " from sequential variable formatted record " << j << ", expected "
+ << buffer[k] << '\n';
+ }
+
+ // BACKSPACE(unit)
+ io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__);
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Backspace (after read)";
+ }
+
+ // CLOSE(UNIT=unit,STATUS='DELETE')
+ io = IONAME(BeginClose)(unit, __FILE__, __LINE__);
+ ASSERT_TRUE(IONAME(SetStatus)(io, "DELETE", 6)) << "SetStatus(DELETE)";
+ ASSERT_EQ(IONAME(EndIoStatement)(io), IostatOk)
+ << "EndIoStatement() for Close";
+}
+++ /dev/null
-// Sanity test for all external I/O modes
-
-#include "testing.h"
-#include "../../runtime/io-api.h"
-#include "../../runtime/main.h"
-#include "../../runtime/stop.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstring>
-
-using namespace Fortran::runtime::io;
-
-void TestDirectUnformatted() {
- llvm::errs() << "begin TestDirectUnformatted()\n";
- // OPEN(NEWUNIT=unit,ACCESS='DIRECT',ACTION='READWRITE',&
- // FORM='UNFORMATTED',RECL=8,STATUS='SCRATCH')
- auto io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)};
- IONAME(SetAccess)(io, "DIRECT", 6) || (Fail() << "SetAccess(DIRECT)", 0);
- IONAME(SetAction)
- (io, "READWRITE", 9) || (Fail() << "SetAction(READWRITE)", 0);
- IONAME(SetForm)
- (io, "UNFORMATTED", 11) || (Fail() << "SetForm(UNFORMATTED)", 0);
- std::int64_t buffer;
- static constexpr std::size_t recl{sizeof buffer};
- IONAME(SetRecl)(io, recl) || (Fail() << "SetRecl()", 0);
- IONAME(SetStatus)(io, "SCRATCH", 7) || (Fail() << "SetStatus(SCRATCH)", 0);
- int unit{-1};
- IONAME(GetNewUnit)(io, unit) || (Fail() << "GetNewUnit()", 0);
- llvm::errs() << "unit=" << unit << '\n';
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for OpenNewUnit", 0);
- static constexpr int records{10};
- for (int j{1}; j <= records; ++j) {
- // WRITE(UNIT=unit,REC=j) j
- io = IONAME(BeginUnformattedOutput)(unit, __FILE__, __LINE__);
- IONAME(SetRec)(io, j) || (Fail() << "SetRec(" << j << ')', 0);
- buffer = j;
- IONAME(OutputUnformattedBlock)
- (io, reinterpret_cast<const char *>(&buffer), recl, recl) ||
- (Fail() << "OutputUnformattedBlock()", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for OutputUnformattedBlock", 0);
- }
- for (int j{records}; j >= 1; --j) {
- // READ(UNIT=unit,REC=j) n
- io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__);
- IONAME(SetRec)
- (io, j) || (Fail() << "SetRec(" << j << ')', 0);
- IONAME(InputUnformattedBlock)
- (io, reinterpret_cast<char *>(&buffer), recl, recl) ||
- (Fail() << "InputUnformattedBlock()", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for InputUnformattedBlock", 0);
- if (buffer != j) {
- Fail() << "Read back " << buffer << " from direct unformatted record "
- << j << ", expected " << j << '\n';
- }
- }
- // CLOSE(UNIT=unit,STATUS='DELETE')
- io = IONAME(BeginClose)(unit, __FILE__, __LINE__);
- IONAME(SetStatus)(io, "DELETE", 6) || (Fail() << "SetStatus(DELETE)", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for Close", 0);
- llvm::errs() << "end TestDirectUnformatted()\n";
-}
-
-void TestDirectUnformattedSwapped() {
- llvm::errs() << "begin TestDirectUnformattedSwapped()\n";
- // OPEN(NEWUNIT=unit,ACCESS='DIRECT',ACTION='READWRITE',&
- // FORM='UNFORMATTED',RECL=8,STATUS='SCRATCH',CONVERT='NATIVE')
- auto io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)};
- IONAME(SetAccess)(io, "DIRECT", 6) || (Fail() << "SetAccess(DIRECT)", 0);
- IONAME(SetAction)
- (io, "READWRITE", 9) || (Fail() << "SetAction(READWRITE)", 0);
- IONAME(SetForm)
- (io, "UNFORMATTED", 11) || (Fail() << "SetForm(UNFORMATTED)", 0);
- IONAME(SetConvert)
- (io, "NATIVE", 6) || (Fail() << "SetConvert(NATIVE)", 0);
- std::int64_t buffer;
- static constexpr std::size_t recl{sizeof buffer};
- IONAME(SetRecl)(io, recl) || (Fail() << "SetRecl()", 0);
- IONAME(SetStatus)(io, "SCRATCH", 7) || (Fail() << "SetStatus(SCRATCH)", 0);
- int unit{-1};
- IONAME(GetNewUnit)(io, unit) || (Fail() << "GetNewUnit()", 0);
- llvm::errs() << "unit=" << unit << '\n';
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for OpenNewUnit", 0);
- static constexpr int records{10};
- for (int j{1}; j <= records; ++j) {
- // WRITE(UNIT=unit,REC=j) j
- io = IONAME(BeginUnformattedOutput)(unit, __FILE__, __LINE__);
- IONAME(SetRec)(io, j) || (Fail() << "SetRec(" << j << ')', 0);
- buffer = j;
- IONAME(OutputUnformattedBlock)
- (io, reinterpret_cast<const char *>(&buffer), recl, recl) ||
- (Fail() << "OutputUnformattedBlock()", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for OutputUnformattedBlock", 0);
- }
- // OPEN(UNIT=unit,STATUS='OLD',CONVERT='SWAP')
- io = IONAME(BeginOpenUnit)(unit, __FILE__, __LINE__);
- IONAME(SetStatus)(io, "OLD", 3) || (Fail() << "SetStatus(OLD)", 0);
- IONAME(SetConvert)
- (io, "SWAP", 4) || (Fail() << "SetConvert(SWAP)", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for OpenUnit", 0);
- for (int j{records}; j >= 1; --j) {
- // READ(UNIT=unit,REC=j) n
- io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__);
- IONAME(SetRec)
- (io, j) || (Fail() << "SetRec(" << j << ')', 0);
- IONAME(InputUnformattedBlock)
- (io, reinterpret_cast<char *>(&buffer), recl, recl) ||
- (Fail() << "InputUnformattedBlock()", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for InputUnformattedBlock", 0);
- if (buffer >> 56 != j) {
- Fail() << "Read back " << (buffer >> 56)
- << " from direct unformatted record " << j << ", expected " << j
- << '\n';
- }
- }
- // CLOSE(UNIT=unit,STATUS='DELETE')
- io = IONAME(BeginClose)(unit, __FILE__, __LINE__);
- IONAME(SetStatus)(io, "DELETE", 6) || (Fail() << "SetStatus(DELETE)", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for Close", 0);
- llvm::errs() << "end TestDirectUnformatted()\n";
-}
-
-void TestSequentialFixedUnformatted() {
- llvm::errs() << "begin TestSequentialFixedUnformatted()\n";
- // OPEN(NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',&
- // FORM='UNFORMATTED',RECL=8,STATUS='SCRATCH')
- auto io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)};
- IONAME(SetAccess)
- (io, "SEQUENTIAL", 10) || (Fail() << "SetAccess(SEQUENTIAL)", 0);
- IONAME(SetAction)
- (io, "READWRITE", 9) || (Fail() << "SetAction(READWRITE)", 0);
- IONAME(SetForm)
- (io, "UNFORMATTED", 11) || (Fail() << "SetForm(UNFORMATTED)", 0);
- std::int64_t buffer;
- static constexpr std::size_t recl{sizeof buffer};
- IONAME(SetRecl)(io, recl) || (Fail() << "SetRecl()", 0);
- IONAME(SetStatus)(io, "SCRATCH", 7) || (Fail() << "SetStatus(SCRATCH)", 0);
- int unit{-1};
- IONAME(GetNewUnit)(io, unit) || (Fail() << "GetNewUnit()", 0);
- llvm::errs() << "unit=" << unit << '\n';
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for OpenNewUnit", 0);
- static const int records{10};
- for (int j{1}; j <= records; ++j) {
- // DO J=1,RECORDS; WRITE(UNIT=unit) j; END DO
- io = IONAME(BeginUnformattedOutput)(unit, __FILE__, __LINE__);
- buffer = j;
- IONAME(OutputUnformattedBlock)
- (io, reinterpret_cast<const char *>(&buffer), recl, recl) ||
- (Fail() << "OutputUnformattedBlock()", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for OutputUnformattedBlock", 0);
- }
- // REWIND(UNIT=unit)
- io = IONAME(BeginRewind)(unit, __FILE__, __LINE__);
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for Rewind", 0);
- for (int j{1}; j <= records; ++j) {
- // DO J=1,RECORDS; READ(UNIT=unit) n; check n; END DO
- io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__);
- IONAME(InputUnformattedBlock)
- (io, reinterpret_cast<char *>(&buffer), recl, recl) ||
- (Fail() << "InputUnformattedBlock()", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for InputUnformattedBlock", 0);
- if (buffer != j) {
- Fail() << "Read back " << buffer
- << " from sequential fixed unformatted record " << j
- << ", expected " << j << '\n';
- }
- }
- for (int j{records}; j >= 1; --j) {
- // BACKSPACE(UNIT=unit)
- io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for Backspace (before read)", 0);
- // READ(UNIT=unit) n
- io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__);
- IONAME(InputUnformattedBlock)
- (io, reinterpret_cast<char *>(&buffer), recl, recl) ||
- (Fail() << "InputUnformattedBlock()", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for InputUnformattedBlock", 0);
- if (buffer != j) {
- Fail() << "Read back " << buffer
- << " from sequential fixed unformatted record " << j
- << " after backspacing, expected " << j << '\n';
- }
- // BACKSPACE(UNIT=unit)
- io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for Backspace (after read)", 0);
- }
- // CLOSE(UNIT=unit,STATUS='DELETE')
- io = IONAME(BeginClose)(unit, __FILE__, __LINE__);
- IONAME(SetStatus)(io, "DELETE", 6) || (Fail() << "SetStatus(DELETE)", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for Close", 0);
- llvm::errs() << "end TestSequentialFixedUnformatted()\n";
-}
-
-void TestSequentialVariableUnformatted() {
- llvm::errs() << "begin TestSequentialVariableUnformatted()\n";
- // OPEN(NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',&
- // FORM='UNFORMATTED',STATUS='SCRATCH')
- auto io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)};
- IONAME(SetAccess)
- (io, "SEQUENTIAL", 10) || (Fail() << "SetAccess(SEQUENTIAL)", 0);
- IONAME(SetAction)
- (io, "READWRITE", 9) || (Fail() << "SetAction(READWRITE)", 0);
- IONAME(SetForm)
- (io, "UNFORMATTED", 11) || (Fail() << "SetForm(UNFORMATTED)", 0);
- IONAME(SetStatus)(io, "SCRATCH", 7) || (Fail() << "SetStatus(SCRATCH)", 0);
- int unit{-1};
- IONAME(GetNewUnit)(io, unit) || (Fail() << "GetNewUnit()", 0);
- llvm::errs() << "unit=" << unit << '\n';
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for OpenNewUnit", 0);
- static const int records{10};
- std::int64_t buffer[records]; // INTEGER*8 :: BUFFER(0:9) = [(j,j=0,9)]
- for (int j{0}; j < records; ++j) {
- buffer[j] = j;
- }
- for (int j{1}; j <= records; ++j) {
- // DO J=1,RECORDS; WRITE(UNIT=unit) BUFFER(0:j); END DO
- io = IONAME(BeginUnformattedOutput)(unit, __FILE__, __LINE__);
- IONAME(OutputUnformattedBlock)
- (io, reinterpret_cast<const char *>(&buffer), j * sizeof *buffer,
- sizeof *buffer) ||
- (Fail() << "OutputUnformattedBlock()", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for OutputUnformattedBlock", 0);
- }
- // REWIND(UNIT=unit)
- io = IONAME(BeginRewind)(unit, __FILE__, __LINE__);
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for Rewind", 0);
- for (int j{1}; j <= records; ++j) {
- // DO J=1,RECORDS; READ(UNIT=unit) n; check n; END DO
- io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__);
- IONAME(InputUnformattedBlock)
- (io, reinterpret_cast<char *>(&buffer), j * sizeof *buffer,
- sizeof *buffer) ||
- (Fail() << "InputUnformattedBlock()", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for InputUnformattedBlock", 0);
- for (int k{0}; k < j; ++k) {
- if (buffer[k] != k) {
- Fail() << "Read back [" << k << "]=" << buffer[k]
- << " from direct unformatted record " << j << ", expected " << k
- << '\n';
- }
- }
- }
- for (int j{records}; j >= 1; --j) {
- // BACKSPACE(unit)
- io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for Backspace (before read)", 0);
- // READ(unit=unit) n; check
- io = IONAME(BeginUnformattedInput)(unit, __FILE__, __LINE__);
- IONAME(InputUnformattedBlock)
- (io, reinterpret_cast<char *>(&buffer), j * sizeof *buffer,
- sizeof *buffer) ||
- (Fail() << "InputUnformattedBlock()", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for InputUnformattedBlock", 0);
- for (int k{0}; k < j; ++k) {
- if (buffer[k] != k) {
- Fail() << "Read back [" << k << "]=" << buffer[k]
- << " from sequential variable unformatted record " << j
- << ", expected " << k << '\n';
- }
- }
- // BACKSPACE(unit)
- io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for Backspace (after read)", 0);
- }
- // CLOSE(UNIT=unit,STATUS='DELETE')
- io = IONAME(BeginClose)(unit, __FILE__, __LINE__);
- IONAME(SetStatus)(io, "DELETE", 6) || (Fail() << "SetStatus(DELETE)", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for Close", 0);
- llvm::errs() << "end TestSequentialVariableUnformatted()\n";
-}
-
-void TestDirectFormatted() {
- llvm::errs() << "begin TestDirectFormatted()\n";
- // OPEN(NEWUNIT=unit,ACCESS='DIRECT',ACTION='READWRITE',&
- // FORM='FORMATTED',RECL=8,STATUS='SCRATCH')
- auto io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)};
- IONAME(SetAccess)(io, "DIRECT", 6) || (Fail() << "SetAccess(DIRECT)", 0);
- IONAME(SetAction)
- (io, "READWRITE", 9) || (Fail() << "SetAction(READWRITE)", 0);
- IONAME(SetForm)
- (io, "FORMATTED", 9) || (Fail() << "SetForm(FORMATTED)", 0);
- static constexpr std::size_t recl{8};
- IONAME(SetRecl)(io, recl) || (Fail() << "SetRecl()", 0);
- IONAME(SetStatus)(io, "SCRATCH", 7) || (Fail() << "SetStatus(SCRATCH)", 0);
- int unit{-1};
- IONAME(GetNewUnit)(io, unit) || (Fail() << "GetNewUnit()", 0);
- llvm::errs() << "unit=" << unit << '\n';
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for OpenNewUnit", 0);
- static constexpr int records{10};
- static const char fmt[]{"(I4)"};
- for (int j{1}; j <= records; ++j) {
- // WRITE(UNIT=unit,FMT=fmt,REC=j) j
- io = IONAME(BeginExternalFormattedOutput)(
- fmt, sizeof fmt - 1, unit, __FILE__, __LINE__);
- IONAME(SetRec)(io, j) || (Fail() << "SetRec(" << j << ')', 0);
- IONAME(OutputInteger64)(io, j) || (Fail() << "OutputInteger64()", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for OutputInteger64", 0);
- }
- for (int j{records}; j >= 1; --j) {
- // READ(UNIT=unit,FMT=fmt,REC=j) n
- io = IONAME(BeginExternalFormattedInput)(
- fmt, sizeof fmt - 1, unit, __FILE__, __LINE__);
- IONAME(SetRec)(io, j) || (Fail() << "SetRec(" << j << ')', 0);
- std::int64_t buffer;
- IONAME(InputInteger)(io, buffer) || (Fail() << "InputInteger()", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for InputInteger", 0);
- if (buffer != j) {
- Fail() << "Read back " << buffer << " from direct formatted record " << j
- << ", expected " << j << '\n';
- }
- }
- // CLOSE(UNIT=unit,STATUS='DELETE')
- io = IONAME(BeginClose)(unit, __FILE__, __LINE__);
- IONAME(SetStatus)(io, "DELETE", 6) || (Fail() << "SetStatus(DELETE)", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for Close", 0);
- llvm::errs() << "end TestDirectformatted()\n";
-}
-
-void TestSequentialVariableFormatted() {
- llvm::errs() << "begin TestSequentialVariableFormatted()\n";
- // OPEN(NEWUNIT=unit,ACCESS='SEQUENTIAL',ACTION='READWRITE',&
- // FORM='FORMATTED',STATUS='SCRATCH')
- auto io{IONAME(BeginOpenNewUnit)(__FILE__, __LINE__)};
- IONAME(SetAccess)
- (io, "SEQUENTIAL", 10) || (Fail() << "SetAccess(SEQUENTIAL)", 0);
- IONAME(SetAction)
- (io, "READWRITE", 9) || (Fail() << "SetAction(READWRITE)", 0);
- IONAME(SetForm)
- (io, "FORMATTED", 9) || (Fail() << "SetForm(FORMATTED)", 0);
- IONAME(SetStatus)(io, "SCRATCH", 7) || (Fail() << "SetStatus(SCRATCH)", 0);
- int unit{-1};
- IONAME(GetNewUnit)(io, unit) || (Fail() << "GetNewUnit()", 0);
- llvm::errs() << "unit=" << unit << '\n';
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for OpenNewUnit", 0);
- static const int records{10};
- std::int64_t buffer[records]; // INTEGER*8 :: BUFFER(0:9) = [(j,j=0,9)]
- for (int j{0}; j < records; ++j) {
- buffer[j] = j;
- }
- char fmt[32];
- for (int j{1}; j <= records; ++j) {
- std::snprintf(fmt, sizeof fmt, "(%dI4)", j);
- // DO J=1,RECORDS; WRITE(UNIT=unit,FMT=fmt) BUFFER(0:j); END DO
- io = IONAME(BeginExternalFormattedOutput)(
- fmt, std::strlen(fmt), unit, __FILE__, __LINE__);
- for (int k{0}; k < j; ++k) {
- IONAME(OutputInteger64)
- (io, buffer[k]) || (Fail() << "OutputInteger64()", 0);
- }
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for OutputInteger64", 0);
- }
- // REWIND(UNIT=unit)
- io = IONAME(BeginRewind)(unit, __FILE__, __LINE__);
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for Rewind", 0);
- for (int j{1}; j <= records; ++j) {
- std::snprintf(fmt, sizeof fmt, "(%dI4)", j);
- // DO J=1,RECORDS; READ(UNIT=unit,FMT=fmt) n; check n; END DO
- io = IONAME(BeginExternalFormattedInput)(
- fmt, std::strlen(fmt), unit, __FILE__, __LINE__);
- std::int64_t check[records];
- for (int k{0}; k < j; ++k) {
- IONAME(InputInteger)(io, check[k]) || (Fail() << "InputInteger()", 0);
- }
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for InputInteger", 0);
- for (int k{0}; k < j; ++k) {
- if (buffer[k] != check[k]) {
- Fail() << "Read back [" << k << "]=" << check[k]
- << " from sequential variable formatted record " << j
- << ", expected " << buffer[k] << '\n';
- }
- }
- }
- for (int j{records}; j >= 1; --j) {
- // BACKSPACE(unit)
- io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for Backspace (before read)", 0);
- std::snprintf(fmt, sizeof fmt, "(%dI4)", j);
- // READ(UNIT=unit,FMT=fmt) n; check
- io = IONAME(BeginExternalFormattedInput)(
- fmt, std::strlen(fmt), unit, __FILE__, __LINE__);
- std::int64_t check[records];
- for (int k{0}; k < j; ++k) {
- IONAME(InputInteger)(io, check[k]) || (Fail() << "InputInteger()", 0);
- }
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for InputInteger", 0);
- for (int k{0}; k < j; ++k) {
- if (buffer[k] != check[k]) {
- Fail() << "Read back [" << k << "]=" << buffer[k]
- << " from sequential variable formatted record " << j
- << ", expected " << buffer[k] << '\n';
- }
- }
- // BACKSPACE(unit)
- io = IONAME(BeginBackspace)(unit, __FILE__, __LINE__);
- IONAME(EndIoStatement)
- (io) == IostatOk ||
- (Fail() << "EndIoStatement() for Backspace (after read)", 0);
- }
- // CLOSE(UNIT=unit,STATUS='DELETE')
- io = IONAME(BeginClose)(unit, __FILE__, __LINE__);
- IONAME(SetStatus)(io, "DELETE", 6) || (Fail() << "SetStatus(DELETE)", 0);
- IONAME(EndIoStatement)
- (io) == IostatOk || (Fail() << "EndIoStatement() for Close", 0);
- llvm::errs() << "end TestSequentialVariableFormatted()\n";
-}
-
-void TestStreamUnformatted() {
- // TODO
-}
-
-int main() {
- StartTests();
- TestDirectUnformatted();
- TestDirectUnformattedSwapped();
- TestSequentialFixedUnformatted();
- TestSequentialVariableUnformatted();
- TestDirectFormatted();
- TestSequentialVariableFormatted();
- TestStreamUnformatted();
- return EndTests();
-}
+++ /dev/null
-#include "testing.h"
-#include "../../runtime/terminator.h"
-#include <algorithm>
-#include <cstdarg>
-#include <cstdio>
-#include <cstring>
-#include <string>
-
-static int failures{0};
-
-// Override the Fortran runtime's Crash() for testing purposes
-[[noreturn]] static void CatchCrash(
- const char *sourceFile, int sourceLine, const char *message, va_list &ap) {
- char buffer[1000];
- std::vsnprintf(buffer, sizeof buffer, message, ap);
- va_end(ap);
- llvm::errs() << (sourceFile ? sourceFile : "unknown source file") << '('
- << sourceLine << "): CRASH: " << buffer << '\n';
- throw std::string{buffer};
-}
-
-void StartTests() {
- Fortran::runtime::Terminator::RegisterCrashHandler(CatchCrash);
-}
-
-llvm::raw_ostream &Fail() {
- ++failures;
- return llvm::errs();
-}
-
-int EndTests() {
- if (failures == 0) {
- llvm::outs() << "PASS\n";
- } else {
- llvm::outs() << "FAIL " << failures << " tests\n";
- }
- return failures != 0;
-}
+++ /dev/null
-#ifndef FORTRAN_TEST_RUNTIME_TESTING_H_
-#define FORTRAN_TEST_RUNTIME_TESTING_H_
-
-#include "llvm/Support/raw_ostream.h"
-#include <cstddef>
-
-namespace llvm {
-class raw_ostream;
-}
-
-void StartTests();
-llvm::raw_ostream &Fail();
-int EndTests();
-
-#endif // FORTRAN_TEST_RUNTIME_TESTING_H_
+++ /dev/null
-add_flang_unittest(FlangRuntimeTests
- BufferTest.cpp
- CharacterTest.cpp
- CrashHandlerFixture.cpp
- Format.cpp
- ListInputTest.cpp
- Matmul.cpp
- MiscIntrinsic.cpp
- Namelist.cpp
- Numeric.cpp
- NumericalFormatTest.cpp
- Random.cpp
- Reduction.cpp
- RuntimeCrashTest.cpp
- Time.cpp
- Transformational.cpp
-)
-
-target_link_libraries(FlangRuntimeTests
- PRIVATE
- FortranRuntime
-)