LCOV - code coverage report
Current view: top level - src/bindings/io/test - test_mix.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 78 84 92.9 %
Date: 2019-09-12 12:28:41 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Tests for I/O bindings
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  * See test_fd.c for why `pipe()` is used.
       9             :  */
      10             : 
      11             : #include <stdio.h>
      12             : #include <stdlib.h>
      13             : #include <string.h>
      14             : #include <unistd.h>
      15             : 
      16             : #include <tests.h>
      17             : 
      18             : #include "test.h"
      19             : #include <kdbio.h>
      20             : #include <kdbiotest.h>
      21             : 
      22             : #define MIX_TIMER_INTERVAL 100
      23             : #define MIX_DIFF_WARNING_THRESHOLD 5
      24             : #define MIX_DIFF_ERROR_THRESHOLD (MIX_DIFF_WARNING_THRESHOLD * 100)
      25             : 
      26             : #define MIX_BUFFER_TESTDATA "T"
      27             : #define MIX_BUFFER_TESTDATA_LENGTH 1
      28             : 
      29             : // Indices for array returned by pipe()
      30             : #define MIX_READ_END 0
      31             : #define MIX_WRITE_END 1
      32             : 
      33             : ElektraIoTestSuiteStop testStop;
      34             : 
      35             : int testIdleNotStarveTimerTimerCalled;
      36             : int testIdleNotStarveTimerIdleCalled;
      37             : struct timespec testIdleNotStarveTimerTimeStarted;
      38             : struct timespec testIdleNotStarveTimerTimeCalled;
      39             : 
      40             : int testIdleNotStarveFdStep;
      41             : int testIdleNotStarveFdFdCalled;
      42             : int testIdleNotStarveFdIdleCalled;
      43             : int testIdleNotStarveFdWriteFd;
      44             : struct timespec testIdleNotStarveFdTimeReadable;
      45             : struct timespec testIdleNotStarveFdTimeWrite;
      46             : 
      47           6 : static void testMixIdleShouldNotStarveTimerTimer (ElektraIoTimerOperation * timerOp ELEKTRA_UNUSED)
      48             : {
      49           6 :         elektraIoTestSuiteUtilGetCurrentTime (&testIdleNotStarveTimerTimeCalled);
      50           6 :         testIdleNotStarveTimerTimerCalled = 1;
      51           6 :         testStop ();
      52           6 : }
      53             : 
      54      191988 : static void testMixIdleShouldNotStarveTimerIdle (ElektraIoIdleOperation * timerOp ELEKTRA_UNUSED)
      55             : {
      56      191988 :         testIdleNotStarveTimerIdleCalled = 1;
      57      191988 : }
      58             : 
      59           6 : static void testMixIdleShouldNotStarveTimer (ElektraIoTestSuiteCreateBinding createBinding, ElektraIoTestSuiteStart start,
      60             :                                              ElektraIoTestSuiteStop stop)
      61             : {
      62           6 :         ElektraIoTimerOperation * timerOp = elektraIoNewTimerOperation (MIX_TIMER_INTERVAL, 1, testMixIdleShouldNotStarveTimerTimer, NULL);
      63             : 
      64           6 :         ElektraIoIdleOperation * idleOp = elektraIoNewIdleOperation (1, testMixIdleShouldNotStarveTimerIdle, NULL);
      65             : 
      66           6 :         ElektraIoInterface * binding = createBinding ();
      67           6 :         elektraIoBindingAddTimer (binding, timerOp);
      68           6 :         elektraIoBindingAddIdle (binding, idleOp);
      69             : 
      70           6 :         testStop = stop;
      71           6 :         testIdleNotStarveTimerTimerCalled = 0;
      72           6 :         testIdleNotStarveTimerIdleCalled = 0;
      73             : 
      74           6 :         elektraIoTestSuiteUtilGetCurrentTime (&testIdleNotStarveTimerTimeStarted);
      75             : 
      76           6 :         start ();
      77             : 
      78           6 :         succeed_if (testIdleNotStarveTimerTimerCalled, "timer callback was not called");
      79           6 :         succeed_if (testIdleNotStarveTimerIdleCalled, "idle callback was not called");
      80             : 
      81           6 :         long diff = elektraIoTestSuiteUtilGetTimeDifference (testIdleNotStarveTimerTimeStarted, testIdleNotStarveTimerTimeCalled);
      82           6 :         int deviation = labs (MIX_TIMER_INTERVAL - diff);
      83           6 :         if (deviation > MIX_DIFF_WARNING_THRESHOLD)
      84             :         {
      85           0 :                 printf ("testMixIdleShouldNotStarveTimer (warning): measured %ldms, expected %dms - deviation %dms.\n", diff,
      86             :                         MIX_TIMER_INTERVAL, deviation);
      87             :         }
      88           6 :         succeed_if (deviation <= MIX_DIFF_ERROR_THRESHOLD, "timer interval not within error threshold");
      89             : 
      90           6 :         elektraIoBindingRemoveTimer (timerOp);
      91           6 :         elektraIoBindingRemoveIdle (idleOp);
      92           6 :         elektraIoBindingCleanup (binding);
      93           6 :         elektraFree (timerOp);
      94           6 :         elektraFree (idleOp);
      95           6 : }
      96             : 
      97             : 
      98           6 : static void testMixIdleShouldNotStarveFdFd (ElektraIoFdOperation * fdOp ELEKTRA_UNUSED, int flags ELEKTRA_UNUSED)
      99             : {
     100           6 :         elektraIoTestSuiteUtilGetCurrentTime (&testIdleNotStarveFdTimeReadable);
     101           6 :         succeed_if (testIdleNotStarveFdStep != 0, "fd called before data was written");
     102             : 
     103           6 :         testIdleNotStarveFdFdCalled = 1;
     104           6 :         testStop ();
     105           6 : }
     106             : 
     107           6 : static void testMixIdleShouldNotStarveFdControl (ElektraIoTimerOperation * timerOp ELEKTRA_UNUSED)
     108             : {
     109           6 :         switch (testIdleNotStarveFdStep)
     110             :         {
     111             :         case 0:
     112           6 :                 testIdleNotStarveFdStep++;
     113           6 :                 succeed_if (write (testIdleNotStarveFdWriteFd, MIX_BUFFER_TESTDATA, MIX_BUFFER_TESTDATA_LENGTH) ==
     114             :                                     MIX_BUFFER_TESTDATA_LENGTH,
     115             :                             "write failed");
     116           6 :                 elektraIoTestSuiteUtilGetCurrentTime (&testIdleNotStarveFdTimeWrite);
     117           6 :                 break;
     118             :         case 1:
     119           0 :                 yield_error ("timeout; test failed");
     120           0 :                 testStop ();
     121           0 :                 break;
     122             :         }
     123           6 : }
     124             : 
     125      191691 : static void testMixIdleShouldNotStarveFdIdle (ElektraIoIdleOperation * idleOp ELEKTRA_UNUSED)
     126             : {
     127      191691 :         testIdleNotStarveFdIdleCalled = 1;
     128      191691 : }
     129             : 
     130           6 : static void testMixIdleShouldNotStarveFd (ElektraIoTestSuiteCreateBinding createBinding, ElektraIoTestSuiteStart start,
     131             :                                           ElektraIoTestSuiteStop stop)
     132             : {
     133             : 
     134             :         int fds[2];
     135           6 :         if (pipe (fds) == -1)
     136             :         {
     137           0 :                 yield_error ("pipe() failed");
     138           0 :                 return;
     139             :         }
     140             : 
     141           6 :         ElektraIoTimerOperation * timerOp = elektraIoNewTimerOperation (MIX_TIMER_INTERVAL, 1, testMixIdleShouldNotStarveFdControl, NULL);
     142             : 
     143           6 :         ElektraIoFdOperation * fdOp = elektraIoNewFdOperation (fds[MIX_READ_END],
     144             :                                                                ELEKTRA_IO_READABLE, // gets changed by control timer
     145             :                                                                1, testMixIdleShouldNotStarveFdFd, NULL);
     146             : 
     147           6 :         ElektraIoIdleOperation * idleOp = elektraIoNewIdleOperation (1, testMixIdleShouldNotStarveFdIdle, NULL);
     148             : 
     149           6 :         ElektraIoInterface * binding = createBinding ();
     150           6 :         elektraIoBindingAddFd (binding, fdOp);
     151           6 :         elektraIoBindingAddTimer (binding, timerOp);
     152           6 :         elektraIoBindingAddIdle (binding, idleOp);
     153             : 
     154           6 :         testIdleNotStarveFdWriteFd = fds[1];
     155           6 :         testIdleNotStarveFdStep = 0;
     156           6 :         testIdleNotStarveFdFdCalled = 0;
     157           6 :         testIdleNotStarveFdIdleCalled = 0;
     158           6 :         testStop = stop;
     159             : 
     160           6 :         start ();
     161             : 
     162           6 :         succeed_if (testIdleNotStarveFdFdCalled, "fd callback was not called");
     163           6 :         succeed_if (testIdleNotStarveFdIdleCalled, "idle callback was not called");
     164             : 
     165           6 :         elektraIoBindingRemoveFd (fdOp);
     166           6 :         elektraIoBindingRemoveTimer (timerOp);
     167           6 :         elektraIoBindingRemoveIdle (idleOp);
     168           6 :         elektraIoBindingCleanup (binding);
     169           6 :         elektraFree (fdOp);
     170           6 :         elektraFree (timerOp);
     171           6 :         elektraFree (idleOp);
     172           6 :         close (fds[0]);
     173           6 :         close (fds[1]);
     174             : }
     175             : 
     176             : /**
     177             :  * Test mixed requirements of the I/O binding returned by createBinding.
     178             :  * Requires the following operations: Fd, Timer, Idle
     179             :  *
     180             :  * @param createBinding binding creation function
     181             :  * @param start         starts I/O operations
     182             :  * @param stop          stops I/O operations
     183             :  */
     184           6 : void elektraIoTestSuiteMix (ElektraIoTestSuiteCreateBinding createBinding, ElektraIoTestSuiteStart start, ElektraIoTestSuiteStop stop)
     185             : {
     186           6 :         printf ("test mix\n");
     187             : 
     188           6 :         testMixIdleShouldNotStarveTimer (createBinding, start, stop);
     189             : 
     190           6 :         testMixIdleShouldNotStarveFd (createBinding, start, stop);
     191           6 : }

Generated by: LCOV version 1.13