brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · eaaf2a6 Raw
171 lines · cpp
1//===-- unittests/Runtime/RuntimeCrashTest.cpp ------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9/// Selected APIs are tested here to support development of unit tests for other10/// runtime components and ensure the test fixture handles crashes as we expect.11//12//===----------------------------------------------------------------------===//13#include "CrashHandlerFixture.h"14#include "tools.h"15#include "flang-rt/runtime/terminator.h"16#include "flang/Runtime/io-api.h"17#include "flang/Runtime/transformational.h"18#include <gtest/gtest.h>19 20using namespace Fortran::runtime;21using namespace Fortran::runtime::io;22using Fortran::common::TypeCategory;23 24//------------------------------------------------------------------------------25/// Test crashes through direct calls to terminator methods26//------------------------------------------------------------------------------27struct TestTerminator : CrashHandlerFixture {};28 29#define TEST_CRASH_HANDLER_MESSAGE \30  "Intentionally crashing runtime for unit test"31 32TEST(TestTerminator, CrashTest) {33  static Fortran::runtime::Terminator t;34  ASSERT_DEATH(t.Crash(TEST_CRASH_HANDLER_MESSAGE), TEST_CRASH_HANDLER_MESSAGE);35}36 37#undef TEST_CRASH_HANDLER_MESSAGE38 39TEST(TestTerminator, CheckFailedLocationTest) {40  static Fortran::runtime::Terminator t;41  ASSERT_DEATH(t.CheckFailed("predicate", "someFileName", 789),42      "RUNTIME_CHECK\\(predicate\\) failed at someFileName\\(789\\)");43}44 45TEST(TestTerminator, CheckFailedTest) {46  static Fortran::runtime::Terminator t("someFileName");47  ASSERT_DEATH(t.CheckFailed("predicate"),48      "RUNTIME_CHECK\\(predicate\\) failed at someFileName\\(0\\)");49}50 51//------------------------------------------------------------------------------52/// Test misuse of io api53//------------------------------------------------------------------------------54struct TestIOCrash : CrashHandlerFixture {};55 56TEST(TestIOCrash, InvalidFormatCharacterTest) {57  static constexpr int bufferSize{1};58  static char buffer[bufferSize];59  static const char *format{"(C1)"};60  auto *cookie{IONAME(BeginInternalFormattedOutput)(61      buffer, bufferSize, format, std::strlen(format))};62  ASSERT_DEATH(IONAME(OutputInteger64)(cookie, 0xfeedface),63      "Unknown 'C' edit descriptor in FORMAT");64}65 66//------------------------------------------------------------------------------67/// Test buffer overwrites with Output* functions68/// Each test performs the tested IO operation correctly first, before causing69/// an overwrite to demonstrate that the failure is caused by the overwrite and70/// not a misuse of the API.71//------------------------------------------------------------------------------72TEST(TestIOCrash, OverwriteBufferAsciiTest) {73  static constexpr int bufferSize{4};74  static char buffer[bufferSize];75  static const char *format{"(A4)"};76  auto *cookie{IONAME(BeginInternalFormattedOutput)(77      buffer, bufferSize, format, std::strlen(format))};78  IONAME(OutputAscii)(cookie, "four", bufferSize);79  ASSERT_DEATH(IONAME(OutputAscii)(cookie, "Too many characters!", 20),80      "Internal write overran available records");81}82 83TEST(TestIOCrash, OverwriteBufferCharacterTest) {84  static constexpr int bufferSize{1};85  static char buffer[bufferSize];86  static const char *format{"(A1)"};87  auto *cookie{IONAME(BeginInternalFormattedOutput)(88      buffer, bufferSize, format, std::strlen(format))};89  IONAME(OutputCharacter)(cookie, "a", 1);90  ASSERT_DEATH(IONAME(OutputCharacter)(cookie, "a", 1),91      "Internal write overran available records");92}93 94TEST(TestIOCrash, OverwriteBufferLogicalTest) {95  static constexpr int bufferSize{1};96  static char buffer[bufferSize];97  static const char *format{"(L1)"};98  auto *cookie{IONAME(BeginInternalFormattedOutput)(99      buffer, bufferSize, format, std::strlen(format))};100  IONAME(OutputLogical)(cookie, true);101  ASSERT_DEATH(IONAME(OutputLogical)(cookie, true),102      "Internal write overran available records");103}104 105TEST(TestIOCrash, OverwriteBufferRealTest) {106  static constexpr int bufferSize{1};107  static char buffer[bufferSize];108  static const char *format{"(F1)"};109  auto *cookie{IONAME(BeginInternalFormattedOutput)(110      buffer, bufferSize, format, std::strlen(format))};111  IONAME(OutputReal32)(cookie, 1.);112  EXPECT_DEATH(IONAME(OutputReal32)(cookie, 1.),113      "Internal write overran available records");114 115  std::memset(buffer, '\0', bufferSize);116  cookie = IONAME(BeginInternalFormattedOutput)(117      buffer, bufferSize, format, std::strlen(format));118  IONAME(OutputReal64)(cookie, 1.);119  EXPECT_DEATH(IONAME(OutputReal64)(cookie, 1.),120      "Internal write overran available records");121}122 123TEST(TestIOCrash, OverwriteBufferComplexTest) {124  static constexpr int bufferSize{8};125  static char buffer[bufferSize];126  static const char *format{"(Z1,Z1)"};127  auto *cookie{IONAME(BeginInternalFormattedOutput)(128      buffer, bufferSize, format, std::strlen(format))};129  IONAME(OutputComplex32)(cookie, 1., 1.);130  EXPECT_DEATH(IONAME(OutputComplex32)(cookie, 1., 1.),131      "Internal write overran available records");132 133  std::memset(buffer, '\0', bufferSize);134  cookie = IONAME(BeginInternalFormattedOutput)(135      buffer, bufferSize, format, std::strlen(format));136  IONAME(OutputComplex64)(cookie, 1., 1.);137  EXPECT_DEATH(IONAME(OutputComplex64)(cookie, 1., 1.),138      "Internal write overran available records");139}140 141TEST(TestIOCrash, OverwriteBufferIntegerTest) {142  static constexpr int bufferSize{1};143  static char buffer[bufferSize];144  static const char *format{"(I1)"};145  auto *cookie{IONAME(BeginInternalFormattedOutput)(146      buffer, bufferSize, format, std::strlen(format))};147  IONAME(OutputInteger64)(cookie, 0xdeadbeef);148  ASSERT_DEATH(IONAME(OutputInteger64)(cookie, 0xdeadbeef),149      "Internal write overran available records");150}151 152//------------------------------------------------------------------------------153/// Test conformity issue reports in transformational intrinsics154//------------------------------------------------------------------------------155struct TestIntrinsicCrash : CrashHandlerFixture {};156 157TEST(TestIntrinsicCrash, ConformityErrors) {158  // ARRAY(2,3) and MASK(2,4) should trigger a runtime error.159  auto array{MakeArray<TypeCategory::Integer, 4>(160      std::vector<int>{2, 3}, std::vector<std::int32_t>{1, 2, 3, 4, 5, 6})};161  auto mask{MakeArray<TypeCategory::Logical, 1>(std::vector<int>{2, 4},162      std::vector<std::uint8_t>{163          false, true, true, false, false, true, true, true})};164  StaticDescriptor<1, true> statDesc;165  Descriptor &result{statDesc.descriptor()};166 167  ASSERT_DEATH(RTNAME(Pack)(result, *array, *mask, nullptr, __FILE__, __LINE__),168      "Incompatible array arguments to PACK: dimension 2 of ARRAY= has extent "169      "3 but MASK= has extent 4");170}171