From f2fdc06c4d8c932ddf84ce1dd76a823a67778034 Mon Sep 17 00:00:00 2001
From: Giovanni Di Sirio <gdisirio@gmail.com>
Date: Fri, 1 Apr 2016 05:08:20 +0000
Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9192
 35acf78f-673a-0410-8e92-d51de3d6d3f4

---
 test/rt/.cproject                       |   2 +-
 test/rt/configuration.xml               | 257 +++++++++++++++++++++++++++++
 test/rt/source/test/test_root.c         |   2 +
 test/rt/source/test/test_root.h         |   2 +
 test/rt/source/test/test_sequence_011.c | 281 ++++++++++++++++++++++++++++++++
 test/rt/source/test/test_sequence_011.h |  17 ++
 test/rt/test.mk                         |   3 +-
 7 files changed, 562 insertions(+), 2 deletions(-)
 create mode 100644 test/rt/source/test/test_sequence_011.c
 create mode 100644 test/rt/source/test/test_sequence_011.h

(limited to 'test')

diff --git a/test/rt/.cproject b/test/rt/.cproject
index e92ac3785..e849ada7d 100644
--- a/test/rt/.cproject
+++ b/test/rt/.cproject
@@ -36,8 +36,8 @@
 						</toolChain>
 					</folderInfo>
 					<sourceEntries>
-						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="components"/>
 						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="source"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="components"/>
 					</sourceEntries>
 				</configuration>
 			</storageModule>
diff --git a/test/rt/configuration.xml b/test/rt/configuration.xml
index cfeff88f4..326e7359d 100644
--- a/test/rt/configuration.xml
+++ b/test/rt/configuration.xml
@@ -76,6 +76,7 @@ union test_buffers {
   uint8_t buffer[WA_SIZE * 5];
 };
 
+extern union test_buffers test;
 extern thread_t *threads[MAX_THREADS];
 extern void * ROMCONST wa[5];
 
@@ -3800,6 +3801,262 @@ test_assert(p1 == NULL, "allocation not failed");]]></value>
               </case>
             </cases>
           </sequence>
+          <sequence>
+            <type index="0">
+              <value>Internal Tests</value>
+            </type>
+            <brief>
+              <value>Dynamic threads.</value>
+            </brief>
+            <description>
+              <value>This module implements the test sequence for the dynamic thread creation APIs.</value>
+            </description>
+            <condition>
+              <value>CH_CFG_USE_DYNAMIC</value>
+            </condition>
+            <shared_code>
+              <value><![CDATA[#if CH_CFG_USE_HEAP
+static memory_heap_t heap1;
+#endif
+#if CH_CFG_USE_MEMPOOLS
+static memory_pool_t mp1;
+#endif
+
+static THD_FUNCTION(dyn_thread1, p) {
+
+  test_emit_token(*(char *)p);
+}]]></value>
+            </shared_code>
+            <cases>
+              <case>
+                <brief>
+                  <value>Threads creation from Memory Heap.</value>
+                </brief>
+                <description>
+                  <value>Two threads are started by allocating the memory from the Memory Heap then the remaining heap space is arbitrarily allocated and a third tread startup is attempted.&lt;br&gt;&#xD;
+The test expects the first two threads to successfully start and the last one to fail.</value>
+                </description>
+                <condition>
+                  <value>CH_CFG_USE_HEAP</value>
+                </condition>
+                <various_code>
+                  <setup_code>
+                    <value><![CDATA[chHeapObjectInit(&heap1, test.buffer, sizeof(union test_buffers));]]></value>
+                  </setup_code>
+                  <teardown_code>
+                    <value />
+                  </teardown_code>
+                  <local_variables>
+                    <value><![CDATA[size_t n1, total1, largest1;
+size_t n2, total2, largest2;
+tprio_t prio;]]></value>
+                  </local_variables>
+                </various_code>
+                <steps>
+                  <step>
+                    <description>
+                      <value>Getting base priority for threads.</value>
+                    </description>
+                    <tags>
+                      <value />
+                    </tags>
+                    <code>
+                      <value><![CDATA[prio = chThdGetPriorityX();]]></value>
+                    </code>
+                  </step>
+                  <step>
+                    <description>
+                      <value>Getting heap info before the test.</value>
+                    </description>
+                    <tags>
+                      <value />
+                    </tags>
+                    <code>
+                      <value><![CDATA[n1 = chHeapStatus(&heap1, &total1, &largest1);
+test_assert(n1 == 1, "heap fragmented");]]></value>
+                    </code>
+                  </step>
+                  <step>
+                    <description>
+                      <value>Creating 1, it is expected to succeed.</value>
+                    </description>
+                    <tags>
+                      <value />
+                    </tags>
+                    <code>
+                      <value><![CDATA[threads[0] = chThdCreateFromHeap(&heap1,
+                                 THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE),
+                                 "dyn1",
+                                 prio-1, dyn_thread1, "A");
+test_assert(threads[0] != NULL, "thread creation failed");]]></value>
+                    </code>
+                  </step>
+                  <step>
+                    <description>
+                      <value>Creating thread 2, it is expected to succeed.</value>
+                    </description>
+                    <tags>
+                      <value />
+                    </tags>
+                    <code>
+                      <value><![CDATA[threads[1] = chThdCreateFromHeap(&heap1,
+                                 THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE),
+                                 "dyn2",
+                                 prio-2, dyn_thread1, "B");
+test_assert(threads[1] != NULL, "thread creation failed");]]></value>
+                    </code>
+                  </step>
+                  <step>
+                    <description>
+                      <value>Creating thread 3, it is expected to fail</value>
+                    </description>
+                    <tags>
+                      <value />
+                    </tags>
+                    <code>
+                      <value><![CDATA[threads[2] = chThdCreateFromHeap(&heap1,
+                                 THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE * 16),
+                                 "dyn3",
+                                 prio-3, dyn_thread1, "C");
+test_assert(threads[2] == NULL, "thread creation not failed");]]></value>
+                    </code>
+                  </step>
+                  <step>
+                    <description>
+                      <value>Letting threads execute then checking the start order and freeing memory.</value>
+                    </description>
+                    <tags>
+                      <value />
+                    </tags>
+                    <code>
+                      <value><![CDATA[test_wait_threads();
+test_assert_sequence("AB", "invalid sequence");]]></value>
+                    </code>
+                  </step>
+                  <step>
+                    <description>
+                      <value>Getting heap info again for verification.</value>
+                    </description>
+                    <tags>
+                      <value />
+                    </tags>
+                    <code>
+                      <value><![CDATA[n2 = chHeapStatus(&heap1, &total2, &largest2);
+test_assert(n1 == n2, "fragmentation changed");
+test_assert(total1 == total2, "total free space changed");
+test_assert(largest1 == largest2, "largest fragment size changed");]]></value>
+                    </code>
+                  </step>
+                </steps>
+              </case>
+              <case>
+                <brief>
+                  <value>Threads creation from Memory Pool.</value>
+                </brief>
+                <description>
+                  <value>Five thread creation are attempted from a pool containing only four elements.&lt;br&gt;&#xD;
+The test expects the first four threads to successfully start and the last one to fail.</value>
+                </description>
+                <condition>
+                  <value>CH_CFG_USE_MEMPOOLS</value>
+                </condition>
+                <various_code>
+                  <setup_code>
+                    <value><![CDATA[chPoolObjectInit(&mp1, THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE), NULL);]]></value>
+                  </setup_code>
+                  <teardown_code>
+                    <value />
+                  </teardown_code>
+                  <local_variables>
+                    <value><![CDATA[unsigned i;
+tprio_t prio;]]></value>
+                  </local_variables>
+                </various_code>
+                <steps>
+                  <step>
+                    <description>
+                      <value>Adding four working areas to the pool.</value>
+                    </description>
+                    <tags>
+                      <value />
+                    </tags>
+                    <code>
+                      <value><![CDATA[for (i = 0; i < 4; i++)
+  chPoolFree(&mp1, wa[i]);]]></value>
+                    </code>
+                  </step>
+                  <step>
+                    <description>
+                      <value>Getting base priority for threads.</value>
+                    </description>
+                    <tags>
+                      <value />
+                    </tags>
+                    <code>
+                      <value><![CDATA[prio = chThdGetPriorityX();]]></value>
+                    </code>
+                  </step>
+                  <step>
+                    <description>
+                      <value>Creating the five threads.</value>
+                    </description>
+                    <tags>
+                      <value />
+                    </tags>
+                    <code>
+                      <value><![CDATA[threads[0] = chThdCreateFromMemoryPool(&mp1, "dyn1", prio-1, dyn_thread1, "A");
+threads[1] = chThdCreateFromMemoryPool(&mp1, "dyn2", prio-2, dyn_thread1, "B");
+threads[2] = chThdCreateFromMemoryPool(&mp1, "dyn3", prio-3, dyn_thread1, "C");
+threads[3] = chThdCreateFromMemoryPool(&mp1, "dyn4", prio-4, dyn_thread1, "D");
+threads[4] = chThdCreateFromMemoryPool(&mp1, "dyn5", prio-5, dyn_thread1, "E");]]></value>
+                    </code>
+                  </step>
+                  <step>
+                    <description>
+                      <value>Testing that only the fifth thread creation failed.</value>
+                    </description>
+                    <tags>
+                      <value />
+                    </tags>
+                    <code>
+                      <value><![CDATA[test_assert((threads[0] != NULL) &&
+            (threads[1] != NULL) &&
+            (threads[2] != NULL) &&
+            (threads[3] != NULL),
+            "thread creation failed");
+test_assert(threads[4] == NULL,
+            "thread creation not failed");]]></value>
+                    </code>
+                  </step>
+                  <step>
+                    <description>
+                      <value>Letting them run, free the memory then checking the execution sequence.</value>
+                    </description>
+                    <tags>
+                      <value />
+                    </tags>
+                    <code>
+                      <value><![CDATA[test_wait_threads();
+test_assert_sequence("ABCD", "invalid sequence");]]></value>
+                    </code>
+                  </step>
+                  <step>
+                    <description>
+                      <value>Testing that the pool contains four elements again.</value>
+                    </description>
+                    <tags>
+                      <value />
+                    </tags>
+                    <code>
+                      <value><![CDATA[for (i = 0; i < 4; i++)
+  test_assert(chPoolAlloc(&mp1) != NULL, "pool list empty");
+test_assert(chPoolAlloc(&mp1) == NULL, "pool list not empty");]]></value>
+                    </code>
+                  </step>
+                </steps>
+              </case>
+            </cases>
+          </sequence>
         </sequences>
       </instance>
     </instances>
diff --git a/test/rt/source/test/test_root.c b/test/rt/source/test/test_root.c
index 9ecbd3dea..fe8f096c8 100644
--- a/test/rt/source/test/test_root.c
+++ b/test/rt/source/test/test_root.c
@@ -31,6 +31,7 @@
  * - @subpage test_sequence_008
  * - @subpage test_sequence_009
  * - @subpage test_sequence_010
+ * - @subpage test_sequence_011
  * .
  */
 
@@ -63,6 +64,7 @@ const testcase_t * const *test_suite[] = {
   test_sequence_008,
   test_sequence_009,
   test_sequence_010,
+  test_sequence_011,
   NULL
 };
 
diff --git a/test/rt/source/test/test_root.h b/test/rt/source/test/test_root.h
index 6bbb1c989..e0e439eff 100644
--- a/test/rt/source/test/test_root.h
+++ b/test/rt/source/test/test_root.h
@@ -32,6 +32,7 @@
 #include "test_sequence_008.h"
 #include "test_sequence_009.h"
 #include "test_sequence_010.h"
+#include "test_sequence_011.h"
 
 #if !defined(__DOXYGEN__)
 
@@ -96,6 +97,7 @@ union test_buffers {
   uint8_t buffer[WA_SIZE * 5];
 };
 
+extern union test_buffers test;
 extern thread_t *threads[MAX_THREADS];
 extern void * ROMCONST wa[5];
 
diff --git a/test/rt/source/test/test_sequence_011.c b/test/rt/source/test/test_sequence_011.c
new file mode 100644
index 000000000..0f1ac7b21
--- /dev/null
+++ b/test/rt/source/test/test_sequence_011.c
@@ -0,0 +1,281 @@
+/*
+    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.
+*/
+
+#include "hal.h"
+#include "ch_test.h"
+#include "test_root.h"
+
+/**
+ * @page test_sequence_011 [11] Dynamic threads
+ *
+ * File: @ref test_sequence_011.c
+ *
+ * <h2>Description</h2>
+ * This module implements the test sequence for the dynamic thread
+ * creation APIs.
+ *
+ * <h2>Conditions</h2>
+ * This sequence is only executed if the following preprocessor condition
+ * evaluates to true:
+ * - CH_CFG_USE_DYNAMIC
+ * .
+ *
+ * <h2>Test Cases</h2>
+ * - @subpage test_011_001
+ * - @subpage test_011_002
+ * .
+ */
+
+#if (CH_CFG_USE_DYNAMIC) || defined(__DOXYGEN__)
+
+/****************************************************************************
+ * Shared code.
+ ****************************************************************************/
+
+#if CH_CFG_USE_HEAP
+static memory_heap_t heap1;
+#endif
+#if CH_CFG_USE_MEMPOOLS
+static memory_pool_t mp1;
+#endif
+
+static THD_FUNCTION(dyn_thread1, p) {
+
+  test_emit_token(*(char *)p);
+}
+
+/****************************************************************************
+ * Test cases.
+ ****************************************************************************/
+
+#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__)
+/**
+ * @page test_011_001 [11.1] Threads creation from Memory Heap
+ *
+ * <h2>Description</h2>
+ * Two threads are started by allocating the memory from the Memory
+ * Heap then the remaining heap space is arbitrarily allocated and a
+ * third tread startup is attempted.<br> The test expects the first two
+ * threads to successfully start and the last one to fail.
+ *
+ * <h2>Conditions</h2>
+ * This test is only executed if the following preprocessor condition
+ * evaluates to true:
+ * - CH_CFG_USE_HEAP
+ * .
+ *
+ * <h2>Test Steps</h2>
+ * - [11.1.1] Getting base priority for threads.
+ * - [11.1.2] Getting heap info before the test.
+ * - [11.1.3] Creating 1, it is expected to succeed.
+ * - [11.1.4] Creating thread 2, it is expected to succeed.
+ * - [11.1.5] Creating thread 3, it is expected to fail.
+ * - [11.1.6] Letting threads execute then checking the start order and
+ *   freeing memory.
+ * - [11.1.7] Getting heap info again for verification.
+ * .
+ */
+
+static void test_011_001_setup(void) {
+  chHeapObjectInit(&heap1, test.buffer, sizeof(union test_buffers));
+}
+
+static void test_011_001_execute(void) {
+  size_t n1, total1, largest1;
+  size_t n2, total2, largest2;
+  tprio_t prio;
+
+  /* [11.1.1] Getting base priority for threads.*/
+  test_set_step(1);
+  {
+    prio = chThdGetPriorityX();
+  }
+
+  /* [11.1.2] Getting heap info before the test.*/
+  test_set_step(2);
+  {
+    n1 = chHeapStatus(&heap1, &total1, &largest1);
+    test_assert(n1 == 1, "heap fragmented");
+  }
+
+  /* [11.1.3] Creating 1, it is expected to succeed.*/
+  test_set_step(3);
+  {
+    threads[0] = chThdCreateFromHeap(&heap1,
+                                     THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE),
+                                     "dyn1",
+                                     prio-1, dyn_thread1, "A");
+    test_assert(threads[0] != NULL, "thread creation failed");
+  }
+
+  /* [11.1.4] Creating thread 2, it is expected to succeed.*/
+  test_set_step(4);
+  {
+    threads[1] = chThdCreateFromHeap(&heap1,
+                                     THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE),
+                                     "dyn2",
+                                     prio-2, dyn_thread1, "B");
+    test_assert(threads[1] != NULL, "thread creation failed");
+  }
+
+  /* [11.1.5] Creating thread 3, it is expected to fail.*/
+  test_set_step(5);
+  {
+    threads[2] = chThdCreateFromHeap(&heap1,
+                                     THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE * 16),
+                                     "dyn3",
+                                     prio-3, dyn_thread1, "C");
+    test_assert(threads[2] == NULL, "thread creation not failed");
+  }
+
+  /* [11.1.6] Letting threads execute then checking the start order and
+     freeing memory.*/
+  test_set_step(6);
+  {
+    test_wait_threads();
+    test_assert_sequence("AB", "invalid sequence");
+  }
+
+  /* [11.1.7] Getting heap info again for verification.*/
+  test_set_step(7);
+  {
+    n2 = chHeapStatus(&heap1, &total2, &largest2);
+    test_assert(n1 == n2, "fragmentation changed");
+    test_assert(total1 == total2, "total free space changed");
+    test_assert(largest1 == largest2, "largest fragment size changed");
+  }
+}
+
+static const testcase_t test_011_001 = {
+  "Threads creation from Memory Heap",
+  test_011_001_setup,
+  NULL,
+  test_011_001_execute
+};
+#endif /* CH_CFG_USE_HEAP */
+
+#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
+/**
+ * @page test_011_002 [11.2] Threads creation from Memory Pool
+ *
+ * <h2>Description</h2>
+ * Five thread creation are attempted from a pool containing only four
+ * elements.<br> The test expects the first four threads to
+ * successfully start and the last one to fail.
+ *
+ * <h2>Conditions</h2>
+ * This test is only executed if the following preprocessor condition
+ * evaluates to true:
+ * - CH_CFG_USE_MEMPOOLS
+ * .
+ *
+ * <h2>Test Steps</h2>
+ * - [11.2.1] Adding four working areas to the pool.
+ * - [11.2.2] Getting base priority for threads.
+ * - [11.2.3] Creating the five threads.
+ * - [11.2.4] Testing that only the fifth thread creation failed.
+ * - [11.2.5] Letting them run, free the memory then checking the
+ *   execution sequence.
+ * - [11.2.6] Testing that the pool contains four elements again.
+ * .
+ */
+
+static void test_011_002_setup(void) {
+  chPoolObjectInit(&mp1, THD_WORKING_AREA_SIZE(THREADS_STACK_SIZE), NULL);
+}
+
+static void test_011_002_execute(void) {
+  unsigned i;
+  tprio_t prio;
+
+  /* [11.2.1] Adding four working areas to the pool.*/
+  test_set_step(1);
+  {
+    for (i = 0; i < 4; i++)
+      chPoolFree(&mp1, wa[i]);
+  }
+
+  /* [11.2.2] Getting base priority for threads.*/
+  test_set_step(2);
+  {
+    prio = chThdGetPriorityX();
+  }
+
+  /* [11.2.3] Creating the five threads.*/
+  test_set_step(3);
+  {
+    threads[0] = chThdCreateFromMemoryPool(&mp1, "dyn1", prio-1, dyn_thread1, "A");
+    threads[1] = chThdCreateFromMemoryPool(&mp1, "dyn2", prio-2, dyn_thread1, "B");
+    threads[2] = chThdCreateFromMemoryPool(&mp1, "dyn3", prio-3, dyn_thread1, "C");
+    threads[3] = chThdCreateFromMemoryPool(&mp1, "dyn4", prio-4, dyn_thread1, "D");
+    threads[4] = chThdCreateFromMemoryPool(&mp1, "dyn5", prio-5, dyn_thread1, "E");
+  }
+
+  /* [11.2.4] Testing that only the fifth thread creation failed.*/
+  test_set_step(4);
+  {
+    test_assert((threads[0] != NULL) &&
+                (threads[1] != NULL) &&
+                (threads[2] != NULL) &&
+                (threads[3] != NULL),
+                "thread creation failed");
+    test_assert(threads[4] == NULL,
+                "thread creation not failed");
+  }
+
+  /* [11.2.5] Letting them run, free the memory then checking the
+     execution sequence.*/
+  test_set_step(5);
+  {
+    test_wait_threads();
+    test_assert_sequence("ABCD", "invalid sequence");
+  }
+
+  /* [11.2.6] Testing that the pool contains four elements again.*/
+  test_set_step(6);
+  {
+    for (i = 0; i < 4; i++)
+      test_assert(chPoolAlloc(&mp1) != NULL, "pool list empty");
+    test_assert(chPoolAlloc(&mp1) == NULL, "pool list not empty");
+  }
+}
+
+static const testcase_t test_011_002 = {
+  "Threads creation from Memory Pool",
+  test_011_002_setup,
+  NULL,
+  test_011_002_execute
+};
+#endif /* CH_CFG_USE_MEMPOOLS */
+
+/****************************************************************************
+ * Exported data.
+ ****************************************************************************/
+
+/**
+ * @brief   Dynamic threads.
+ */
+const testcase_t * const test_sequence_011[] = {
+#if (CH_CFG_USE_HEAP) || defined(__DOXYGEN__)
+  &test_011_001,
+#endif
+#if (CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
+  &test_011_002,
+#endif
+  NULL
+};
+
+#endif /* CH_CFG_USE_DYNAMIC */
diff --git a/test/rt/source/test/test_sequence_011.h b/test/rt/source/test/test_sequence_011.h
new file mode 100644
index 000000000..8d865a9f0
--- /dev/null
+++ b/test/rt/source/test/test_sequence_011.h
@@ -0,0 +1,17 @@
+/*
+    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.
+*/
+
+extern const testcase_t * const test_sequence_011[];
diff --git a/test/rt/test.mk b/test/rt/test.mk
index 2afe2ce8d..b47ad6658 100644
--- a/test/rt/test.mk
+++ b/test/rt/test.mk
@@ -10,7 +10,8 @@ TESTSRC = ${CHIBIOS}/test/lib/ch_test.c \
           ${CHIBIOS}/test/rt/source/test/test_sequence_007.c \
           ${CHIBIOS}/test/rt/source/test/test_sequence_008.c \
           ${CHIBIOS}/test/rt/source/test/test_sequence_009.c \
-          ${CHIBIOS}/test/rt/source/test/test_sequence_010.c
+          ${CHIBIOS}/test/rt/source/test/test_sequence_010.c \
+          ${CHIBIOS}/test/rt/source/test/test_sequence_011.c
 
 # Required include directories
 TESTINC = ${CHIBIOS}/test/lib \
-- 
cgit v1.2.3