summaryrefslogtreecommitdiffstats
path: root/testsuites/libtests/block08/bdbuf_tests.h
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2010-01-19 08:55:18 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2010-01-19 08:55:18 +0000
commit64734fc14b1015c1568c2906c9aeab1c6a7db82d (patch)
tree853af83fb05c8fcf05e3d7c44308895377b0028d /testsuites/libtests/block08/bdbuf_tests.h
parent2010-01-18 Joel Sherrill <joel.sherrill@oarcorp.com> (diff)
downloadrtems-64734fc14b1015c1568c2906c9aeab1c6a7db82d.tar.bz2
updates and new test cases
Diffstat (limited to 'testsuites/libtests/block08/bdbuf_tests.h')
-rw-r--r--testsuites/libtests/block08/bdbuf_tests.h504
1 files changed, 504 insertions, 0 deletions
diff --git a/testsuites/libtests/block08/bdbuf_tests.h b/testsuites/libtests/block08/bdbuf_tests.h
new file mode 100644
index 0000000000..e8affa1cbc
--- /dev/null
+++ b/testsuites/libtests/block08/bdbuf_tests.h
@@ -0,0 +1,504 @@
+/*! @file
+ * @brief Common declarations of bdbuf tests.
+ *
+ * Copyright (C) 2010 OKTET Labs, St.-Petersburg, Russia
+ * Author: Oleg Kravtsov <Oleg.Kravtsov@oktetlabs.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef BDBUF_TESTS_H
+#define BDBUF_TESTS_H
+
+#include <stdio.h>
+#include <errno.h>
+#include <rtems/diskdevs.h>
+#include <rtems/bdbuf.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void run_bdbuf_tests(void);
+
+extern void bdbuf_test1_1_main(void);
+extern void bdbuf_test1_2_main(void);
+extern void bdbuf_test1_3_main(void);
+extern void bdbuf_test1_4_main(void);
+extern void bdbuf_test1_5_main(void);
+
+extern void bdbuf_test2_1_main(void);
+extern void bdbuf_test2_2_main(void);
+extern void bdbuf_test2_3_main(void);
+extern void bdbuf_test2_4_main(void);
+extern void bdbuf_test2_5_main(void);
+
+extern void bdbuf_test3_1_main(void);
+extern void bdbuf_test3_2_main(void);
+extern void bdbuf_test3_3_main(void);
+
+extern void bdbuf_test4_1_main(void);
+extern void bdbuf_test4_2_main(void);
+extern void bdbuf_test4_3_main(void);
+
+extern rtems_device_driver
+test_disk_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg);
+
+#define ARRAY_NUM(a_) (sizeof(a_) / sizeof(a_[0]))
+
+/**
+ * Configuration parameters of Test disk device.
+ */
+#define TEST_DISK_BLOCK_SIZE 512
+#define TEST_DISK_BLOCK_NUM 1024
+#define TEST_DISK_NAME "/dev/testdisk"
+
+/** Type of messages between test disk driver and main test task */
+enum bdbuf_test_msg_type {
+ /** Message sent by disk driver to main test task */
+ BDBUF_TEST_MSG_TYPE_DRIVER_REQ,
+ /**
+ * Message sent main test task to disk driver
+ * in reply to request.
+ */
+ BDBUF_TEST_MSG_TYPE_DRIVER_REPLY,
+};
+
+/**
+ * Message used in communication between test disk driver
+ * and main test task.
+ * All R/W requests obtained by driver (from bdbuf library)
+ * are directed to main test task. Then main test task
+ * sends a reply after which test disk driver notifies
+ * bdbuf library about operation complete event.
+ */
+typedef struct bdbuf_test_msg {
+ /** Message type */
+ enum bdbuf_test_msg_type type;
+
+ union {
+ struct driver_req {
+ dev_t dev;
+ uint32_t req;
+ void *argp;
+ } driver_req;
+ struct driver_reply {
+ int ret_val;
+ int ret_errno;
+ rtems_status_code res_status;
+ int res_errno;
+ } driver_reply;
+ } val;
+} bdbuf_test_msg;
+
+
+typedef enum bdbuf_rest_thread_prio {
+ BDBUF_TEST_THREAD_PRIO_NORMAL = 3,
+ BDBUF_TEST_THREAD_PRIO_LOW = 7,
+ BDBUF_TEST_THREAD_PRIO_HIGH = 5,
+} bdbuf_rest_thread_prio;
+
+
+typedef struct test_ctx {
+ /**
+ * Message queue used by main task to get messages from
+ * disk device driver.
+ */
+ Objects_Id test_qid;
+
+ /**
+ * Object ID for disk driver queue.
+ * Test task will send messages to this queue in reply
+ * to messages received on @a test_qid.
+ */
+ Objects_Id test_drv_qid;
+
+ /** Test name */
+ const char *test_name;
+
+ /**
+ * Semaphore used for synchronization between test thread
+ * and main test task.
+ * Main test task blocks on one of these semaphores and an auxiliary thread
+ * releases it in order to pass control to main task again.
+ */
+ rtems_id test_sync_main[3];
+
+ /**
+ * This semaphore is used for synchornization between main test task
+ * and the END of auxiliary threads.
+ */
+ rtems_id test_end_main;
+
+ /**
+ * Semaphore used for synchronization between test thread
+ * and main test task.
+ * Thread #N blocks on this semaphore and the main task releases it
+ * when it wants to pass control to the auxiliary thread #N.
+ */
+ rtems_id test_sync[3];
+
+ /** Task Id values of auxiliary threads */
+ Objects_Id test_task[3];
+} test_ctx;
+
+extern test_ctx g_test_ctx;
+
+/** Device ID used for testing */
+extern dev_t test_dev;
+
+/**
+ * Create a message queue for test driver that is used for
+ * receiving messages from test task.
+ *
+ * @param[out] id RTEMS message queue identifier
+ *
+ * @return Status of the operation
+ */
+extern rtems_status_code bdbuf_test_create_drv_rx_queue(Objects_Id *id);
+
+/**
+ * Obtain a message queue for test driver that is used for
+ * sending messages to test task.
+ *
+ * @param[out] id RTEMS message queue identifier
+ *
+ * @return Status of the operation
+ */
+extern rtems_status_code bdbuf_test_create_drv_tx_queue(Objects_Id *id);
+
+/**
+ * Start a separate test task represented by function @p func
+ * and associated with task index @p idx.
+ *
+ * @param[in] idx Task index
+ * @param[in] func Test task function
+ */
+extern rtems_status_code bdbuf_test_start_thread(unsigned int idx,
+ rtems_task_entry func);
+
+/**
+ * Finalize test run.
+ */
+extern rtems_status_code bdbuf_test_end(void);
+
+/** Test result variable */
+extern bool good_test_result;
+
+#define BDBUF_TEST_BLOCK_TIMEOUT (2 * rtems_clock_get_ticks_per_second())
+
+#define SET_THREAD_PRIORITY(t_num_, prio_) \
+ do { \
+ rtems_task_priority old_prio; \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_task_set_priority( \
+ g_test_ctx.test_task[(t_num_) - 1], \
+ BDBUF_TEST_THREAD_PRIO_ ## prio_, &old_prio); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to change priority of test thread #" \
+ #t_num_ " in test %s\n", g_test_ctx.test_name); \
+ return; \
+ } \
+ } while (0)
+
+/**
+ * Start thread number @p t_num_ with @p func_ function
+ * as an entry point of the thread.
+ *
+ * @param t_num_ thread number.
+ * @param func_ thread entry point.
+ */
+#define START_THREAD(t_num_, func_) \
+ do { \
+ if (bdbuf_test_start_thread((t_num_) - 1, func_) != \
+ RTEMS_SUCCESSFUL) \
+ { \
+ return; \
+ } \
+ printk("Thread #" #t_num_ " started\n"); \
+ } while (0)
+
+/**
+ * Wait for a message from device driver.
+ *
+ * @param[out] msg_ Pointer to a message data structure
+ */
+#define WAIT_DRV_MSG(msg_) \
+ do { \
+ rtems_status_code rc_; \
+ size_t msg_size_ = sizeof(*(msg_)); \
+ \
+ rc_ = rtems_message_queue_receive(g_test_ctx.test_qid, \
+ (msg_), &msg_size_, \
+ RTEMS_WAIT, \
+ RTEMS_NO_TIMEOUT); \
+ if (rc_ != RTEMS_SUCCESSFUL || \
+ msg_size_ != sizeof(*(msg_))) \
+ { \
+ printk("Error at %s:%d\n", __FILE__, __LINE__); \
+ return; \
+ } \
+ if ((msg_)->type != BDBUF_TEST_MSG_TYPE_DRIVER_REQ) \
+ { \
+ printk("Unexpected message received: %d\n", \
+ (msg_)->type); \
+ return; \
+ } \
+ } while (0)
+
+#define WAIT_DRV_MSG_WR(msg_) \
+ do { \
+ WAIT_DRV_MSG(msg_); \
+ if ((msg_)->val.driver_req.req != RTEMS_BLKIO_REQUEST || \
+ (msg_)->val.driver_req.dev != test_dev || \
+ ((rtems_blkdev_request *) \
+ ((msg_)->val.driver_req.argp))->req != \
+ RTEMS_BLKDEV_REQ_WRITE) \
+ { \
+ printk("Unexpected message received by disk driver: " \
+ "req - 0x%x (0x%x), dev - %d (%d)\n", \
+ (msg_)->val.driver_req.req, RTEMS_BLKIO_REQUEST, \
+ (msg_)->val.driver_req.dev, test_dev); \
+ return; \
+ } \
+ } while (0)
+
+#define CHECK_NO_DRV_MSG() \
+ do { \
+ rtems_status_code rc_; \
+ bdbuf_test_msg msg_; \
+ size_t msg_size_ = sizeof(msg_); \
+ \
+ rc_ = rtems_message_queue_receive(g_test_ctx.test_qid, \
+ (&msg_), &msg_size_, \
+ RTEMS_WAIT, \
+ BDBUF_TEST_BLOCK_TIMEOUT); \
+ if (rc_ != RTEMS_TIMEOUT) \
+ { \
+ printk("Error at %s:%d\n", __FILE__, __LINE__); \
+ return; \
+ } \
+ } while (0)
+
+extern bdbuf_test_msg test_drv_msg;
+
+/**
+ * Send a message to device driver (in order to complete
+ * blocked I/O operation).
+ *
+ * @param ret_val_ Return value to use when returning from
+ * ioctl() function.
+ * @param ret_errno_ errno value to set to errno variable.
+ * @param res_status_ In case return value from the ioctl()
+ * function is equal to 0, this value
+ * is used as status code in asynchronous
+ * notification.
+ * @param res_errno_ In case return value from the ioctl()
+ * function is equal to 0, this value
+ * is used as error value in asynchronous
+ * notification.
+ *
+ */
+#define SEND_DRV_MSG(ret_val_, ret_errno_, res_status_, res_errno_) \
+ do { \
+ rtems_status_code rc_; \
+ \
+ memset(&test_drv_msg, 0, sizeof(test_drv_msg)); \
+ test_drv_msg.type = BDBUF_TEST_MSG_TYPE_DRIVER_REPLY; \
+ test_drv_msg.val.driver_reply.ret_val = (ret_val_); \
+ test_drv_msg.val.driver_reply.ret_errno = (ret_errno_); \
+ test_drv_msg.val.driver_reply.res_status = (res_status_); \
+ test_drv_msg.val.driver_reply.res_errno = (res_errno_); \
+ \
+ rc_ = rtems_message_queue_send(g_test_ctx.test_drv_qid, \
+ &test_drv_msg, \
+ sizeof(test_drv_msg)); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Error while sending a message to " \
+ "disk driver: %u\n", rc_); \
+ return; \
+ } \
+ } while (0)
+
+/**
+ * Block main test task until a thread passes back control
+ * with CONTINUE_MAIN().
+ *
+ * @param t_num_ thread number from which the main thread
+ * is waiting for a sync.
+ */
+#define WAIT_THREAD_SYNC(t_num_) \
+ do { \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_semaphore_obtain( \
+ g_test_ctx.test_sync_main[(t_num_) - 1], \
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to get sync with a thread: %d\n", rc_); \
+ return; \
+ } \
+ } while (0)
+
+/**
+ * Check that a particular thread is blocked.
+ *
+ * @param t_num_ thread number that we want to check for blocking
+ */
+#define CHECK_THREAD_BLOCKED(t_num_) \
+ do { \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_semaphore_obtain( \
+ g_test_ctx.test_sync_main[(t_num_) - 1], \
+ RTEMS_WAIT, BDBUF_TEST_BLOCK_TIMEOUT); \
+ if (rc_ != RTEMS_TIMEOUT) \
+ { \
+ printk("Thread %d is not blocked at%s:%d\n", \
+ t_num_, __FILE__, __LINE__); \
+ return; \
+ } \
+ } while (0)
+
+/**
+ * Main test task gives control to the particular thread.
+ *
+ * @param t_num_ thread number to which main test task wants
+ * to give control.
+ */
+#define CONTINUE_THREAD(t_num_) \
+ do { \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_semaphore_release( \
+ g_test_ctx.test_sync[(t_num_) - 1]); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to give control to thread #" \
+ #t_num_ ": %d\n", rc_); \
+ return; \
+ } \
+ } while (0)
+
+/**
+ * Passes control back to the main test task from a thread.
+ *
+ * @param t_num_ Current thread number
+ */
+#define CONTINUE_MAIN(t_num_) \
+ do { \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_semaphore_release( \
+ g_test_ctx.test_sync_main[(t_num_) - 1]); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to give control to " \
+ "main task: %d", rc_); \
+ return; \
+ } \
+ rc_ = rtems_semaphore_obtain( \
+ g_test_ctx.test_sync[(t_num_) - 1], \
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to block on thread #" \
+ #t_num_ ": %d\n", rc_); \
+ return; \
+ } \
+ } while (0)
+
+#define WAIT_MAIN_SYNC(t_num_) \
+ do { \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_semaphore_obtain( \
+ g_test_ctx.test_sync[(t_num_) - 1], \
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT); \
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to block on thread #" \
+ #t_num_ ": %d\n", rc_); \
+ return; \
+ } \
+ } while (0)
+
+
+#define TEST_START(test_name_) \
+ do { \
+ good_test_result = true; \
+ g_test_ctx.test_name = test_name_; \
+ printk("%s - STARTED\n", \
+ g_test_ctx.test_name); \
+ } while (0)
+
+#define TEST_CHECK_RESULT(step_) \
+ do { \
+ if (!good_test_result) \
+ { \
+ printk("TEST FAILED (Step %s)\n", \
+ step_); \
+ rtems_task_delete(RTEMS_SELF); \
+ } \
+ else \
+ { \
+ printk("%s: Step %s - OK\n", \
+ g_test_ctx.test_name, step_); \
+ } \
+ } while (0)
+
+#define TEST_END() \
+ do { \
+ bdbuf_test_end(); \
+ \
+ if (good_test_result) \
+ printk("TEST PASSED\n"); \
+ else \
+ printk("TEST FAILED (END)"); \
+ } while (0)
+
+#define THREAD_END() \
+ do { \
+ rtems_status_code rc_; \
+ \
+ rc_ = rtems_semaphore_release(g_test_ctx.test_end_main);\
+ if (rc_ != RTEMS_SUCCESSFUL) \
+ { \
+ printk("Failed to give control to " \
+ "main task: %d", rc_); \
+ return; \
+ } \
+ rtems_task_delete(RTEMS_SELF); \
+ } while (0)
+
+#define TEST_FAILED() \
+ do { \
+ good_test_result = false; \
+ } while (0)
+
+#define SLEEP() \
+ rtems_task_wake_after(BDBUF_TEST_BLOCK_TIMEOUT)
+
+
+extern rtems_status_code
+bdbuf_test_start_aux_task(rtems_name name,
+ rtems_task_entry entry_point,
+ rtems_task_argument arg,
+ Objects_Id *id);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BDBUF_TESTS_H */
+