source: rtems/testsuites/libtests/block08/bdbuf_tests.h @ 78da8ac3

4.115
Last change on this file since 78da8ac3 was 64734fc, checked in by Thomas Doerfler <Thomas.Doerfler@…>, on 01/19/10 at 08:55:18

updates and new test cases

  • Property mode set to 100644
File size: 20.0 KB
Line 
1/*! @file
2 * @brief Common declarations of bdbuf tests.
3 *
4 * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
5 * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
6 *
7 * The license and distribution terms for this file may be
8 * found in the file LICENSE in this distribution or at
9 * http://www.rtems.com/license/LICENSE.
10 *
11 * $Id$
12 */
13
14#ifndef BDBUF_TESTS_H
15#define BDBUF_TESTS_H
16
17#include <stdio.h>
18#include <errno.h>
19#include <rtems/diskdevs.h>
20#include <rtems/bdbuf.h>
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26extern void run_bdbuf_tests(void);
27
28extern void bdbuf_test1_1_main(void);
29extern void bdbuf_test1_2_main(void);
30extern void bdbuf_test1_3_main(void);
31extern void bdbuf_test1_4_main(void);
32extern void bdbuf_test1_5_main(void);
33
34extern void bdbuf_test2_1_main(void);
35extern void bdbuf_test2_2_main(void);
36extern void bdbuf_test2_3_main(void);
37extern void bdbuf_test2_4_main(void);
38extern void bdbuf_test2_5_main(void);
39
40extern void bdbuf_test3_1_main(void);
41extern void bdbuf_test3_2_main(void);
42extern void bdbuf_test3_3_main(void);
43
44extern void bdbuf_test4_1_main(void);
45extern void bdbuf_test4_2_main(void);
46extern void bdbuf_test4_3_main(void);
47
48extern rtems_device_driver
49test_disk_initialize(
50    rtems_device_major_number major,
51    rtems_device_minor_number minor,
52    void *arg);
53
54#define ARRAY_NUM(a_) (sizeof(a_) / sizeof(a_[0]))
55
56/**
57 * Configuration parameters of Test disk device.
58 */
59#define TEST_DISK_BLOCK_SIZE   512
60#define TEST_DISK_BLOCK_NUM    1024
61#define TEST_DISK_NAME         "/dev/testdisk"
62
63/** Type of messages between test disk driver and main test task */
64enum bdbuf_test_msg_type {
65    /** Message sent by disk driver to main test task */
66    BDBUF_TEST_MSG_TYPE_DRIVER_REQ,
67    /**
68     * Message sent main test task to disk driver
69     * in reply to request.
70     */
71    BDBUF_TEST_MSG_TYPE_DRIVER_REPLY,
72};
73
74/**
75 * Message used in communication between test disk driver
76 * and main test task.
77 * All R/W requests obtained by driver (from bdbuf library)
78 * are directed to main test task. Then main test task
79 * sends a reply after which test disk driver notifies
80 * bdbuf library about operation complete event.
81 */
82typedef struct bdbuf_test_msg {
83    /** Message type */
84    enum bdbuf_test_msg_type type;
85
86    union {
87        struct driver_req {
88            dev_t     dev;
89            uint32_t  req;
90            void     *argp;
91        } driver_req;
92        struct driver_reply {
93            int               ret_val;
94            int               ret_errno;
95            rtems_status_code res_status;
96            int               res_errno;
97        } driver_reply;
98    } val;
99} bdbuf_test_msg;
100
101
102typedef enum bdbuf_rest_thread_prio {
103    BDBUF_TEST_THREAD_PRIO_NORMAL = 3,
104    BDBUF_TEST_THREAD_PRIO_LOW = 7,
105    BDBUF_TEST_THREAD_PRIO_HIGH = 5,
106} bdbuf_rest_thread_prio;
107
108
109typedef struct test_ctx {
110    /**
111     * Message queue used by main task to get messages from
112     * disk device driver.
113     */
114    Objects_Id test_qid;
115   
116    /**
117     * Object ID for disk driver queue.
118     * Test task will send messages to this queue in reply
119     * to messages received on @a test_qid.
120     */
121    Objects_Id test_drv_qid;
122
123    /** Test name */
124    const char *test_name;
125
126    /**
127     * Semaphore used for synchronization between test thread
128     * and main test task.
129     * Main test task blocks on one of these semaphores and an auxiliary thread
130     * releases it in order to pass control to main task again.
131     */
132    rtems_id   test_sync_main[3];
133
134    /**
135     * This semaphore is used for synchornization between main test task
136     * and the END of auxiliary threads.
137     */
138    rtems_id   test_end_main;
139
140    /**
141     * Semaphore used for synchronization between test thread
142     * and main test task.
143     * Thread #N blocks on this semaphore and the main task releases it
144     * when it wants to pass control to the auxiliary thread #N.
145     */
146    rtems_id   test_sync[3];
147
148    /** Task Id values of auxiliary threads */
149    Objects_Id test_task[3];
150} test_ctx;
151
152extern test_ctx g_test_ctx;
153
154/** Device ID used for testing */
155extern dev_t      test_dev;
156
157/**
158 * Create a message queue for test driver that is used for
159 * receiving messages from test task.
160 *
161 * @param[out] id  RTEMS message queue identifier
162 *
163 * @return Status of the operation
164 */
165extern rtems_status_code bdbuf_test_create_drv_rx_queue(Objects_Id *id);
166
167/**
168 * Obtain a message queue for test driver that is used for
169 * sending messages to test task.
170 *
171 * @param[out] id  RTEMS message queue identifier
172 *
173 * @return Status of the operation
174 */
175extern rtems_status_code bdbuf_test_create_drv_tx_queue(Objects_Id *id);
176
177/**
178 * Start a separate test task represented by function @p func
179 * and associated with task index @p idx.
180 *
181 * @param[in] idx   Task index
182 * @param[in] func  Test task function
183 */
184extern rtems_status_code bdbuf_test_start_thread(unsigned int idx,
185                                                 rtems_task_entry func);
186
187/**
188 * Finalize test run.
189 */
190extern rtems_status_code bdbuf_test_end(void);
191
192/** Test result variable */
193extern bool       good_test_result;
194
195#define BDBUF_TEST_BLOCK_TIMEOUT (2 * rtems_clock_get_ticks_per_second())
196
197#define SET_THREAD_PRIORITY(t_num_, prio_) \
198    do {                                                        \
199        rtems_task_priority old_prio;                           \
200        rtems_status_code   rc_;                                \
201                                                                \
202        rc_ = rtems_task_set_priority(                          \
203                g_test_ctx.test_task[(t_num_) - 1],             \
204                BDBUF_TEST_THREAD_PRIO_ ## prio_, &old_prio);   \
205        if (rc_ != RTEMS_SUCCESSFUL)                            \
206        {                                                       \
207            printk("Failed to change priority of test thread #" \
208                   #t_num_ " in test %s\n", g_test_ctx.test_name);         \
209            return;                                             \
210        }                                                       \
211    } while (0)
212
213/**
214 * Start thread number @p t_num_ with @p func_ function
215 * as an entry point of the thread.
216 *
217 * @param t_num_  thread number.
218 * @param func_   thread entry point.
219 */
220#define START_THREAD(t_num_, func_) \
221    do {                                                        \
222        if (bdbuf_test_start_thread((t_num_) - 1, func_) !=     \
223                RTEMS_SUCCESSFUL)                               \
224        {                                                       \
225            return;                                             \
226        }                                                       \
227        printk("Thread #" #t_num_ " started\n");                \
228    } while (0)
229
230/**
231 * Wait for a message from device driver.
232 *
233 * @param[out] msg_  Pointer to a message data structure
234 */
235#define WAIT_DRV_MSG(msg_) \
236    do {                                                        \
237        rtems_status_code rc_;                                  \
238        size_t            msg_size_ = sizeof(*(msg_));          \
239                                                                \
240        rc_ = rtems_message_queue_receive(g_test_ctx.test_qid,  \
241                                          (msg_), &msg_size_,   \
242                                          RTEMS_WAIT,           \
243                                          RTEMS_NO_TIMEOUT);    \
244        if (rc_ != RTEMS_SUCCESSFUL ||                          \
245            msg_size_ != sizeof(*(msg_)))                       \
246        {                                                       \
247            printk("Error at %s:%d\n", __FILE__, __LINE__);     \
248            return;                                             \
249        }                                                       \
250        if ((msg_)->type != BDBUF_TEST_MSG_TYPE_DRIVER_REQ)     \
251        {                                                       \
252            printk("Unexpected message received: %d\n",         \
253                   (msg_)->type);                               \
254            return;                                             \
255        }                                                       \
256    } while (0)
257
258#define WAIT_DRV_MSG_WR(msg_) \
259    do {                                                                \
260        WAIT_DRV_MSG(msg_);                                             \
261        if ((msg_)->val.driver_req.req != RTEMS_BLKIO_REQUEST ||        \
262            (msg_)->val.driver_req.dev != test_dev ||                   \
263            ((rtems_blkdev_request *)                                   \
264                 ((msg_)->val.driver_req.argp))->req !=                 \
265                 RTEMS_BLKDEV_REQ_WRITE)                                \
266        {                                                               \
267            printk("Unexpected message received by disk driver: "       \
268                   "req - 0x%x (0x%x), dev - %d (%d)\n",                \
269                   (msg_)->val.driver_req.req, RTEMS_BLKIO_REQUEST,     \
270                   (msg_)->val.driver_req.dev, test_dev);               \
271            return;                                                     \
272        }                                                               \
273    } while (0)
274
275#define CHECK_NO_DRV_MSG() \
276    do {                                                        \
277        rtems_status_code rc_;                                  \
278        bdbuf_test_msg    msg_;                                 \
279        size_t            msg_size_ = sizeof(msg_);             \
280                                                                \
281        rc_ = rtems_message_queue_receive(g_test_ctx.test_qid,  \
282                  (&msg_), &msg_size_,                          \
283                  RTEMS_WAIT,                                   \
284                  BDBUF_TEST_BLOCK_TIMEOUT);                    \
285        if (rc_ != RTEMS_TIMEOUT)                               \
286        {                                                       \
287            printk("Error at %s:%d\n", __FILE__, __LINE__);     \
288            return;                                             \
289        }                                                       \
290    } while (0)
291
292extern bdbuf_test_msg test_drv_msg;
293
294/**
295 * Send a message to device driver (in order to complete
296 * blocked I/O operation).
297 *
298 * @param ret_val_     Return value to use when returning from
299 *                     ioctl() function.
300 * @param ret_errno_   errno value to set to errno variable.
301 * @param res_status_  In case return value from the ioctl()
302 *                     function is equal to 0, this value
303 *                     is used as status code in asynchronous
304 *                     notification.
305 * @param res_errno_   In case return value from the ioctl()
306 *                     function is equal to 0, this value
307 *                     is used as error value in asynchronous
308 *                     notification.
309 *
310 */
311#define SEND_DRV_MSG(ret_val_, ret_errno_, res_status_, res_errno_) \
312    do {                                                                \
313        rtems_status_code rc_;                                          \
314                                                                        \
315        memset(&test_drv_msg, 0, sizeof(test_drv_msg));                 \
316        test_drv_msg.type = BDBUF_TEST_MSG_TYPE_DRIVER_REPLY;           \
317        test_drv_msg.val.driver_reply.ret_val = (ret_val_);             \
318        test_drv_msg.val.driver_reply.ret_errno = (ret_errno_);         \
319        test_drv_msg.val.driver_reply.res_status = (res_status_);       \
320        test_drv_msg.val.driver_reply.res_errno = (res_errno_);         \
321                                                                        \
322        rc_ = rtems_message_queue_send(g_test_ctx.test_drv_qid,         \
323                                       &test_drv_msg,                   \
324                                       sizeof(test_drv_msg));           \
325        if (rc_ != RTEMS_SUCCESSFUL)                                    \
326        {                                                               \
327            printk("Error while sending a message to "                  \
328                   "disk driver: %u\n", rc_);                           \
329            return;                                                     \
330        }                                                               \
331    } while (0)
332
333/**
334 * Block main test task until a thread passes back control
335 * with CONTINUE_MAIN().
336 *
337 * @param t_num_  thread number from which the main thread
338 *                is waiting for a sync.
339 */
340#define WAIT_THREAD_SYNC(t_num_) \
341    do {                                                                \
342        rtems_status_code rc_;                                          \
343                                                                        \
344        rc_ = rtems_semaphore_obtain(                                   \
345                g_test_ctx.test_sync_main[(t_num_) - 1],                \
346                RTEMS_WAIT, RTEMS_NO_TIMEOUT);                          \
347        if (rc_ != RTEMS_SUCCESSFUL)                                    \
348        {                                                               \
349            printk("Failed to get sync with a thread: %d\n", rc_);      \
350            return;                                                     \
351        }                                                               \
352    } while (0)
353
354/**
355 * Check that a particular thread is blocked.
356 *
357 * @param t_num_  thread number that we want to check for blocking
358 */
359#define CHECK_THREAD_BLOCKED(t_num_) \
360    do {                                                                \
361        rtems_status_code rc_;                                          \
362                                                                        \
363        rc_ = rtems_semaphore_obtain(                                   \
364                g_test_ctx.test_sync_main[(t_num_) - 1],                \
365                RTEMS_WAIT, BDBUF_TEST_BLOCK_TIMEOUT);                  \
366        if (rc_ != RTEMS_TIMEOUT)                                       \
367        {                                                               \
368            printk("Thread %d is not blocked at%s:%d\n",                \
369                   t_num_, __FILE__, __LINE__);                         \
370            return;                                                     \
371        }                                                               \
372    } while (0)
373
374/**
375 * Main test task gives control to the particular thread.
376 *
377 * @param t_num_  thread number to which main test task wants
378 *                to give control.
379 */
380#define CONTINUE_THREAD(t_num_) \
381    do {                                                        \
382        rtems_status_code rc_;                                  \
383                                                                \
384        rc_ = rtems_semaphore_release(                          \
385                g_test_ctx.test_sync[(t_num_) - 1]);            \
386        if (rc_ != RTEMS_SUCCESSFUL)                            \
387        {                                                       \
388            printk("Failed to give control to thread #"         \
389                   #t_num_ ": %d\n", rc_);                      \
390            return;                                             \
391        }                                                       \
392    } while (0)
393
394/**
395 * Passes control back to the main test task from a thread.
396 *
397 * @param t_num_ Current thread number
398 */
399#define CONTINUE_MAIN(t_num_) \
400    do {                                                        \
401        rtems_status_code rc_;                                  \
402                                                                \
403        rc_ = rtems_semaphore_release(                          \
404                g_test_ctx.test_sync_main[(t_num_) - 1]);       \
405        if (rc_ != RTEMS_SUCCESSFUL)                            \
406        {                                                       \
407            printk("Failed to give control to "                 \
408                   "main task: %d", rc_);                       \
409            return;                                             \
410        }                                                       \
411        rc_ = rtems_semaphore_obtain(                           \
412                g_test_ctx.test_sync[(t_num_) - 1],             \
413                RTEMS_WAIT, RTEMS_NO_TIMEOUT);                  \
414        if (rc_ != RTEMS_SUCCESSFUL)                            \
415        {                                                       \
416            printk("Failed to block on thread #"                \
417                   #t_num_ ": %d\n", rc_);                      \
418            return;                                             \
419        }                                                       \
420    } while (0)
421
422#define WAIT_MAIN_SYNC(t_num_) \
423    do {                                                        \
424        rtems_status_code rc_;                                  \
425                                                                \
426        rc_ = rtems_semaphore_obtain(                           \
427                g_test_ctx.test_sync[(t_num_) - 1],             \
428                RTEMS_WAIT, RTEMS_NO_TIMEOUT);                  \
429        if (rc_ != RTEMS_SUCCESSFUL)                            \
430        {                                                       \
431            printk("Failed to block on thread #"                \
432                   #t_num_ ": %d\n", rc_);                      \
433            return;                                             \
434        }                                                       \
435    } while (0)
436
437
438#define TEST_START(test_name_) \
439    do {                                \
440        good_test_result = true;        \
441        g_test_ctx.test_name = test_name_; \
442        printk("%s - STARTED\n",        \
443               g_test_ctx.test_name);              \
444    } while (0)
445
446#define TEST_CHECK_RESULT(step_) \
447    do {                                        \
448        if (!good_test_result)                  \
449        {                                       \
450            printk("TEST FAILED (Step %s)\n",   \
451                   step_);                      \
452            rtems_task_delete(RTEMS_SELF);      \
453        }                                       \
454        else                                    \
455        {                                       \
456            printk("%s: Step %s - OK\n",        \
457                   g_test_ctx.test_name, step_);           \
458        }                                       \
459    } while (0)
460
461#define TEST_END() \
462    do {                                 \
463        bdbuf_test_end();                \
464                                         \
465        if (good_test_result)            \
466            printk("TEST PASSED\n");     \
467        else                             \
468            printk("TEST FAILED (END)"); \
469    } while (0)
470
471#define THREAD_END() \
472    do {                                                        \
473        rtems_status_code rc_;                                  \
474                                                                \
475        rc_ = rtems_semaphore_release(g_test_ctx.test_end_main);\
476        if (rc_ != RTEMS_SUCCESSFUL)                            \
477        {                                                       \
478            printk("Failed to give control to "                 \
479                   "main task: %d", rc_);                       \
480            return;                                             \
481        }                                                       \
482        rtems_task_delete(RTEMS_SELF);                          \
483    } while (0)
484
485#define TEST_FAILED() \
486    do {                                \
487        good_test_result = false;       \
488    } while (0)
489
490#define SLEEP() \
491    rtems_task_wake_after(BDBUF_TEST_BLOCK_TIMEOUT)
492
493
494extern rtems_status_code
495bdbuf_test_start_aux_task(rtems_name name,
496                          rtems_task_entry entry_point,
497                          rtems_task_argument arg,
498                          Objects_Id *id);
499#ifdef __cplusplus
500}
501#endif
502
503#endif /* BDBUF_TESTS_H */
504
Note: See TracBrowser for help on using the repository browser.