[flang-commits] [flang] 168b206 - [flang] Unittests for runtime terminator
Andrzej Warzynski via flang-commits
flang-commits at lists.llvm.org
Thu Mar 18 08:55:05 PDT 2021
Author: Asher Mancinelli
Date: 2021-03-18T15:54:48Z
New Revision: 168b206cd8efb59438a1db65d8e1639ae2c9f662
URL: https://github.com/llvm/llvm-project/commit/168b206cd8efb59438a1db65d8e1639ae2c9f662
DIFF: https://github.com/llvm/llvm-project/commit/168b206cd8efb59438a1db65d8e1639ae2c9f662.diff
LOG: [flang] Unittests for runtime terminator
Create test fixture for runtime tests which enables verification
of failure cases. Test some runtime IO APIs for failure cases.
Support testing efforts in D98303. Expand on effort discussed
in D98601.
Reviewed By: awarzynski
Differential Revision: https://reviews.llvm.org/D98652
Added:
flang/unittests/RuntimeGTest/CrashHandlerFixture.cpp
flang/unittests/RuntimeGTest/CrashHandlerFixture.h
flang/unittests/RuntimeGTest/RuntimeCrashTest.cpp
Modified:
flang/unittests/RuntimeGTest/CMakeLists.txt
Removed:
################################################################################
diff --git a/flang/unittests/RuntimeGTest/CMakeLists.txt b/flang/unittests/RuntimeGTest/CMakeLists.txt
index 77aff3069f14..f26cb44be5fe 100644
--- a/flang/unittests/RuntimeGTest/CMakeLists.txt
+++ b/flang/unittests/RuntimeGTest/CMakeLists.txt
@@ -1,5 +1,7 @@
add_flang_unittest(FlangRuntimeTests
CharacterTest.cpp
+ RuntimeCrashTest.cpp
+ CrashHandlerFixture.cpp
)
target_link_libraries(FlangRuntimeTests
diff --git a/flang/unittests/RuntimeGTest/CrashHandlerFixture.cpp b/flang/unittests/RuntimeGTest/CrashHandlerFixture.cpp
new file mode 100644
index 000000000000..315a555789e7
--- /dev/null
+++ b/flang/unittests/RuntimeGTest/CrashHandlerFixture.cpp
@@ -0,0 +1,34 @@
+//===-- flang/unittests/RuntimeGTest/CrashHandlerFixture.cpp ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "CrashHandlerFixture.h"
+#include "../../runtime/terminator.h"
+#include <cstdarg>
+#include <cstdlib>
+
+// Replaces Fortran runtime's crash handler so we can verify the crash message
+[[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()
+ << "Test "
+ << ::testing::UnitTest::GetInstance()->current_test_info()->name()
+ << " crashed in file "
+ << (sourceFile ? sourceFile : "unknown source file") << '(' << sourceLine
+ << "): " << buffer << '\n';
+ std::exit(EXIT_FAILURE);
+}
+
+// Register the crash handler above when creating each unit test in this suite
+void CrashHandlerFixture::SetUp() {
+ static bool isCrashHanlderRegistered{false};
+ if (not isCrashHanlderRegistered)
+ Fortran::runtime::Terminator::RegisterCrashHandler(CatchCrash);
+ isCrashHanlderRegistered = true;
+}
diff --git a/flang/unittests/RuntimeGTest/CrashHandlerFixture.h b/flang/unittests/RuntimeGTest/CrashHandlerFixture.h
new file mode 100644
index 000000000000..d368c6fb55ba
--- /dev/null
+++ b/flang/unittests/RuntimeGTest/CrashHandlerFixture.h
@@ -0,0 +1,21 @@
+//===-- flang/unittests/RuntimeGTest/CrashHandlerFixture.h ------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+/// Test fixture registers a custom crash handler to ensure death tests fail
+/// with expected message.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_FLANG_UNITTESTS_RUNTIMEGTEST_CRASHHANDLERFIXTURE_H
+#define LLVM_FLANG_UNITTESTS_RUNTIMEGTEST_CRASHHANDLERFIXTURE_H
+#include <gtest/gtest.h>
+
+struct CrashHandlerFixture : testing::Test {
+ void SetUp();
+};
+
+#endif
diff --git a/flang/unittests/RuntimeGTest/RuntimeCrashTest.cpp b/flang/unittests/RuntimeGTest/RuntimeCrashTest.cpp
new file mode 100644
index 000000000000..c8945409c8c7
--- /dev/null
+++ b/flang/unittests/RuntimeGTest/RuntimeCrashTest.cpp
@@ -0,0 +1,157 @@
+//===-- flang/unittests/RuntimeGTest/CrashHandlerFixture.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
+//
+//===----------------------------------------------------------------------===//
+//
+/// Selected APIs are tested here to support development of unit tests for other
+/// runtime components and ensure the test fixture handles crashes as we expect.
+//
+//===----------------------------------------------------------------------===//
+#include "CrashHandlerFixture.h"
+#include "../../runtime/io-api.h"
+#include "../../runtime/terminator.h"
+#include <gtest/gtest.h>
+
+using namespace Fortran::runtime;
+using namespace Fortran::runtime::io;
+
+//------------------------------------------------------------------------------
+/// Test crashes through direct calls to terminator methods
+//------------------------------------------------------------------------------
+struct TestTerminator : CrashHandlerFixture {};
+
+#define TEST_CRASH_HANDLER_MESSAGE \
+ "Intentionally crashing runtime for unit test"
+
+TEST(TestTerminator, CrashTest) {
+ static Fortran::runtime::Terminator t;
+ ASSERT_DEATH(t.Crash(TEST_CRASH_HANDLER_MESSAGE), TEST_CRASH_HANDLER_MESSAGE);
+}
+
+#undef TEST_CRASH_HANDLER_MESSAGE
+
+TEST(TestTerminator, CheckFailedLocationTest) {
+ static Fortran::runtime::Terminator t;
+ ASSERT_DEATH(t.CheckFailed("predicate", "someFileName", 789),
+ "RUNTIME_CHECK\\(predicate\\) failed at someFileName\\(789\\)");
+}
+
+TEST(TestTerminator, CheckFailedTest) {
+ static Fortran::runtime::Terminator t;
+ ASSERT_DEATH(t.CheckFailed("predicate"),
+ "RUNTIME_CHECK\\(predicate\\) failed at \\(null\\)\\(0\\)");
+}
+
+//------------------------------------------------------------------------------
+/// Test misuse of io api
+//------------------------------------------------------------------------------
+struct TestIOCrash : CrashHandlerFixture {};
+
+TEST(TestIOCrash, FormatDescriptorWriteMismatchTest) {
+ static constexpr int bufferSize{4};
+ static char buffer[bufferSize];
+ static const char *format{"(A4)"};
+ auto *cookie{IONAME(BeginInternalFormattedOutput)(
+ buffer, bufferSize, format, std::strlen(format))};
+ ASSERT_DEATH(IONAME(OutputInteger64)(cookie, 0xfeedface),
+ "Data edit descriptor 'A' may not be used with an INTEGER data item");
+}
+
+TEST(TestIOCrash, InvalidFormatCharacterTest) {
+ static constexpr int bufferSize{1};
+ static char buffer[bufferSize];
+ static const char *format{"(C1)"};
+ auto *cookie{IONAME(BeginInternalFormattedOutput)(
+ buffer, bufferSize, format, std::strlen(format))};
+ ASSERT_DEATH(IONAME(OutputInteger64)(cookie, 0xfeedface),
+ "Unknown 'C' edit descriptor in FORMAT");
+}
+
+//------------------------------------------------------------------------------
+/// Test buffer overwrites with Output* functions
+/// Each test performs the tested IO operation correctly first, before causing
+/// an overwrite to demonstrate that the failure is caused by the overwrite and
+/// not a misuse of the API.
+//------------------------------------------------------------------------------
+TEST(TestIOCrash, OverwriteBufferAsciiTest) {
+ static constexpr int bufferSize{4};
+ static char buffer[bufferSize];
+ static const char *format{"(A4)"};
+ auto *cookie{IONAME(BeginInternalFormattedOutput)(
+ buffer, bufferSize, format, std::strlen(format))};
+ IONAME(OutputAscii)(cookie, "four", bufferSize);
+ ASSERT_DEATH(IONAME(OutputAscii)(cookie, "Too many characters!", 20),
+ "Internal write overran available records");
+}
+
+TEST(TestIOCrash, OverwriteBufferCharacterTest) {
+ static constexpr int bufferSize{1};
+ static char buffer[bufferSize];
+ static const char *format{"(A1)"};
+ auto *cookie{IONAME(BeginInternalFormattedOutput)(
+ buffer, bufferSize, format, std::strlen(format))};
+ IONAME(OutputCharacter)(cookie, "a", 1);
+ ASSERT_DEATH(IONAME(OutputCharacter)(cookie, "a", 1),
+ "Internal write overran available records");
+}
+
+TEST(TestIOCrash, OverwriteBufferLogicalTest) {
+ static constexpr int bufferSize{1};
+ static char buffer[bufferSize];
+ static const char *format{"(L1)"};
+ auto *cookie{IONAME(BeginInternalFormattedOutput)(
+ buffer, bufferSize, format, std::strlen(format))};
+ IONAME(OutputLogical)(cookie, true);
+ ASSERT_DEATH(IONAME(OutputLogical)(cookie, true),
+ "Internal write overran available records");
+}
+
+TEST(TestIOCrash, OverwriteBufferRealTest) {
+ static constexpr int bufferSize{1};
+ static char buffer[bufferSize];
+ static const char *format{"(F1)"};
+ auto *cookie{IONAME(BeginInternalFormattedOutput)(
+ buffer, bufferSize, format, std::strlen(format))};
+ IONAME(OutputReal32)(cookie, 1.);
+ EXPECT_DEATH(IONAME(OutputReal32)(cookie, 1.),
+ "Internal write overran available records");
+
+ std::memset(buffer, '\0', bufferSize);
+ cookie = IONAME(BeginInternalFormattedOutput)(
+ buffer, bufferSize, format, std::strlen(format));
+ IONAME(OutputReal64)(cookie, 1.);
+ EXPECT_DEATH(IONAME(OutputReal64)(cookie, 1.),
+ "Internal write overran available records");
+}
+
+TEST(TestIOCrash, OverwriteBufferComplexTest) {
+ static constexpr int bufferSize{8};
+ static char buffer[bufferSize];
+ static const char *format{"(Z1,Z1)"};
+ auto *cookie{IONAME(BeginInternalFormattedOutput)(
+ buffer, bufferSize, format, std::strlen(format))};
+ IONAME(OutputComplex32)(cookie, 1., 1.);
+ EXPECT_DEATH(IONAME(OutputComplex32)(cookie, 1., 1.),
+ "Internal write overran available records");
+
+ std::memset(buffer, '\0', bufferSize);
+ cookie = IONAME(BeginInternalFormattedOutput)(
+ buffer, bufferSize, format, std::strlen(format));
+ IONAME(OutputComplex64)(cookie, 1., 1.);
+ EXPECT_DEATH(IONAME(OutputComplex64)(cookie, 1., 1.),
+ "Internal write overran available records");
+}
+
+TEST(TestIOCrash, OverwriteBufferIntegerTest) {
+ static constexpr int bufferSize{1};
+ static char buffer[bufferSize];
+ static const char *format{"(I1)"};
+ auto *cookie{IONAME(BeginInternalFormattedOutput)(
+ buffer, bufferSize, format, std::strlen(format))};
+ IONAME(OutputInteger64)(cookie, 0xdeadbeef);
+ ASSERT_DEATH(IONAME(OutputInteger64)(cookie, 0xdeadbeef),
+ "Internal write overran available records");
+}
More information about the flang-commits
mailing list