LCOV - code coverage report
Current view: top level - tests - catch_lockfile.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 92.4 % 290 268
Test Date: 2026-08-02 20:00:41 Functions: 100.0 % 9 9
Legend: Lines: hit not hit

            Line data    Source code
       1              : // Copyright (c) 2018-2026  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 lockfile classes work as expected.
      21              :  *
      22              :  * This file implements tests to verify the lockfile and lockfd functionality.
      23              :  */
      24              : 
      25              : // file being tested
      26              : //
      27              : #include    <snapdev/lockfile.h>
      28              : 
      29              : 
      30              : // self
      31              : //
      32              : #include    "catch_main.h"
      33              : 
      34              : 
      35              : // snapdev
      36              : //
      37              : #include    <snapdev/timespec_ex.h>
      38              : 
      39              : 
      40              : // C++
      41              : //
      42              : #include    <thread>
      43              : 
      44              : 
      45              : // last include
      46              : //
      47              : #include    <snapdev/poison.h>
      48              : 
      49              : 
      50              : 
      51              : namespace
      52              : {
      53              : 
      54              : 
      55              : class lockfile_thread
      56              : {
      57              : public:
      58            7 :     lockfile_thread(
      59              :               std::string const & filename
      60              :             , snapdev::operation_t operation = snapdev::operation_t::OPERATION_EXCLUSIVE)
      61            7 :         : f_filename(filename)
      62            7 :         , f_operation(operation)
      63              :     {
      64            7 :     }
      65              : 
      66              :     lockfile_thread(lockfile_thread const &) = delete;
      67              :     lockfile_thread & operator = (lockfile_thread const &) = delete;
      68              : 
      69            7 :     ~lockfile_thread()
      70              :     {
      71            7 :         if(f_thread != nullptr)
      72              :         {
      73            7 :             f_thread->join();
      74            7 :             delete f_thread;
      75              :         }
      76            7 :     }
      77              : 
      78            7 :     void start_thread(int try_lock = 0)
      79              :     {
      80            7 :         f_running = true;
      81            7 :         if(try_lock)
      82              :         {
      83            4 :             f_thread = new std::thread(&lockfile_thread::run_try_lock, this, try_lock);
      84              :         }
      85              :         else
      86              :         {
      87            3 :             f_thread = new std::thread(&lockfile_thread::run, this);
      88              :         }
      89            7 :     }
      90              : 
      91            3 :     void run()
      92              :     {
      93            3 :         snapdev::lockfile lock(f_filename, f_operation);
      94            3 :         if(lock.is_locked())
      95              :         {
      96            0 :             throw std::runtime_error("file is locked on creation.");
      97              :         }
      98            3 :         lock.lock();
      99            3 :         if(!lock.is_locked())
     100              :         {
     101            0 :             throw std::runtime_error("file could not be locked.");
     102              :         }
     103              : 
     104            3 :         std::lock_guard<std::mutex> guard(f_mutex);
     105            3 :         f_running = false;
     106            6 :     }
     107              : 
     108            4 :     void run_try_lock(int try_lock)
     109              :     {
     110            4 :         snapdev::lockfile lock(f_filename, f_operation);
     111            4 :         if(lock.is_locked())
     112              :         {
     113            0 :             throw std::runtime_error("file is locked on creation.");
     114              :         }
     115            4 :         lock.try_lock();
     116            4 :         if(try_lock == 1)
     117              :         {
     118            1 :             if(!lock.is_locked())
     119              :             {
     120            0 :                 throw std::runtime_error("file did not get locked on first try.");
     121              :             }
     122              :         }
     123              :         else
     124              :         {
     125            3 :             if(lock.is_locked())
     126              :             {
     127            0 :                 throw std::runtime_error("file did get locked on further tries.");
     128              :             }
     129              :         }
     130              : 
     131            4 :         std::lock_guard<std::mutex> guard(f_mutex);
     132            4 :         f_running = false;
     133            8 :     }
     134              : 
     135           15 :     bool is_running() const
     136              :     {
     137           15 :         std::lock_guard<std::mutex> guard(f_mutex);
     138           15 :         return f_running;
     139           15 :     }
     140              : 
     141              : private:
     142              :     mutable std::mutex      f_mutex = std::mutex();
     143              :     std::string             f_filename = std::string();
     144              :     snapdev::operation_t    f_operation = snapdev::operation_t::OPERATION_EXCLUSIVE;
     145              :     std::thread *           f_thread = nullptr;
     146              :     bool                    f_running = false;
     147              : };
     148              : 
     149              : 
     150              : } // no name namespace
     151              : 
     152              : 
     153              : 
     154            9 : CATCH_TEST_CASE("lockfile", "[lock][file]")
     155              : {
     156            9 :     CATCH_START_SECTION("lockfile: simple lock/unlock test")
     157              :     {
     158            1 :         std::string const path(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     159            1 :         std::string const filename(path + "/test-1.lock");
     160            1 :         snapdev::lockfile lock(filename);
     161            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     162            1 :         lock.lock();
     163            1 :         CATCH_REQUIRE(lock.is_locked());
     164            1 :         lock.lock();
     165            1 :         CATCH_REQUIRE(lock.is_locked());
     166            1 :         lock.unlock();
     167            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     168            1 :         lock.unlock();
     169            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     170              : 
     171            1 :         CATCH_REQUIRE(lock.get_path() == filename);
     172            1 :         CATCH_REQUIRE(lock.get_operation() == snapdev::operation_t::OPERATION_EXCLUSIVE);
     173            1 :     }
     174            9 :     CATCH_END_SECTION()
     175              : 
     176            9 :     CATCH_START_SECTION("lockfile: test a lock with a thread")
     177              :     {
     178            1 :         std::string const path(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     179            1 :         std::string const filename(path + "/test-2.lock");
     180              : 
     181            1 :         snapdev::lockfile lock(filename);
     182            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     183            1 :         lock.lock();
     184            1 :         CATCH_REQUIRE(lock.is_locked());
     185              : 
     186            1 :         lockfile_thread t(filename);
     187            1 :         t.start_thread();
     188            1 :         CATCH_REQUIRE(t.is_running());
     189              : 
     190              :         // still locked
     191              :         //
     192            1 :         CATCH_REQUIRE(lock.is_locked());
     193            1 :         CATCH_REQUIRE(t.is_running());
     194              : 
     195              :         // sleep a bit to make sure things stay locked
     196              :         //
     197            1 :         sleep(2);
     198            1 :         CATCH_REQUIRE(lock.is_locked());
     199            1 :         CATCH_REQUIRE(t.is_running());
     200              : 
     201            1 :         lock.unlock();
     202            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     203              : 
     204              :         for(;;)
     205              :         {
     206            2 :             if(!t.is_running())
     207              :             {
     208            1 :                 break;
     209              :             }
     210            1 :             snapdev::timespec_ex wait(0.001); // 1ms
     211            1 :             CATCH_REQUIRE(nanosleep(&wait, nullptr) == 0);
     212            1 :         }
     213              : 
     214            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     215            1 :     }
     216            9 :     CATCH_END_SECTION()
     217              : 
     218            9 :     CATCH_START_SECTION("lockfile: verify the automatic unlock with a thread")
     219              :     {
     220            1 :         std::string const path(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     221            1 :         std::string const filename(path + "/test-3.lock");
     222              : 
     223            1 :         snapdev::lockfile * lock(new snapdev::lockfile(filename));
     224            1 :         CATCH_REQUIRE_FALSE(lock->is_locked());
     225            1 :         lock->lock();
     226            1 :         CATCH_REQUIRE(lock->is_locked());
     227              : 
     228            1 :         lockfile_thread t(filename);
     229            1 :         t.start_thread();
     230            1 :         CATCH_REQUIRE(t.is_running());
     231              : 
     232              :         // still locked
     233              :         //
     234            1 :         CATCH_REQUIRE(lock->is_locked());
     235            1 :         CATCH_REQUIRE(t.is_running());
     236              : 
     237              :         // sleep a bit to make sure things stay locked
     238              :         //
     239            1 :         sleep(2);
     240            1 :         CATCH_REQUIRE(lock->is_locked());
     241            1 :         CATCH_REQUIRE(t.is_running());
     242              : 
     243              :         // verify that the delete removes the lock
     244              :         //
     245            1 :         delete lock;
     246              : 
     247              :         for(;;)
     248              :         {
     249            2 :             if(!t.is_running())
     250              :             {
     251            1 :                 break;
     252              :             }
     253            1 :             snapdev::timespec_ex const wait(0.001); // 1ms
     254            1 :             int const r(nanosleep(&wait, nullptr));
     255            1 :             if(r != 0)
     256              :             {
     257            0 :                 int const e(errno);
     258              :                 std::cerr
     259            0 :                     << "error: nanosleep() returned an error ("
     260              :                     << e
     261              :                     << ", "
     262            0 :                     << strerror(e)
     263            0 :                     << ")\n";
     264              :             }
     265            1 :             CATCH_REQUIRE(r == 0);
     266            1 :         }
     267            1 :     }
     268            9 :     CATCH_END_SECTION()
     269              : 
     270            9 :     CATCH_START_SECTION("lockfile: a shared lock does not prevent the thread from finishing")
     271              :     {
     272            1 :         std::string const path(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     273            1 :         std::string const filename(path + "/test-4.lock");
     274              : 
     275            1 :         snapdev::lockfile lock(filename, snapdev::operation_t::OPERATION_SHARED);
     276            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     277            1 :         lock.lock();
     278            1 :         CATCH_REQUIRE(lock.is_locked());
     279              : 
     280            1 :         lockfile_thread t(filename, snapdev::operation_t::OPERATION_SHARED);
     281            1 :         t.start_thread();
     282              :         //CATCH_REQUIRE(t.is_running()); -- the thread may return at any time, so we cannot check whether it is running
     283              : 
     284              :         // still locked
     285              :         //
     286            1 :         CATCH_REQUIRE(lock.is_locked());
     287              : 
     288              :         // sleep a bit to make sure things stay locked
     289              :         //
     290            1 :         sleep(2);
     291            1 :         CATCH_REQUIRE(lock.is_locked());
     292              : 
     293              :         // the thread will die on its own without us having to unlock()
     294              :         //
     295              :         for(;;)
     296              :         {
     297            1 :             if(!t.is_running())
     298              :             {
     299            1 :                 break;
     300              :             }
     301              :             //snapdev::timespec_ex wait(0.001); // 1ms
     302              :             //CATCH_REQUIRE(nanosleep(&wait, nullptr) == 0);
     303            0 :             sleep(1);
     304              :         }
     305              : 
     306              :         // still locked and the thread returned as expected
     307              :         //
     308            1 :         CATCH_REQUIRE(lock.is_locked());
     309            1 :     }
     310            9 :     CATCH_END_SECTION()
     311              : 
     312            9 :     CATCH_START_SECTION("lockfile: test a try_lock() with a thread")
     313              :     {
     314            1 :         std::string const path(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     315            1 :         std::string const filename(path + "/test-5.lock");
     316              : 
     317            1 :         snapdev::lockfile lock(filename);
     318            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     319            1 :         lock.lock();
     320            1 :         CATCH_REQUIRE(lock.is_locked());
     321              : 
     322            1 :         lockfile_thread t(filename);
     323            1 :         t.start_thread(2);  // the try_lock will fail
     324              :         //CATCH_REQUIRE(t.is_running()); -- the thread may return at any time, so we cannot check whether it is running
     325              : 
     326              :         // still locked
     327              :         //
     328            1 :         CATCH_REQUIRE(lock.is_locked());
     329              : 
     330              :         // sleep a bit to make sure things stay locked
     331              :         //
     332            1 :         sleep(2);
     333            1 :         CATCH_REQUIRE(lock.is_locked());
     334              : 
     335              :         for(;;)
     336              :         {
     337            1 :             if(!t.is_running())
     338              :             {
     339            1 :                 break;
     340              :             }
     341            0 :             snapdev::timespec_ex wait(0.001); // 1ms
     342            0 :             CATCH_REQUIRE(nanosleep(&wait, nullptr) == 0);
     343            0 :         }
     344              : 
     345              :         // still locked and the thread returned as expected
     346              :         //
     347            1 :         CATCH_REQUIRE(lock.is_locked());
     348            1 :     }
     349            9 :     CATCH_END_SECTION()
     350              : 
     351            9 :     CATCH_START_SECTION("lockfile: test a shared lock and try_lock() with a thread")
     352              :     {
     353            1 :         std::string const path(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     354            1 :         std::string const filename(path + "/test-6.lock");
     355              : 
     356            1 :         snapdev::lockfile lock(filename, snapdev::operation_t::OPERATION_SHARED);
     357            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     358            1 :         lock.lock();
     359            1 :         CATCH_REQUIRE(lock.is_locked());
     360              : 
     361            1 :         lockfile_thread t(filename, snapdev::operation_t::OPERATION_SHARED);
     362            1 :         t.start_thread(1);  // the try_lock will succeed
     363              :         //CATCH_REQUIRE(t.is_running()); -- the thread may return at any time, so we cannot check whether it is running
     364              : 
     365              :         // still locked
     366              :         //
     367            1 :         CATCH_REQUIRE(lock.is_locked());
     368              : 
     369              :         // sleep a bit to make sure things stay locked
     370              :         //
     371            1 :         sleep(2);
     372            1 :         CATCH_REQUIRE(lock.is_locked());
     373              : 
     374              :         for(;;)
     375              :         {
     376            1 :             if(!t.is_running())
     377              :             {
     378            1 :                 break;
     379              :             }
     380            0 :             snapdev::timespec_ex wait(0.001); // 1ms
     381            0 :             CATCH_REQUIRE(nanosleep(&wait, nullptr) == 0);
     382            0 :         }
     383              : 
     384              :         // still locked and the thread returned as expected
     385              :         //
     386            1 :         CATCH_REQUIRE(lock.is_locked());
     387            1 :         CATCH_REQUIRE(lock.get_operation() == snapdev::operation_t::OPERATION_SHARED);
     388            1 :     }
     389            9 :     CATCH_END_SECTION()
     390              : 
     391            9 :     CATCH_START_SECTION("lockfile: test an exclusive lock and a shared try_lock() lock with a thread")
     392              :     {
     393            1 :         std::string const path(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     394            1 :         std::string const filename(path + "/test-7.lock");
     395              : 
     396            1 :         snapdev::lockfile lock(filename);
     397            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     398            1 :         lock.lock();
     399            1 :         CATCH_REQUIRE(lock.is_locked());
     400              : 
     401            1 :         lockfile_thread t(filename, snapdev::operation_t::OPERATION_SHARED);
     402            1 :         t.start_thread(2);  // the try_lock will fail anyway
     403              :         //CATCH_REQUIRE(t.is_running()); -- the thread may return at any time, so we cannot check whether it is running
     404              : 
     405              :         // still locked
     406              :         //
     407            1 :         CATCH_REQUIRE(lock.is_locked());
     408              : 
     409              :         // sleep a bit to make sure things stay locked
     410              :         //
     411            1 :         sleep(2);
     412            1 :         CATCH_REQUIRE(lock.is_locked());
     413              : 
     414              :         for(;;)
     415              :         {
     416            1 :             if(!t.is_running())
     417              :             {
     418            1 :                 break;
     419              :             }
     420            0 :             snapdev::timespec_ex wait(0.001); // 1ms
     421            0 :             CATCH_REQUIRE(nanosleep(&wait, nullptr) == 0);
     422            0 :         }
     423              : 
     424              :         // still locked and the thread returned as expected
     425              :         //
     426            1 :         CATCH_REQUIRE(lock.is_locked());
     427            1 :     }
     428            9 :     CATCH_END_SECTION()
     429              : 
     430            9 :     CATCH_START_SECTION("lockfile: test a shared lock and an exclusive try_lock() lock with a thread")
     431              :     {
     432            1 :         std::string const path(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     433            1 :         std::string const filename(path + "/test-8.lock");
     434              : 
     435            1 :         snapdev::lockfile lock(filename, snapdev::operation_t::OPERATION_SHARED);
     436            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     437            1 :         lock.lock();
     438            1 :         CATCH_REQUIRE(lock.is_locked());
     439              : 
     440            1 :         lockfile_thread t(filename);
     441            1 :         t.start_thread(2);  // the try_lock will fail anyway
     442              :         //CATCH_REQUIRE(t.is_running()); -- the thread may return at any time, so we cannot check whether it is running
     443              : 
     444              :         // still locked
     445              :         //
     446            1 :         CATCH_REQUIRE(lock.is_locked());
     447              : 
     448              :         // sleep a bit to make sure things stay locked
     449              :         //
     450            1 :         sleep(2);
     451            1 :         CATCH_REQUIRE(lock.is_locked());
     452              : 
     453              :         for(;;)
     454              :         {
     455            1 :             if(!t.is_running())
     456              :             {
     457            1 :                 break;
     458              :             }
     459            0 :             snapdev::timespec_ex wait(0.001); // 1ms
     460            0 :             CATCH_REQUIRE(nanosleep(&wait, nullptr) == 0);
     461            0 :         }
     462              : 
     463              :         // still locked and the thread returned as expected
     464              :         //
     465            1 :         CATCH_REQUIRE(lock.is_locked());
     466            1 :         CATCH_REQUIRE(lock.get_operation() == snapdev::operation_t::OPERATION_SHARED);
     467            1 :     }
     468            9 :     CATCH_END_SECTION()
     469              : 
     470            9 :     CATCH_START_SECTION("lockfile: test copying a lockfile")
     471              :     {
     472            1 :         std::string const path(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     473            1 :         std::string const filename(path + "/test-9.lock");
     474            1 :         snapdev::lockfile lock(filename);
     475            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     476            1 :         lock.lock();
     477            1 :         CATCH_REQUIRE(lock.is_locked());
     478            1 :         lock.lock();
     479            1 :         CATCH_REQUIRE(lock.is_locked());
     480            1 :         lock.unlock();
     481            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     482            1 :         lock.unlock();
     483            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     484              : 
     485              :         {
     486            1 :             snapdev::lockfile copy(lock);
     487              : 
     488            1 :             CATCH_REQUIRE_FALSE(lock.is_locked());
     489            1 :             CATCH_REQUIRE_FALSE(copy.is_locked());
     490            1 :             lock.lock();
     491            1 :             CATCH_REQUIRE(lock.is_locked());
     492            1 :             CATCH_REQUIRE(copy.is_locked());
     493              : 
     494            1 :             CATCH_REQUIRE(copy.get_path() == filename);
     495            1 :             CATCH_REQUIRE(copy.get_operation() == snapdev::operation_t::OPERATION_EXCLUSIVE);
     496            1 :         }
     497              : 
     498              :         {
     499            1 :             snapdev::lockfile copy(lock);
     500              : 
     501            1 :             CATCH_REQUIRE(lock.is_locked());
     502            1 :             CATCH_REQUIRE(copy.is_locked());
     503            1 :             lock.unlock();
     504            1 :             CATCH_REQUIRE_FALSE(lock.is_locked());
     505            1 :             CATCH_REQUIRE_FALSE(copy.is_locked());
     506              : 
     507            1 :             CATCH_REQUIRE(copy.get_path() == filename);
     508            1 :             CATCH_REQUIRE(copy.get_operation() == snapdev::operation_t::OPERATION_EXCLUSIVE);
     509            1 :         }
     510              : 
     511            1 :         CATCH_REQUIRE(lock.get_path() == filename);
     512            1 :         CATCH_REQUIRE(lock.get_operation() == snapdev::operation_t::OPERATION_EXCLUSIVE);
     513            1 :     }
     514            9 :     CATCH_END_SECTION()
     515            9 : }
     516              : 
     517              : 
     518            1 : CATCH_TEST_CASE("lockfile_error", "[lock][file]")
     519              : {
     520            1 :     CATCH_START_SECTION("lockfile_error: no path generates an error trying to create the lock file")
     521              :     {
     522            1 :         int const e(ENOENT);
     523            4 :         CATCH_REQUIRE_THROWS_MATCHES(
     524              :                   snapdev::lockfile(std::string())
     525              :                 , snapdev::file_error
     526              :                 , Catch::Matchers::ExceptionMessage(
     527              :                           "lockfile_error: Error creating lock file \"\" (errno: "
     528              :                         + std::to_string(e)
     529              :                         + ", "
     530              :                         + strerror(e)
     531              :                         + ")."));
     532              :     }
     533            1 :     CATCH_END_SECTION()
     534            1 : }
     535              : 
     536              : 
     537            3 : CATCH_TEST_CASE("lockfd", "[lock][file]")
     538              : {
     539            3 :     CATCH_START_SECTION("lockfd: test exclusive lock with -1, nothing happens")
     540              :     {
     541            1 :         snapdev::lockfd lock(-1);
     542            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     543            1 :         CATCH_REQUIRE_FALSE(lock.lock());
     544            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     545            1 :         lock.unlock();
     546            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     547            1 :     }
     548            3 :     CATCH_END_SECTION()
     549              : 
     550            3 :     CATCH_START_SECTION("lockfd: test shared lock with -1, nothing happens")
     551              :     {
     552            1 :         snapdev::lockfd lock(-1, snapdev::operation_t::OPERATION_SHARED);
     553            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     554            1 :         CATCH_REQUIRE_FALSE(lock.lock());
     555            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     556            1 :         lock.unlock();
     557            1 :         CATCH_REQUIRE_FALSE(lock.is_locked());
     558            1 :     }
     559            3 :     CATCH_END_SECTION()
     560              : 
     561            3 :     CATCH_START_SECTION("lockfd: test shared lock with actual file")
     562              :     {
     563            1 :         std::string const path(SNAP_CATCH2_NAMESPACE::g_tmp_dir());
     564            1 :         std::string const filename(path + "/fd-test-1.lock");
     565            1 :         int const fd(::open(filename.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH));
     566              :         {
     567            1 :             snapdev::lockfd lock(fd, snapdev::operation_t::OPERATION_SHARED);
     568            1 :             CATCH_REQUIRE(lock.is_locked());
     569            1 :             lock.unlock();
     570            1 :             CATCH_REQUIRE_FALSE(lock.is_locked());
     571            1 :             CATCH_REQUIRE(lock.lock());
     572            1 :             CATCH_REQUIRE(lock.is_locked());
     573            1 :         }
     574            1 :         close(fd);
     575            1 :     }
     576            3 :     CATCH_END_SECTION()
     577            3 : }
     578              : 
     579              : 
     580              : 
     581              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

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