/* arch/arm/mach-msm/smp2p_test_common.h * * Copyright (c) 2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef _ARCH_ARM_MACH_MSM_SMP2P_TEST_COMMON_H_ #define _ARCH_ARM_MACH_MSM_SMP2P_TEST_COMMON_H_ #include /** * Unit test assertion for logging test cases. * * @a lval * @b rval * @cmp comparison operator * * Assertion fails if (@a cmp @b) is not true which then * logs the function and line number where the error occurred * along with the values of @a and @b. * * Assumes that the following local variables exist: * @s - sequential output file pointer * @failed - set to true if test fails */ #define UT_ASSERT_INT(a, cmp, b) \ { \ int a_tmp = (a); \ int b_tmp = (b); \ if (!((a_tmp)cmp(b_tmp))) { \ seq_printf(s, \ "%s:%d Fail: " #a "(%d) " #cmp " " #b "(%d)\n", \ __func__, __LINE__, \ a_tmp, b_tmp); \ failed = 1; \ break; \ } \ } #define UT_ASSERT_PTR(a, cmp, b) \ { \ void *a_tmp = (a); \ void *b_tmp = (b); \ if (!((a_tmp)cmp(b_tmp))) { \ seq_printf(s, \ "%s:%d Fail: " #a "(%p) " #cmp " " #b "(%p)\n", \ __func__, __LINE__, \ a_tmp, b_tmp); \ failed = 1; \ break; \ } \ } #define UT_ASSERT_UINT(a, cmp, b) \ { \ unsigned a_tmp = (a); \ unsigned b_tmp = (b); \ if (!((a_tmp)cmp(b_tmp))) { \ seq_printf(s, \ "%s:%d Fail: " #a "(%u) " #cmp " " #b "(%u)\n", \ __func__, __LINE__, \ a_tmp, b_tmp); \ failed = 1; \ break; \ } \ } #define UT_ASSERT_HEX(a, cmp, b) \ { \ unsigned a_tmp = (a); \ unsigned b_tmp = (b); \ if (!((a_tmp)cmp(b_tmp))) { \ seq_printf(s, \ "%s:%d Fail: " #a "(%x) " #cmp " " #b "(%x)\n", \ __func__, __LINE__, \ a_tmp, b_tmp); \ failed = 1; \ break; \ } \ } /** * In-range unit test assertion for test cases. * * @a lval * @minv Minimum value * @maxv Maximum value * * Assertion fails if @a is not on the exclusive range minv, maxv * ((@a < @minv) or (@a > @maxv)). In the failure case, the macro * logs the function and line number where the error occurred along * with the values of @a and @minv, @maxv. * * Assumes that the following local variables exist: * @s - sequential output file pointer * @failed - set to true if test fails */ #define UT_ASSERT_INT_IN_RANGE(a, minv, maxv) \ { \ int a_tmp = (a); \ int minv_tmp = (minv); \ int maxv_tmp = (maxv); \ if (((a_tmp) < (minv_tmp)) || ((a_tmp) > (maxv_tmp))) { \ seq_printf(s, \ "%s:%d Fail: " #a "(%d) < " #minv "(%d) or " \ #a "(%d) > " #maxv "(%d)\n", \ __func__, __LINE__, \ a_tmp, minv_tmp, a_tmp, maxv_tmp); \ failed = 1; \ break; \ } \ } /* Structure to track state changes for the notifier callback. */ struct mock_cb_data { bool initialized; spinlock_t lock; struct notifier_block nb; /* events */ struct completion cb_completion; int cb_count; int event_open; int event_entry_update; struct msm_smp2p_update_notif entry_data; }; void smp2p_debug_create(const char *name, void (*show)(struct seq_file *)); static inline int smp2p_test_notify(struct notifier_block *self, unsigned long event, void *data); /** * Reset mock callback data to default values. * * @cb: Mock callback data */ static inline void mock_cb_data_reset(struct mock_cb_data *cb) { INIT_COMPLETION(cb->cb_completion); cb->cb_count = 0; cb->event_open = 0; cb->event_entry_update = 0; memset(&cb->entry_data, 0, sizeof(struct msm_smp2p_update_notif)); } /** * Initialize mock callback data. * * @cb: Mock callback data */ static inline void mock_cb_data_init(struct mock_cb_data *cb) { if (!cb->initialized) { init_completion(&cb->cb_completion); spin_lock_init(&cb->lock); cb->initialized = true; cb->nb.notifier_call = smp2p_test_notify; memset(&cb->entry_data, 0, sizeof(struct msm_smp2p_update_notif)); } mock_cb_data_reset(cb); } /** * Notifier function passed into SMP2P for testing. * * @self: Pointer to calling notifier block * @event: Event * @data: Event-specific data * @returns: 0 */ static inline int smp2p_test_notify(struct notifier_block *self, unsigned long event, void *data) { struct mock_cb_data *cb_data_ptr; unsigned long flags; cb_data_ptr = container_of(self, struct mock_cb_data, nb); spin_lock_irqsave(&cb_data_ptr->lock, flags); switch (event) { case SMP2P_OPEN: ++cb_data_ptr->event_open; if (data) { cb_data_ptr->entry_data = *(struct msm_smp2p_update_notif *)(data); } break; case SMP2P_ENTRY_UPDATE: ++cb_data_ptr->event_entry_update; if (data) { cb_data_ptr->entry_data = *(struct msm_smp2p_update_notif *)(data); } break; default: pr_err("%s Unknown event\n", __func__); break; } ++cb_data_ptr->cb_count; complete(&cb_data_ptr->cb_completion); spin_unlock_irqrestore(&cb_data_ptr->lock, flags); return 0; } #endif /* _ARCH_ARM_MACH_MSM_SMP2P_TEST_COMMON_H_ */