LCOV - code coverage report
Current view: top level - lib/tdb/test - run-mutex-die.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 86 114 75.4 %
Date: 2024-04-21 15:09:00 Functions: 8 9 88.9 %

          Line data    Source code
       1             : #include "../common/tdb_private.h"
       2             : #include "lock-tracking.h"
       3             : static ssize_t pwrite_check(int fd, const void *buf, size_t count, off_t offset);
       4             : static ssize_t write_check(int fd, const void *buf, size_t count);
       5             : static int ftruncate_check(int fd, off_t length);
       6             : 
       7             : #define pwrite pwrite_check
       8             : #define write write_check
       9             : #define fcntl fcntl_with_lockcheck
      10             : #define ftruncate ftruncate_check
      11             : 
      12             : #include "../common/io.c"
      13             : #include "../common/tdb.c"
      14             : #include "../common/lock.c"
      15             : #include "../common/freelist.c"
      16             : #include "../common/traverse.c"
      17             : #include "../common/transaction.c"
      18             : #include "../common/error.c"
      19             : #include "../common/open.c"
      20             : #include "../common/check.c"
      21             : #include "../common/hash.c"
      22             : #include "../common/mutex.c"
      23             : #include "tap-interface.h"
      24             : #include <stdlib.h>
      25             : #include <stdbool.h>
      26             : #include <stdarg.h>
      27             : #include "external-agent.h"
      28             : #include "logging.h"
      29             : 
      30             : #undef write
      31             : #undef pwrite
      32             : #undef fcntl
      33             : #undef ftruncate
      34             : 
      35             : static int target, current;
      36             : #define TEST_DBNAME "run-mutex-die.tdb"
      37             : #define KEY_STRING "helloworld"
      38             : 
      39         542 : static void maybe_die(int fd)
      40             : {
      41         542 :         if (target == 0) {
      42         542 :                 return;
      43             :         }
      44           0 :         current += 1;
      45           0 :         if (current == target) {
      46           0 :                 _exit(1);
      47             :         }
      48             : }
      49             : 
      50           0 : static ssize_t pwrite_check(int fd,
      51             :                             const void *buf, size_t count, off_t offset)
      52             : {
      53             :         ssize_t ret;
      54             : 
      55           0 :         maybe_die(fd);
      56             : 
      57           0 :         ret = pwrite(fd, buf, count, offset);
      58           0 :         if (ret != count)
      59           0 :                 return ret;
      60             : 
      61           0 :         maybe_die(fd);
      62           0 :         return ret;
      63             : }
      64             : 
      65          67 : static ssize_t write_check(int fd, const void *buf, size_t count)
      66             : {
      67             :         ssize_t ret;
      68             : 
      69          67 :         maybe_die(fd);
      70             : 
      71          67 :         ret = write(fd, buf, count);
      72          67 :         if (ret != count)
      73           0 :                 return ret;
      74             : 
      75          67 :         maybe_die(fd);
      76          67 :         return ret;
      77             : }
      78             : 
      79          66 : static int ftruncate_check(int fd, off_t length)
      80             : {
      81             :         int ret;
      82             : 
      83          66 :         maybe_die(fd);
      84             : 
      85          66 :         ret = ftruncate(fd, length);
      86             : 
      87          66 :         maybe_die(fd);
      88          66 :         return ret;
      89             : }
      90             : 
      91          33 : static enum agent_return flakey_ops(struct agent *a)
      92             : {
      93             :         enum agent_return ret;
      94             : 
      95             :         /*
      96             :          * Run in the external agent child
      97             :          */
      98             : 
      99          33 :         ret = external_agent_operation(a, OPEN_WITH_CLEAR_IF_FIRST, TEST_DBNAME);
     100          33 :         if (ret != SUCCESS) {
     101           0 :                 fprintf(stderr, "Agent failed to open: %s\n",
     102             :                         agent_return_name(ret));
     103           0 :                 return ret;
     104             :         }
     105          33 :         ret = external_agent_operation(a, UNMAP, "");
     106          33 :         if (ret != SUCCESS) {
     107           0 :                 fprintf(stderr, "Agent failed to unmap: %s\n",
     108             :                         agent_return_name(ret));
     109           0 :                 return ret;
     110             :         }
     111          33 :         ret = external_agent_operation(a, STORE, "xyz");
     112          33 :         if (ret != SUCCESS) {
     113          13 :                 fprintf(stderr, "Agent failed to store: %s\n",
     114             :                         agent_return_name(ret));
     115          13 :                 return ret;
     116             :         }
     117          20 :         ret = external_agent_operation(a, STORE, KEY_STRING);
     118          20 :         if (ret != SUCCESS) {
     119          18 :                 fprintf(stderr, "Agent failed store: %s\n",
     120             :                         agent_return_name(ret));
     121          18 :                 return ret;
     122             :         }
     123           2 :         ret = external_agent_operation(a, FETCH, KEY_STRING);
     124           2 :         if (ret != SUCCESS) {
     125           1 :                 fprintf(stderr, "Agent failed find key: %s\n",
     126             :                         agent_return_name(ret));
     127           1 :                 return ret;
     128             :         }
     129           1 :         ret = external_agent_operation(a, PING, "");
     130           1 :         if (ret != SUCCESS) {
     131           0 :                 fprintf(stderr, "Agent failed ping: %s\n",
     132             :                         agent_return_name(ret));
     133           0 :                 return ret;
     134             :         }
     135           1 :         return ret;
     136             : }
     137             : 
     138          33 : static bool prep_db(void) {
     139             :         struct tdb_context *tdb;
     140             :         TDB_DATA key;
     141             :         TDB_DATA data;
     142             : 
     143          33 :         key.dptr = discard_const_p(uint8_t, KEY_STRING);
     144          33 :         key.dsize = strlen((char *)key.dptr);
     145          33 :         data.dptr = discard_const_p(uint8_t, "foo");
     146          33 :         data.dsize = strlen((char *)data.dptr);
     147             : 
     148          33 :         unlink(TEST_DBNAME);
     149             : 
     150          33 :         tdb = tdb_open_ex(
     151             :                 TEST_DBNAME, 2,
     152             :                 TDB_INCOMPATIBLE_HASH|TDB_MUTEX_LOCKING|TDB_CLEAR_IF_FIRST,
     153             :                 O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL);
     154          33 :         if (tdb == NULL) {
     155           0 :                 return false;
     156             :         }
     157             : 
     158          33 :         if (tdb_store(tdb, key, data, TDB_INSERT) != 0) {
     159           0 :                 return false;
     160             :         }
     161             : 
     162          33 :         tdb_close(tdb);
     163          33 :         tdb = NULL;
     164             : 
     165          33 :         forget_locking();
     166             : 
     167          33 :         return true;
     168             : }
     169             : 
     170          33 : static bool test_db(void) {
     171             :         struct tdb_context *tdb;
     172             :         int ret;
     173             : 
     174          33 :         tdb = tdb_open_ex(
     175             :                 TEST_DBNAME, 1024, TDB_INCOMPATIBLE_HASH,
     176             :                 O_RDWR, 0600, &taplogctx, NULL);
     177             : 
     178          33 :         if (tdb == NULL) {
     179           0 :                 perror("tdb_open_ex failed");
     180           0 :                 return false;
     181             :         }
     182             : 
     183          33 :         ret = tdb_traverse(tdb, NULL, NULL);
     184          33 :         if (ret == -1) {
     185           0 :                 perror("traverse failed");
     186           0 :                 goto fail;
     187             :         }
     188             : 
     189          33 :         tdb_close(tdb);
     190             : 
     191          33 :         forget_locking();
     192             : 
     193          33 :         return true;
     194             : 
     195           0 : fail:
     196           0 :         tdb_close(tdb);
     197           0 :         return false;
     198             : }
     199             : 
     200           1 : static bool test_one(void)
     201             : {
     202             :         enum agent_return ret;
     203             : 
     204           1 :         ret = AGENT_DIED;
     205           1 :         target = 19;
     206             : 
     207          34 :         while (ret != SUCCESS) {
     208             :                 struct agent *agent;
     209             : 
     210             :                 {
     211          33 :                         int child_target = target;
     212             :                         bool pret;
     213          33 :                         target = 0;
     214          33 :                         pret = prep_db();
     215          33 :                         ok1(pret);
     216          33 :                         target = child_target;
     217             :                 }
     218             : 
     219          33 :                 agent = prepare_external_agent();
     220             : 
     221          33 :                 ret = flakey_ops(agent);
     222             : 
     223          33 :                 diag("Agent (target=%d) returns %s",
     224             :                      target, agent_return_name(ret));
     225             : 
     226          33 :                 if (ret == SUCCESS) {
     227           1 :                         ok((target > 19), "At least one AGENT_DIED expected");
     228             :                 } else {
     229          32 :                         ok(ret == AGENT_DIED, "AGENT_DIED expected");
     230             :                 }
     231             : 
     232          33 :                 shutdown_agent(agent);
     233             : 
     234             :                 {
     235          33 :                         int child_target = target;
     236             :                         bool tret;
     237          33 :                         target = 0;
     238          33 :                         tret = test_db();
     239          33 :                         ok1(tret);
     240          33 :                         target = child_target;
     241             :                 }
     242             : 
     243          33 :                 target += 1;
     244             :         }
     245             : 
     246           1 :         return true;
     247             : }
     248             : 
     249           1 : int main(int argc, char *argv[])
     250             : {
     251             :         bool ret;
     252             :         bool runtime_support;
     253             : 
     254           1 :         runtime_support = tdb_runtime_check_for_robust_mutexes();
     255             : 
     256           1 :         if (!runtime_support) {
     257           0 :                 skip(1, "No robust mutex support");
     258           0 :                 return exit_status();
     259             :         }
     260             : 
     261             :         plan_tests(12);
     262           1 :         unlock_callback = maybe_die;
     263             : 
     264           1 :         ret = test_one();
     265           1 :         ok1(ret);
     266             : 
     267           1 :         diag("done");
     268           1 :         return exit_status();
     269             : }

Generated by: LCOV version 1.14