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 : */
9 :
10 : #include <stdio.h>
11 : #include <stdlib.h>
12 : #include <string.h>
13 :
14 : #include <kdbhelper.h>
15 : #include <tests.h>
16 :
17 : #include "test.h"
18 : #include <kdbio.h>
19 : #include <kdbiotest.h>
20 :
21 : #define IDLE_TEST_INTERVAL 1
22 : #define IDLE_TEST_CONTROL_TIMES 3
23 : #define IDLE_DIFF_WARNING_THRESHOLD 5
24 : #define IDLE_DIFF_ERROR_THRESHOLD (IDLE_DIFF_WARNING_THRESHOLD * 100)
25 :
26 : ElektraIoTestSuiteStop testStop;
27 :
28 : int testCallbackCalled;
29 : struct timespec testCallbackTimeStarted;
30 : struct timespec testCallbackTimeCalled;
31 :
32 : int testUpdateEnabledControlCalled;
33 : int testUpdateEnabledProbeCalled;
34 : ElektraIoIdleOperation * testUpdateEnabledIdleProbe;
35 : ElektraIoInterface * testUpdateEnabledBinding;
36 :
37 : int testRemoveControlCalled;
38 : int testRemoveProbeCalled;
39 : ElektraIoIdleOperation * testRemoveIdleProbe;
40 : ElektraIoInterface * testRemoveBinding;
41 :
42 0 : static void testIdleBasicsCallback (ElektraIoIdleOperation * idleOp ELEKTRA_UNUSED)
43 : {
44 0 : yield_error ("should not be called");
45 0 : }
46 :
47 6 : static void testIdleBasics (ElektraIoTestSuiteCreateBinding createBinding)
48 : {
49 6 : ElektraIoIdleOperation * idleOp = elektraIoNewIdleOperation (0, testIdleBasicsCallback, NULL);
50 :
51 6 : ElektraIoInterface * binding = createBinding ();
52 6 : succeed_if (elektraIoBindingAddIdle (binding, idleOp), "addIdle did not succeed");
53 6 : succeed_if (elektraIoBindingAddIdle (binding, idleOp) == 0, "addIdle: should not be able to reassign operation to a binding");
54 :
55 6 : elektraIoIdleSetEnabled (idleOp, 1);
56 6 : succeed_if (elektraIoBindingUpdateIdle (idleOp), "updateIdle did not succeed");
57 :
58 6 : succeed_if (elektraIoBindingRemoveIdle (idleOp), "removeIdle did not succeed");
59 :
60 6 : succeed_if (elektraIoBindingAddIdle (binding, idleOp), "addIdle: should be able to assign operation after removal");
61 6 : succeed_if (elektraIoBindingRemoveIdle (idleOp), "removeIdle did not succeed");
62 6 : elektraIoBindingCleanup (binding);
63 6 : elektraFree (idleOp);
64 6 : }
65 :
66 6 : static void testIdleShouldCallbackImmediatelyProbe (ElektraIoIdleOperation * idleOp ELEKTRA_UNUSED)
67 : {
68 6 : testCallbackCalled = 1;
69 6 : elektraIoTestSuiteUtilGetCurrentTime (&testCallbackTimeCalled);
70 6 : testStop ();
71 6 : }
72 :
73 6 : static void testIdleShouldCallbackImmediately (ElektraIoTestSuiteCreateBinding createBinding, ElektraIoTestSuiteStart start,
74 : ElektraIoTestSuiteStop stop)
75 : {
76 6 : ElektraIoIdleOperation * idleOp = elektraIoNewIdleOperation (1, testIdleShouldCallbackImmediatelyProbe, NULL);
77 :
78 6 : ElektraIoInterface * binding = createBinding ();
79 6 : elektraIoBindingAddIdle (binding, idleOp);
80 :
81 6 : testStop = stop;
82 6 : testCallbackCalled = 0;
83 :
84 6 : elektraIoTestSuiteUtilGetCurrentTime (&testCallbackTimeStarted);
85 :
86 6 : start ();
87 :
88 6 : succeed_if (testCallbackCalled, "callback was not called");
89 :
90 6 : long diff = elektraIoTestSuiteUtilGetTimeDifference (testCallbackTimeStarted, testCallbackTimeCalled);
91 6 : int deviation = labs (IDLE_TEST_INTERVAL - diff);
92 6 : if (deviation > IDLE_DIFF_WARNING_THRESHOLD)
93 : {
94 2 : printf ("testIdleShouldCallbackImmediately (warning): measured %ldms, expected %dms - deviation %dms.\n", diff,
95 : IDLE_TEST_INTERVAL, deviation);
96 : }
97 6 : succeed_if (deviation <= IDLE_DIFF_ERROR_THRESHOLD, "idle timing not within error threshold");
98 :
99 6 : elektraIoBindingRemoveIdle (idleOp);
100 6 : elektraIoBindingCleanup (binding);
101 6 : elektraFree (idleOp);
102 6 : }
103 :
104 18 : static void testIdleShouldUpdateEnabledControl (ElektraIoIdleOperation * idleOp ELEKTRA_UNUSED)
105 : {
106 18 : testUpdateEnabledControlCalled++;
107 :
108 : // Disable probe operation on second run
109 18 : if (testUpdateEnabledProbeCalled == IDLE_TEST_CONTROL_TIMES - 1)
110 : {
111 10 : elektraIoIdleSetEnabled (testUpdateEnabledIdleProbe, 0);
112 10 : elektraIoBindingUpdateIdle (testUpdateEnabledIdleProbe);
113 : }
114 :
115 : // Stop test when control limit was reached or probe was called twice
116 18 : if (testUpdateEnabledControlCalled == IDLE_TEST_CONTROL_TIMES || testUpdateEnabledProbeCalled > 2)
117 : {
118 6 : testStop ();
119 : }
120 18 : }
121 :
122 12 : static void testIdleShouldUpdateEnabledProbe (ElektraIoIdleOperation * idleOp ELEKTRA_UNUSED)
123 : {
124 12 : testUpdateEnabledProbeCalled++;
125 12 : }
126 :
127 6 : static void testIdleShouldUpdateEnabled (ElektraIoTestSuiteCreateBinding createBinding, ElektraIoTestSuiteStart start,
128 : ElektraIoTestSuiteStop stop)
129 : {
130 6 : ElektraIoIdleOperation * idleControl = elektraIoNewIdleOperation (1, testIdleShouldUpdateEnabledControl, NULL);
131 :
132 6 : ElektraIoIdleOperation * idleProbe = elektraIoNewIdleOperation (1, testIdleShouldUpdateEnabledProbe, NULL);
133 :
134 6 : ElektraIoInterface * binding = createBinding ();
135 6 : elektraIoBindingAddIdle (binding, idleControl);
136 6 : elektraIoBindingAddIdle (binding, idleProbe);
137 :
138 6 : testStop = stop;
139 6 : testUpdateEnabledControlCalled = 0; // IDLE_TEST_CONTROL_TIMES;
140 6 : testUpdateEnabledProbeCalled = 0;
141 6 : testUpdateEnabledIdleProbe = idleProbe;
142 6 : testUpdateEnabledBinding = binding;
143 :
144 6 : start ();
145 :
146 6 : succeed_if (testUpdateEnabledProbeCalled > 0 && testUpdateEnabledProbeCalled <= 2, "idle callback was not disabled");
147 6 : succeed_if (testUpdateEnabledControlCalled == IDLE_TEST_CONTROL_TIMES,
148 : "idle control callback was not called required amount of times");
149 :
150 6 : elektraIoBindingRemoveIdle (idleControl);
151 6 : elektraIoBindingRemoveIdle (idleProbe);
152 6 : elektraIoBindingCleanup (binding);
153 6 : elektraFree (idleControl);
154 6 : elektraFree (idleProbe);
155 6 : }
156 :
157 18 : static void testIdleShouldRemoveControl (ElektraIoIdleOperation * idleOp ELEKTRA_UNUSED)
158 : {
159 18 : testRemoveControlCalled++;
160 :
161 : // Remove probe operation on first run
162 18 : if (testRemoveControlCalled == IDLE_TEST_CONTROL_TIMES - 1)
163 : {
164 6 : elektraIoBindingRemoveIdle (testRemoveIdleProbe);
165 : }
166 :
167 18 : if (testRemoveControlCalled == IDLE_TEST_CONTROL_TIMES || testRemoveProbeCalled > 2)
168 : {
169 6 : testStop ();
170 : }
171 18 : }
172 :
173 10 : static void testIdleShouldRemoveProbe (ElektraIoIdleOperation * idleOp ELEKTRA_UNUSED)
174 : {
175 10 : testRemoveProbeCalled++;
176 10 : }
177 :
178 6 : static void testIdleShouldRemove (ElektraIoTestSuiteCreateBinding createBinding, ElektraIoTestSuiteStart start, ElektraIoTestSuiteStop stop)
179 : {
180 6 : ElektraIoIdleOperation * idleControl = elektraIoNewIdleOperation (1, testIdleShouldRemoveControl, NULL);
181 :
182 6 : ElektraIoIdleOperation * idleProbe = elektraIoNewIdleOperation (1, testIdleShouldRemoveProbe, NULL);
183 :
184 6 : ElektraIoInterface * binding = createBinding ();
185 6 : elektraIoBindingAddIdle (binding, idleControl);
186 6 : elektraIoBindingAddIdle (binding, idleProbe);
187 :
188 6 : testStop = stop;
189 6 : testRemoveControlCalled = 0;
190 6 : testRemoveProbeCalled = 0;
191 6 : testRemoveIdleProbe = idleProbe;
192 6 : testRemoveBinding = binding;
193 :
194 6 : start ();
195 :
196 6 : succeed_if (testRemoveProbeCalled > 0 && testRemoveProbeCalled <= 2, "idle callback was not removed");
197 :
198 6 : succeed_if (testRemoveControlCalled == IDLE_TEST_CONTROL_TIMES, "idle control callback was not called required amount of times");
199 :
200 6 : elektraIoBindingRemoveIdle (idleControl);
201 6 : elektraIoBindingCleanup (binding);
202 6 : elektraFree (idleControl);
203 6 : elektraFree (idleProbe);
204 6 : }
205 :
206 :
207 : /**
208 : * Test idle functions of the I/O binding returned by createBinding.
209 : * Requires the following operations: Idle
210 : *
211 : * @param createBinding binding creation function
212 : * @param start starts I/O operations
213 : * @param stop stops I/O operations
214 : */
215 6 : void elektraIoTestSuiteIdle (ElektraIoTestSuiteCreateBinding createBinding, ElektraIoTestSuiteStart start, ElektraIoTestSuiteStop stop)
216 : {
217 6 : printf ("test idle\n");
218 :
219 6 : testIdleBasics (createBinding);
220 :
221 6 : testIdleShouldCallbackImmediately (createBinding, start, stop);
222 :
223 6 : testIdleShouldUpdateEnabled (createBinding, start, stop);
224 :
225 6 : testIdleShouldRemove (createBinding, start, stop);
226 6 : }
|