1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
// SPDX-License-Identifier: BSD-2-Clause
/* Copyright (C) 2015 - 2021 Intel Corporation. */
/*
This file contain self-tests for Allocator Perf Tool.
*/
#pragma once
#include <unistd.h>
#include "AllocationSizes.hpp"
#include "AllocatorFactory.hpp"
#include "Configuration.hpp"
#include "ScenarioWorkload.h"
#include "StandardAllocatorWithTimer.hpp"
#include "Task.hpp"
#include "TaskFactory.hpp"
#include "VectorIterator.hpp"
// Basic test for allocators. Allocate 32 bytes by malloc, then deallocate it by
// free.
void test_allocator(Allocator &allocator, const char *allocator_name)
{
printf("\n============= Allocator (%s) test ============= \n",
allocator_name);
memory_operation data = allocator.wrapped_malloc(32);
printf("malloc: %p \n", data.ptr);
assert(data.ptr != NULL);
allocator.wrapped_free(data.ptr);
printf("free: %p \n", data.ptr);
printf("\n==================================================== \n");
}
// Test for the workload classes. This test count and validate the number or
// runs.
void test_workload(Workload &workload, const int N, const char *workload_name)
{
printf("\n============= Work load (%s) test ============= \n",
workload_name);
assert(
workload
.run()); // Do "single" memory operation (allocate or deallocate).
int i;
for (i = 1; workload.run(); i++)
; // Do the rest of operations.
assert(i == N);
printf("\n==================================================== \n");
}
// Simulate time consuming memory operation.
memory_operation time_consuming_memory_operation(unsigned int seconds)
{
size_t size;
START_TEST(0, 0)
sleep(seconds);
END_TEST
}
// This test check if timer has measured time.
void test_timer()
{
float total_time = time_consuming_memory_operation(2).total_time;
bool test_res = (total_time >= 2.0) && (total_time < 2.2);
if (!test_res)
printf("test_timer(): unexpected timing %f", total_time);
assert(test_res);
}
// Test for iterators. Check the number of iterations, such as:
// N == number of iterations.
template <class T>
void test_iterator(Iterator<T> &it, const int N)
{
printf("\n================= Iterator test ==================== \n");
assert(it.size() == N);
int i;
for (i = 0; it.has_next(); i++) {
it.next();
}
printf("iterations=%d/%d\n", i, N);
assert(i == N);
printf("\n==================================================== \n");
}
// This test validate range of values generated by random generators.
template <class T, class C>
void test_iterator_values(VectorIterator<T> &it, const C from, const C to)
{
for (int i = 0; it.has_next(); i++) {
T val = it.next();
if (val < from)
std::cout << "ivalid value: actual=" << val
<< ", expected= >=" << from << std::endl;
if (val > to)
std::cout << "ivalid value: actual=" << val
<< ", expected= <=" << to << std::endl;
}
}
// Test time counting instrumentation in StandardAllocatorWithTimer.
// The instrumentation is made with START_TEST and END_TEST macros from
// WrapperMacros.h.
void test_allocator_with_timer(int N, int seed)
{
printf("\n============= Allocator with timer test ============= \n");
StandardAllocatorWithTimer allocator;
VectorIterator<size_t> allocation_sizes =
AllocationSizes::generate_random_sizes(N, 32, 2048, seed);
memory_operation data;
double elaspsed_time = 0;
for (int i = 0; i < N; i++) {
data = allocator.wrapped_malloc(allocation_sizes.next());
elaspsed_time += data.total_time;
allocator.wrapped_free(data.ptr);
}
printf("%d allocations and frees done in time: %f \n", N, elaspsed_time);
printf("\n==================================================== \n");
}
// Test behavior of TypesConfiguration class, by enabling and disabling types.
void test_types_conf()
{
TypesConf types;
for (unsigned i = 0; i < FunctionCalls::NUM_OF_FUNCTIONS; i++) {
types.enable_type(i);
assert(types.is_enabled(i));
types.disable_type(i);
assert(!types.is_enabled(i));
}
}
void execute_self_tests()
{
const int N = 10000;
const size_t size_from = 32, size_to = 2048;
const unsigned seed = 11;
test_types_conf();
{
VectorIterator<size_t> it =
AllocationSizes::generate_random_sizes(N, size_from, size_to, seed);
test_iterator_values(it, size_from, size_to);
}
{
TypesConf enable_func_calls;
enable_func_calls.enable_type(FunctionCalls::MALLOC);
VectorIterator<int> it =
FunctionCalls::generate_random_allocator_func_calls(
N, seed, enable_func_calls);
test_iterator(it, N);
}
// Timer implementation __cplusplus < 201100L is based on CPU clocks counting
// and it will fail on this test.
#if __cplusplus > 201100L
test_timer();
#endif
printf("Test completed! (press ENTER to continue)\n");
}
|