From 61c53373ee8f15e70bf0315b5c78ae9dc423a27d Mon Sep 17 00:00:00 2001 From: Sharron LIU Date: Wed, 28 Dec 2016 11:37:51 +0800 Subject: [PATCH] tests: kernel: added memory pool concept test TestPurpose: verify memory pool concepts. All TESTPOINTs extracted from kernel documentation. https://www.zephyrproject.org/doc/kernel/memory/pools.html#concepts ZEP-1210 Change-Id: I6250e4c26ddf361e74a76c23082cfdb376705560 Signed-off-by: Sharron LIU --- .../mem_pool/test_mpool_concept/Makefile | 4 + .../mem_pool/test_mpool_concept/prj.conf | 1 + .../mem_pool/test_mpool_concept/src/Makefile | 5 + .../mem_pool/test_mpool_concept/src/main.c | 33 +++++ .../test_mpool_concept/src/test_mpool.h | 23 ++++ .../src/test_mpool_alloc_size.c | 47 +++++++ .../src/test_mpool_alloc_wait.c | 126 ++++++++++++++++++ .../src/test_mpool_merge_fail_diff_parent.c | 55 ++++++++ .../src/test_mpool_merge_fail_diff_size.c | 68 ++++++++++ .../mem_pool/test_mpool_concept/testcase.ini | 2 + 10 files changed, 364 insertions(+) create mode 100644 tests/kernel/mem_pool/test_mpool_concept/Makefile create mode 100644 tests/kernel/mem_pool/test_mpool_concept/prj.conf create mode 100644 tests/kernel/mem_pool/test_mpool_concept/src/Makefile create mode 100644 tests/kernel/mem_pool/test_mpool_concept/src/main.c create mode 100644 tests/kernel/mem_pool/test_mpool_concept/src/test_mpool.h create mode 100644 tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_alloc_size.c create mode 100644 tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_alloc_wait.c create mode 100644 tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_merge_fail_diff_parent.c create mode 100644 tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_merge_fail_diff_size.c create mode 100644 tests/kernel/mem_pool/test_mpool_concept/testcase.ini diff --git a/tests/kernel/mem_pool/test_mpool_concept/Makefile b/tests/kernel/mem_pool/test_mpool_concept/Makefile new file mode 100644 index 00000000000..e70a750a88d --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_concept/Makefile @@ -0,0 +1,4 @@ +BOARD ?= qemu_x86 +CONF_FILE = prj.conf + +include ${ZEPHYR_BASE}/Makefile.test diff --git a/tests/kernel/mem_pool/test_mpool_concept/prj.conf b/tests/kernel/mem_pool/test_mpool_concept/prj.conf new file mode 100644 index 00000000000..9467c292689 --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_concept/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/tests/kernel/mem_pool/test_mpool_concept/src/Makefile b/tests/kernel/mem_pool/test_mpool_concept/src/Makefile new file mode 100644 index 00000000000..9b06b259bad --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_concept/src/Makefile @@ -0,0 +1,5 @@ +include $(ZEPHYR_BASE)/tests/Makefile.test + +obj-y = main.o test_mpool_alloc_wait.o test_mpool_alloc_size.o +obj-y += test_mpool_merge_fail_diff_parent.o +obj-y += test_mpool_merge_fail_diff_size.o diff --git a/tests/kernel/mem_pool/test_mpool_concept/src/main.c b/tests/kernel/mem_pool/test_mpool_concept/src/main.c new file mode 100644 index 00000000000..42a0cea77d8 --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_concept/src/main.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +extern void test_mpool_alloc_wait_prio(void); +extern void test_mpool_alloc_size_roundup(void); +extern void test_mpool_alloc_merge_failed_diff_size(void); +extern void test_mpool_alloc_merge_failed_diff_parent(void); + +/*test case main entry*/ +void test_main(void *p1, void *p2, void *p3) +{ + ztest_test_suite(test_mpool_concept, + ztest_unit_test(test_mpool_alloc_wait_prio), + ztest_unit_test(test_mpool_alloc_size_roundup), + ztest_unit_test(test_mpool_alloc_merge_failed_diff_size), + ztest_unit_test(test_mpool_alloc_merge_failed_diff_parent)); + ztest_run_test_suite(test_mpool_concept); +} + diff --git a/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool.h b/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool.h new file mode 100644 index 00000000000..596852bb68c --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define TIMEOUT 2000 +#define STACK_SIZE 512 +#define BLK_SIZE_MIN 4 +#define BLK_SIZE_MAX 16 +#define BLK_NUM_MIN 8 +#define BLK_NUM_MAX 2 +#define BLK_ALIGN BLK_SIZE_MIN diff --git a/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_alloc_size.c b/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_alloc_size.c new file mode 100644 index 00000000000..45b7a55b2e0 --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_alloc_size.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "test_mpool.h" + +#define TEST_SIZE ((BLK_SIZE_MAX>>2)+1) + +extern struct k_mem_pool mpool1; + +/*test cases*/ +void test_mpool_alloc_size_roundup(void) +{ + struct k_mem_block block[BLK_NUM_MAX], block_fail; + + /** + * TESTPOINT: When an application issues a request for a memory block, + * the memory pool first determines the size of the smallest block that + * will satisfy the request + */ + for (int i = 0; i < BLK_NUM_MAX; i++) { + /*request a size for the mpool to round up to "BLK_SIZE_MAX"*/ + assert_true(k_mem_pool_alloc(&mpool1, &block[i], TEST_SIZE, + K_NO_WAIT) == 0, NULL); + } + /*verify consequently no more blocks available*/ + assert_true(k_mem_pool_alloc(&mpool1, &block_fail, BLK_SIZE_MIN, + K_NO_WAIT) == -ENOMEM, NULL); + + /*test case tear down*/ + for (int i = 0; i < BLK_NUM_MAX; i++) { + k_mem_pool_free(&block[i]); + } +} diff --git a/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_alloc_wait.c b/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_alloc_wait.c new file mode 100644 index 00000000000..a6c86186456 --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_alloc_wait.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @addtogroup t_mpool + * @{ + * @defgroup t_mpool_concept test_mpool_concept + * @brief TestPurpose: verify memory pool concepts. + * @details All TESTPOINTs extracted from kernel documentation. + * TESTPOINTs cover testable kernel behaviours that preserve across internal + * implementation change or kernel version change. + * As a black-box test, TESTPOINTs do not cover internal operations. + * + * TESTPOINTs duplicated to are covered in API test: + * - TESTPOINT: ensure that all memory blocks in the buffer are similarly + * aligned to this boundary + * - TESTPOINT: Following a successful allocation, the data field of the block + * descriptor supplied by the thread indicates the starting address of the + * memory block + * - TESTPOINT: memory pool blocks can be recursively partitioned into quarters + * until blocks of the minimum size are obtained + * - TESTPOINT: if a suitable block can’t be created, the allocation request + * fails + * + * TESTPOINTs related to kconfig are covered in kconfig test: + * - TESTPOINT: If the block set does not contain a free block, the memory pool + * attempts to create one automatically by splitting a free block of a larger + * size or by merging free blocks of smaller sizes + * + * TESTPOINTS related to multiple instances are covered in re-entrance test: + * - TESTPOINT: More than one memory pool can be defined, if needed. For + * example, different applications can utilize different memory pools + * @} + */ + +#include +#include "test_mpool.h" + +#define THREAD_NUM 3 +K_MEM_POOL_DEFINE(mpool1, BLK_SIZE_MIN, BLK_SIZE_MAX, BLK_NUM_MAX, BLK_ALIGN); + +static char __noinit __stack tstack[THREAD_NUM][STACK_SIZE]; +static struct k_sem sync_sema; +static struct k_mem_block block_ok; + +/*thread entry*/ +void tmpool_alloc_wait_timeout(void *p1, void *p2, void *p3) +{ + struct k_mem_block block; + + assert_true(k_mem_pool_alloc(&mpool1, &block, BLK_SIZE_MIN, + TIMEOUT) == -EAGAIN, NULL); + k_sem_give(&sync_sema); +} + +void tmpool_alloc_wait_ok(void *p1, void *p2, void *p3) +{ + assert_true(k_mem_pool_alloc(&mpool1, &block_ok, BLK_SIZE_MIN, + TIMEOUT) == 0, NULL); + k_sem_give(&sync_sema); +} + +/*test cases*/ +void test_mpool_alloc_wait_prio(void) +{ + struct k_mem_block block[BLK_NUM_MIN]; + k_tid_t tid[THREAD_NUM]; + + k_sem_init(&sync_sema, 0, THREAD_NUM); + /*allocated up all blocks*/ + for (int i = 0; i < BLK_NUM_MIN; i++) { + assert_true(k_mem_pool_alloc(&mpool1, &block[i], BLK_SIZE_MIN, + K_NO_WAIT) == 0, NULL); + } + + /** + * TESTPOINT: when a suitable memory block becomes available, it is + * given to the highest-priority thread that has waited the longest + */ + /** + * TESTPOINT: If a block of the desired size is unavailable, a thread + * can optionally wait for one to become available + */ + /*the low-priority thread*/ + tid[0] = k_thread_spawn(tstack[0], STACK_SIZE, + tmpool_alloc_wait_timeout, NULL, NULL, NULL, + K_PRIO_PREEMPT(1), 0, 0); + /*the highest-priority thread that has waited the longest*/ + tid[1] = k_thread_spawn(tstack[1], STACK_SIZE, + tmpool_alloc_wait_ok, NULL, NULL, NULL, + K_PRIO_PREEMPT(0), 0, 10); + /*the highest-priority thread that has waited shorter*/ + tid[2] = k_thread_spawn(tstack[2], STACK_SIZE, + tmpool_alloc_wait_timeout, NULL, NULL, NULL, + K_PRIO_PREEMPT(0), 0, 20); + /*relinquish CPU for above threads to start */ + k_sleep(30); + /*free one block, expected to unblock thread "tid[1]"*/ + k_mem_pool_free(&block[0]); + /*wait for all threads exit*/ + for (int i = 0; i < THREAD_NUM; i++) { + k_sem_take(&sync_sema, K_FOREVER); + } + + /*test case tear down*/ + for (int i = 0; i < THREAD_NUM; i++) { + k_thread_abort(tid[i]); + } + k_mem_pool_free(&block_ok); + for (int i = 1; i < BLK_NUM_MIN; i++) { + k_mem_pool_free(&block[i]); + } +} diff --git a/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_merge_fail_diff_parent.c b/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_merge_fail_diff_parent.c new file mode 100644 index 00000000000..2452deee66e --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_merge_fail_diff_parent.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "test_mpool.h" + +extern struct k_mem_pool mpool1; + +/*test cases*/ +void test_mpool_alloc_merge_failed_diff_parent(void) +{ + struct k_mem_block block[BLK_NUM_MIN], block_fail; + + /** + * TESTPOINT: nor can it merge adjacent free blocks of the same + * size if they belong to different parent quad-blocks + * Test steps: 1. allocate block [0~7] in minimum block size + * 2. free block [2~5], belong to diff parental quad-blocks + * 3. request a big block + * verify blocks [2, 3] and blocks [4, 5] can't be merged + * 4. tear down, free blocks [0, 1, 6, 7] + */ + for (int i = 0; i < BLK_NUM_MIN; i++) { + /* 1. allocated up all blocks*/ + assert_true(k_mem_pool_alloc(&mpool1, &block[i], BLK_SIZE_MIN, + K_NO_WAIT) == 0, NULL); + } + /* 2. free adjacent blocks belong to different parent quad-blocks*/ + for (int i = 2; i < 6; i++) { + k_mem_pool_free(&block[i]); + } + /* 3. request a big block, expected failed to merge*/ + k_mem_pool_defrag(&mpool1); + assert_true(k_mem_pool_alloc(&mpool1, &block_fail, BLK_SIZE_MAX, + TIMEOUT) == -EAGAIN, NULL); + + /* 4. test case tear down*/ + k_mem_pool_free(&block[0]); + k_mem_pool_free(&block[1]); + k_mem_pool_free(&block[6]); + k_mem_pool_free(&block[7]); +} diff --git a/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_merge_fail_diff_size.c b/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_merge_fail_diff_size.c new file mode 100644 index 00000000000..dffa2b96fc8 --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_concept/src/test_mpool_merge_fail_diff_size.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#define TIMEOUT 2000 +#define BLK_SIZE_MIN 4 +#define BLK_SIZE_MID 16 +#define BLK_SIZE_MAX 64 +#define BLK_NUM_MIN 32 +#define BLK_NUM_MAX 2 +#define BLK_ALIGN BLK_SIZE_MIN + +K_MEM_POOL_DEFINE(mpool3, BLK_SIZE_MIN, BLK_SIZE_MAX, BLK_NUM_MAX, BLK_ALIGN); + +/*test cases*/ +void test_mpool_alloc_merge_failed_diff_size(void) +{ + struct k_mem_block block[BLK_NUM_MIN], block_fail; + size_t block_size[] = { + BLK_SIZE_MIN, BLK_SIZE_MIN, BLK_SIZE_MIN, BLK_SIZE_MIN, + BLK_SIZE_MID, BLK_SIZE_MID, BLK_SIZE_MID, + BLK_SIZE_MIN, BLK_SIZE_MIN, BLK_SIZE_MIN, BLK_SIZE_MIN, + BLK_SIZE_MID, BLK_SIZE_MID, BLK_SIZE_MID}; + int block_count = sizeof(block_size)/sizeof(size_t); + + /** + * TESTPOINT: the merging algorithm cannot combine adjacent free blocks + * of different sizes + * Test steps: 1. allocate 14 blocks in different sizes + * 2. free block [2~8], in different sizes + * 3. request a big block + * verify blocks [2~8] can't be merged + * 4. tear down, free blocks [0, 1, 9~13] + */ + for (int i = 0; i < block_count; i++) { + /* 1. allocate blocks in different sizes*/ + assert_true(k_mem_pool_alloc(&mpool3, &block[i], block_size[i], + K_NO_WAIT) == 0, NULL); + } + /* 2. free block [2~8], in different sizes*/ + for (int i = 2; i < 9; i++) { + k_mem_pool_free(&block[i]); + } + /* 3. request a big block, expected failed to merge*/ + k_mem_pool_defrag(&mpool3); + assert_true(k_mem_pool_alloc(&mpool3, &block_fail, BLK_SIZE_MAX, + TIMEOUT) == -EAGAIN, NULL); + + /* 4. test case tear down*/ + k_mem_pool_free(&block[0]); + k_mem_pool_free(&block[1]); + for (int i = 9; i < block_count; i++) { + k_mem_pool_free(&block[i]); + } +} diff --git a/tests/kernel/mem_pool/test_mpool_concept/testcase.ini b/tests/kernel/mem_pool/test_mpool_concept/testcase.ini new file mode 100644 index 00000000000..58c4d1a1747 --- /dev/null +++ b/tests/kernel/mem_pool/test_mpool_concept/testcase.ini @@ -0,0 +1,2 @@ +[test] +tags = kernel