From 0c31cc62d0e3ce92aa3bf6f49cfd76fabadb9ea5 Mon Sep 17 00:00:00 2001 From: Adam Rutkowski Date: Mon, 2 Sep 2019 18:22:19 -0400 Subject: [PATCH] Freelist test Signed-off-by: Adam Rutkowski --- tests/unit/framework/tests_config.py | 2 +- tests/unit/tests/ocf_env/ocf_env.c | 40 +- tests/unit/tests/ocf_env/ocf_env.h | 18 +- .../ocf_freelist.c/ocf_freelist_get_put.c | 382 ++++++++++++++++++ .../tests/ocf_freelist.c/ocf_freelist_init.c | 68 ++++ .../tests/ocf_freelist.c/ocf_freelist_locks.c | 213 ++++++++++ .../ocf_freelist.c/ocf_freelist_populate.c | 138 +++++++ 7 files changed, 841 insertions(+), 20 deletions(-) create mode 100644 tests/unit/tests/ocf_freelist.c/ocf_freelist_get_put.c create mode 100644 tests/unit/tests/ocf_freelist.c/ocf_freelist_init.c create mode 100644 tests/unit/tests/ocf_freelist.c/ocf_freelist_locks.c create mode 100644 tests/unit/tests/ocf_freelist.c/ocf_freelist_populate.c diff --git a/tests/unit/framework/tests_config.py b/tests/unit/framework/tests_config.py index 59d299c..654b3cb 100644 --- a/tests/unit/framework/tests_config.py +++ b/tests/unit/framework/tests_config.py @@ -14,7 +14,7 @@ MAIN_DIRECTORY_OF_UNIT_TESTS = "../tests/" # Paths to all directories, in which tests are stored. All paths should be relative to # MAIN_DIRECTORY_OF_UNIT_TESTS DIRECTORIES_WITH_TESTS_LIST = ["cleaning/", "metadata/", "mngt/", "concurrency/", "engine/", - "eviction/", "utils/", "promotion/"] + "eviction/", "utils/", "promotion/", "ocf_freelist.c/"] # Paths to all directories containing files with sources. All paths should be relative to # MAIN_DIRECTORY_OF_TESTED_PROJECT diff --git a/tests/unit/tests/ocf_env/ocf_env.c b/tests/unit/tests/ocf_env/ocf_env.c index d6cbd96..7b0c417 100644 --- a/tests/unit/tests/ocf_env/ocf_env.c +++ b/tests/unit/tests/ocf_env/ocf_env.c @@ -150,28 +150,25 @@ void env_completion_complete(env_completion *completion) int env_mutex_init(env_mutex *mutex) { - function_called(); - check_expected_ptr(mutex); - return mock(); + return 0; +} + +int env_mutex_destroy(env_mutex *mutex) +{ + return 0; } void env_mutex_lock(env_mutex *mutex) { - function_called(); - check_expected_ptr(mutex); } int env_mutex_lock_interruptible(env_mutex *mutex) { - function_called(); - check_expected_ptr(mutex); - return mock(); + return 0; } void env_mutex_unlock(env_mutex *mutex) { - function_called(); - check_expected_ptr(mutex); } int env_rmutex_init(env_rmutex *rmutex) @@ -361,22 +358,27 @@ long env_atomic64_cmpxchg(env_atomic64 *a, long old, long new) return oldval; } -void env_spinlock_init(env_spinlock *l) +int env_spinlock_init(env_spinlock *l) { - function_called(); - check_expected_ptr(l); + return 0; +} + +int env_spinlock_destroy(env_spinlock *l) +{ + return 0; } void env_spinlock_lock(env_spinlock *l) { - function_called(); - check_expected_ptr(l); +} + +int env_spinlock_trylock(env_spinlock *l) +{ + return 0; } void env_spinlock_unlock(env_spinlock *l) { - function_called(); - check_expected_ptr(l); } void env_rwlock_init(env_rwlock *l) @@ -535,3 +537,7 @@ uint32_t env_crc32(uint32_t crc, uint8_t const *data, size_t len) check_expected_ptr(data); return mock(); } + +void env_cond_resched(void) +{ +} diff --git a/tests/unit/tests/ocf_env/ocf_env.h b/tests/unit/tests/ocf_env/ocf_env.h index ebec304..6fdc2e1 100644 --- a/tests/unit/tests/ocf_env/ocf_env.h +++ b/tests/unit/tests/ocf_env/ocf_env.h @@ -71,7 +71,13 @@ typedef uint64_t sector_t; abort(); \ }) -#define ENV_BUG_ON(cond) bug_on((int)cond); +#define ENV_BUG_ON(cond) ({ \ + int eval = cond; \ + if (eval) { \ + print_message("%s:%u BUG: %s\n", __FILE__, __LINE__, #cond); \ + bug_on(eval); \ + } \ + }) #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ @@ -128,6 +134,8 @@ typedef struct { int env_mutex_init(env_mutex *mutex); +int env_mutex_destroy(env_mutex *mutex); + void env_mutex_lock(env_mutex *mutex); int env_mutex_lock_interruptible(env_mutex *mutex); @@ -231,10 +239,14 @@ void env_completion_complete(env_completion *completion); typedef struct { } env_spinlock; -void env_spinlock_init(env_spinlock *l); +int env_spinlock_init(env_spinlock *l); + +int env_spinlock_destroy(env_spinlock *l); void env_spinlock_lock(env_spinlock *l); +int env_spinlock_trylock(env_spinlock *l); + void env_spinlock_unlock(env_spinlock *l); #define env_spinlock_lock_irqsave(l, flags) \ @@ -327,4 +339,6 @@ void env_msleep(uint64_t n); uint32_t env_crc32(uint32_t crc, uint8_t const *data, size_t len); +void env_cond_resched(void); + #endif /* __OCF_ENV_H__ */ diff --git a/tests/unit/tests/ocf_freelist.c/ocf_freelist_get_put.c b/tests/unit/tests/ocf_freelist.c/ocf_freelist_get_put.c new file mode 100644 index 0000000..7ee9181 --- /dev/null +++ b/tests/unit/tests/ocf_freelist.c/ocf_freelist_get_put.c @@ -0,0 +1,382 @@ +/* + * src/ocf_freelist.c + * ocf_freelist_get_cache_line + * + * ocf_freelist_init + * ocf_freelist_deinit + * ocf_freelist_populate + * next_phys_invalid + * ocf_freelist_lock + * ocf_freelist_trylock + * ocf_freelist_unlock + * _ocf_freelist_remove_cache_line + * ocf_freelist_get_cache_line_fast + * ocf_freelist_get_cache_line_slow + * ocf_freelist_add_cache_line + * ocf_freelist_get_cache_line_ctx + * get_next_victim_freelist + * ocf_freelist_put_cache_line + * + */ + +#undef static + +#undef inline + + +#include +#include +#include +#include +#include "print_desc.h" + +#include "ocf/ocf.h" +#include "metadata/metadata.h" + +#include "ocf_freelist.c/ocf_freelist_get_put_generated_warps.c" + +ocf_cache_line_t __wrap_ocf_metadata_collision_table_entries(ocf_cache_t cache) +{ + return mock(); +} + +unsigned __wrap_env_get_execution_context_count(void) +{ + return mock(); +} + +unsigned __wrap_env_get_execution_context(void) +{ + return mock(); +} + +void __wrap_env_put_execution_context(unsigned ctx) +{ +} + +/* simulate no striping */ +ocf_cache_line_t __wrap_ocf_metadata_map_phy2lg(ocf_cache_t cache, ocf_cache_line_t phy) +{ + return phy; +} + +bool __wrap_metadata_test_valid_any(ocf_cache_t cache, ocf_cache_line_t cline) +{ + return mock(); +} + +/* metadata partition info interface mock: */ + +#define max_clines 100 + +struct { + ocf_cache_line_t prev; + ocf_cache_line_t next; +} partition_list[max_clines]; + + +void __wrap_ocf_metadata_set_partition_info(struct ocf_cache *cache, + ocf_cache_line_t line, ocf_part_id_t part_id, + ocf_cache_line_t next_line, ocf_cache_line_t prev_line) +{ + assert_int_equal(part_id, PARTITION_INVALID); + partition_list[line].prev = prev_line; + partition_list[line].next = next_line; +} + +void __wrap_ocf_metadata_get_partition_info(struct ocf_cache *cache, + ocf_cache_line_t line, ocf_part_id_t *part_id, + ocf_cache_line_t *next_line, ocf_cache_line_t *prev_line) +{ + if (part_id) + *part_id = PARTITION_INVALID; + if (prev_line) + *prev_line = partition_list[line].prev; + if (next_line) + *next_line = partition_list[line].next; +} + +void __wrap_ocf_metadata_set_partition_prev(struct ocf_cache *cache, + ocf_cache_line_t line, ocf_cache_line_t prev_line) +{ + partition_list[line].prev = prev_line; +} + +void __wrap_ocf_metadata_set_partition_next(struct ocf_cache *cache, + ocf_cache_line_t line, ocf_cache_line_t next_line) +{ + partition_list[line].next = next_line; +} + +static void ocf_freelist_get_cache_line_get_fast(void **state) +{ + unsigned num_cls = 8; + unsigned num_ctxts = 3; + ocf_freelist_t freelist; + unsigned ctx_iter, cl_iter; + ocf_cache_line_t line; + + print_test_description("Verify get free cache line get fast path"); + + will_return_maybe(__wrap_ocf_metadata_collision_table_entries, num_cls); + will_return_maybe(__wrap_env_get_execution_context_count, num_ctxts); + will_return_maybe(__wrap_metadata_test_valid_any, false); + + freelist = ocf_freelist_init(NULL); + + ocf_freelist_populate(freelist, num_cls); + + /* now there are following cachelines on per-context lists: + * ctx 0: 0, 1, 2 + * ctx 1: 3, 4, 5 + * ctx 2: 6, 7 + */ + + /* get cline from context 1 */ + will_return(__wrap_env_get_execution_context, 1); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 3); + + /* ctx 0: 0, 1, 2 + * ctx 1: _, 4, 5 + * ctx 2: 6, 7 */ + + /* get cline from context 2 */ + will_return(__wrap_env_get_execution_context, 2); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 6); + + /* ctx 0: 0, 1, 2 + * ctx 1: _, 4, 5 + * ctx 2: _, 7 */ + + /* get cline from context 1 */ + will_return(__wrap_env_get_execution_context, 1); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 4); + + /* ctx 0: 0, 1, 2 + * ctx 1: _, _, 5 + * ctx 2: _, 7 */ + + /* get cline from context 0 */ + will_return(__wrap_env_get_execution_context, 0); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 0); + + /* ctx 0: _, 1, 2 + * ctx 1: _, _, 5 + * ctx 2: _, 7 */ + + /* get cline from context 0 */ + will_return(__wrap_env_get_execution_context, 0); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 1); + + /* ctx 0: _, _, 2 + * ctx 1: _, _, 5 + * ctx 2: _, 7 */ + + /* get cline from context 0 */ + will_return(__wrap_env_get_execution_context, 0); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 2); + + /* ctx 0: _, _, _, + * ctx 1: _, _, 5 + * ctx 2: _, 7 */ + + /* get cline from context 2 */ + will_return(__wrap_env_get_execution_context, 2); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 7); + + /* ctx 0: _, _, _, + * ctx 1: _, _, _5 + * ctx 2: _, _ */ + + /* get cline from context 1 */ + will_return(__wrap_env_get_execution_context, 1); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 5); + + /* ctx 0: _, _, _, + * ctx 1: _, _, _ + * ctx 2: _, _ */ + + ocf_freelist_deinit(freelist); +} + +static void ocf_freelist_get_cache_line_get_slow(void **state) +{ + unsigned num_cls = 8; + unsigned num_ctxts = 3; + ocf_freelist_t freelist; + unsigned ctx_iter, cl_iter; + ocf_cache_line_t line; + + print_test_description("Verify get free cache line get slow path"); + + will_return_maybe(__wrap_ocf_metadata_collision_table_entries, num_cls); + will_return_maybe(__wrap_env_get_execution_context_count, num_ctxts); + will_return_maybe(__wrap_metadata_test_valid_any, false); + + /* always return exec ctx 0 */ + will_return_maybe(__wrap_env_get_execution_context, 0); + + freelist = ocf_freelist_init(NULL); + + ocf_freelist_populate(freelist, num_cls); + + /* now there are following cachelines on per-context lists: + * ctx 0: 0, 1, 2 + * ctx 1: 3, 4, 5 + * ctx 2: 6, 7 + */ + + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 0); + + /* ctx 0: _, 1, 2 + * ctx 1: 3, 4, 5 + * ctx 2: 6, 7 */ + + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 1); + + /* ctx 0: _, _, 2 + * ctx 1: 3, 4, 5 + * ctx 2: 6, 7 */ + + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 2); + + /* ctx 0: _, _, _ + * ctx 1: 3, 4, 5 + * ctx 2: 6, 7 */ + + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 3); + + /* ctx 0: _, _, _ + * ctx 1: _, 4, 5 + * ctx 2: 6, 7 */ + + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 6); + + /* ctx 0: _, _, _ + * ctx 1: _, 4, 5 + * ctx 2: _, 7 */ + + + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 4); + + /* ctx 0: _, _, _ + * ctx 1: _, _, 5 + * ctx 2: _, 7 */ + + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 7); + + /* ctx 0: _, _, _ + * ctx 1: _, _, 5 + * ctx 2: _, _ */ + + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 5); + + /* ctx 0: _, _, _, + * ctx 1: _, _, _ + * ctx 2: _, _ */ + + ocf_freelist_deinit(freelist); +} + +static void ocf_freelist_get_cache_line_put(void **state) +{ + unsigned num_cls = 8; + unsigned num_ctxts = 3; + ocf_freelist_t freelist; + unsigned ctx_iter, cl_iter; + ocf_cache_line_t line; + + print_test_description("Verify freelist cacheline put"); + + will_return_maybe(__wrap_ocf_metadata_collision_table_entries, num_cls); + will_return_maybe(__wrap_env_get_execution_context_count, num_ctxts); + will_return_maybe(__wrap_metadata_test_valid_any, false); + + freelist = ocf_freelist_init(NULL); + + ocf_freelist_populate(freelist, num_cls); + + /* get some clines from the freelists */ + will_return(__wrap_env_get_execution_context, 0); + ocf_freelist_get_cache_line(freelist, &line); + will_return(__wrap_env_get_execution_context, 0); + ocf_freelist_get_cache_line(freelist, &line); + will_return(__wrap_env_get_execution_context, 0); + ocf_freelist_get_cache_line(freelist, &line); + will_return(__wrap_env_get_execution_context, 0); + ocf_freelist_get_cache_line(freelist, &line); + will_return(__wrap_env_get_execution_context, 0); + ocf_freelist_get_cache_line(freelist, &line); + + /* ctx 0: + * ctx 1: 4, 5 + * ctx 2: 7 */ + + will_return(__wrap_env_get_execution_context, 1); + ocf_freelist_put_cache_line(freelist, 0); + + will_return(__wrap_env_get_execution_context, 1); + ocf_freelist_put_cache_line(freelist, 2); + + will_return(__wrap_env_get_execution_context, 2); + ocf_freelist_put_cache_line(freelist, 3); + + /* ctx 0: + * ctx 1: 4, 5, 0, 2 + * ctx 2: 7, 3*/ + + will_return(__wrap_env_get_execution_context, 1); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 4); + + will_return(__wrap_env_get_execution_context, 1); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 5); + + will_return(__wrap_env_get_execution_context, 1); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 0); + + will_return(__wrap_env_get_execution_context, 1); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 2); + + will_return(__wrap_env_get_execution_context, 2); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 7); + + will_return(__wrap_env_get_execution_context, 2); + assert(ocf_freelist_get_cache_line(freelist, &line)); + assert_int_equal(line, 3); + + ocf_freelist_deinit(freelist); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(ocf_freelist_get_cache_line_get_fast), + cmocka_unit_test(ocf_freelist_get_cache_line_get_slow), + cmocka_unit_test(ocf_freelist_get_cache_line_put) + }; + + print_message("Unit test for ocf_freelist_get_cache_line\n"); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/unit/tests/ocf_freelist.c/ocf_freelist_init.c b/tests/unit/tests/ocf_freelist.c/ocf_freelist_init.c new file mode 100644 index 0000000..c81cf83 --- /dev/null +++ b/tests/unit/tests/ocf_freelist.c/ocf_freelist_init.c @@ -0,0 +1,68 @@ +/* + * src/ocf_freelist.c + * ocf_freelist_populate + * + * ocf_freelist_init + * ocf_freelist_deinit + * + */ + +#undef static + +#undef inline + + +#include +#include +#include +#include +#include "print_desc.h" + +#include "ocf/ocf.h" +#include "metadata/metadata.h" + +#include "ocf_freelist.c/ocf_freelist_init_generated_warps.c" + +ocf_cache_line_t __wrap_ocf_metadata_collision_table_entries(ocf_cache_t cache) +{ + function_called(); + return mock(); +} + +ocf_cache_line_t __wrap_env_get_execution_context_count(ocf_cache_t cache) +{ + function_called(); + return mock(); +} + +static void ocf_freelist_init_test01(void **state) +{ + unsigned num_cls = 9; + unsigned num_ctxts = 3; + ocf_freelist_t freelist; + ocf_cache_t cache = 0x1234; + + print_test_description("Freelist initialization test"); + + expect_function_call(__wrap_ocf_metadata_collision_table_entries); + will_return(__wrap_ocf_metadata_collision_table_entries, num_cls); + + expect_function_call(__wrap_env_get_execution_context_count); + will_return(__wrap_env_get_execution_context_count, num_ctxts); + + freelist = ocf_freelist_init(cache); + assert(freelist != NULL); + + ocf_freelist_deinit(freelist); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(ocf_freelist_init_test01) + }; + + print_message("Unit test of ocf_freelist_init\n"); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/unit/tests/ocf_freelist.c/ocf_freelist_locks.c b/tests/unit/tests/ocf_freelist.c/ocf_freelist_locks.c new file mode 100644 index 0000000..0a05094 --- /dev/null +++ b/tests/unit/tests/ocf_freelist.c/ocf_freelist_locks.c @@ -0,0 +1,213 @@ +/* + * src/ocf_freelist.c + * ocf_freelist_get_cache_line + * + * ocf_freelist_init + * ocf_freelist_deinit + * ocf_freelist_populate + * next_phys_invalid + * ocf_freelist_unlock + * _ocf_freelist_remove_cache_line + * ocf_freelist_get_cache_line_fast + * ocf_freelist_get_cache_line_slow + * ocf_freelist_add_cache_line + * ocf_freelist_get_cache_line_ctx + * get_next_victim_freelist + * ocf_freelist_put_cache_line + * + */ + +#undef static + +#undef inline + + +#include +#include +#include +#include +#include "print_desc.h" + +#include "ocf/ocf.h" +#include "metadata/metadata.h" + +#include "ocf_freelist.c/ocf_freelist_get_put_generated_warps.c" + +ocf_cache_line_t __wrap_ocf_metadata_collision_table_entries(ocf_cache_t cache) +{ + return mock(); +} + +unsigned __wrap_env_get_execution_context_count(void) +{ + return mock(); +} + +unsigned __wrap_env_get_execution_context(void) +{ + return mock(); +} + +void __wrap_env_put_execution_context(unsigned ctx) +{ +} + +/* simulate no striping */ +ocf_cache_line_t __wrap_ocf_metadata_map_phy2lg(ocf_cache_t cache, ocf_cache_line_t phy) +{ + return phy; +} + +bool __wrap_metadata_test_valid_any(ocf_cache_t cache, ocf_cache_line_t cline) +{ + return mock(); +} + +void __wrap_ocf_freelist_lock(ocf_freelist_t freelist, uint32_t ctx) +{ + function_called(); + check_expected(ctx); +} + +int __wrap_ocf_freelist_trylock(ocf_freelist_t freelist, uint32_t ctx) +{ + function_called(); + check_expected(ctx); + return mock(); +} + +/* metadata partition info interface mock: */ + +#define max_clines 100 + +struct { + ocf_cache_line_t prev; + ocf_cache_line_t next; +} partition_list[max_clines]; + + +void __wrap_ocf_metadata_set_partition_info(struct ocf_cache *cache, + ocf_cache_line_t line, ocf_part_id_t part_id, + ocf_cache_line_t next_line, ocf_cache_line_t prev_line) +{ + assert_int_equal(part_id, PARTITION_INVALID); + partition_list[line].prev = prev_line; + partition_list[line].next = next_line; +} + +void __wrap_ocf_metadata_get_partition_info(struct ocf_cache *cache, + ocf_cache_line_t line, ocf_part_id_t *part_id, + ocf_cache_line_t *next_line, ocf_cache_line_t *prev_line) +{ + if (part_id) + *part_id = PARTITION_INVALID; + if (prev_line) + *prev_line = partition_list[line].prev; + if (next_line) + *next_line = partition_list[line].next; +} + +void __wrap_ocf_metadata_set_partition_prev(struct ocf_cache *cache, + ocf_cache_line_t line, ocf_cache_line_t prev_line) +{ + partition_list[line].prev = prev_line; +} + +void __wrap_ocf_metadata_set_partition_next(struct ocf_cache *cache, + ocf_cache_line_t line, ocf_cache_line_t next_line) +{ + partition_list[line].next = next_line; +} + +static void ocf_freelist_get_put_locks(void **state) +{ + unsigned num_cls = 4; + unsigned num_ctxts = 3; + ocf_freelist_t freelist; + unsigned ctx_iter, cl_iter; + ocf_cache_line_t line; + + print_test_description("Verify lock/trylock sequence in get free cacheline"); + + will_return_maybe(__wrap_ocf_metadata_collision_table_entries, num_cls); + will_return_maybe(__wrap_env_get_execution_context_count, num_ctxts); + will_return_maybe(__wrap_metadata_test_valid_any, false); + + /* simulate context 1 for the entire test duration */ + will_return_maybe(__wrap_env_get_execution_context, 1); + + freelist = ocf_freelist_init(NULL); + + ocf_freelist_populate(freelist, num_cls); + + /****************************************************************/ + /* verify fast path locking - scucessfull trylock */ + + /* ctx 0: 0, 3 + * ctx 1: 1 + * ctx 2: 2 + * slowpath next victim: 0 + */ + + expect_value(__wrap_ocf_freelist_trylock, ctx, 1); + expect_function_call(__wrap_ocf_freelist_trylock); + will_return(__wrap_ocf_freelist_trylock, 0); + ocf_freelist_get_cache_line(freelist, &line); + + /****************************************************************/ + /* verify fast path locking - scucessfull trylock in slowpath */ + + /* ctx 0: 0, 3 + * ctx 1: + * ctx 2: 2 + * slowpath next victim: 0 */ + + /* we expect trylock for context 0, since context 1 has empty list */ + expect_value(__wrap_ocf_freelist_trylock, ctx, 0); + expect_function_call(__wrap_ocf_freelist_trylock); + will_return(__wrap_ocf_freelist_trylock, 0); + ocf_freelist_get_cache_line(freelist, &line); + + /****************************************************************/ + /* verify fast path locking - trylock failure in slowpath */ + + /* ctx 0: 3 + * ctx 1: + * ctx 2: 2 + * slowpath next victim: 1 */ + + /* fastpath will fail immediately - context 1 list is empty */ + /* next slowpath victim context (1) is empty - will move to ctx 2 */ + /* so now we expect trylock for context no 2 - injecting error here*/ + expect_value(__wrap_ocf_freelist_trylock, ctx, 2); + expect_function_call(__wrap_ocf_freelist_trylock); + will_return(__wrap_ocf_freelist_trylock, 1); + + /* slowpath will attempt to trylock next non-empty context - 0 + * - injecting error here as well */ + expect_value(__wrap_ocf_freelist_trylock, ctx, 0); + expect_function_call(__wrap_ocf_freelist_trylock); + will_return(__wrap_ocf_freelist_trylock, 1); + + /* slowpath trylock loop failed - expecting full lock */ + expect_value(__wrap_ocf_freelist_lock, ctx, 2); + expect_function_call(__wrap_ocf_freelist_lock); + + /* execute freelist_get_cache_line */ + ocf_freelist_get_cache_line(freelist, &line); + + /****************************************************************/ + + ocf_freelist_deinit(freelist); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(ocf_freelist_get_put_locks) + }; + + print_message("Unit test for ocf_freelist_get_cache_line locking\n"); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/unit/tests/ocf_freelist.c/ocf_freelist_populate.c b/tests/unit/tests/ocf_freelist.c/ocf_freelist_populate.c new file mode 100644 index 0000000..419f240 --- /dev/null +++ b/tests/unit/tests/ocf_freelist.c/ocf_freelist_populate.c @@ -0,0 +1,138 @@ +/* + * src/ocf_freelist.c + * ocf_freelist_populate + * + * ocf_freelist_init + * ocf_freelist_deinit + * ocf_freelist_populate + * next_phys_invalid + * + */ + +#undef static + +#undef inline + + +#include +#include +#include +#include +#include "print_desc.h" + +#include "ocf/ocf.h" +#include "metadata/metadata.h" + +#include "ocf_freelist.c/ocf_freelist_populate_generated_warps.c" + +ocf_cache_line_t __wrap_ocf_metadata_collision_table_entries(ocf_cache_t cache) +{ + return mock(); +} + +ocf_cache_line_t __wrap_env_get_execution_context_count(ocf_cache_t cache) +{ + return mock(); +} + +/* simulate no striping */ +ocf_cache_line_t __wrap_ocf_metadata_map_phy2lg(ocf_cache_t cache, ocf_cache_line_t phy) +{ + return phy; +} + +bool __wrap_metadata_test_valid_any(ocf_cache_t cache, ocf_cache_line_t cline) +{ + return mock(); +} + +void __wrap_ocf_metadata_set_partition_info(struct ocf_cache *cache, + ocf_cache_line_t line, ocf_part_id_t part_id, + ocf_cache_line_t next_line, ocf_cache_line_t prev_line) +{ + print_message("%s %u %u %u\n", __func__, prev_line, line, next_line); + check_expected(line); + check_expected(part_id); + check_expected(next_line); + check_expected(prev_line); +} + +#define expect_set_info(curr, part, next, prev) \ + expect_value(__wrap_ocf_metadata_set_partition_info, line, curr); \ + expect_value(__wrap_ocf_metadata_set_partition_info, part_id, part); \ + expect_value(__wrap_ocf_metadata_set_partition_info, next_line, next); \ + expect_value(__wrap_ocf_metadata_set_partition_info, prev_line, prev); + +static void ocf_freelist_populate_test01(void **state) +{ + unsigned num_cls = 8; + unsigned num_ctxts = 3; + ocf_freelist_t freelist; + unsigned ctx_iter, cl_iter; + + print_test_description("Verify proper set_partition_info order and arguments - empty cache"); + + will_return_maybe(__wrap_ocf_metadata_collision_table_entries, num_cls); + will_return_maybe(__wrap_env_get_execution_context_count, num_ctxts); + will_return_maybe(__wrap_metadata_test_valid_any, false); + + freelist = ocf_freelist_init(NULL); + + expect_set_info(0, PARTITION_INVALID, 1 , num_cls); + expect_set_info(1, PARTITION_INVALID, 2 , 0); + expect_set_info(2, PARTITION_INVALID, num_cls, 1); + expect_set_info(3, PARTITION_INVALID, 4 , num_cls); + expect_set_info(4, PARTITION_INVALID, 5 , 3); + expect_set_info(5, PARTITION_INVALID, num_cls, 4); + expect_set_info(6, PARTITION_INVALID, 7 , num_cls); + expect_set_info(7, PARTITION_INVALID, num_cls, 6); + + ocf_freelist_populate(freelist, num_cls); + + ocf_freelist_deinit(freelist); +} + +static void ocf_freelist_populate_test02(void **state) +{ + unsigned num_cls = 8; + unsigned num_ctxts = 3; + ocf_freelist_t freelist; + unsigned ctx_iter, cl_iter; + + print_test_description("Verify proper set_partition_info order and arguments - some valid clines"); + + will_return_maybe(__wrap_ocf_metadata_collision_table_entries, num_cls); + will_return_maybe(__wrap_env_get_execution_context_count, num_ctxts); + + freelist = ocf_freelist_init(NULL); + + /* simulate only cachelines 2, 3, 4, 7 invalid */ + will_return(__wrap_metadata_test_valid_any, true); + will_return(__wrap_metadata_test_valid_any, true); + will_return(__wrap_metadata_test_valid_any, false); + will_return(__wrap_metadata_test_valid_any, false); + will_return(__wrap_metadata_test_valid_any, false); + will_return(__wrap_metadata_test_valid_any, true); + will_return(__wrap_metadata_test_valid_any, true); + will_return(__wrap_metadata_test_valid_any, false); + + expect_set_info(2, PARTITION_INVALID, 3 , num_cls); + expect_set_info(3, PARTITION_INVALID, num_cls, 2); + expect_set_info(4, PARTITION_INVALID, num_cls, num_cls); + expect_set_info(7, PARTITION_INVALID, num_cls, num_cls); + + ocf_freelist_populate(freelist, 4); + + ocf_freelist_deinit(freelist); +} +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(ocf_freelist_populate_test01), + cmocka_unit_test(ocf_freelist_populate_test02) + }; + + print_message("Unit test of src/ocf_freelist.c\n"); + + return cmocka_run_group_tests(tests, NULL, NULL); +}