Skip to content

Commit

Permalink
栈池 单元测试
Browse files Browse the repository at this point in the history
  • Loading branch information
owent committed May 10, 2017
1 parent eb48d25 commit 3c0b596
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 12 deletions.
6 changes: 5 additions & 1 deletion include/libcopp/stack/stack_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ namespace copp {
return conf_.stack_size = sz;
}
size_t get_stack_size() const { return conf_.stack_size; }
size_t get_stack_size_offset() const { return conf_.stack_offset; }

inline void set_max_stack_size(size_t sz) COPP_MACRO_NOEXCEPT { conf_.max_stack_size = sz; }
inline size_t get_max_stack_size() const COPP_MACRO_NOEXCEPT { return conf_.max_stack_size; }
Expand All @@ -93,6 +94,9 @@ namespace copp {
inline void set_auto_gc(bool v) COPP_MACRO_NOEXCEPT { conf_.auto_gc = v; }
inline bool is_auto_gc() const COPP_MACRO_NOEXCEPT { return conf_.auto_gc; }

inline void set_gc_once_number(size_t v) COPP_MACRO_NOEXCEPT { conf_.gc_number = v; }
inline size_t get_gc_once_number() const COPP_MACRO_NOEXCEPT { return conf_.gc_number; }

// actions

/**
Expand All @@ -110,7 +114,7 @@ namespace copp {
return;
}

if (0 != conf_.max_stack_number && limits_.used_stack_size + conf_.stack_size > conf_.max_stack_size) {
if (0 != conf_.max_stack_size && limits_.used_stack_size + conf_.stack_size > conf_.max_stack_size) {
ctx.sp = NULL;
ctx.size = 0;
return;
Expand Down
194 changes: 183 additions & 11 deletions test/case/stack_pool_test.cpp
Original file line number Diff line number Diff line change
@@ -1,33 +1,205 @@
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>

#include <libcopp/stack/stack_pool.h>
#include <libcotask/task.h>

#include "frame/test_macros.h"
#include "libcopp/fcontext/all.hpp"
#include "libcopp/stack/stack_allocator.h"
#include "libcopp/stack/stack_pool.h"

typedef copp::stack_pool<copp::allocator::default_statck_allocator> stack_pool_t;
typedef copp::stack_pool<copp::allocator::stack_allocator_malloc> stack_pool_t;
struct stack_pool_test_macro_coroutine {
typedef copp::detail::coroutine_context_base coroutine_t;
typedef copp::allocator::stack_allocator_pool<stack_pool_t> stack_allocator_t;

typedef copp::detail::coroutine_context_container<coroutine_t, stack_allocator_t> coroutine_container_t;
};
static stack_pool_t::ptr_t global_stack_pool;

struct stack_pool_test_task_allocator : public cotask::macro_task::task_allocator_t {
public:
#if defined(COPP_MACRO_ENABLE_VARIADIC_TEMPLATE) && COPP_MACRO_ENABLE_VARIADIC_TEMPLATE
template <typename Ty, typename... TARGS>
static std::shared_ptr<Ty> allocate(Ty *t, TARGS COPP_MACRO_RV_REF... args) {
std::shared_ptr<Ty> ret = cotask::macro_task::task_allocator_t::allocate(t, COPP_MACRO_STD_FORWARD(TARGS, args)...);
ret->get_coroutine_context().get_allocator().attach(global_stack_pool);
return COPP_MACRO_STD_MOVE(ret);
}
#else
template <typename Ty>
static std::shared_ptr<Ty> allocate(Ty *t) {
std::shared_ptr<Ty> ret = cotask::macro_task::task_allocator_t::allocate(t);
ret->get_coroutine_context().get_allocator().attach(global_stack_pool);
return COPP_MACRO_STD_MOVE(ret);
}
#endif
};

struct stack_pool_test_macro_task {
typedef cotask::macro_task::id_t id_t;
typedef cotask::macro_task::id_allocator_t id_allocator_t;

typedef cotask::macro_task::action_allocator_t action_allocator_t;
typedef stack_pool_test_task_allocator task_allocator_t;
};

typedef cotask::task<stack_pool_test_macro_coroutine, stack_pool_test_macro_task> stack_pool_test_task_t;

static int stack_pool_test_task_action() { return 0; }

CASE_TEST(stack_pool_test, basic) {
stack_pool_t::ptr_t stack_pool = stack_pool_t::create();
global_stack_pool = stack_pool_t::create();
std::vector<stack_pool_test_task_t::ptr_t> task_arr;
const size_t task_arr_sz = 64;

// alloc
for (size_t i = 0; i < task_arr_sz; ++i) {
stack_pool_test_task_t::ptr_t tp = stack_pool_test_task_t::create(stack_pool_test_task_action);
task_arr.push_back(tp);
}
CASE_EXPECT_EQ(task_arr_sz, global_stack_pool->get_limit().used_stack_number);
CASE_EXPECT_EQ(task_arr_sz * (global_stack_pool->get_stack_size() + global_stack_pool->get_stack_size_offset()),
global_stack_pool->get_limit().used_stack_size);

CASE_EXPECT_EQ(0, global_stack_pool->get_limit().free_stack_number);
CASE_EXPECT_EQ(0, global_stack_pool->get_limit().free_stack_size);

// recycle to free list
for (size_t i = 0; i < task_arr_sz / 2; ++i) {
task_arr.pop_back();
}
CASE_EXPECT_EQ(task_arr_sz - task_arr_sz / 2, global_stack_pool->get_limit().used_stack_number);
CASE_EXPECT_EQ(task_arr_sz / 2, global_stack_pool->get_limit().free_stack_number);
CASE_EXPECT_EQ((task_arr_sz - task_arr_sz / 2) * (global_stack_pool->get_stack_size() + global_stack_pool->get_stack_size_offset()),
global_stack_pool->get_limit().used_stack_size);
CASE_EXPECT_EQ((task_arr_sz / 2) * (global_stack_pool->get_stack_size() + global_stack_pool->get_stack_size_offset()),
global_stack_pool->get_limit().free_stack_size);

// auto_gc
task_arr.pop_back();
CASE_EXPECT_EQ(task_arr_sz / 4, global_stack_pool->get_limit().free_stack_number);
CASE_EXPECT_EQ((task_arr_sz / 4) * (global_stack_pool->get_stack_size() + global_stack_pool->get_stack_size_offset()),
global_stack_pool->get_limit().free_stack_size);

global_stack_pool.reset();
}

CASE_TEST(stack_pool_test, full) {
stack_pool_t::ptr_t stack_pool = stack_pool_t::create();
CASE_TEST(stack_pool_test, full_number) {
global_stack_pool = stack_pool_t::create();
// full

std::vector<stack_pool_test_task_t::ptr_t> task_arr;
const size_t task_arr_sz = 64;
global_stack_pool->set_max_stack_number(task_arr_sz);
// alloc
for (size_t i = 0; i < task_arr_sz; ++i) {
stack_pool_test_task_t::ptr_t tp = stack_pool_test_task_t::create(stack_pool_test_task_action);
CASE_EXPECT_TRUE(!!tp);
task_arr.push_back(tp);
}

{
stack_pool_test_task_t::ptr_t tp = stack_pool_test_task_t::create(stack_pool_test_task_action);
CASE_EXPECT_TRUE(!tp);
}

global_stack_pool.reset();
}

CASE_TEST(stack_pool_test, no_gc) {
stack_pool_t::ptr_t stack_pool = stack_pool_t::create();
// no_gc
CASE_TEST(stack_pool_test, custom_gc) {
global_stack_pool = stack_pool_t::create();
std::vector<stack_pool_test_task_t::ptr_t> task_arr;
const size_t task_arr_sz = 64;

global_stack_pool->set_min_stack_number(task_arr_sz);

// alloc
for (size_t i = 0; i < task_arr_sz; ++i) {
stack_pool_test_task_t::ptr_t tp = stack_pool_test_task_t::create(stack_pool_test_task_action);
task_arr.push_back(tp);
}

CASE_EXPECT_EQ(task_arr_sz, global_stack_pool->get_limit().used_stack_number);
CASE_EXPECT_EQ(task_arr_sz * (global_stack_pool->get_stack_size() + global_stack_pool->get_stack_size_offset()),
global_stack_pool->get_limit().used_stack_size);

CASE_EXPECT_EQ(0, global_stack_pool->get_limit().free_stack_number);
CASE_EXPECT_EQ(0, global_stack_pool->get_limit().free_stack_size);

for (size_t i = 0; i < task_arr_sz; ++i) {
task_arr.pop_back();
}

CASE_EXPECT_EQ(0, global_stack_pool->get_limit().used_stack_number);
CASE_EXPECT_EQ(0, global_stack_pool->get_limit().used_stack_size);

CASE_EXPECT_EQ(task_arr_sz, global_stack_pool->get_limit().free_stack_number);
CASE_EXPECT_EQ(task_arr_sz * (global_stack_pool->get_stack_size() + global_stack_pool->get_stack_size_offset()),
global_stack_pool->get_limit().free_stack_size);

global_stack_pool->set_min_stack_number(0);
global_stack_pool.reset();
}

CASE_TEST(stack_pool_test, gc_once) {
stack_pool_t::ptr_t stack_pool = stack_pool_t::create();
global_stack_pool = stack_pool_t::create();
// gc_once
std::vector<stack_pool_test_task_t::ptr_t> task_arr;
const size_t task_arr_sz = 64;

global_stack_pool->set_auto_gc(false);
global_stack_pool->set_gc_once_number(10);

// alloc
for (size_t i = 0; i < task_arr_sz; ++i) {
stack_pool_test_task_t::ptr_t tp = stack_pool_test_task_t::create(stack_pool_test_task_action);
task_arr.push_back(tp);
}

CASE_EXPECT_EQ(task_arr_sz, global_stack_pool->get_limit().used_stack_number);
CASE_EXPECT_EQ(task_arr_sz * (global_stack_pool->get_stack_size() + global_stack_pool->get_stack_size_offset()),
global_stack_pool->get_limit().used_stack_size);

CASE_EXPECT_EQ(0, global_stack_pool->get_limit().free_stack_number);
CASE_EXPECT_EQ(0, global_stack_pool->get_limit().free_stack_size);

for (size_t i = 0; i < task_arr_sz; ++i) {
task_arr.pop_back();
}

CASE_EXPECT_EQ(0, global_stack_pool->get_limit().used_stack_number);
CASE_EXPECT_EQ(0, global_stack_pool->get_limit().used_stack_size);

CASE_EXPECT_EQ(task_arr_sz, global_stack_pool->get_limit().free_stack_number);
CASE_EXPECT_EQ(task_arr_sz * (global_stack_pool->get_stack_size() + global_stack_pool->get_stack_size_offset()),
global_stack_pool->get_limit().free_stack_size);

global_stack_pool->gc();

CASE_EXPECT_EQ(task_arr_sz - 10, global_stack_pool->get_limit().free_stack_number);
CASE_EXPECT_EQ((task_arr_sz - 10) * (global_stack_pool->get_stack_size() + global_stack_pool->get_stack_size_offset()),
global_stack_pool->get_limit().free_stack_size);

global_stack_pool.reset();
}

CASE_TEST(stack_pool_test, full_size) {
global_stack_pool = stack_pool_t::create();
// full size

std::vector<stack_pool_test_task_t::ptr_t> task_arr;
stack_pool_test_task_t::ptr_t tp1;
stack_pool_test_task_t::ptr_t tp2;

global_stack_pool->set_max_stack_size(128 * 1024);
global_stack_pool->set_stack_size(100 * 1024);
// alloc
tp1 = stack_pool_test_task_t::create(stack_pool_test_task_action);
CASE_EXPECT_TRUE(!!tp1);

tp2 = stack_pool_test_task_t::create(stack_pool_test_task_action);
CASE_EXPECT_TRUE(!tp2);

global_stack_pool.reset();
}

0 comments on commit 3c0b596

Please sign in to comment.