Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:13:09

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Plugins/FpeMonitoring/FpeMonitor.hpp"
0012 
0013 #include <cmath>
0014 #include <optional>
0015 
0016 namespace {
0017 
0018 __attribute__((noinline)) void divbyzero() {
0019   volatile float j = 0.0;
0020   volatile float r = 123 / j;
0021   (void)r;
0022 }
0023 
0024 __attribute__((noinline)) void overflow() {
0025   std::cout << "PRE OVERFLOW" << std::endl;
0026   volatile float j = std::numeric_limits<float>::max();
0027   volatile float r = j * j;
0028   (void)r;
0029   std::cout << "POST OVERFLOW" << std::endl;
0030 }
0031 
0032 __attribute__((noinline)) void invalid() {
0033   volatile float j = -1;
0034   volatile float r = std::sqrt(j);
0035   (void)r;
0036 }
0037 
0038 __attribute__((noinline)) void invalid2() {
0039   volatile float k = 0;
0040   volatile float p = k / 0.0;
0041   (void)p;
0042 }
0043 
0044 }  // namespace
0045 
0046 namespace Acts::Test {
0047 
0048 BOOST_AUTO_TEST_SUITE(FpeMonitorTest)
0049 
0050 BOOST_AUTO_TEST_CASE(Invalid) {
0051   FpeMonitor mon;
0052   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0053   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0054   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0055 
0056   invalid();
0057 
0058   BOOST_CHECK(mon.result().encountered(FpeType::FLTINV));
0059   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0060   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0061 }
0062 
0063 BOOST_AUTO_TEST_CASE(DivByZero) {
0064   FpeMonitor mon;
0065   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0066   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0067   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0068 
0069   divbyzero();
0070 
0071   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0072   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0073   BOOST_CHECK(mon.result().encountered(FpeType::FLTDIV));
0074 }
0075 
0076 BOOST_AUTO_TEST_CASE(Overflow) {
0077   FpeMonitor mon;
0078   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0079   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0080   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0081 
0082   overflow();
0083   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0084   BOOST_CHECK(mon.result().encountered(FpeType::FLTOVF));
0085   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0086 }
0087 
0088 BOOST_AUTO_TEST_CASE(Combinations) {
0089   FpeMonitor mon;
0090   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0091   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0092   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0093 
0094   invalid();
0095   BOOST_CHECK(mon.result().encountered(FpeType::FLTINV));
0096   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0097   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0098 
0099   overflow();
0100   BOOST_CHECK(mon.result().encountered(FpeType::FLTINV));
0101   BOOST_CHECK(mon.result().encountered(FpeType::FLTOVF));
0102   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0103 
0104   divbyzero();
0105 
0106   BOOST_CHECK(mon.result().encountered(FpeType::FLTINV));
0107   BOOST_CHECK(mon.result().encountered(FpeType::FLTOVF));
0108   BOOST_CHECK(mon.result().encountered(FpeType::FLTDIV));
0109 }
0110 
0111 BOOST_AUTO_TEST_CASE(ClearOnEnter) {
0112   invalid();
0113   divbyzero();
0114   overflow();
0115 
0116   FpeMonitor mon;
0117   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0118   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0119   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0120 }
0121 
0122 BOOST_AUTO_TEST_CASE(CheckRearmCount) {
0123   FpeMonitor mon;
0124   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 0);
0125   BOOST_CHECK(mon.result().stackTraces().empty());
0126 
0127   invalid();
0128   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 1);
0129   BOOST_CHECK_EQUAL(mon.result().stackTraces().size(), 1);
0130 
0131   invalid();
0132   // We can't observe this again because it's masked!
0133   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 1);
0134   BOOST_CHECK_EQUAL(mon.result().stackTraces().size(), 1);
0135 
0136   mon.rearm();
0137   invalid();
0138   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 2);
0139   BOOST_CHECK_EQUAL(mon.result().stackTraces().size(),
0140                     1);  // still at one because we deduplicated
0141 
0142   mon.rearm();
0143   invalid2();
0144   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 3);
0145   BOOST_CHECK_EQUAL(mon.result().stackTraces().size(), 2);
0146   mon.result().deduplicate();  // doesn't do anything here actually
0147   BOOST_CHECK_EQUAL(mon.result().stackTraces().size(), 2);
0148 }
0149 
0150 BOOST_AUTO_TEST_CASE(Scoping) {
0151   FpeMonitor mon;
0152   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0153   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0154   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0155 
0156   invalid();
0157 
0158   {
0159     FpeMonitor mon2;
0160     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTINV));
0161     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTOVF));
0162     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTDIV));
0163 
0164     overflow();
0165 
0166     {
0167       FpeMonitor mon3;
0168       BOOST_CHECK(!mon3.result().encountered(FpeType::FLTINV));
0169       BOOST_CHECK(!mon3.result().encountered(FpeType::FLTOVF));
0170       BOOST_CHECK(!mon3.result().encountered(FpeType::FLTDIV));
0171 
0172       divbyzero();
0173 
0174       BOOST_CHECK(!mon3.result().encountered(FpeType::FLTINV));
0175       BOOST_CHECK(!mon3.result().encountered(FpeType::FLTOVF));
0176       BOOST_CHECK(mon3.result().encountered(FpeType::FLTDIV));
0177 
0178       // Test merging here
0179       auto merged = mon.result().merged(mon2.result());
0180       BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 1);
0181       BOOST_CHECK_EQUAL(mon2.result().count(FpeType::FLTOVF), 1);
0182       BOOST_CHECK_EQUAL(merged.count(FpeType::FLTINV), 1);
0183       BOOST_CHECK_EQUAL(merged.count(FpeType::FLTOVF), 1);
0184       BOOST_CHECK_EQUAL(merged.numStackTraces(), 2);
0185       merged = merged.merged(mon3.result());
0186       BOOST_CHECK_EQUAL(merged.count(FpeType::FLTINV), 1);
0187       BOOST_CHECK_EQUAL(merged.count(FpeType::FLTOVF), 1);
0188       BOOST_CHECK_EQUAL(merged.count(FpeType::FLTDIV), 1);
0189       BOOST_CHECK_EQUAL(merged.numStackTraces(), 3);
0190     }
0191 
0192     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTINV));
0193     BOOST_CHECK(mon2.result().encountered(FpeType::FLTOVF));
0194     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTDIV));
0195   }
0196 
0197   BOOST_CHECK(mon.result().encountered(FpeType::FLTINV));
0198   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0199   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0200 }
0201 
0202 BOOST_AUTO_TEST_CASE(MergeDeduplication) {
0203   FpeMonitor mon;
0204   invalid();
0205   {
0206     FpeMonitor mon2;
0207     invalid();
0208 
0209     auto merged = mon.result().merged(mon2.result());
0210     BOOST_CHECK_EQUAL(merged.count(FpeType::FLTINV), 2);
0211     BOOST_CHECK_EQUAL(merged.stackTraces().size(), 1);
0212   }
0213 }
0214 
0215 BOOST_AUTO_TEST_CASE(ScopedSuppression) {
0216   FpeMonitor mon;
0217   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0218   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0219   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0220 
0221   invalid();
0222 
0223   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 1);
0224   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTOVF), 0);
0225   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTDIV), 0);
0226 
0227   {
0228     FpeMonitor mon2{0};  // disable all
0229     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTINV));
0230     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTOVF));
0231     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTDIV));
0232     invalid();
0233     divbyzero();
0234     overflow();
0235     // were not registered in inner scope
0236     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTINV));
0237     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTOVF));
0238     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTDIV));
0239   }
0240 
0241   // outer scope is also unchanged
0242   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 1);
0243   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTOVF), 0);
0244   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTDIV), 0);
0245 
0246   invalid();
0247 
0248   // outer scope gets signal after being restored on the stack
0249   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 2);
0250   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTOVF), 0);
0251   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTDIV), 0);
0252 }
0253 
0254 BOOST_AUTO_TEST_SUITE_END()
0255 
0256 }  // namespace Acts::Test