Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-16 08:04:41

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 "ActsPlugins/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 using namespace ActsPlugins;
0047 
0048 namespace ActsTests {
0049 
0050 BOOST_AUTO_TEST_SUITE(FpeMonitoringSuite)
0051 
0052 BOOST_AUTO_TEST_CASE(Invalid) {
0053   FpeMonitor mon;
0054   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0055   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0056   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0057 
0058   invalid();
0059 
0060   BOOST_CHECK(mon.result().encountered(FpeType::FLTINV));
0061   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0062   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0063 }
0064 
0065 BOOST_AUTO_TEST_CASE(DivByZero) {
0066   FpeMonitor mon;
0067   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0068   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0069   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0070 
0071   divbyzero();
0072 
0073   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0074   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0075   BOOST_CHECK(mon.result().encountered(FpeType::FLTDIV));
0076 }
0077 
0078 BOOST_AUTO_TEST_CASE(Overflow) {
0079   FpeMonitor mon;
0080   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0081   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0082   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0083 
0084   overflow();
0085   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0086   BOOST_CHECK(mon.result().encountered(FpeType::FLTOVF));
0087   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0088 }
0089 
0090 BOOST_AUTO_TEST_CASE(Combinations) {
0091   FpeMonitor mon;
0092   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0093   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0094   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0095 
0096   invalid();
0097   BOOST_CHECK(mon.result().encountered(FpeType::FLTINV));
0098   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0099   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0100 
0101   overflow();
0102   BOOST_CHECK(mon.result().encountered(FpeType::FLTINV));
0103   BOOST_CHECK(mon.result().encountered(FpeType::FLTOVF));
0104   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0105 
0106   divbyzero();
0107 
0108   BOOST_CHECK(mon.result().encountered(FpeType::FLTINV));
0109   BOOST_CHECK(mon.result().encountered(FpeType::FLTOVF));
0110   BOOST_CHECK(mon.result().encountered(FpeType::FLTDIV));
0111 }
0112 
0113 BOOST_AUTO_TEST_CASE(ClearOnEnter) {
0114   invalid();
0115   divbyzero();
0116   overflow();
0117 
0118   FpeMonitor mon;
0119   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0120   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0121   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0122 }
0123 
0124 BOOST_AUTO_TEST_CASE(CheckRearmCount) {
0125   FpeMonitor mon;
0126   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 0);
0127   BOOST_CHECK(mon.result().stackTraces().empty());
0128 
0129   invalid();
0130   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 1);
0131   BOOST_CHECK_EQUAL(mon.result().stackTraces().size(), 1);
0132 
0133   invalid();
0134   // We can't observe this again because it's masked!
0135   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 1);
0136   BOOST_CHECK_EQUAL(mon.result().stackTraces().size(), 1);
0137 
0138   mon.rearm();
0139   invalid();
0140   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 2);
0141   BOOST_CHECK_EQUAL(mon.result().stackTraces().size(),
0142                     1);  // still at one because we deduplicated
0143 
0144   mon.rearm();
0145   invalid2();
0146   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 3);
0147   BOOST_CHECK_EQUAL(mon.result().stackTraces().size(), 2);
0148   mon.result().deduplicate();  // doesn't do anything here actually
0149   BOOST_CHECK_EQUAL(mon.result().stackTraces().size(), 2);
0150 }
0151 
0152 BOOST_AUTO_TEST_CASE(Scoping) {
0153   FpeMonitor mon;
0154   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0155   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0156   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0157 
0158   invalid();
0159 
0160   {
0161     FpeMonitor mon2;
0162     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTINV));
0163     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTOVF));
0164     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTDIV));
0165 
0166     overflow();
0167 
0168     {
0169       FpeMonitor mon3;
0170       BOOST_CHECK(!mon3.result().encountered(FpeType::FLTINV));
0171       BOOST_CHECK(!mon3.result().encountered(FpeType::FLTOVF));
0172       BOOST_CHECK(!mon3.result().encountered(FpeType::FLTDIV));
0173 
0174       divbyzero();
0175 
0176       BOOST_CHECK(!mon3.result().encountered(FpeType::FLTINV));
0177       BOOST_CHECK(!mon3.result().encountered(FpeType::FLTOVF));
0178       BOOST_CHECK(mon3.result().encountered(FpeType::FLTDIV));
0179 
0180       // Test merging here
0181       auto merged = mon.result().merged(mon2.result());
0182       BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 1);
0183       BOOST_CHECK_EQUAL(mon2.result().count(FpeType::FLTOVF), 1);
0184       BOOST_CHECK_EQUAL(merged.count(FpeType::FLTINV), 1);
0185       BOOST_CHECK_EQUAL(merged.count(FpeType::FLTOVF), 1);
0186       BOOST_CHECK_EQUAL(merged.numStackTraces(), 2);
0187       merged = merged.merged(mon3.result());
0188       BOOST_CHECK_EQUAL(merged.count(FpeType::FLTINV), 1);
0189       BOOST_CHECK_EQUAL(merged.count(FpeType::FLTOVF), 1);
0190       BOOST_CHECK_EQUAL(merged.count(FpeType::FLTDIV), 1);
0191       BOOST_CHECK_EQUAL(merged.numStackTraces(), 3);
0192     }
0193 
0194     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTINV));
0195     BOOST_CHECK(mon2.result().encountered(FpeType::FLTOVF));
0196     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTDIV));
0197   }
0198 
0199   BOOST_CHECK(mon.result().encountered(FpeType::FLTINV));
0200   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0201   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0202 }
0203 
0204 BOOST_AUTO_TEST_CASE(MergeDeduplication) {
0205   FpeMonitor mon;
0206   invalid();
0207   {
0208     FpeMonitor mon2;
0209     invalid();
0210 
0211     auto merged = mon.result().merged(mon2.result());
0212     BOOST_CHECK_EQUAL(merged.count(FpeType::FLTINV), 2);
0213     BOOST_CHECK_EQUAL(merged.stackTraces().size(), 1);
0214   }
0215 }
0216 
0217 BOOST_AUTO_TEST_CASE(ScopedSuppression) {
0218   FpeMonitor mon;
0219   BOOST_CHECK(!mon.result().encountered(FpeType::FLTINV));
0220   BOOST_CHECK(!mon.result().encountered(FpeType::FLTOVF));
0221   BOOST_CHECK(!mon.result().encountered(FpeType::FLTDIV));
0222 
0223   invalid();
0224 
0225   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 1);
0226   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTOVF), 0);
0227   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTDIV), 0);
0228 
0229   {
0230     FpeMonitor mon2{0};  // disable all
0231     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTINV));
0232     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTOVF));
0233     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTDIV));
0234     invalid();
0235     divbyzero();
0236     overflow();
0237     // were not registered in inner scope
0238     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTINV));
0239     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTOVF));
0240     BOOST_CHECK(!mon2.result().encountered(FpeType::FLTDIV));
0241   }
0242 
0243   // outer scope is also unchanged
0244   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 1);
0245   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTOVF), 0);
0246   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTDIV), 0);
0247 
0248   invalid();
0249 
0250   // outer scope gets signal after being restored on the stack
0251   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTINV), 2);
0252   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTOVF), 0);
0253   BOOST_CHECK_EQUAL(mon.result().count(FpeType::FLTDIV), 0);
0254 }
0255 
0256 BOOST_AUTO_TEST_SUITE_END()
0257 
0258 }  // namespace ActsTests