1 /*
2 * Copyright (c) 2014-2019, Intel Corporation
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * * Neither the name of Intel Corporation nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "ptunit.h"
30
31 #include "pt_event_queue.h"
32
33
34 /* A test fixture providing an initialized event queue. */
35 struct evq_fixture {
36 /* The event queue. */
37 struct pt_event_queue evq;
38
39 /* The test fixture initialization and finalization functions. */
40 struct ptunit_result (*init)(struct evq_fixture *);
41 struct ptunit_result (*fini)(struct evq_fixture *);
42 };
43
44
efix_init(struct evq_fixture * efix)45 static struct ptunit_result efix_init(struct evq_fixture *efix)
46 {
47 pt_evq_init(&efix->evq);
48
49 return ptu_passed();
50 }
51
efix_init_pending(struct evq_fixture * efix)52 static struct ptunit_result efix_init_pending(struct evq_fixture *efix)
53 {
54 struct pt_event *ev;
55 int evb;
56
57 pt_evq_init(&efix->evq);
58
59 for (evb = 0; evb < evb_max; ++evb) {
60 ev = pt_evq_enqueue(&efix->evq, (enum pt_event_binding) evb);
61 ptu_ptr(ev);
62 }
63
64 return ptu_passed();
65 }
66
standalone_null(void)67 static struct ptunit_result standalone_null(void)
68 {
69 struct pt_event *ev;
70
71 ev = pt_evq_standalone(NULL);
72 ptu_null(ev);
73
74 return ptu_passed();
75 }
76
standalone(struct evq_fixture * efix)77 static struct ptunit_result standalone(struct evq_fixture *efix)
78 {
79 struct pt_event *ev;
80
81 ev = pt_evq_standalone(&efix->evq);
82 ptu_ptr(ev);
83 ptu_uint_eq(ev->ip_suppressed, 0ul);
84 ptu_uint_eq(ev->status_update, 0ul);
85
86 return ptu_passed();
87 }
88
enqueue_null(enum pt_event_binding evb)89 static struct ptunit_result enqueue_null(enum pt_event_binding evb)
90 {
91 struct pt_event *ev;
92
93 ev = pt_evq_enqueue(NULL, evb);
94 ptu_null(ev);
95
96 return ptu_passed();
97 }
98
dequeue_null(enum pt_event_binding evb)99 static struct ptunit_result dequeue_null(enum pt_event_binding evb)
100 {
101 struct pt_event *ev;
102
103 ev = pt_evq_dequeue(NULL, evb);
104 ptu_null(ev);
105
106 return ptu_passed();
107 }
108
dequeue_empty(struct evq_fixture * efix,enum pt_event_binding evb)109 static struct ptunit_result dequeue_empty(struct evq_fixture *efix,
110 enum pt_event_binding evb)
111 {
112 struct pt_event *ev;
113
114 ev = pt_evq_dequeue(&efix->evq, evb);
115 ptu_null(ev);
116
117 return ptu_passed();
118 }
119
evq_empty(struct evq_fixture * efix,enum pt_event_binding evb)120 static struct ptunit_result evq_empty(struct evq_fixture *efix,
121 enum pt_event_binding evb)
122 {
123 int status;
124
125 status = pt_evq_empty(&efix->evq, evb);
126 ptu_int_gt(status, 0);
127
128 status = pt_evq_pending(&efix->evq, evb);
129 ptu_int_eq(status, 0);
130
131 return ptu_passed();
132 }
133
evq_pending(struct evq_fixture * efix,enum pt_event_binding evb)134 static struct ptunit_result evq_pending(struct evq_fixture *efix,
135 enum pt_event_binding evb)
136 {
137 int status;
138
139 status = pt_evq_empty(&efix->evq, evb);
140 ptu_int_eq(status, 0);
141
142 status = pt_evq_pending(&efix->evq, evb);
143 ptu_int_gt(status, 0);
144
145 return ptu_passed();
146 }
147
evq_others_empty(struct evq_fixture * efix,enum pt_event_binding evb)148 static struct ptunit_result evq_others_empty(struct evq_fixture *efix,
149 enum pt_event_binding evb)
150 {
151 int other;
152
153 for (other = 0; other < evb_max; ++other) {
154 enum pt_event_binding ob;
155
156 ob = (enum pt_event_binding) other;
157 if (ob != evb)
158 ptu_test(evq_empty, efix, ob);
159 }
160
161 return ptu_passed();
162 }
163
enqueue_all_dequeue(struct evq_fixture * efix,enum pt_event_binding evb,size_t num)164 static struct ptunit_result enqueue_all_dequeue(struct evq_fixture *efix,
165 enum pt_event_binding evb,
166 size_t num)
167 {
168 struct pt_event *in[evq_max], *out[evq_max];
169 size_t idx;
170
171 ptu_uint_le(num, evq_max - 2);
172
173 for (idx = 0; idx < num; ++idx) {
174 in[idx] = pt_evq_enqueue(&efix->evq, evb);
175 ptu_ptr(in[idx]);
176 }
177
178 ptu_test(evq_pending, efix, evb);
179 ptu_test(evq_others_empty, efix, evb);
180
181 for (idx = 0; idx < num; ++idx) {
182 out[idx] = pt_evq_dequeue(&efix->evq, evb);
183 ptu_ptr_eq(out[idx], in[idx]);
184 }
185
186 ptu_test(evq_empty, efix, evb);
187
188 return ptu_passed();
189 }
190
enqueue_one_dequeue(struct evq_fixture * efix,enum pt_event_binding evb,size_t num)191 static struct ptunit_result enqueue_one_dequeue(struct evq_fixture *efix,
192 enum pt_event_binding evb,
193 size_t num)
194 {
195 size_t idx;
196
197 for (idx = 0; idx < num; ++idx) {
198 struct pt_event *in, *out;
199
200 in = pt_evq_enqueue(&efix->evq, evb);
201 ptu_ptr(in);
202
203 out = pt_evq_dequeue(&efix->evq, evb);
204 ptu_ptr_eq(out, in);
205 }
206
207 return ptu_passed();
208 }
209
overflow(struct evq_fixture * efix,enum pt_event_binding evb,size_t num)210 static struct ptunit_result overflow(struct evq_fixture *efix,
211 enum pt_event_binding evb,
212 size_t num)
213 {
214 struct pt_event *in[evq_max], *out[evq_max], *ev;
215 size_t idx;
216
217 ptu_uint_le(num, evq_max - 2);
218
219 for (idx = 0; idx < (evq_max - 2); ++idx) {
220 in[idx] = pt_evq_enqueue(&efix->evq, evb);
221 ptu_ptr(in[idx]);
222 }
223
224 for (idx = 0; idx < num; ++idx) {
225 ev = pt_evq_enqueue(&efix->evq, evb);
226 ptu_null(ev);
227 }
228
229 for (idx = 0; idx < num; ++idx) {
230 out[idx] = pt_evq_dequeue(&efix->evq, evb);
231 ptu_ptr_eq(out[idx], in[idx]);
232 }
233
234 return ptu_passed();
235 }
236
clear_null(enum pt_event_binding evb)237 static struct ptunit_result clear_null(enum pt_event_binding evb)
238 {
239 int errcode;
240
241 errcode = pt_evq_clear(NULL, evb);
242 ptu_int_eq(errcode, -pte_internal);
243
244 return ptu_passed();
245 }
246
clear(struct evq_fixture * efix,enum pt_event_binding evb)247 static struct ptunit_result clear(struct evq_fixture *efix,
248 enum pt_event_binding evb)
249 {
250 int errcode;
251
252 errcode = pt_evq_clear(&efix->evq, evb);
253 ptu_int_eq(errcode, 0);
254
255 ptu_test(evq_empty, efix, evb);
256
257 return ptu_passed();
258 }
259
empty_null(enum pt_event_binding evb)260 static struct ptunit_result empty_null(enum pt_event_binding evb)
261 {
262 int errcode;
263
264 errcode = pt_evq_empty(NULL, evb);
265 ptu_int_eq(errcode, -pte_internal);
266
267 return ptu_passed();
268 }
269
pending_null(enum pt_event_binding evb)270 static struct ptunit_result pending_null(enum pt_event_binding evb)
271 {
272 int errcode;
273
274 errcode = pt_evq_pending(NULL, evb);
275 ptu_int_eq(errcode, -pte_internal);
276
277 return ptu_passed();
278 }
279
find_null(enum pt_event_binding evb,enum pt_event_type evt)280 static struct ptunit_result find_null(enum pt_event_binding evb,
281 enum pt_event_type evt)
282 {
283 struct pt_event *ev;
284
285 ev = pt_evq_find(NULL, evb, evt);
286 ptu_null(ev);
287
288 return ptu_passed();
289 }
290
find_empty(struct evq_fixture * efix,enum pt_event_binding evb,enum pt_event_type evt)291 static struct ptunit_result find_empty(struct evq_fixture *efix,
292 enum pt_event_binding evb,
293 enum pt_event_type evt)
294 {
295 struct pt_event *ev;
296
297 ev = pt_evq_find(&efix->evq, evb, evt);
298 ptu_null(ev);
299
300 return ptu_passed();
301 }
302
find_none_evb(struct evq_fixture * efix,enum pt_event_binding evb,enum pt_event_type evt)303 static struct ptunit_result find_none_evb(struct evq_fixture *efix,
304 enum pt_event_binding evb,
305 enum pt_event_type evt)
306 {
307 struct pt_event *ev;
308 size_t other;
309
310 for (other = 0; other < evb_max; ++other) {
311 enum pt_event_binding ob;
312
313 ob = (enum pt_event_binding) other;
314 if (ob != evb) {
315 ev = pt_evq_enqueue(&efix->evq, ob);
316 ptu_ptr(ev);
317
318 ev->type = evt;
319 }
320 }
321
322 ev = pt_evq_find(&efix->evq, evb, evt);
323 ptu_null(ev);
324
325 return ptu_passed();
326 }
327
evq_enqueue_other(struct evq_fixture * efix,enum pt_event_binding evb,enum pt_event_type evt,size_t num)328 static struct ptunit_result evq_enqueue_other(struct evq_fixture *efix,
329 enum pt_event_binding evb,
330 enum pt_event_type evt,
331 size_t num)
332 {
333 enum pt_event_type ot;
334 struct pt_event *ev;
335 size_t other;
336
337 for (other = 0; other < num; ++other) {
338 ot = (enum pt_event_type) other;
339 if (ot != evt) {
340 ev = pt_evq_enqueue(&efix->evq, evb);
341 ptu_ptr(ev);
342
343 ev->type = ot;
344 }
345 }
346
347 return ptu_passed();
348 }
349
find_none_evt(struct evq_fixture * efix,enum pt_event_binding evb,enum pt_event_type evt,size_t num)350 static struct ptunit_result find_none_evt(struct evq_fixture *efix,
351 enum pt_event_binding evb,
352 enum pt_event_type evt,
353 size_t num)
354 {
355 struct pt_event *ev;
356
357 ptu_test(evq_enqueue_other, efix, evb, evt, num);
358
359 ev = pt_evq_find(&efix->evq, evb, evt);
360 ptu_null(ev);
361
362 return ptu_passed();
363 }
364
find(struct evq_fixture * efix,enum pt_event_binding evb,enum pt_event_type evt,size_t before,size_t after)365 static struct ptunit_result find(struct evq_fixture *efix,
366 enum pt_event_binding evb,
367 enum pt_event_type evt,
368 size_t before, size_t after)
369 {
370 struct pt_event *in, *out;
371
372 ptu_test(evq_enqueue_other, efix, evb, evt, before);
373
374 in = pt_evq_enqueue(&efix->evq, evb);
375 ptu_ptr(in);
376
377 in->type = evt;
378
379 ptu_test(evq_enqueue_other, efix, evb, evt, after);
380
381 out = pt_evq_find(&efix->evq, evb, evt);
382 ptu_ptr_eq(out, in);
383
384 return ptu_passed();
385 }
386
main(int argc,char ** argv)387 int main(int argc, char **argv)
388 {
389 struct evq_fixture efix, pfix;
390 struct ptunit_suite suite;
391
392 efix.init = efix_init;
393 efix.fini = NULL;
394
395 pfix.init = efix_init_pending;
396 pfix.fini = NULL;
397
398 suite = ptunit_mk_suite(argc, argv);
399
400 ptu_run(suite, standalone_null);
401 ptu_run_f(suite, standalone, efix);
402
403 ptu_run_p(suite, enqueue_null, evb_psbend);
404 ptu_run_p(suite, enqueue_null, evb_tip);
405 ptu_run_p(suite, enqueue_null, evb_fup);
406
407 ptu_run_p(suite, dequeue_null, evb_psbend);
408 ptu_run_p(suite, dequeue_null, evb_tip);
409 ptu_run_p(suite, dequeue_null, evb_fup);
410
411 ptu_run_fp(suite, dequeue_empty, efix, evb_psbend);
412 ptu_run_fp(suite, dequeue_empty, efix, evb_tip);
413 ptu_run_fp(suite, dequeue_empty, efix, evb_fup);
414
415 ptu_run_fp(suite, enqueue_all_dequeue, efix, evb_psbend, 1);
416 ptu_run_fp(suite, enqueue_all_dequeue, efix, evb_psbend, 2);
417 ptu_run_fp(suite, enqueue_all_dequeue, efix, evb_tip, 1);
418 ptu_run_fp(suite, enqueue_all_dequeue, efix, evb_tip, 3);
419 ptu_run_fp(suite, enqueue_all_dequeue, efix, evb_fup, 1);
420 ptu_run_fp(suite, enqueue_all_dequeue, efix, evb_fup, 4);
421
422 ptu_run_fp(suite, enqueue_one_dequeue, efix, evb_psbend, evb_max * 2);
423 ptu_run_fp(suite, enqueue_one_dequeue, efix, evb_tip, evb_max * 2);
424 ptu_run_fp(suite, enqueue_one_dequeue, efix, evb_fup, evb_max * 2);
425
426 ptu_run_fp(suite, overflow, efix, evb_psbend, 1);
427 ptu_run_fp(suite, overflow, efix, evb_tip, 2);
428 ptu_run_fp(suite, overflow, efix, evb_fup, 3);
429
430 ptu_run_p(suite, clear_null, evb_psbend);
431 ptu_run_p(suite, clear_null, evb_tip);
432 ptu_run_p(suite, clear_null, evb_fup);
433
434 ptu_run_fp(suite, clear, efix, evb_psbend);
435 ptu_run_fp(suite, clear, pfix, evb_psbend);
436 ptu_run_fp(suite, clear, efix, evb_tip);
437 ptu_run_fp(suite, clear, pfix, evb_tip);
438 ptu_run_fp(suite, clear, efix, evb_fup);
439 ptu_run_fp(suite, clear, pfix, evb_fup);
440
441 ptu_run_p(suite, empty_null, evb_psbend);
442 ptu_run_p(suite, empty_null, evb_tip);
443 ptu_run_p(suite, empty_null, evb_fup);
444
445 ptu_run_p(suite, pending_null, evb_psbend);
446 ptu_run_p(suite, pending_null, evb_tip);
447 ptu_run_p(suite, pending_null, evb_fup);
448
449 ptu_run_p(suite, find_null, evb_psbend, ptev_enabled);
450 ptu_run_p(suite, find_null, evb_tip, ptev_disabled);
451 ptu_run_p(suite, find_null, evb_fup, ptev_paging);
452
453 ptu_run_fp(suite, find_empty, efix, evb_psbend, ptev_enabled);
454 ptu_run_fp(suite, find_empty, efix, evb_tip, ptev_disabled);
455 ptu_run_fp(suite, find_empty, efix, evb_fup, ptev_paging);
456
457 ptu_run_fp(suite, find_none_evb, efix, evb_psbend, ptev_enabled);
458 ptu_run_fp(suite, find_none_evb, efix, evb_tip, ptev_disabled);
459 ptu_run_fp(suite, find_none_evb, efix, evb_fup, ptev_paging);
460
461 ptu_run_fp(suite, find_none_evt, efix, evb_psbend, ptev_enabled, 3);
462 ptu_run_fp(suite, find_none_evt, efix, evb_tip, ptev_disabled, 4);
463 ptu_run_fp(suite, find_none_evt, efix, evb_fup, ptev_paging, 2);
464
465 ptu_run_fp(suite, find, efix, evb_psbend, ptev_enabled, 0, 3);
466 ptu_run_fp(suite, find, efix, evb_tip, ptev_disabled, 2, 0);
467 ptu_run_fp(suite, find, efix, evb_fup, ptev_paging, 1, 4);
468
469 return ptunit_report(&suite);
470 }
471