source: mainline/uspace/srv/sysman/test/job_closure.c@ 102f641

Last change on this file since 102f641 was 102f641, checked in by Matthieu Riolo <matthieu.riolo@…>, 6 years ago

Correcting syntax according to ccheck

  • Property mode set to 100644
File size: 8.0 KB
Line 
1/*
2 * Copyright (c) 2015 Michal Koutny
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <assert.h>
30#include <pcut/pcut.h>
31#include <stdio.h>
32
33#include "../job_closure.h"
34#include "../repo.h"
35
36#include "mock_unit.h"
37
38PCUT_INIT
39
40PCUT_TEST_SUITE(job_closure);
41
42static dyn_array_t exp_closure;
43static dyn_array_t act_closure;
44
45static bool same_job(job_t *expected, job_t *actual)
46{
47 return (expected->unit == actual->unit) &&
48 (expected->target_state == actual->target_state);
49}
50
51static bool same_jobs(dyn_array_t *expected, dyn_array_t *actual)
52{
53 if (expected->size != actual->size) {
54 printf("%s: |expected|, |actual| = %lu, %lu\n",
55 __func__, expected->size, actual->size);
56 return false;
57 }
58
59 /* Verify expected \subseteq actual (we've compared sizes) */
60 dyn_array_foreach(*expected, job_t *, it_exp) {
61 bool found = false;
62 dyn_array_foreach(*actual, job_t *, it_act) {
63 if (same_job(*it_exp, *it_act)) {
64 found = true;
65 break;
66 }
67 }
68 if (!found) {
69 printf("%s: expected job for %s\n",
70 __func__, unit_name((*it_exp)->unit));
71 return false;
72 }
73 }
74
75 return true;
76}
77
78static bool job_blocked(job_t *blocked_job, job_t *blocking_job)
79{
80 bool found = false;
81 dyn_array_foreach(blocking_job->blocked_jobs, job_t *, it) {
82 if (*it == blocked_job) {
83 found = true;
84 break;
85 }
86 }
87 return found;
88}
89
90static job_t *dummy_job(unit_t *unit, unit_state_t target_state)
91{
92 job_t *result = job_create(unit, target_state);
93 return result;
94}
95
96static void dummy_add_closure(dyn_array_t *closure)
97{
98 dyn_array_foreach(*closure, job_t *, it) {
99 (*it)->unit->job = *it;
100 }
101}
102
103static void destroy_job_closure(dyn_array_t *closure)
104{
105 dyn_array_foreach(*closure, job_t *, it) {
106 job_del_ref(&(*it));
107 }
108}
109
110PCUT_TEST_BEFORE
111{
112 mock_create_units();
113 mock_set_units_state(STATE_STOPPED);
114
115 dyn_array_initialize(&exp_closure, job_t *);
116 int rc = dyn_array_reserve(&exp_closure, MAX_TYPES * MAX_UNITS);
117 assert(rc == EOK);
118
119 dyn_array_initialize(&act_closure, job_t *);
120 rc = dyn_array_reserve(&act_closure, MAX_TYPES * MAX_UNITS);
121 assert(rc == EOK);
122
123 repo_init();
124}
125
126PCUT_TEST_AFTER
127{
128 destroy_job_closure(&act_closure);
129 dyn_array_destroy(&act_closure);
130
131 destroy_job_closure(&exp_closure);
132 dyn_array_destroy(&exp_closure);
133
134 mock_destroy_units();
135}
136
137PCUT_TEST(job_closure_linear)
138{
139 unit_t *u0 = mock_units[UNIT_SERVICE][0];
140 unit_t *u1 = mock_units[UNIT_SERVICE][1];
141 unit_t *u2 = mock_units[UNIT_SERVICE][2];
142 unit_t *u3 = mock_units[UNIT_SERVICE][3];
143
144 /*
145 * u0 -> u1 -> u2 -> u3
146 */
147 mock_add_edge(u0, u1);
148 mock_add_edge(u1, u2);
149 mock_add_edge(u2, u3);
150
151 /* Intentionally omit u0 */
152 job_t *main_job = job_create(u1, STATE_STARTED);
153 assert(main_job);
154
155 int rc = job_create_closure(main_job, &act_closure, 0);
156 PCUT_ASSERT_INT_EQUALS(EOK, rc);
157
158 dyn_array_append(&exp_closure, job_t *, dummy_job(u1, STATE_STARTED));
159 dyn_array_append(&exp_closure, job_t *, dummy_job(u2, STATE_STARTED));
160 dyn_array_append(&exp_closure, job_t *, dummy_job(u3, STATE_STARTED));
161
162 dummy_add_closure(&act_closure);
163
164 PCUT_ASSERT_TRUE(same_jobs(&exp_closure, &act_closure));
165 PCUT_ASSERT_TRUE(job_blocked(u1->job, u2->job));
166 PCUT_ASSERT_TRUE(job_blocked(u2->job, u3->job));
167}
168
169PCUT_TEST(job_closure_fork)
170{
171 unit_t *u0 = mock_units[UNIT_SERVICE][0];
172 unit_t *u1 = mock_units[UNIT_SERVICE][1];
173 unit_t *u2 = mock_units[UNIT_SERVICE][2];
174 unit_t *u3 = mock_units[UNIT_SERVICE][3];
175
176 /*
177 * u0 -> u1 -> u2
178 * \-> u3
179 */
180 mock_add_edge(u0, u1);
181 mock_add_edge(u1, u2);
182 mock_add_edge(u1, u3);
183
184 job_t *main_job = job_create(u1, STATE_STARTED);
185 assert(main_job);
186
187 int rc = job_create_closure(main_job, &act_closure, 0);
188 PCUT_ASSERT_INT_EQUALS(EOK, rc);
189
190 dyn_array_append(&exp_closure, job_t *, dummy_job(u1, STATE_STARTED));
191 dyn_array_append(&exp_closure, job_t *, dummy_job(u2, STATE_STARTED));
192 dyn_array_append(&exp_closure, job_t *, dummy_job(u3, STATE_STARTED));
193
194 dummy_add_closure(&act_closure);
195
196 PCUT_ASSERT_TRUE(same_jobs(&exp_closure, &act_closure));
197 PCUT_ASSERT_TRUE(job_blocked(u1->job, u2->job));
198 PCUT_ASSERT_TRUE(job_blocked(u1->job, u3->job));
199}
200
201PCUT_TEST(job_closure_triangle)
202{
203 unit_t *u0 = mock_units[UNIT_SERVICE][0];
204 unit_t *u1 = mock_units[UNIT_SERVICE][1];
205 unit_t *u2 = mock_units[UNIT_SERVICE][2];
206 unit_t *u3 = mock_units[UNIT_SERVICE][3];
207
208 /*
209 * u0 -> u1 -> u2
210 * \ v
211 * \-> u3
212 */
213 mock_add_edge(u0, u1);
214 mock_add_edge(u1, u2);
215 mock_add_edge(u1, u3);
216 mock_add_edge(u2, u3);
217
218 job_t *main_job = job_create(u1, STATE_STARTED);
219 assert(main_job);
220
221 int rc = job_create_closure(main_job, &act_closure, 0);
222 PCUT_ASSERT_INT_EQUALS(EOK, rc);
223
224 dyn_array_append(&exp_closure, job_t *, dummy_job(u1, STATE_STARTED));
225 dyn_array_append(&exp_closure, job_t *, dummy_job(u2, STATE_STARTED));
226 dyn_array_append(&exp_closure, job_t *, dummy_job(u3, STATE_STARTED));
227
228 dummy_add_closure(&act_closure);
229
230 PCUT_ASSERT_TRUE(same_jobs(&exp_closure, &act_closure));
231 PCUT_ASSERT_TRUE(job_blocked(u1->job, u2->job));
232 PCUT_ASSERT_TRUE(job_blocked(u1->job, u3->job));
233 PCUT_ASSERT_TRUE(job_blocked(u2->job, u3->job));
234}
235
236PCUT_TEST(job_closure_isolate_linears)
237{
238 unit_t *u0 = mock_units[UNIT_SERVICE][0];
239 unit_t *u1 = mock_units[UNIT_SERVICE][1];
240 unit_t *u2 = mock_units[UNIT_SERVICE][2];
241 unit_t *u3 = mock_units[UNIT_SERVICE][3];
242 unit_t *u4 = mock_units[UNIT_SERVICE][4];
243 unit_t *u5 = mock_units[UNIT_SERVICE][5];
244 unit_t *u6 = mock_units[UNIT_SERVICE][6];
245 repo_begin_update();
246 for (int i = 0; i < 7; ++i) {
247 repo_add_unit(mock_units[UNIT_SERVICE][i]);
248 }
249 repo_commit();
250
251 /*
252 *
253 * u0 -> u1 -> u2
254 *
255 * u3 -> u4 -> u5
256 *
257 * u6
258 */
259 mock_add_edge(u0, u1);
260 mock_add_edge(u1, u2);
261
262 mock_add_edge(u3, u4);
263 mock_add_edge(u4, u5);
264
265 job_t *main_job = job_create(u1, STATE_STARTED);
266 assert(main_job);
267
268 int rc = job_create_closure(main_job, &act_closure, CLOSURE_ISOLATE);
269 PCUT_ASSERT_INT_EQUALS(EOK, rc);
270
271 dyn_array_append(&exp_closure, job_t *, dummy_job(u0, STATE_STOPPED));
272 dyn_array_append(&exp_closure, job_t *, dummy_job(u1, STATE_STARTED));
273 dyn_array_append(&exp_closure, job_t *, dummy_job(u2, STATE_STARTED));
274 dyn_array_append(&exp_closure, job_t *, dummy_job(u3, STATE_STOPPED));
275 dyn_array_append(&exp_closure, job_t *, dummy_job(u4, STATE_STOPPED));
276 dyn_array_append(&exp_closure, job_t *, dummy_job(u5, STATE_STOPPED));
277 dyn_array_append(&exp_closure, job_t *, dummy_job(u6, STATE_STOPPED));
278
279 dummy_add_closure(&act_closure);
280
281 PCUT_ASSERT_TRUE(same_jobs(&exp_closure, &act_closure));
282 PCUT_ASSERT_TRUE(job_blocked(u1->job, u2->job));
283
284 PCUT_ASSERT_TRUE(job_blocked(u5->job, u4->job));
285 PCUT_ASSERT_TRUE(job_blocked(u4->job, u3->job));
286
287 PCUT_ASSERT_INT_EQUALS(0, u6->job->blocking_jobs);
288 PCUT_ASSERT_INT_EQUALS(0, u0->job->blocking_jobs);
289}
290
291PCUT_EXPORT(job_closure);
Note: See TracBrowser for help on using the repository browser.