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);
+}