LCOV - code coverage report
Current view: top level - tests - catch_safe_object.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 90 91 98.9 %
Date: 2024-01-13 16:46:58 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2019-2024  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/snapdev
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software: you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation, either version 3 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License
      17             : // along with this program.  If not, see <https://www.gnu.org/licenses/>.
      18             : 
      19             : /** \file
      20             :  * \brief Verify that the safe_object template works.
      21             :  *
      22             :  * This file implements tests for the safe_object template to make sure that
      23             :  * it works as expected.
      24             :  */
      25             : 
      26             : // self
      27             : //
      28             : #include    <snapdev/safe_object.h>
      29             : 
      30             : #include    "catch_main.h"
      31             : 
      32             : 
      33             : // snapdev
      34             : //
      35             : #include    <snapdev/not_reached.h>
      36             : 
      37             : 
      38             : // last include
      39             : //
      40             : #include    <snapdev/poison.h>
      41             : 
      42             : 
      43             : namespace
      44             : {
      45             : 
      46             : 
      47             : bool g_allocated = false;
      48             : 
      49          59 : bool object_is_allocated()
      50             : {
      51          59 :     return g_allocated;
      52             : }
      53             : 
      54             : class test_object
      55             : {
      56             : public:
      57          12 :     test_object()
      58             :     {
      59          12 :         g_allocated = true;
      60          12 :     }
      61             : 
      62          12 :     ~test_object()
      63             :     {
      64          12 :         g_allocated = false;
      65          12 :     }
      66             : };
      67             : 
      68             : 
      69             : typedef int     identifier_t;
      70             : 
      71             : typedef std::map<identifier_t, bool>        map_id_t;
      72             : 
      73             : map_id_t        g_map_ids = map_id_t();
      74             : 
      75          10 : identifier_t alloc_id()
      76             : {
      77             :     for(;;)
      78             :     {
      79          10 :         identifier_t id(rand());
      80          10 :         if(g_map_ids.find(id) == g_map_ids.end())
      81             :         {
      82          10 :             g_map_ids[id] = true;
      83          20 :             return id;
      84             :         }
      85           0 :     }
      86             : }
      87             : 
      88          10 : void delete_id(identifier_t id)
      89             : {
      90          10 :     auto it(g_map_ids.find(id));
      91          10 :     CATCH_REQUIRE(it != g_map_ids.end());
      92          10 :     g_map_ids.erase(it);
      93          10 : }
      94             : 
      95          50 : bool id_is_allocated(identifier_t id)
      96             : {
      97          50 :     return g_map_ids.find(id) != g_map_ids.end();
      98             : }
      99             : 
     100             : 
     101             : } // no name namespace
     102             : 
     103             : 
     104           4 : CATCH_TEST_CASE("safe_object", "[raii]")
     105             : {
     106           4 :     CATCH_START_SECTION("safe_object: expected usage")
     107             :     {
     108           1 :         snapdev::safe_object<test_object *> so;
     109           1 :         CATCH_REQUIRE_FALSE(object_is_allocated());
     110           1 :         test_object * obj(new test_object);
     111           1 :         CATCH_REQUIRE(object_is_allocated());
     112           1 :         so.make_safe(obj);
     113           1 :         CATCH_REQUIRE(obj != nullptr);  // this is always true because if new fails, it throws bad_alloc
     114           1 :         CATCH_REQUIRE(object_is_allocated());
     115           1 :         so.release();
     116           1 :         CATCH_REQUIRE(object_is_allocated());
     117           1 :         delete obj;
     118           1 :         CATCH_REQUIRE_FALSE(object_is_allocated());
     119           1 :     }
     120           4 :     CATCH_END_SECTION()
     121             : 
     122           4 :     CATCH_START_SECTION("safe_object: with exception")
     123             :     {
     124             :         try
     125             :         {
     126           1 :             snapdev::safe_object<test_object *> so;
     127           1 :             CATCH_REQUIRE_FALSE(object_is_allocated());
     128           1 :             test_object * obj(new test_object);
     129           1 :             CATCH_REQUIRE(object_is_allocated());
     130           1 :             so.make_safe(obj);
     131           1 :             CATCH_REQUIRE(obj != nullptr);  // this is always true because if new fails, it throws bad_alloc
     132           1 :             CATCH_REQUIRE(object_is_allocated());
     133           1 :             throw std::range_error("test exception");
     134             :             snapdev::NOT_REACHED();
     135           1 :         }
     136           1 :         catch(std::exception const & e)
     137             :         {
     138           1 :             CATCH_REQUIRE_FALSE(object_is_allocated());
     139           1 :         }
     140             :     }
     141           4 :     CATCH_END_SECTION()
     142             : 
     143           4 :     CATCH_START_SECTION("safe_object: test both ways")
     144             :     {
     145          11 :         for(int idx(0); idx < 10; ++idx)
     146             :         {
     147             :             try
     148             :             {
     149          10 :                 snapdev::safe_object<test_object *> so;
     150          10 :                 CATCH_REQUIRE_FALSE(object_is_allocated());
     151          10 :                 test_object * obj(new test_object);
     152          10 :                 CATCH_REQUIRE(object_is_allocated());
     153          10 :                 so.make_safe(obj);
     154          10 :                 CATCH_REQUIRE(obj != nullptr);  // this is always true because if new fails, it throws bad_alloc
     155          10 :                 CATCH_REQUIRE(object_is_allocated());
     156          10 :                 if((idx & 1) == 0)
     157             :                 {
     158           5 :                     throw std::range_error("test exception");
     159             :                     snapdev::NOT_REACHED();
     160             :                 }
     161           5 :                 so.release();
     162           5 :                 CATCH_REQUIRE(object_is_allocated());
     163           5 :                 delete obj;
     164           5 :                 CATCH_REQUIRE_FALSE(object_is_allocated());
     165          10 :             }
     166           5 :             catch(std::exception const & e)
     167             :             {
     168             :                 // prevent propagation
     169           5 :             }
     170          10 :             CATCH_REQUIRE_FALSE(object_is_allocated());
     171             :         }
     172             :     }
     173           4 :     CATCH_END_SECTION()
     174             : 
     175           4 :     CATCH_START_SECTION("safe_object: test with resource identifiers")
     176             :     {
     177          11 :         for(int idx(0); idx < 10; ++idx)
     178             :         {
     179          10 :             identifier_t id(rand());
     180             :             try
     181             :             {
     182          10 :                 snapdev::safe_object<identifier_t, delete_id> so;
     183          10 :                 CATCH_REQUIRE_FALSE(id_is_allocated(id));
     184          10 :                 id = alloc_id();
     185          10 :                 CATCH_REQUIRE(id_is_allocated(id));
     186          10 :                 so.make_safe(id);
     187          10 :                 CATCH_REQUIRE(id_is_allocated(id));
     188          10 :                 if((idx & 1) == 0)
     189             :                 {
     190           5 :                     throw std::range_error("id exception");
     191             :                     snapdev::NOT_REACHED();
     192             :                 }
     193           5 :                 so.release();
     194           5 :                 CATCH_REQUIRE(id_is_allocated(id));
     195           5 :                 delete_id(id);
     196           5 :                 CATCH_REQUIRE_FALSE(id_is_allocated(id));
     197          10 :             }
     198           5 :             catch(std::exception const & e)
     199             :             {
     200             :                 // prevent propagation
     201           5 :             }
     202          10 :             CATCH_REQUIRE_FALSE(id_is_allocated(id));
     203             :         }
     204             :     }
     205           4 :     CATCH_END_SECTION()
     206           4 : }
     207             : 
     208             : 
     209             : 
     210             : // vim: ts=4 sw=4 et
     211             : 

Generated by: LCOV version 1.14

Snap C++ | List of projects | List of versions