unit tests for lru iterator

Signed-off-by: Adam Rutkowski <adam.j.rutkowski@intel.com>
This commit is contained in:
Adam Rutkowski 2020-12-14 17:03:09 +01:00
parent 44efe3e49e
commit d52083a445

View File

@ -0,0 +1,481 @@
/*
* <tested_file_path>src/eviction/lru.c</tested_file_path>
* <tested_function>lru_iter_next</tested_function>
* <functions_to_leave>
* INSERT HERE LIST OF FUNCTIONS YOU WANT TO LEAVE
* ONE FUNCTION PER LINE
* lru_iter_init
* _lru_next_evp
* _lru_evp_is_empty
* _lru_evp_set_empty
* _lru_evp_all_empty
* ocf_rotate_right
* </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 "lru.h"
#include "ops.h"
#include "../utils/utils_cleaner.h"
#include "../utils/utils_cache_line.h"
#include "../concurrency/ocf_concurrency.h"
#include "../mngt/ocf_mngt_common.h"
#include "../engine/engine_zero.h"
#include "../ocf_request.h"
#include "eviction/lru.c/lru_iter_generated_wraps.c"
//#define DEBUG
ocf_cache_line_t test_cases[10 * OCF_NUM_EVICTION_LISTS][OCF_NUM_EVICTION_LISTS][20];
unsigned num_cases = 20;
void write_test_case_description(void)
{
unsigned i, j, l;
unsigned test_case = 0;
// case 0 - all lists empty
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++) {
test_cases[0][i][test_case] = -1;
}
// case 1 - all lists with single element
test_case++;
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++) {
test_cases[0][i][test_case] = 10 * i;
test_cases[1][i][test_case] = -1;
}
// case 2 - all lists have between 1 and 5 elements, increasingly
test_case++;
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++) {
unsigned num_elements = 1 + i / (OCF_NUM_EVICTION_LISTS / 4);
for (j = 0; j < num_elements; j++)
test_cases[j][i][test_case] = 10 * i + j;
test_cases[j][i][test_case] = -1;
}
// case 3 - all lists have between 1 and 5 elements, modulo index
test_case++;
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++) {
unsigned num_elements = 1 + (i % 5);
for (j = 0; j < num_elements; j++)
test_cases[j][i][test_case] = 10 * i + j;
test_cases[j][i][test_case] = -1;
}
// case 4 - all lists have between 0 and 4 elements, increasingly
test_case++;
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++) {
unsigned num_elements = i / (OCF_NUM_EVICTION_LISTS / 4);
for (j = 0; j < num_elements; j++)
test_cases[j][i][test_case] = 10 * i + j;
test_cases[j][i][test_case] = -1;
}
// case 5 - all lists have between 0 and 4 elements, modulo index
test_case++;
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++) {
unsigned num_elements = (i % 5);
for (j = 0; j < num_elements; j++)
test_cases[j][i][test_case] = 10 * i + j;
test_cases[j][i][test_case] = -1;
}
// case 6 - list length increasing by 1 from 0
test_case++;
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++) {
unsigned num_elements = i;
for (j = 0; j < num_elements; j++)
test_cases[j][i][test_case] = OCF_NUM_EVICTION_LISTS * i + j;
test_cases[j][i][test_case] = -1;
}
// case 7 - list length increasing by 1 from 1
test_case++;
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++) {
unsigned num_elements = i + 1;
for (j = 0; j < num_elements; j++)
test_cases[j][i][test_case] = 2 * OCF_NUM_EVICTION_LISTS * i + j;
test_cases[j][i][test_case] = -1;
}
// case 8 - list length increasing by 4 from 0
test_case++;
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++) {
unsigned num_elements = 4 * i;
for (j = 0; j < num_elements; j++)
test_cases[j][i][test_case] = 4 * OCF_NUM_EVICTION_LISTS * i + j;
test_cases[j][i][test_case] = -1;
}
// case 9 - list length increasing by 4 from 1
test_case++;
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++) {
unsigned num_elements = 4 * i + 1;
for (j = 0; j < num_elements; j++)
test_cases[j][i][test_case] = 5 * OCF_NUM_EVICTION_LISTS * i + j;
test_cases[j][i][test_case] = -1;
}
// cases 10-19: cases 0-9 rotated right by 4
l = test_case;
test_case++;
while(test_case < 2 * (l + 1)) {
unsigned matching_case = test_case - l - 1;
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++) {
unsigned curr_list = (i + 4) % OCF_NUM_EVICTION_LISTS;
j = 0;
while(test_cases[j][i][matching_case] != -1) {
test_cases[j][curr_list][test_case] =
test_cases[j][i][matching_case];
j++;
}
test_cases[j][curr_list][test_case] = -1;
}
test_case++;
}
#ifdef DEBUG
for (test_case = 0; test_case < num_cases; test_case++) {
print_message("test case no %d\n", test_case);
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++) {
print_message("list %02u: ", i);
j = 0;
while (test_cases[j][i][test_case] != -1) {
print_message("%u ", test_cases[j][i][test_case]);
j++;
}
print_message("<EOL>\n");
}
print_message("========\n\n");
}
#endif
}
unsigned current_case;
struct ocf_lru_list list;
struct ocf_lru_list *__wrap_evp_lru_get_list(struct ocf_user_part *part,
uint32_t evp, bool clean)
{
unsigned i = 0;
while (test_cases[i][evp][current_case] != -1)
i++;
if (i == 0) {
list.head = -1;
list.tail = -1;
list.num_nodes = 0;
} else {
list.head = test_cases[0][evp][current_case];
list.tail = test_cases[i - 1][evp][current_case];
list.num_nodes = i;
}
return &list;
}
inline struct ocf_lru_list *__wrap_evp_get_cline_list(ocf_cache_t cache,
ocf_cache_line_t cline)
{
return __wrap_evp_lru_get_list(NULL, cline % OCF_NUM_EVICTION_LISTS, true);
}
union eviction_policy_meta policy;
union eviction_policy_meta *__wrap_ocf_metadata_get_eviction_policy(
struct ocf_cache *cache, ocf_cache_line_t line)
{
unsigned i, j;
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++)
{
j = 0;
while (test_cases[j][i][current_case] != -1) {
if (test_cases[j][i][current_case] == line) {
if (j == 0) {
policy.lru.prev = -1;
} else {
policy.lru.prev =
test_cases[j - 1][i][current_case];
}
policy.lru.next = test_cases[j + 1][i][current_case];
#ifdef DEBUG
print_message("[%u] next %u prev %u\n",
line, policy.lru.next,
policy.lru.prev);
#endif
return &policy;
}
j++;
}
}
print_message("use case %d cache line %d not found\n",
current_case, line);
assert(false);
}
static void _lru_run_test(unsigned test_case)
{
unsigned start_pos;
current_case = test_case;
for (start_pos = 0; start_pos < OCF_NUM_EVICTION_LISTS; start_pos++)
{
struct ocf_lru_iter iter;
ocf_cache_line_t cache_line, expected_cache_line;
unsigned curr_evp = start_pos;
unsigned pos[OCF_NUM_EVICTION_LISTS];
unsigned i;
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++)
{
pos[i] = -1;
while(test_cases[pos[i] + 1][i][test_case] != -1)
pos[i]++;
}
lru_iter_init(&iter, NULL, NULL, start_pos, false);
do {
/* get cacheline from iterator */
cache_line = lru_iter_next(&iter);
/* check what is expected to be returned from iterator */
if (pos[curr_evp] == -1) {
i = 1;
while (i < OCF_NUM_EVICTION_LISTS &&
pos[(curr_evp + i) % OCF_NUM_EVICTION_LISTS]
== -1) {
i++;
}
if (i == OCF_NUM_EVICTION_LISTS) {
/* reached end of lists */
expected_cache_line = -1;
} else {
curr_evp = (curr_evp + i) % OCF_NUM_EVICTION_LISTS;
expected_cache_line = test_cases[pos[curr_evp]]
[curr_evp][test_case];
pos[curr_evp]--;
}
} else {
expected_cache_line = test_cases[pos[curr_evp]]
[curr_evp][test_case];
pos[curr_evp]--;
}
assert_int_equal(cache_line, expected_cache_line);
curr_evp = (curr_evp + 1) % OCF_NUM_EVICTION_LISTS;
} while (cache_line != -1);
/* make sure all cachelines are visited */
for (i = 0; i < OCF_NUM_EVICTION_LISTS; i++)
{
assert_int_equal((unsigned)-1, pos[i]);
}
}
}
static void lru_iter_next_test00(void **state)
{
print_test_description("lru iter test case 00\n");
_lru_run_test(0);
return;
}
static void lru_iter_next_test01(void **state)
{
print_test_description("lru iter test case 01\n");
_lru_run_test(1);
return;
}
static void lru_iter_next_test02(void **state)
{
print_test_description("lru iter test case 02\n");
_lru_run_test(2);
return;
}
static void lru_iter_next_test03(void **state)
{
print_test_description("lru iter test case 03\n");
_lru_run_test(3);
return;
}
static void lru_iter_next_test04(void **state)
{
print_test_description("lru iter test case 04\n");
_lru_run_test(4);
return;
}
static void lru_iter_next_test05(void **state)
{
print_test_description("lru iter test case 05\n");
_lru_run_test(5);
return;
}
static void lru_iter_next_test06(void **state)
{
print_test_description("lru iter test case 06\n");
_lru_run_test(6);
return;
}
static void lru_iter_next_test07(void **state)
{
print_test_description("lru iter test case 07\n");
_lru_run_test(7);
return;
}
static void lru_iter_next_test08(void **state)
{
print_test_description("lru iter test case 08\n");
_lru_run_test(8);
return;
}
static void lru_iter_next_test09(void **state)
{
print_test_description("lru iter test case 09\n");
_lru_run_test(9);
return;
}
static void lru_iter_next_test10(void **state)
{
print_test_description("lru iter test case 00\n");
_lru_run_test(10);
return;
}
static void lru_iter_next_test11(void **state)
{
print_test_description("lru iter test case 11\n");
_lru_run_test(11);
return;
}
static void lru_iter_next_test12(void **state)
{
print_test_description("lru iter test case 12\n");
_lru_run_test(12);
return;
}
static void lru_iter_next_test13(void **state)
{
print_test_description("lru iter test case 13\n");
_lru_run_test(13);
return;
}
static void lru_iter_next_test14(void **state)
{
print_test_description("lru iter test case 14\n");
_lru_run_test(14);
return;
}
static void lru_iter_next_test15(void **state)
{
print_test_description("lru iter test case 15\n");
_lru_run_test(15);
return;
}
static void lru_iter_next_test16(void **state)
{
print_test_description("lru iter test case 16\n");
_lru_run_test(16);
return;
}
static void lru_iter_next_test17(void **state)
{
print_test_description("lru iter test case 17\n");
_lru_run_test(17);
return;
}
static void lru_iter_next_test18(void **state)
{
print_test_description("lru iter test case 18\n");
_lru_run_test(18);
return;
}
static void lru_iter_next_test19(void **state)
{
print_test_description("lru iter test case 19\n");
_lru_run_test(19);
return;
}
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(lru_iter_next_test00),
cmocka_unit_test(lru_iter_next_test01),
cmocka_unit_test(lru_iter_next_test02),
cmocka_unit_test(lru_iter_next_test03),
cmocka_unit_test(lru_iter_next_test04),
cmocka_unit_test(lru_iter_next_test05),
cmocka_unit_test(lru_iter_next_test06),
cmocka_unit_test(lru_iter_next_test07),
cmocka_unit_test(lru_iter_next_test08),
cmocka_unit_test(lru_iter_next_test09),
cmocka_unit_test(lru_iter_next_test10),
cmocka_unit_test(lru_iter_next_test11),
cmocka_unit_test(lru_iter_next_test12),
cmocka_unit_test(lru_iter_next_test13),
cmocka_unit_test(lru_iter_next_test14),
cmocka_unit_test(lru_iter_next_test15),
cmocka_unit_test(lru_iter_next_test16),
cmocka_unit_test(lru_iter_next_test17),
cmocka_unit_test(lru_iter_next_test18),
cmocka_unit_test(lru_iter_next_test19)
};
print_message("Unit test for lru_iter_next\n");
write_test_case_description();
return cmocka_run_group_tests(tests, NULL, NULL);
}