Merge pull request #451 from arutk/exact_evict_count

only request evict size equal to request unmapped count
This commit is contained in:
Robert Baldyga
2021-02-11 10:47:12 +01:00
committed by GitHub
8 changed files with 409 additions and 676 deletions

View File

@@ -44,8 +44,7 @@ void __wrap_ocf_req_hash_unlock_wr(struct ocf_request *req)
{
}
uint32_t __wrap_ocf_part_check_space(struct ocf_request *req,
uint32_t *to_evict)
uint32_t __wrap_ocf_part_has_space(struct ocf_request *req)
{
return mock();
}
@@ -98,7 +97,7 @@ static void ocf_prepare_clines_miss_test01(void **state)
{
struct ocf_request req = {};
print_test_description("Target part is disabled and empty\n");
will_return(__wrap_ocf_part_check_space, OCF_PART_IS_DISABLED);
will_return(__wrap_ocf_part_is_enabled, false);
expect_function_call(__wrap_ocf_req_set_mapping_error);
assert_int_equal(ocf_prepare_clines_miss(&req, NULL), -OCF_ERR_NO_LOCK);
}
@@ -107,13 +106,8 @@ static void ocf_prepare_clines_miss_test02(void **state)
{
struct ocf_request req = {};
print_test_description("Target part is disabled but has cachelines assigned.\n");
print_test_description("\tTrigger eviction and mark mapping error\n");
print_test_description("\tMark mapping error\n");
will_return(__wrap_ocf_part_check_space, OCF_PART_IS_FULL);
will_return(__wrap_ocf_part_check_space, OCF_PART_IS_FULL);
expect_function_call(__wrap_space_managment_evict_do);
will_return(__wrap_space_managment_evict_do, LOOKUP_MAPPED);
will_return(__wrap_ocf_part_is_enabled, false);
expect_function_call(__wrap_ocf_req_set_mapping_error);
@@ -126,12 +120,12 @@ static void ocf_prepare_clines_miss_test03(void **state)
print_test_description("Target part is enabled but doesn't have enough space.\n");
print_test_description("\tEviction is ok and cachelines lock is acquired.\n");
will_return(__wrap_ocf_part_check_space, OCF_PART_IS_FULL);
will_return(__wrap_ocf_part_check_space, OCF_PART_IS_FULL);
will_return(__wrap_ocf_part_is_enabled, true);
will_return(__wrap_ocf_part_has_space, false);
will_return(__wrap_ocf_part_has_space, false);
expect_function_call(__wrap_space_managment_evict_do);
will_return(__wrap_space_managment_evict_do, LOOKUP_MAPPED);
will_return(__wrap_ocf_part_is_enabled, true);
expect_function_call(__wrap_ocf_engine_map);
@@ -149,9 +143,10 @@ static void ocf_prepare_clines_miss_test04(void **state)
print_test_description("Target part is enabled but doesn't have enough space.\n");
print_test_description("\tEviction failed\n");
will_return(__wrap_ocf_part_check_space, OCF_PART_IS_FULL);
will_return(__wrap_ocf_part_check_space, OCF_PART_IS_FULL);
will_return(__wrap_ocf_part_is_enabled, true);
will_return(__wrap_ocf_part_has_space, false);
will_return(__wrap_ocf_part_has_space, false);
expect_function_call(__wrap_space_managment_evict_do);
will_return(__wrap_space_managment_evict_do, LOOKUP_MISS);
expect_function_call(__wrap_ocf_req_set_mapping_error);
@@ -165,8 +160,8 @@ static void ocf_prepare_clines_miss_test05(void **state)
print_test_description("Target part is enabled but doesn't have enough space.\n");
print_test_description("Eviction is ok, but mapping failed.\n");
will_return(__wrap_ocf_part_check_space, OCF_PART_IS_FULL);
will_return(__wrap_ocf_part_check_space, OCF_PART_IS_FULL);
will_return(__wrap_ocf_part_has_space, false);
will_return(__wrap_ocf_part_has_space, false);
expect_function_call(__wrap_space_managment_evict_do);
will_return(__wrap_space_managment_evict_do, LOOKUP_HIT);
@@ -185,8 +180,8 @@ static void ocf_prepare_clines_miss_test06(void **state)
print_test_description("Target part is enabled but doesn't have enough space.\n");
print_test_description("Eviction and mapping were ok, but failed to lock cachelines.\n");
will_return(__wrap_ocf_part_check_space, OCF_PART_IS_FULL);
will_return(__wrap_ocf_part_check_space, OCF_PART_IS_FULL);
will_return(__wrap_ocf_part_has_space, false);
will_return(__wrap_ocf_part_has_space, false);
expect_function_call(__wrap_space_managment_evict_do);
will_return(__wrap_space_managment_evict_do, LOOKUP_HIT);
@@ -210,8 +205,8 @@ static void ocf_prepare_clines_miss_test07(void **state)
print_test_description("Target part is enabled but doesn't have enough space.\n");
print_test_description("Eviction and mapping were ok, lock not acquired.\n");
will_return(__wrap_ocf_part_check_space, OCF_PART_IS_FULL);
will_return(__wrap_ocf_part_check_space, OCF_PART_IS_FULL);
will_return(__wrap_ocf_part_has_space, false);
will_return(__wrap_ocf_part_has_space, false);
expect_function_call(__wrap_space_managment_evict_do);
will_return(__wrap_space_managment_evict_do, LOOKUP_HIT);
@@ -233,7 +228,8 @@ static void ocf_prepare_clines_miss_test08(void **state)
print_test_description("Target part is enabled has enough space.\n");
print_test_description("\tMapping and cacheline lock are both ok\n");
will_return(__wrap_ocf_part_check_space, OCF_PART_HAS_SPACE);
will_return(__wrap_ocf_part_is_enabled, true);
will_return(__wrap_ocf_part_has_space, true);
expect_function_call(__wrap_ocf_engine_map);
will_return(__wrap_ocf_req_test_mapping_error, false);

View File

@@ -0,0 +1,291 @@
/*
* <tested_file_path>src/eviction/eviction.c</tested_file_path>
* <tested_function>ocf_evict_do</tested_function>
* <functions_to_leave>
ocf_evict_partitions
* </functions_to_leave>
*/
#undef static
#undef inline
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
#include "print_desc.h"
#include "eviction.h"
#include "ops.h"
#include "../utils/utils_part.h"
#include "eviction/eviction.c/eviction_generated_wraps.c"
struct test_cache
{
struct ocf_cache cache;
struct ocf_user_part_config part[OCF_IO_CLASS_MAX];
struct ocf_user_part upart[OCF_IO_CLASS_MAX];
uint32_t overflow[OCF_IO_CLASS_MAX];
uint32_t evictable[OCF_IO_CLASS_MAX];
};
bool __wrap_ocf_eviction_can_evict(ocf_cache_t cache)
{
return true;
}
uint32_t __wrap_ocf_part_overflow_size(struct ocf_cache *cache,
struct ocf_user_part *part)
{
struct test_cache* tcache = cache;
return tcache->overflow[part->id];
}
uint32_t __wrap_ocf_evict_calculate(ocf_cache_t cache,
struct ocf_user_part *part, uint32_t to_evict, bool roundup)
{
struct test_cache* tcache = cache;
return min(tcache->evictable[part->id], to_evict);
}
uint32_t __wrap_ocf_eviction_need_space(struct ocf_cache *cache,
ocf_queue_t io_queue, struct ocf_user_part *part,
uint32_t clines)
{
struct test_cache *tcache = (struct test_cache *)cache;
unsigned overflown_consumed = min(clines, tcache->overflow[part->id]);
tcache->overflow[part->id] -= overflown_consumed;
tcache->evictable[part->id] -= clines;
check_expected(part);
check_expected(clines);
function_called();
return mock();
}
int __wrap_ocf_log_raw(ocf_logger_t logger, ocf_logger_lvl_t lvl,
const char *fmt, ...)
{
}
int __wrap_ocf_log_stack_trace_raw(ocf_logger_t logger)
{
return 0;
}
ocf_ctx_t __wrap_ocf_cache_get_ctx(ocf_cache_t cache)
{
return NULL;
}
bool ocf_cache_is_device_attached(ocf_cache_t cache)
{
return true;
}
/* FIXME: copy-pasted from OCF */
int ocf_part_lst_cmp_valid(struct ocf_cache *cache,
struct ocf_lst_entry *e1, struct ocf_lst_entry *e2)
{
struct ocf_user_part *p1 = container_of(e1, struct ocf_user_part,
lst_valid);
struct ocf_user_part *p2 = container_of(e2, struct ocf_user_part,
lst_valid);
size_t p1_size = ocf_cache_is_device_attached(cache) ?
p1->runtime->curr_size : 0;
size_t p2_size = ocf_cache_is_device_attached(cache) ?
p2->runtime->curr_size : 0;
int v1 = p1->config->priority;
int v2 = p2->config->priority;
/*
* If partition is invalid the priority depends on current size:
* 1. Partition is empty - move to the end of list
* 2. Partition is not empty - move to the beginning of the list. This
* partition will be evicted first
*/
if (p1->config->priority == OCF_IO_CLASS_PRIO_PINNED)
p1->config->flags.eviction = false;
else
p1->config->flags.eviction = true;
if (p2->config->priority == OCF_IO_CLASS_PRIO_PINNED)
p2->config->flags.eviction = false;
else
p2->config->flags.eviction = true;
if (!p1->config->flags.valid) {
if (p1_size) {
v1 = SHRT_MAX;
p1->config->flags.eviction = true;
} else {
v1 = SHRT_MIN;
p1->config->flags.eviction = false;
}
}
if (!p2->config->flags.valid) {
if (p2_size) {
v2 = SHRT_MAX;
p2->config->flags.eviction = true;
} else {
v2 = SHRT_MIN;
p2->config->flags.eviction = false;
}
}
if (v1 == v2) {
v1 = p1 - cache->user_parts;
v2 = p2 - cache->user_parts;
}
return v2 - v1;
}
static struct ocf_lst_entry *_list_getter(
struct ocf_cache *cache, ocf_cache_line_t idx)
{
struct test_cache* tcache = cache;
return &tcache->upart[idx].lst_valid;
}
static void init_part_list(struct test_cache *tcache)
{
unsigned i;
for (i = 0; i < OCF_IO_CLASS_MAX; i++) {
tcache->upart[i].id = i;
tcache->upart[i].config = &tcache->part[i];
tcache->upart[i].config->priority = i+1;
tcache->upart[i].config->flags.eviction = 1;
}
ocf_lst_init((ocf_cache_t)tcache, &tcache->cache.lst_part, OCF_IO_CLASS_MAX,
_list_getter, ocf_part_lst_cmp_valid);
for (i = 0; i < OCF_IO_CLASS_MAX; i++) {
ocf_lst_init_entry(&tcache->cache.lst_part, &tcache->upart[i].lst_valid);
ocf_lst_add_tail(&tcache->cache.lst_part, i);
}
}
#define _expect_evict_call(tcache, part_id, req_count, ret_count) \
do { \
expect_value(__wrap_ocf_eviction_need_space, part, &tcache.upart[part_id]); \
expect_value(__wrap_ocf_eviction_need_space, clines, req_count); \
expect_function_call(__wrap_ocf_eviction_need_space); \
will_return(__wrap_ocf_eviction_need_space, ret_count); \
} while (false);
static void ocf_evict_do_test01(void **state)
{
struct test_cache tcache = {};
unsigned evicted;
print_test_description("one IO class, no overflow\n");
init_part_list(&tcache);
tcache.evictable[10] = 100;
_expect_evict_call(tcache, 10, 50, 50);
evicted = ocf_evict_do((ocf_cache_t *)&tcache, NULL, 50, &tcache.upart[0]);
assert_int_equal(evicted, 50);
}
static void ocf_evict_do_test02(void **state)
{
struct test_cache tcache = {};
unsigned i;
unsigned evicted;
print_test_description("one overflown IO class\n");
init_part_list(&tcache);
tcache.evictable[10] = 100;
tcache.overflow[10] = 100;
_expect_evict_call(tcache, 10, 50, 50);
evicted = ocf_evict_do((ocf_cache_t *)&tcache, NULL, 50, &tcache.upart[0]);
assert_int_equal(evicted, 50);
}
static void ocf_evict_do_test03(void **state)
{
struct test_cache tcache = {};
unsigned i;
unsigned evicted;
print_test_description("multiple non-overflown IO class\n");
init_part_list(&tcache);
tcache.evictable[10] = 100;
tcache.evictable[12] = 100;
tcache.evictable[16] = 100;
tcache.evictable[17] = 100;
_expect_evict_call(tcache, 10, 100, 100);
_expect_evict_call(tcache, 12, 100, 100);
_expect_evict_call(tcache, 16, 100, 100);
_expect_evict_call(tcache, 17, 50, 50);
evicted = ocf_evict_do((ocf_cache_t *)&tcache, NULL, 350, &tcache.upart[0]);
assert_int_equal(evicted, 350);
}
static void ocf_evict_do_test04(void **state)
{
struct test_cache tcache = {};
unsigned i;
unsigned evicted;
print_test_description("multiple IO class with and without overflow\n");
init_part_list(&tcache);
tcache.evictable[10] = 100;
tcache.evictable[12] = 100;
tcache.overflow[12] = 40;
tcache.evictable[14] = 100;
tcache.overflow[14] = 100;
tcache.evictable[16] = 100;
tcache.evictable[17] = 100;
tcache.evictable[18] = 100;
tcache.overflow[18] = 100;
_expect_evict_call(tcache, 12, 40, 40);
_expect_evict_call(tcache, 14, 100, 100);
_expect_evict_call(tcache, 18, 100, 100);
_expect_evict_call(tcache, 10, 100, 100);
_expect_evict_call(tcache, 12, 60, 60);
_expect_evict_call(tcache, 16, 100, 100);
_expect_evict_call(tcache, 17, 80, 80);
evicted = ocf_evict_do((ocf_cache_t *)&tcache, NULL, 580, &tcache.upart[0]);
assert_int_equal(evicted, 580);
}
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(ocf_evict_do_test01),
cmocka_unit_test(ocf_evict_do_test02),
cmocka_unit_test(ocf_evict_do_test03),
cmocka_unit_test(ocf_evict_do_test04)
};
return cmocka_run_group_tests(tests, NULL, NULL);
}

View File

@@ -1,516 +0,0 @@
/*
* <tested_file_path>src/utils/utils_part.c</tested_file_path>
* <tested_function>ocf_part_evict_size</tested_function>
* <functions_to_leave>
* INSERT HERE LIST OF FUNCTIONS YOU WANT TO LEAVE
* ONE FUNCTION PER LINE
* </functions_to_leave>
*/
#undef static
#undef inline
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
#include "print_desc.h"
#include "ocf/ocf.h"
#include "../ocf_cache_priv.h"
#include "../ocf_request.h"
#include "../metadata/metadata.h"
#include "../engine/cache_engine.h"
#include "../eviction/ops.h"
#include "utils_part.h"
#include "utils/utils_part.c/ocf_part_evict_size_generated_wraps.c"
uint32_t __wrap_ocf_part_get_max_size(ocf_cache_t cache,
struct ocf_user_part *target_part)
{
return mock();
}
uint32_t __wrap_ocf_engine_repart_count(struct ocf_request *req)
{
return mock();
}
uint32_t __wrap_ocf_engine_unmapped_count(struct ocf_request *req)
{
return mock();
}
uint32_t __wrap_ocf_part_get_occupancy(struct ocf_user_part *target_part)
{
return mock();
}
ocf_cache_line_t __wrap_ocf_freelist_num_free(ocf_freelist_t freelist)
{
return mock();
}
void __wrap_ocf_req_set_part_evict(struct ocf_request *req)
{
function_called();
}
void __wrap_ocf_req_clear_part_evict(struct ocf_request *req)
{
function_called();
}
static void ocf_part_evict_size_test01(void **state)
{
uint32_t max_part_size = 1024;
uint32_t cachelines_to_repart = 0;
uint32_t cachelines_to_map = 320;
uint32_t part_occupied_cachelines = 512;
uint32_t freelist_size = 500;
struct ocf_request req;
req.cache = test_malloc(sizeof(struct ocf_cache));
print_test_description("Enough free space available");
will_return(__wrap_ocf_part_get_max_size, max_part_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
will_return(__wrap_ocf_engine_repart_count, cachelines_to_repart);
will_return(__wrap_ocf_part_get_occupancy, part_occupied_cachelines);
// Enough free cachelines to map a whole request
will_return(__wrap_ocf_freelist_num_free, freelist_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
assert_int_equal(ocf_part_evict_size(&req), 0);
test_free(req.cache);
}
static void ocf_part_evict_size_test02(void **state)
{
uint32_t max_part_size = 1024;
uint32_t cachelines_to_repart = 0;
uint32_t cachelines_to_map = 320;
uint32_t part_occupied_cachelines = 960;
uint32_t freelist_size = 500;
struct ocf_request req;
req.cache = test_malloc(sizeof(struct ocf_cache));
uint32_t available_cachelines = max_part_size - part_occupied_cachelines;
uint32_t cachelines_to_evict = cachelines_to_map - available_cachelines;
print_test_description("Cache has enough free cachelines,"
" but target partition must be evicted");
will_return(__wrap_ocf_part_get_max_size, max_part_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
will_return(__wrap_ocf_engine_repart_count, cachelines_to_repart);
will_return(__wrap_ocf_part_get_occupancy, part_occupied_cachelines);
will_return(__wrap_ocf_freelist_num_free, freelist_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
expect_function_call(__wrap_ocf_req_set_part_evict);
assert_int_equal(ocf_part_evict_size(&req), cachelines_to_evict);
test_free(req.cache);
}
static void ocf_part_evict_size_test03(void **state)
{
uint32_t max_part_size = 1024;
uint32_t cachelines_to_repart = 320;
uint32_t cachelines_to_map = 0;
uint32_t part_occupied_cachelines = 512;
uint32_t freelist_size = 0;
struct ocf_request req;
req.cache = test_malloc(sizeof(struct ocf_cache));
uint32_t cachelines_to_evict = 0;
print_test_description("Only repart (no mapping). Freelist is empty but "
"space in a target part is availabe,");
print_test_description("\tso no cachelines should be "
" evcited from cache");
will_return(__wrap_ocf_part_get_max_size, max_part_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
will_return(__wrap_ocf_engine_repart_count, cachelines_to_repart);
will_return(__wrap_ocf_part_get_occupancy, part_occupied_cachelines);
will_return(__wrap_ocf_freelist_num_free, freelist_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
assert_int_equal(ocf_part_evict_size(&req), cachelines_to_evict);
test_free(req.cache);
}
static void ocf_part_evict_size_test04(void **state)
{
uint32_t max_part_size = 1024;
uint32_t cachelines_to_repart = 320;
uint32_t cachelines_to_map = 0;
uint32_t part_occupied_cachelines = 1100;
uint32_t freelist_size = 0;
struct ocf_request req;
req.cache = test_malloc(sizeof(struct ocf_cache));
uint32_t cachelines_debt = part_occupied_cachelines - max_part_size;
uint32_t cachelines_to_evict = cachelines_to_repart + cachelines_debt;
print_test_description("Only repart (no mapping). Freelist is empty and no"
" space in target part is availabe.");
print_test_description("\tEvict only from target partition");
will_return(__wrap_ocf_part_get_max_size, max_part_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
will_return(__wrap_ocf_engine_repart_count, cachelines_to_repart);
will_return(__wrap_ocf_part_get_occupancy, part_occupied_cachelines);
will_return(__wrap_ocf_freelist_num_free, freelist_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
expect_function_call(__wrap_ocf_req_set_part_evict);
assert_int_equal(ocf_part_evict_size(&req), cachelines_to_evict);
test_free(req.cache);
}
static void ocf_part_evict_size_test05(void **state)
{
uint32_t max_part_size = 1024;
uint32_t cachelines_to_repart = 0;
uint32_t cachelines_to_map = 320;
uint32_t part_occupied_cachelines = 960;
uint32_t freelist_size = 0;
struct ocf_request req;
req.cache = test_malloc(sizeof(struct ocf_cache));
uint32_t available_cachelines = max_part_size - part_occupied_cachelines;
uint32_t cachelines_to_evict = cachelines_to_map - available_cachelines;
print_test_description("Freelist is empty and no space in the target part "
"is available");
will_return(__wrap_ocf_part_get_max_size, max_part_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
will_return(__wrap_ocf_engine_repart_count, cachelines_to_repart);
will_return(__wrap_ocf_part_get_occupancy, part_occupied_cachelines);
will_return(__wrap_ocf_freelist_num_free, freelist_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
expect_function_call(__wrap_ocf_req_set_part_evict);
assert_int_equal(ocf_part_evict_size(&req), cachelines_to_evict);
test_free(req.cache);
}
static void ocf_part_evict_size_test06(void **state)
{
uint32_t max_part_size = 1024;
uint32_t cachelines_to_repart = 0;
uint32_t cachelines_to_map = 320;
uint32_t part_occupied_cachelines = 320;
uint32_t freelist_size = 0;
struct ocf_request req;
req.cache = test_malloc(sizeof(struct ocf_cache));
uint32_t available_cachelines = max_part_size - part_occupied_cachelines;
uint32_t cachelines_to_evict = cachelines_to_map;
print_test_description("Freelist is empty but target part has enough space");
will_return(__wrap_ocf_part_get_max_size, max_part_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
will_return(__wrap_ocf_engine_repart_count, cachelines_to_repart);
will_return(__wrap_ocf_part_get_occupancy, part_occupied_cachelines);
will_return(__wrap_ocf_freelist_num_free, freelist_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
expect_function_call(__wrap_ocf_req_clear_part_evict);
assert_int_equal(ocf_part_evict_size(&req), cachelines_to_evict);
test_free(req.cache);
}
static void ocf_part_evict_size_test07(void **state)
{
uint32_t max_part_size = 1024;
uint32_t cachelines_to_repart = 0;
uint32_t cachelines_to_map = 320;
uint32_t part_occupied_cachelines = 1280;
uint32_t freelist_size = 0;
struct ocf_request req;
req.cache = test_malloc(sizeof(struct ocf_cache));
uint32_t debt_cachelines = part_occupied_cachelines - max_part_size;
uint32_t cachelines_to_evict = cachelines_to_map + debt_cachelines;
print_test_description("Freelist is empty and part occupancy exceeded");
will_return(__wrap_ocf_part_get_max_size, max_part_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
will_return(__wrap_ocf_engine_repart_count, cachelines_to_repart);
will_return(__wrap_ocf_part_get_occupancy, part_occupied_cachelines);
will_return(__wrap_ocf_freelist_num_free, freelist_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
expect_function_call(__wrap_ocf_req_set_part_evict);
assert_int_equal(ocf_part_evict_size(&req),
(part_occupied_cachelines - max_part_size) + cachelines_to_map);
test_free(req.cache);
}
static void ocf_part_evict_size_test08(void **state)
{
uint32_t max_part_size = 1024;
uint32_t cachelines_to_repart = 320;
uint32_t cachelines_to_map = 0;
uint32_t part_occupied_cachelines = 1280;
uint32_t freelist_size = 0;
struct ocf_request req;
req.cache = test_malloc(sizeof(struct ocf_cache));
uint32_t debt_cachelines = part_occupied_cachelines - max_part_size;
uint32_t cachelines_to_evict = debt_cachelines + cachelines_to_repart;
print_test_description("Target part occupancy limit is exceeded during "
"repart");
will_return(__wrap_ocf_part_get_max_size, max_part_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
will_return(__wrap_ocf_engine_repart_count, cachelines_to_repart);
will_return(__wrap_ocf_part_get_occupancy, part_occupied_cachelines);
will_return(__wrap_ocf_freelist_num_free, freelist_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
expect_function_call(__wrap_ocf_req_set_part_evict);
assert_int_equal(ocf_part_evict_size(&req),
(part_occupied_cachelines - max_part_size) + cachelines_to_repart);
test_free(req.cache);
}
static void ocf_part_evict_size_test09(void **state)
{
uint32_t max_part_size = 1024;
uint32_t cachelines_to_repart = 320;
uint32_t cachelines_to_map = 0;
uint32_t part_occupied_cachelines = 320;
uint32_t freelist_size = 0;
struct ocf_request req;
req.cache = test_malloc(sizeof(struct ocf_cache));
uint32_t cachelines_to_evict = 0;
print_test_description("Repart while target part has enough of available "
"space");
will_return(__wrap_ocf_part_get_max_size, max_part_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
will_return(__wrap_ocf_engine_repart_count, cachelines_to_repart);
will_return(__wrap_ocf_part_get_occupancy, part_occupied_cachelines);
will_return(__wrap_ocf_freelist_num_free, freelist_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
assert_int_equal(ocf_part_evict_size(&req), cachelines_to_evict);
test_free(req.cache);
}
static void ocf_part_evict_size_test10(void **state)
{
uint32_t max_part_size = 1024;
uint32_t cachelines_to_repart = 0;
uint32_t cachelines_to_map = 320;
uint32_t part_occupied_cachelines = 320;
uint32_t freelist_size = 320;
struct ocf_request req;
req.cache = test_malloc(sizeof(struct ocf_cache));
uint32_t cachelines_to_evict = 0;
print_test_description("Enough of available cachelines in target part, "
"freelist has exactly required number of free cachelines");
will_return(__wrap_ocf_part_get_max_size, max_part_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
will_return(__wrap_ocf_engine_repart_count, cachelines_to_repart);
will_return(__wrap_ocf_part_get_occupancy, part_occupied_cachelines);
will_return(__wrap_ocf_freelist_num_free, freelist_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
assert_int_equal(ocf_part_evict_size(&req), cachelines_to_evict);
test_free(req.cache);
}
static void ocf_part_evict_size_test11(void **state)
{
uint32_t max_part_size = 1024;
uint32_t cachelines_to_repart = 320;
uint32_t cachelines_to_map = 0;
uint32_t part_occupied_cachelines = 384;
uint32_t freelist_size = 0;
struct ocf_request req;
req.cache = test_malloc(sizeof(struct ocf_cache));
uint32_t cachelines_to_evict = 0;
print_test_description("Number of cachelines to repart is equal to number "
"of cachelines available in the target partition");
will_return(__wrap_ocf_part_get_max_size, max_part_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
will_return(__wrap_ocf_engine_repart_count, cachelines_to_repart);
will_return(__wrap_ocf_part_get_occupancy, part_occupied_cachelines);
will_return(__wrap_ocf_freelist_num_free, freelist_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
assert_int_equal(ocf_part_evict_size(&req), cachelines_to_evict);
test_free(req.cache);
}
static void ocf_part_evict_size_test12(void **state)
{
uint32_t max_part_size = 0;
uint32_t cachelines_to_repart = 0;
uint32_t cachelines_to_map = 320;
uint32_t part_occupied_cachelines = 384;
uint32_t freelist_size = 0;
struct ocf_request req;
req.cache = test_malloc(sizeof(struct ocf_cache));
uint32_t cachelines_to_evict =
part_occupied_cachelines + cachelines_to_map;
print_test_description("Freelist IS empty. Max occupancy set to 0, but "
"some cachelines are still assigned to traget part - evict them");
will_return(__wrap_ocf_part_get_max_size, max_part_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
will_return(__wrap_ocf_engine_repart_count, cachelines_to_repart);
will_return(__wrap_ocf_part_get_occupancy, part_occupied_cachelines);
will_return(__wrap_ocf_freelist_num_free, freelist_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
expect_function_call(__wrap_ocf_req_set_part_evict);
assert_true(ocf_part_evict_size(&req) >= part_occupied_cachelines);
test_free(req.cache);
}
static void ocf_part_evict_size_test13(void **state)
{
uint32_t max_part_size = 0;
uint32_t cachelines_to_repart = 0;
uint32_t cachelines_to_map = 320;
uint32_t part_occupied_cachelines = 384;
uint32_t freelist_size = 1024;
struct ocf_request req;
req.cache = test_malloc(sizeof(struct ocf_cache));
uint32_t cachelines_to_evict =
part_occupied_cachelines + cachelines_to_map;
print_test_description("Freelist IS NOT empty. Max occupancy set to 0, but"
" some cachelines are still assigned to traget part - evict them");
will_return(__wrap_ocf_part_get_max_size, max_part_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
will_return(__wrap_ocf_engine_repart_count, cachelines_to_repart);
will_return(__wrap_ocf_part_get_occupancy, part_occupied_cachelines);
will_return(__wrap_ocf_freelist_num_free, freelist_size);
will_return(__wrap_ocf_engine_unmapped_count, cachelines_to_map);
expect_function_call(__wrap_ocf_req_set_part_evict);
assert_true(ocf_part_evict_size(&req) >= part_occupied_cachelines);
test_free(req.cache);
}
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(ocf_part_evict_size_test01),
cmocka_unit_test(ocf_part_evict_size_test02),
cmocka_unit_test(ocf_part_evict_size_test03),
cmocka_unit_test(ocf_part_evict_size_test04),
cmocka_unit_test(ocf_part_evict_size_test05),
cmocka_unit_test(ocf_part_evict_size_test06),
cmocka_unit_test(ocf_part_evict_size_test07),
cmocka_unit_test(ocf_part_evict_size_test08),
cmocka_unit_test(ocf_part_evict_size_test09),
cmocka_unit_test(ocf_part_evict_size_test10),
cmocka_unit_test(ocf_part_evict_size_test11),
cmocka_unit_test(ocf_part_evict_size_test12),
cmocka_unit_test(ocf_part_evict_size_test13)
};
print_message("Unit test for ocf_part_evict_size\n");
return cmocka_run_group_tests(tests, NULL, NULL);
}