diff options
author | Giovanni Di Sirio <gdisirio@gmail.com> | 2016-03-19 15:09:05 +0000 |
---|---|---|
committer | Giovanni Di Sirio <gdisirio@gmail.com> | 2016-03-19 15:09:05 +0000 |
commit | 20481792013d3b5944f40b2a7208714e3c10b2cf (patch) | |
tree | a4454fb9ca3cd1ead890318ed8c9b6c579c0b2ac /test/nil | |
parent | 590c27ea84385d15797224785e80d2a003df8997 (diff) | |
download | ChibiOS-20481792013d3b5944f40b2a7208714e3c10b2cf.tar.gz ChibiOS-20481792013d3b5944f40b2a7208714e3c10b2cf.tar.bz2 ChibiOS-20481792013d3b5944f40b2a7208714e3c10b2cf.zip |
Heaps tested in NIL.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9140 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'test/nil')
-rw-r--r-- | test/nil/configuration.xml | 244 | ||||
-rw-r--r-- | test/nil/source/test/test_sequence_006.c | 192 |
2 files changed, 418 insertions, 18 deletions
diff --git a/test/nil/configuration.xml b/test/nil/configuration.xml index 2b9fe9cad..bb6fbaf4e 100644 --- a/test/nil/configuration.xml +++ b/test/nil/configuration.xml @@ -10,20 +10,20 @@ <instance locked="false" id="org.chibios.spc5.components.chibios_unitary_tests_engine">
<description>
<copyright>
- <value><![CDATA[/*
- ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
-
- 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.
+ <value><![CDATA[/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + 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. */]]></value>
</copyright>
<introduction>
@@ -1205,7 +1205,11 @@ test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");]]></value> <value>This sequence tests the ChibiOS/NIL functionalities related to memory heaps.</value>
</description>
<shared_code>
- <value />
+ <value><![CDATA[#define ALLOC_SIZE 16 +#define HEAP_SIZE (ALLOC_SIZE * 8) + +static memory_heap_t test_heap; +static CH_HEAP_AREA(myheap, HEAP_SIZE);]]></value>
</shared_code>
<cases>
<case>
@@ -1220,16 +1224,222 @@ test_assert(chPoolAlloc(&mp1) == NULL, "provider returned memory");]]></value> </condition>
<various_code>
<setup_code>
- <value><![CDATA[chHeapObjectInit(&test_heap, test.buffer, sizeof(union test_buffers));]]></value>
+ <value><![CDATA[chHeapObjectInit(&test_heap, myheap, sizeof(myheap));]]></value>
</setup_code>
<teardown_code>
<value />
</teardown_code>
<local_variables>
+ <value><![CDATA[void *p1, *p2, *p3; +size_t n, sz;]]></value>
+ </local_variables>
+ </various_code>
+ <steps>
+ <step>
+ <description>
+ <value>Testing initial conditions, the heap must not be fragmented and one free block present.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[test_assert(chHeapStatus(&test_heap, &sz, NULL) == 1, "heap fragmented");]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Trying to allocate an block bigger than available space, an error is expected.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[p1 = chHeapAlloc(&test_heap, HEAP_SIZE * 2); +test_assert(p1 == NULL, "allocation not failed");]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Single block allocation using chHeapAlloc() then the block is freed using chHeapFree(), must not fail.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); +test_assert(p1 != NULL, "allocation failed"); +chHeapFree(p1);]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Using chHeapStatus() to assess the heap state. There must be at least one free block of sufficient size.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[size_t total_size, largest_size; + +n = chHeapStatus(&test_heap, &total_size, &largest_size); +test_assert(n == 1, "missing free block"); +test_assert(total_size >= ALLOC_SIZE, "unexpected heap state"); +test_assert(total_size == largest_size, "unexpected heap state");]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Allocating then freeing in the same order.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); +p2 = chHeapAlloc(&test_heap, ALLOC_SIZE); +p3 = chHeapAlloc(&test_heap, ALLOC_SIZE); +chHeapFree(p1); /* Does not merge.*/ +chHeapFree(p2); /* Merges backward.*/ +chHeapFree(p3); /* Merges both sides.*/ +test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Allocating then freeing in reverse order.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); +p2 = chHeapAlloc(&test_heap, ALLOC_SIZE); +p3 = chHeapAlloc(&test_heap, ALLOC_SIZE); +chHeapFree(p3); /* Merges forward.*/ +chHeapFree(p2); /* Merges forward.*/ +chHeapFree(p1); /* Merges forward.*/ +test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Small fragments handling. Checking the behavior when allocating blocks with size not multiple of alignment unit.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[p1 = chHeapAlloc(&test_heap, ALLOC_SIZE + 1); +p2 = chHeapAlloc(&test_heap, ALLOC_SIZE); +chHeapFree(p1); +test_assert(chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state"); +p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); +/* Note, the first situation happens when the alignment size is smaller + than the header size, the second in the other cases.*/ +test_assert((chHeapStatus(&test_heap, &n, NULL) == 1) || + (chHeapStatus(&test_heap, &n, NULL) == 2), "heap fragmented"); +chHeapFree(p2); +chHeapFree(p1); +test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Skipping a fragment, the first fragment in the list is too small so the allocator must pick the second one.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); +p2 = chHeapAlloc(&test_heap, ALLOC_SIZE); +chHeapFree(p1); +test_assert( chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state"); +p1 = chHeapAlloc(&test_heap, ALLOC_SIZE * 2); /* Skips first fragment.*/ +chHeapFree(p1); +chHeapFree(p2); +test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Allocating the whole available space.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[(void)chHeapStatus(&test_heap, &n, NULL); +p1 = chHeapAlloc(&test_heap, n); +test_assert(p1 != NULL, "allocation failed"); +test_assert(chHeapStatus(&test_heap, NULL, NULL) == 0, "not empty"); +chHeapFree(p1);]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Testing final conditions. The heap geometry must be the same than the one registered at beginning.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented"); +test_assert(n == sz, "size changed");]]></value>
+ </code>
+ </step>
+ </steps>
+ </case>
+ <case>
+ <brief>
+ <value>Default Heap.</value>
+ </brief>
+ <description>
+ <value>The default heap is pre-allocated in the system. We test base functionality.</value>
+ </description>
+ <condition>
+ <value>CH_CFG_USE_HEAP</value>
+ </condition>
+ <various_code>
+ <setup_code>
<value />
+ </setup_code>
+ <teardown_code>
+ <value />
+ </teardown_code>
+ <local_variables>
+ <value><![CDATA[void *p1;
+size_t total_size, largest_size;]]></value>
</local_variables>
</various_code>
- <steps />
+ <steps>
+ <step>
+ <description>
+ <value>Single block allocation using chHeapAlloc() then the block is freed using chHeapFree(), must not fail.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[(void)chHeapStatus(NULL, &total_size, &largest_size);
+p1 = chHeapAlloc(&test_heap, ALLOC_SIZE); +test_assert(p1 != NULL, "allocation failed"); +chHeapFree(p1);]]></value>
+ </code>
+ </step>
+ <step>
+ <description>
+ <value>Testing allocation failure.</value>
+ </description>
+ <tags>
+ <value />
+ </tags>
+ <code>
+ <value><![CDATA[p1 = chHeapAlloc(NULL, (size_t)-256);
+test_assert(p1 == NULL, "allocation not failed");]]></value>
+ </code>
+ </step>
+ </steps>
</case>
</cases>
</sequence>
diff --git a/test/nil/source/test/test_sequence_006.c b/test/nil/source/test/test_sequence_006.c index fe3e2aaf6..0261f1026 100644 --- a/test/nil/source/test/test_sequence_006.c +++ b/test/nil/source/test/test_sequence_006.c @@ -29,6 +29,7 @@ *
* <h2>Test Cases</h2>
* - @subpage test_006_001
+ * - @subpage test_006_002
* .
*/
@@ -36,6 +37,11 @@ * Shared code.
****************************************************************************/
+#define ALLOC_SIZE 16 +#define HEAP_SIZE (ALLOC_SIZE * 8) + +static memory_heap_t test_heap; +static CH_HEAP_AREA(myheap, HEAP_SIZE);
/****************************************************************************
* Test cases.
@@ -58,13 +64,143 @@ * .
*
* <h2>Test Steps</h2>
+ * - Testing initial conditions, the heap must not be fragmented and
+ * one free block present.
+ * - Trying to allocate an block bigger than available space, an error
+ * is expected.
+ * - Single block allocation using chHeapAlloc() then the block is
+ * freed using chHeapFree(), must not fail.
+ * - Using chHeapStatus() to assess the heap state. There must be at
+ * least one free block of sufficient size.
+ * - Allocating then freeing in the same order.
+ * - Allocating then freeing in reverse order.
+ * - Small fragments handling. Checking the behavior when allocating
+ * blocks with size not multiple of alignment unit.
+ * - Skipping a fragment, the first fragment in the list is too small
+ * so the allocator must pick the second one.
+ * - Allocating the whole available space.
+ * - Testing final conditions. The heap geometry must be the same than
+ * the one registered at beginning.
+ * .
*/
static void test_006_001_setup(void) {
- chHeapObjectInit(&test_heap, test.buffer, sizeof(union test_buffers));
+ chHeapObjectInit(&test_heap, myheap, sizeof(myheap));
}
static void test_006_001_execute(void) {
+ void *p1, *p2, *p3;
+ size_t n, sz;
+
+ /* Testing initial conditions, the heap must not be fragmented and
+ one free block present.*/
+ test_set_step(1);
+ {
+ test_assert(chHeapStatus(&test_heap, &sz, NULL) == 1, "heap fragmented");
+ }
+
+ /* Trying to allocate an block bigger than available space, an error
+ is expected.*/
+ test_set_step(2);
+ {
+ p1 = chHeapAlloc(&test_heap, HEAP_SIZE * 2);
+ test_assert(p1 == NULL, "allocation not failed");
+ }
+
+ /* Single block allocation using chHeapAlloc() then the block is
+ freed using chHeapFree(), must not fail.*/
+ test_set_step(3);
+ {
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ test_assert(p1 != NULL, "allocation failed");
+ chHeapFree(p1);
+ }
+
+ /* Using chHeapStatus() to assess the heap state. There must be at
+ least one free block of sufficient size.*/
+ test_set_step(4);
+ {
+ size_t total_size, largest_size;
+
+ n = chHeapStatus(&test_heap, &total_size, &largest_size);
+ test_assert(n == 1, "missing free block");
+ test_assert(total_size >= ALLOC_SIZE, "unexpected heap state");
+ test_assert(total_size == largest_size, "unexpected heap state");
+ }
+
+ /* Allocating then freeing in the same order.*/
+ test_set_step(5);
+ {
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ p3 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ chHeapFree(p1); /* Does not merge.*/
+ chHeapFree(p2); /* Merges backward.*/
+ chHeapFree(p3); /* Merges both sides.*/
+ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
+ }
+
+ /* Allocating then freeing in reverse order.*/
+ test_set_step(6);
+ {
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ p3 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ chHeapFree(p3); /* Merges forward.*/
+ chHeapFree(p2); /* Merges forward.*/
+ chHeapFree(p1); /* Merges forward.*/
+ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
+ }
+
+ /* Small fragments handling. Checking the behavior when allocating
+ blocks with size not multiple of alignment unit.*/
+ test_set_step(7);
+ {
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE + 1);
+ p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ chHeapFree(p1);
+ test_assert(chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state");
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ /* Note, the first situation happens when the alignment size is smaller
+ than the header size, the second in the other cases.*/
+ test_assert((chHeapStatus(&test_heap, &n, NULL) == 1) ||
+ (chHeapStatus(&test_heap, &n, NULL) == 2), "heap fragmented");
+ chHeapFree(p2);
+ chHeapFree(p1);
+ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
+ }
+
+ /* Skipping a fragment, the first fragment in the list is too small
+ so the allocator must pick the second one.*/
+ test_set_step(8);
+ {
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ p2 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ chHeapFree(p1);
+ test_assert( chHeapStatus(&test_heap, &n, NULL) == 2, "invalid state");
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE * 2); /* Skips first fragment.*/
+ chHeapFree(p1);
+ chHeapFree(p2);
+ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
+ }
+
+ /* Allocating the whole available space.*/
+ test_set_step(9);
+ {
+ (void)chHeapStatus(&test_heap, &n, NULL);
+ p1 = chHeapAlloc(&test_heap, n);
+ test_assert(p1 != NULL, "allocation failed");
+ test_assert(chHeapStatus(&test_heap, NULL, NULL) == 0, "not empty");
+ chHeapFree(p1);
+ }
+
+ /* Testing final conditions. The heap geometry must be the same than
+ the one registered at beginning.*/
+ test_set_step(10);
+ {
+ test_assert(chHeapStatus(&test_heap, &n, NULL) == 1, "heap fragmented");
+ test_assert(n == sz, "size changed");
+ }
}
static const testcase_t test_006_001 = {
@@ -75,6 +211,57 @@ static const testcase_t test_006_001 = { };
#endif /* CH_CFG_USE_HEAP */
+#if CH_CFG_USE_HEAP || defined(__DOXYGEN__)
+/**
+ * @page test_006_002 Default Heap
+ *
+ * <h2>Description</h2>
+ * The default heap is pre-allocated in the system. We test base
+ * functionality.
+ *
+ * <h2>Conditions</h2>
+ * This test is only executed if the following preprocessor condition
+ * evaluates to true:
+ * - CH_CFG_USE_HEAP
+ * .
+ *
+ * <h2>Test Steps</h2>
+ * - Single block allocation using chHeapAlloc() then the block is
+ * freed using chHeapFree(), must not fail.
+ * - Testing allocation failure.
+ * .
+ */
+
+static void test_006_002_execute(void) {
+ void *p1;
+ size_t total_size, largest_size;
+
+ /* Single block allocation using chHeapAlloc() then the block is
+ freed using chHeapFree(), must not fail.*/
+ test_set_step(1);
+ {
+ (void)chHeapStatus(NULL, &total_size, &largest_size);
+ p1 = chHeapAlloc(&test_heap, ALLOC_SIZE);
+ test_assert(p1 != NULL, "allocation failed");
+ chHeapFree(p1);
+ }
+
+ /* Testing allocation failure.*/
+ test_set_step(2);
+ {
+ p1 = chHeapAlloc(NULL, (size_t)-256);
+ test_assert(p1 == NULL, "allocation not failed");
+ }
+}
+
+static const testcase_t test_006_002 = {
+ "Default Heap",
+ NULL,
+ NULL,
+ test_006_002_execute
+};
+#endif /* CH_CFG_USE_HEAP */
+
/****************************************************************************
* Exported data.
****************************************************************************/
@@ -86,5 +273,8 @@ const testcase_t * const test_sequence_006[] = { #if CH_CFG_USE_HEAP || defined(__DOXYGEN__)
&test_006_001,
#endif
+#if CH_CFG_USE_HEAP || defined(__DOXYGEN__)
+ &test_006_002,
+#endif
NULL
};
|