On 19/03/2019 06:21, Chris Johns wrote:
On 14/3/19 9:23 pm, Sebastian Huber wrote:
Update #3199.
---
  eng/index.rst          |    3 +
  eng/test-framework.rst | 2077 ++++++++++++++++++++++++++++++++++++++++++++++++
  2 files changed, 2080 insertions(+)
  create mode 100644 eng/test-framework.rst

diff --git a/eng/index.rst b/eng/index.rst
index fe51e91..f29d0f3 100644
--- a/eng/index.rst
+++ b/eng/index.rst
@@ -11,6 +11,8 @@ RTEMS Software Engineering (|version|)
.. topic:: Copyrights and License + | |copy| 2018, 2019 embedded brains GmbH
+    | |copy| 2018, 2019 Sebastian Huber
      | |copy| 1988, 2015 On-Line Applications Research Corporation (OAR)
.. include:: ../common/license.rst
@@ -26,6 +28,7 @@ RTEMS Software Engineering (|version|)
      stakeholders
      management
      test-plan
+    test-framework
      release-mgmt
      users-manuals
      license-requirements
diff --git a/eng/test-framework.rst b/eng/test-framework.rst
new file mode 100644
index 0000000..dda13bc
--- /dev/null
+++ b/eng/test-framework.rst
@@ -0,0 +1,2077 @@
+.. SPDX-License-Identifier: CC-BY-SA-4.0
+
+.. Copyright (C) 2018, 2019 embedded brains GmbH
+.. Copyright (C) 2018, 2019 Sebastian Huber
+
+Software Test Framework
+***********************
+
+.. _TheTTestFramework:
+
+The T Test Framework
+====================
+
+The `T Test Framework` helps to write test suites.  A `test suite` is a
+collection of test cases.  A `test case` consists of individual test actions
+and checks.  A `test check` determines if the outcome of a test action meets
+its expectation.  A `test action` is a program sequence with an observable
+outcome, for example a function invocation with a return status.  If the test
+action outcome is all right, then the test check passes, otherwise the test
+check fails.  The test check failures of a test case are summed up.  A test
+case passes, if the failure count of this test case is zero, otherwise the test
+case fails.  The test suite passes if all test cases pass, otherwise it fails.
I think this needs a little more clarification. The density of that is being
expressed is too compact and I think it requires some expansion. For example
from this I cannot tell where an executable boundary is and given RTEMS has had
'testsuites' I feel expanding and explaining each of these is important in
relationship to what RTEMS has and needs. For example:

   The `T Test Framework` helps to write test suites.  A `test suite` is a
   collection of test cases ......

and then ...

   ... where tests for specific functionality are grouped for example
   `fstests`.

This chapter should just describe the test framework and not an RTEMS specific test suite. This is a different topic. The test framework should enable you to organize your tests one way or another.


Is a test executable a collection of "test cases" or a single case? How is this
decided?

A test executable can contain one or more test suites. Test cases using the T_TEST_CASE() macro are registered via a linker set. However, you can run test cases also individually. See the attached example which contains two test suites. It is a conversion of testsuites/sptests/spsysinit01/init.c. It demonstrates that you can test the system initialization procedure with this framework. How you organize the tests is up to you and a separate topic. The test framework is just a tool to write test cases.


What is the expected number of tests once this SMP qual work ends?

I don't know. I guess it will be similar to the existing test suite. Probably a bit more performance tests.

Is hardware
testing a requirement?

Yes, although thanks to Jiri Gaisler's work we probably don't have to run the tests often on real hardware. We need it for the runtime measurements though.


An outline of the problem domain being addressed would help?

What do you mean with problem domain? From my point of view the problem domain is writing test cases?


Can there please be some explanation of what the issues this framework is
attempt to solve are, what it does well, what it does not do well or is not,
plus things like target requirements, test duration, etc?

Ok, good idea. I will put an overview/features section at the top of the chapter.


I feel if this is done the detail that follows will be just that the detail.

Chris

--
Sebastian Huber, embedded brains GmbH

Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone   : +49 89 189 47 41-16
Fax     : +49 89 189 47 41-09
E-Mail  : sebastian.hu...@embedded-brains.de
PGP     : Public key available on request.

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.

/*
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright (C) 2015, 2018 embedded brains GmbH
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#undef __STRICT_ANSI__

#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>

#include <assert.h>
#include <fcntl.h>
#include <mqueue.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <rtems.h>
#include <rtems/ioimpl.h>
#include <rtems/libio_.h>
#include <rtems/sysinit.h>

#include <rtems/extensionimpl.h>
#include <rtems/posix/barrierimpl.h>
#include <rtems/posix/mqueueimpl.h>
#include <rtems/posix/muteximpl.h>
#ifdef RTEMS_POSIX_API
#include <rtems/posix/psignalimpl.h>
#endif /* RTEMS_POSIX_API */
#include <rtems/posix/pthreadimpl.h>
#include <rtems/posix/rwlockimpl.h>
#include <rtems/posix/semaphoreimpl.h>
#include <rtems/posix/shmimpl.h>
#ifdef RTEMS_POSIX_API
#include <rtems/posix/timerimpl.h>
#endif /* RTEMS_POSIX_API */
#include <rtems/posix/keyimpl.h>
#include <rtems/rtems/barrierimpl.h>
#include <rtems/rtems/dpmemimpl.h>
#include <rtems/rtems/messageimpl.h>
#include <rtems/rtems/partimpl.h>
#include <rtems/rtems/ratemonimpl.h>
#include <rtems/rtems/regionimpl.h>
#include <rtems/rtems/semimpl.h>
#include <rtems/rtems/tasksimpl.h>
#include <rtems/rtems/timerimpl.h>
#include <rtems/score/apimutex.h>
#include <rtems/score/chainimpl.h>
#include <rtems/score/sysstate.h>
#include <rtems/score/userextimpl.h>
#include <rtems/score/wkspace.h>

#include <t.h>

static const T_config sysinit_config = {
	.name = "sysinit",
	.verbosity = T_VERBOSE,
	.now = T_now_dummy
};

static const T_resource_checker resource_checkers[] = {
	T_RESOURCE_FILE_DESCRIPTORS,
	T_RESOURCE_RTEMS_BARRIERS,
	T_RESOURCE_RTEMS_EXTENSIONS,
	T_RESOURCE_RTEMS_MESSAGE_QUEUES,
	T_RESOURCE_RTEMS_PARTITIONS,
	T_RESOURCE_RTEMS_PERIODS,
	T_RESOURCE_RTEMS_REGIONS,
	T_RESOURCE_RTEMS_SEMAPHORES,
	T_RESOURCE_RTEMS_TASKS,
	T_RESOURCE_RTEMS_TIMERS,
	T_RESOURCE_POSIX_KEYS,
	T_RESOURCE_HEAP
};

static const T_config task_config = {
	.name = "task",
	.verbosity = T_VERBOSE,
	.now = T_now_dummy,
	.resource_checker_count = T_ARRAY_SIZE(resource_checkers),
	.resource_checkers = resource_checkers
};

typedef enum {
  BSP_WORK_AREAS_PRE,
  BSP_WORK_AREAS_POST,
  BSP_START_PRE,
  BSP_START_POST,
  CPU_COUNTER_PRE,
  CPU_COUNTER_POST,
  INITIAL_EXTENSIONS_PRE,
  INITIAL_EXTENSIONS_POST,
  DATA_STRUCTURES_PRE,
  DATA_STRUCTURES_POST,
  USER_EXTENSIONS_PRE,
  USER_EXTENSIONS_POST,
  CLASSIC_TASKS_PRE,
  CLASSIC_TASKS_POST,
  CLASSIC_TIMER_PRE,
  CLASSIC_TIMER_POST,
  CLASSIC_SIGNAL_PRE,
  CLASSIC_SIGNAL_POST,
  CLASSIC_EVENT_PRE,
  CLASSIC_EVENT_POST,
  CLASSIC_MESSAGE_QUEUE_PRE,
  CLASSIC_MESSAGE_QUEUE_POST,
  CLASSIC_SEMAPHORE_PRE,
  CLASSIC_SEMAPHORE_POST,
  CLASSIC_PARTITION_PRE,
  CLASSIC_PARTITION_POST,
  CLASSIC_REGION_PRE,
  CLASSIC_REGION_POST,
  CLASSIC_DUAL_PORTED_MEMORY_PRE,
  CLASSIC_DUAL_PORTED_MEMORY_POST,
  CLASSIC_RATE_MONOTONIC_PRE,
  CLASSIC_RATE_MONOTONIC_POST,
  CLASSIC_BARRIER_PRE,
  CLASSIC_BARRIER_POST,
#ifdef RTEMS_POSIX_API
  POSIX_SIGNALS_PRE,
  POSIX_SIGNALS_POST,
#endif /* RTEMS_POSIX_API */
  POSIX_THREADS_PRE,
  POSIX_THREADS_POST,
  POSIX_MESSAGE_QUEUE_PRE,
  POSIX_MESSAGE_QUEUE_POST,
  POSIX_SEMAPHORE_PRE,
  POSIX_SEMAPHORE_POST,
#ifdef RTEMS_POSIX_API
  POSIX_TIMER_PRE,
  POSIX_TIMER_POST,
#endif /* RTEMS_POSIX_API */
  POSIX_SHM_PRE,
  POSIX_SHM_POST,
  POSIX_KEYS_PRE,
  POSIX_KEYS_POST,
  POSIX_CLEANUP_PRE,
  POSIX_CLEANUP_POST,
  IDLE_THREADS_PRE,
  IDLE_THREADS_POST,
  LIBIO_PRE,
  LIBIO_POST,
  ROOT_FILESYSTEM_PRE,
  ROOT_FILESYSTEM_POST,
  BSP_PRE_DRIVERS_PRE,
  BSP_PRE_DRIVERS_POST,
  DEVICE_DRIVERS_PRE,
  DEVICE_DRIVERS_POST,
  CLASSIC_USER_TASKS_PRE,
  CLASSIC_USER_TASKS_POST,
  POSIX_USER_THREADS_PRE,
  POSIX_USER_THREADS_POST,
  STD_FILE_DESCRIPTORS_PRE,
  STD_FILE_DESCRIPTORS_POST,
  LAST_FIRST,
  LAST_SECOND,
  LAST_THIRD,
  LAST_FOURTH,
  LAST_FIFTH,
  LAST_SIXTH,
  LAST_SEVENTH,
  LAST_EIGHTH,
  LAST_NINETH,
  LAST_TENTH,
  LAST_MIDDLE,
  LAST_LAST,
  INIT_TASK,
  DONE
} init_step;

#define FIRST(x) \
  static void x##_first(void); \
  RTEMS_SYSINIT_ITEM( \
    x##_first, \
    x, \
    RTEMS_SYSINIT_ORDER_FIRST \
  ); \
  static void x##_first(void)

#define LAST(x) \
  static void x##_last(void); \
  RTEMS_SYSINIT_ITEM( \
    x##_last, \
    x, \
    RTEMS_SYSINIT_ORDER_LAST \
  ); \
  static void x##_last(void)

#define LAST_STEP(x) \
  static void last_##x(void) \
  { \
    T_eq_int(step(), LAST_##x); \
  } \
  RTEMS_SYSINIT_ITEM( \
    last_##x, \
    RTEMS_SYSINIT_LAST, \
    RTEMS_SYSINIT_ORDER_##x \
  )

static init_step step_counter;

static init_step step(void)
{
  init_step current;

  current = step_counter;
  step_counter = current + 1;
  return current;
}

#define test_obj_info_not_init(info) \
  T_true(_Chain_Is_empty(&(info)->Inactive), "inactive chain not empty")

#define test_inactive_obj(info, e) \
  T_eq_sz(e, _Chain_Node_count_unprotected(&(info)->Inactive))

FIRST(RTEMS_SYSINIT_BSP_WORK_AREAS)
{
  T_eq_ulong(_Workspace_Area.area_begin, 0);
  T_eq_int(step(), BSP_WORK_AREAS_PRE);
}

LAST(RTEMS_SYSINIT_BSP_WORK_AREAS)
{
  T_ne_ulong(_Workspace_Area.area_begin, 0);
  T_eq_int(step(), BSP_WORK_AREAS_POST);
}

FIRST(RTEMS_SYSINIT_BSP_START)
{
  /*
   * Since the work performed here is BSP-specific, there is no way to test pre
   * and post conditions.
   */
  T_eq_int(step(), BSP_START_PRE);
}

LAST(RTEMS_SYSINIT_BSP_START)
{
  /*
   * Some BSPs initialize the printk() support in bsp_start().  So, print begin
   * of test after bsp_start().
   */
  T_run_initialize(&sysinit_config);
  T_case_begin("sysinit", NULL);

  T_eq_int(step(), BSP_START_POST);
}

FIRST(RTEMS_SYSINIT_CPU_COUNTER)
{
  /*
   * Since the work performed here is BSP-specific, there is no way to test pre
   * and post conditions.
   */
  T_eq_int(step(), CPU_COUNTER_PRE);
}

LAST(RTEMS_SYSINIT_CPU_COUNTER)
{
  T_eq_int(step(), CPU_COUNTER_POST);
}

FIRST(RTEMS_SYSINIT_INITIAL_EXTENSIONS)
{
  T_true(_Chain_Is_empty(&_User_extensions_Switches_list), "ext");
  T_eq_int(step(), INITIAL_EXTENSIONS_PRE);
}

LAST(RTEMS_SYSINIT_INITIAL_EXTENSIONS)
{
  T_false(_Chain_Is_empty(&_User_extensions_Switches_list), "ext");
  T_eq_int(step(), INITIAL_EXTENSIONS_POST);
}

FIRST(RTEMS_SYSINIT_DATA_STRUCTURES)
{
  test_obj_info_not_init(&_Thread_Information.Objects)
  T_eq_int(step(), DATA_STRUCTURES_PRE);
}

LAST(RTEMS_SYSINIT_DATA_STRUCTURES)
{
  test_inactive_obj(&_Thread_Information.Objects, 1);
  T_eq_int(step(), DATA_STRUCTURES_POST);
}

FIRST(RTEMS_SYSINIT_USER_EXTENSIONS)
{
  test_obj_info_not_init(&_Extension_Information)
  T_eq_int(step(), USER_EXTENSIONS_PRE);
}

LAST(RTEMS_SYSINIT_USER_EXTENSIONS)
{
  test_inactive_obj(&_Extension_Information, 1);
  T_eq_int(step(), USER_EXTENSIONS_POST);
}

FIRST(RTEMS_SYSINIT_CLASSIC_TASKS)
{
  test_obj_info_not_init(&_RTEMS_tasks_Information.Objects)
  T_eq_int(step(), CLASSIC_TASKS_PRE);
}

LAST(RTEMS_SYSINIT_CLASSIC_TASKS)
{
  test_inactive_obj(&_RTEMS_tasks_Information.Objects, 2);
  T_eq_int(step(), CLASSIC_TASKS_POST);
}

FIRST(RTEMS_SYSINIT_CLASSIC_TIMER)
{
  test_obj_info_not_init(&_Timer_Information)
  T_eq_int(step(), CLASSIC_TIMER_PRE);
}

LAST(RTEMS_SYSINIT_CLASSIC_TIMER)
{
  test_inactive_obj(&_Timer_Information, 1);
  T_eq_int(step(), CLASSIC_TIMER_POST);
}

FIRST(RTEMS_SYSINIT_CLASSIC_SIGNAL)
{
  /* There is nothing to do in case RTEMS_MULTIPROCESSING is not defined */
  T_eq_int(step(), CLASSIC_SIGNAL_PRE);
}

LAST(RTEMS_SYSINIT_CLASSIC_SIGNAL)
{
  T_eq_int(step(), CLASSIC_SIGNAL_POST);
}

FIRST(RTEMS_SYSINIT_CLASSIC_EVENT)
{
  /* There is nothing to do in case RTEMS_MULTIPROCESSING is not defined */
  T_eq_int(step(), CLASSIC_EVENT_PRE);
}

LAST(RTEMS_SYSINIT_CLASSIC_EVENT)
{
  T_eq_int(step(), CLASSIC_EVENT_POST);
}

FIRST(RTEMS_SYSINIT_CLASSIC_MESSAGE_QUEUE)
{
  test_obj_info_not_init(&_Message_queue_Information)
  T_eq_int(step(), CLASSIC_MESSAGE_QUEUE_PRE);
}

LAST(RTEMS_SYSINIT_CLASSIC_MESSAGE_QUEUE)
{
  test_inactive_obj(&_Message_queue_Information, 1);
  T_eq_int(step(), CLASSIC_MESSAGE_QUEUE_POST);
}

FIRST(RTEMS_SYSINIT_CLASSIC_SEMAPHORE)
{
  test_obj_info_not_init(&_Semaphore_Information)
  T_eq_int(step(), CLASSIC_SEMAPHORE_PRE);
}

LAST(RTEMS_SYSINIT_CLASSIC_SEMAPHORE)
{
  test_inactive_obj(&_Semaphore_Information, 1);
  T_eq_int(step(), CLASSIC_SEMAPHORE_POST);
}

FIRST(RTEMS_SYSINIT_CLASSIC_PARTITION)
{
  test_obj_info_not_init(&_Partition_Information)
  T_eq_int(step(), CLASSIC_PARTITION_PRE);
}

LAST(RTEMS_SYSINIT_CLASSIC_PARTITION)
{
  test_inactive_obj(&_Partition_Information, 1);
  T_eq_int(step(), CLASSIC_PARTITION_POST);
}

FIRST(RTEMS_SYSINIT_CLASSIC_REGION)
{
  test_obj_info_not_init(&_Region_Information)
  T_eq_int(step(), CLASSIC_REGION_PRE);
}

LAST(RTEMS_SYSINIT_CLASSIC_REGION)
{
  test_inactive_obj(&_Region_Information, 1);
  T_eq_int(step(), CLASSIC_REGION_POST);
}

FIRST(RTEMS_SYSINIT_CLASSIC_DUAL_PORTED_MEMORY)
{
  test_obj_info_not_init(&_Dual_ported_memory_Information)
  T_eq_int(step(), CLASSIC_DUAL_PORTED_MEMORY_PRE);
}

LAST(RTEMS_SYSINIT_CLASSIC_DUAL_PORTED_MEMORY)
{
  test_inactive_obj(&_Dual_ported_memory_Information, 1);
  T_eq_int(step(), CLASSIC_DUAL_PORTED_MEMORY_POST);
}

FIRST(RTEMS_SYSINIT_CLASSIC_RATE_MONOTONIC)
{
  test_obj_info_not_init(&_Rate_monotonic_Information)
  T_eq_int(step(), CLASSIC_RATE_MONOTONIC_PRE);
}

LAST(RTEMS_SYSINIT_CLASSIC_RATE_MONOTONIC)
{
  test_inactive_obj(&_Rate_monotonic_Information, 1);
  T_eq_int(step(), CLASSIC_RATE_MONOTONIC_POST);
}

FIRST(RTEMS_SYSINIT_CLASSIC_BARRIER)
{
  test_obj_info_not_init(&_Barrier_Information)
  T_eq_int(step(), CLASSIC_BARRIER_PRE);
}

LAST(RTEMS_SYSINIT_CLASSIC_BARRIER)
{
  test_inactive_obj(&_Barrier_Information, 1);
  T_eq_int(step(), CLASSIC_BARRIER_POST);
}

#ifdef RTEMS_POSIX_API
FIRST(RTEMS_SYSINIT_POSIX_SIGNALS)
{
  T_ne_mem(
    &_POSIX_signals_Vectors,
    _POSIX_signals_Default_vectors,
    sizeof(_POSIX_signals_Vectors)
  );
  T_eq_int(step(), POSIX_SIGNALS_PRE);
}

LAST(RTEMS_SYSINIT_POSIX_SIGNALS)
{
  T_eq_mem(
    &_POSIX_signals_Vectors,
    _POSIX_signals_Default_vectors,
    sizeof(_POSIX_signals_Vectors)
  );
  T_eq_int(step(), POSIX_SIGNALS_POST);
}
#endif /* RTEMS_POSIX_API */

FIRST(RTEMS_SYSINIT_POSIX_THREADS)
{
  test_obj_info_not_init(&_POSIX_Threads_Information.Objects)
  T_eq_int(step(), POSIX_THREADS_PRE);
}

LAST(RTEMS_SYSINIT_POSIX_THREADS)
{
  test_inactive_obj(&_POSIX_Threads_Information.Objects, 1);
  T_eq_int(step(), POSIX_THREADS_POST);
}

FIRST(RTEMS_SYSINIT_POSIX_MESSAGE_QUEUE)
{
  test_obj_info_not_init(&_POSIX_Message_queue_Information)
  T_eq_int(step(), POSIX_MESSAGE_QUEUE_PRE);
}

LAST(RTEMS_SYSINIT_POSIX_MESSAGE_QUEUE)
{
  test_inactive_obj(&_POSIX_Message_queue_Information, 1);
  T_eq_int(step(), POSIX_MESSAGE_QUEUE_POST);
}

FIRST(RTEMS_SYSINIT_POSIX_SEMAPHORE)
{
  test_obj_info_not_init(&_POSIX_Semaphore_Information)
  T_eq_int(step(), POSIX_SEMAPHORE_PRE);
}

LAST(RTEMS_SYSINIT_POSIX_SEMAPHORE)
{
  test_inactive_obj(&_POSIX_Semaphore_Information, 1);
  T_eq_int(step(), POSIX_SEMAPHORE_POST);
}

#ifdef RTEMS_POSIX_API
FIRST(RTEMS_SYSINIT_POSIX_TIMER)
{
  test_obj_info_not_init(&_POSIX_Timer_Information)
  T_eq_int(step(), POSIX_TIMER_PRE);
}

LAST(RTEMS_SYSINIT_POSIX_TIMER)
{
  test_inactive_obj(&_POSIX_Timer_Information, 1);
  T_eq_int(step(), POSIX_TIMER_POST);
}
#endif /* RTEMS_POSIX_API */

FIRST(RTEMS_SYSINIT_POSIX_SHM)
{
  test_obj_info_not_init(&_POSIX_Shm_Information)
  T_eq_int(step(), POSIX_SHM_PRE);
}

LAST(RTEMS_SYSINIT_POSIX_SHM)
{
  test_inactive_obj(&_POSIX_Shm_Information, 1);
  T_eq_int(step(), POSIX_SHM_POST);
}

static size_t user_extensions_pre_posix_cleanup;

FIRST(RTEMS_SYSINIT_POSIX_CLEANUP)
{
  user_extensions_pre_posix_cleanup =
    _Chain_Node_count_unprotected(&_User_extensions_List.Active);
  T_eq_int(step(), POSIX_CLEANUP_PRE);
}

LAST(RTEMS_SYSINIT_POSIX_CLEANUP)
{
  T_eq_ulong(
    user_extensions_pre_posix_cleanup + 1,
    _Chain_Node_count_unprotected(&_User_extensions_List.Active)
  );
  T_eq_int(step(), POSIX_CLEANUP_POST);
}

FIRST(RTEMS_SYSINIT_POSIX_KEYS)
{
  test_obj_info_not_init(&_POSIX_Keys_Information)
  T_eq_int(step(), POSIX_KEYS_PRE);
}

LAST(RTEMS_SYSINIT_POSIX_KEYS)
{
  test_inactive_obj(&_POSIX_Keys_Information, 2);
  T_eq_int(step(), POSIX_KEYS_POST);
}

FIRST(RTEMS_SYSINIT_IDLE_THREADS)
{
  T_true(_System_state_Is_before_initialization(_System_state_Get()), "idle");
  T_eq_int(step(), IDLE_THREADS_PRE);
}

LAST(RTEMS_SYSINIT_IDLE_THREADS)
{
  T_true(_System_state_Is_before_multitasking(_System_state_Get()), "idle");
  T_eq_int(step(), IDLE_THREADS_POST);
}

FIRST(RTEMS_SYSINIT_LIBIO)
{
  T_null(rtems_libio_iop_free_head);
  T_eq_int(step(), LIBIO_PRE);
}

LAST(RTEMS_SYSINIT_LIBIO)
{
  T_eq_ptr(rtems_libio_iop_free_head, &rtems_libio_iops[0]);
  T_eq_int(step(), LIBIO_POST);
}

FIRST(RTEMS_SYSINIT_ROOT_FILESYSTEM)
{
  struct stat st;
  int rv;

  errno = 0;
  rv = stat("/", &st);
  T_psx_error(rv, ENXIO);
  T_eq_int(step(), ROOT_FILESYSTEM_PRE);
}

LAST(RTEMS_SYSINIT_ROOT_FILESYSTEM)
{
  struct stat st;
  int rv;

  rv = stat("/", &st);
  T_psx_success(rv);
  T_eq_int(step(), ROOT_FILESYSTEM_POST);
}

FIRST(RTEMS_SYSINIT_BSP_PRE_DRIVERS)
{
  /*
   * Since the work performed here is BSP-specific, there is no way to test pre
   * and post conditions.
   */
  T_eq_int(step(), BSP_PRE_DRIVERS_PRE);
}

LAST(RTEMS_SYSINIT_BSP_PRE_DRIVERS)
{
  T_eq_int(step(), BSP_PRE_DRIVERS_POST);
}

FIRST(RTEMS_SYSINIT_DEVICE_DRIVERS)
{
  T_false(_IO_All_drivers_initialized, "drivers");
  T_eq_int(step(), DEVICE_DRIVERS_PRE);
}

LAST(RTEMS_SYSINIT_DEVICE_DRIVERS)
{
  T_true(_IO_All_drivers_initialized, "drivers");
  T_eq_int(step(), DEVICE_DRIVERS_POST);
}

FIRST(RTEMS_SYSINIT_CLASSIC_USER_TASKS)
{
  _Objects_Allocator_lock();
  T_eq_uint(_Objects_Active_count(&_RTEMS_tasks_Information.Objects), 0);
  _Objects_Allocator_unlock();
  T_eq_int(step(), CLASSIC_USER_TASKS_PRE);
}

LAST(RTEMS_SYSINIT_CLASSIC_USER_TASKS)
{
  _Objects_Allocator_lock();
  T_eq_uint(_Objects_Active_count(&_RTEMS_tasks_Information.Objects), 1);
  _Objects_Allocator_unlock();
  T_eq_int(step(), CLASSIC_USER_TASKS_POST);
}

FIRST(RTEMS_SYSINIT_POSIX_USER_THREADS)
{
  _Objects_Allocator_lock();
  T_eq_uint(_Objects_Active_count(&_POSIX_Threads_Information.Objects), 0);
  _Objects_Allocator_unlock();
  T_eq_int(step(), POSIX_USER_THREADS_PRE);
}

LAST(RTEMS_SYSINIT_POSIX_USER_THREADS)
{
  _Objects_Allocator_lock();
  T_eq_uint(_Objects_Active_count(&_POSIX_Threads_Information.Objects), 1);
  _Objects_Allocator_unlock();
  T_eq_int(step(), POSIX_USER_THREADS_POST);
}

FIRST(RTEMS_SYSINIT_STD_FILE_DESCRIPTORS)
{
  struct stat st;
  int rv;

  errno = 0;
  rv = fstat(0, &st);
  T_psx_error(rv, EBADF);
  T_eq_int(step(), STD_FILE_DESCRIPTORS_PRE);
}

LAST(RTEMS_SYSINIT_STD_FILE_DESCRIPTORS)
{
  struct stat st;
  int rv;

  rv = fstat(0, &st);
  T_psx_success(rv);
  T_eq_int(step(), STD_FILE_DESCRIPTORS_POST);
}

LAST_STEP(FIRST);
LAST_STEP(SECOND);
LAST_STEP(THIRD);
LAST_STEP(FOURTH);
LAST_STEP(FIFTH);
LAST_STEP(SIXTH);
LAST_STEP(SEVENTH);
LAST_STEP(EIGHTH);
LAST_STEP(NINETH);
LAST_STEP(TENTH);
LAST_STEP(MIDDLE);
LAST_STEP(LAST);

T_TEST_CASE(barrier_create)
{
  rtems_status_code sc;
  rtems_id id;

  sc = rtems_barrier_create(
    rtems_build_name('T', 'E', 'S', 'T'),
    RTEMS_DEFAULT_ATTRIBUTES,
    1,
    &id
  );
  T_rsc_success(sc);

  sc = rtems_barrier_delete(id);
  T_rsc_success(sc);
}

T_TEST_CASE(extensions_create)
{
  rtems_status_code sc;
  rtems_id id;
  rtems_extensions_table table;

  memset(&table, 0, sizeof(table));
  sc = rtems_extension_create(
    rtems_build_name('T', 'E', 'S', 'T'),
    &table,
    &id
  );
  T_rsc_success(sc);

  sc = rtems_extension_delete(id);
  T_rsc_success(sc);
}

T_TEST_CASE(message_queue_create)
{
  rtems_status_code sc;
  rtems_id id;

  sc = rtems_message_queue_create(
    rtems_build_name('T', 'E', 'S', 'T'),
    1,
    1,
    RTEMS_DEFAULT_ATTRIBUTES,
    &id
  );
  T_rsc_success(sc);

  sc = rtems_message_queue_delete(id);
  T_rsc_success(sc);
}

T_TEST_CASE(partition_create)
{
  rtems_status_code sc;
  rtems_id id;
  long buf[32];

  sc = rtems_partition_create(
    rtems_build_name('T', 'E', 'S', 'T'),
    buf,
    sizeof(buf),
    sizeof(buf),
    RTEMS_DEFAULT_ATTRIBUTES,
    &id
  );
  T_rsc_success(sc);

  sc = rtems_partition_delete(id);
  T_rsc_success(sc);
}

T_TEST_CASE(period_create)
{
  rtems_status_code sc;
  rtems_id id;

  sc = rtems_rate_monotonic_create(
    rtems_build_name('T', 'E', 'S', 'T'),
    &id
  );
  T_rsc_success(sc);

  sc = rtems_rate_monotonic_delete(id);
  T_rsc_success(sc);
}

T_TEST_CASE(port_create)
{
  rtems_status_code sc;
  rtems_id id;

  sc = rtems_port_create(
    rtems_build_name('T', 'E', 'S', 'T'),
    NULL,
    NULL,
    1,
    &id
  );
  T_rsc_success(sc);

  sc = rtems_port_delete(id);
  T_rsc_success(sc);
}

T_TEST_CASE(region_create)
{
  rtems_status_code sc;
  rtems_id id;
  long buf[32];

  sc = rtems_region_create(
    rtems_build_name('T', 'E', 'S', 'T'),
    buf,
    sizeof(buf),
    1,
    RTEMS_DEFAULT_ATTRIBUTES,
    &id
  );
  T_rsc_success(sc);

  sc = rtems_region_delete(id);
  T_rsc_success(sc);
}

T_TEST_CASE(semaphore_create)
{
  rtems_status_code sc;
  rtems_id id;

  sc = rtems_semaphore_create(
    rtems_build_name('T', 'E', 'S', 'T'),
    0,
    RTEMS_DEFAULT_ATTRIBUTES,
    0,
    &id
  );
  T_rsc_success(sc);

  sc = rtems_semaphore_delete(id);
  T_rsc_success(sc);
}

T_TEST_CASE(task_create)
{
  rtems_status_code sc;
  rtems_id id;

  sc = rtems_task_create(
    rtems_build_name('T', 'E', 'S', 'T'),
    1,
    RTEMS_MINIMUM_STACK_SIZE,
    RTEMS_DEFAULT_MODES,
    RTEMS_DEFAULT_ATTRIBUTES,
    &id
  );
  T_rsc_success(sc);

  sc = rtems_task_delete(id);
  T_rsc_success(sc);
}

T_TEST_CASE(timer_create)
{
  rtems_status_code sc;
  rtems_id id;

  sc = rtems_timer_create(rtems_build_name('T', 'E', 'S', 'T'), &id);
  T_rsc_success(sc);

  sc = rtems_timer_delete(id);
  T_rsc_success(sc);
}

T_TEST_CASE(cleanup_push_pop)
{
  pthread_cleanup_push(NULL, NULL);
  pthread_cleanup_pop(0);
}

T_TEST_CASE(posix_mq_open)
{
  struct mq_attr attr;
  mqd_t mq;
  int rv;

  memset(&attr, 0, sizeof(attr));
  attr.mq_maxmsg = 1;
  attr.mq_msgsize = 1;
  mq = mq_open("mq", O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO, &attr);
  T_ne(mq, (mqd_t) -1, "mq_open failed");

  rv = mq_close(mq);
  T_psx_success(rv);

  rv = mq_unlink("mq");
  T_psx_success(rv);
}

T_TEST_CASE(posix_sem_open)
{
  sem_t *sem;
  int rv;

  sem = sem_open("sem", O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
  T_ne_ptr(sem, SEM_FAILED);

  rv = sem_close(sem);
  T_psx_success(rv);

  rv = sem_unlink("sem");
  T_psx_success(rv);
}

T_TEST_CASE(posix_shm_open)
{
  int fd;
  int rv;

  fd = shm_open("/shm", O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
  T_ge_int(fd, 0);

  rv = close(fd);
  T_psx_success(rv);

  rv = shm_unlink("/shm");
  T_psx_success(rv);
}

#ifdef RTEMS_POSIX_API
T_TEST_CASE(posix_timer_create)
{
  int rv;
  timer_t timer;

  rv = timer_create(CLOCK_REALTIME, NULL, &timer);
  T_psx_success(rv);

  rv = timer_delete(timer);
  T_psx_success(rv);
}
#endif /* RTEMS_POSIX_API */

static void Init(rtems_task_argument arg)
{
  (void) arg;
  pthread_cleanup_push(NULL, NULL);
  pthread_cleanup_pop(0);
  T_eq_int(step(), INIT_TASK);
  T_case_end();
  T_run_finalize();
  T_register();
  T_main(&task_config);
  exit(0);
}

static void *POSIX_Init(void *arg)
{
  (void) arg;
  return NULL;
}

#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER

#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER

#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4

#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1

#define CONFIGURE_MAXIMUM_BARRIERS 1

#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 1

#define CONFIGURE_MAXIMUM_PARTITIONS 1

#define CONFIGURE_MAXIMUM_PERIODS 1

#define CONFIGURE_MAXIMUM_PORTS 1

#define CONFIGURE_MAXIMUM_REGIONS 1

#define CONFIGURE_MAXIMUM_SEMAPHORES 1

#define CONFIGURE_MAXIMUM_TASKS 2

#define CONFIGURE_MAXIMUM_TIMERS 1

#define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES 1

#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 1

#define CONFIGURE_MAXIMUM_POSIX_SHMS 1

#ifdef RTEMS_POSIX_API
#define CONFIGURE_MAXIMUM_POSIX_TIMERS 1
#endif /* RTEMS_POSIX_API */

#define CONFIGURE_MAXIMUM_POSIX_THREADS 1

#define CONFIGURE_POSIX_INIT_THREAD_TABLE

#define CONFIGURE_MAXIMUM_POSIX_KEYS 1

#define CONFIGURE_MESSAGE_BUFFER_MEMORY \
  CONFIGURE_MESSAGE_BUFFERS_FOR_QUEUE(1, 1)

#define CONFIGURE_RTEMS_INIT_TASKS_TABLE

#define CONFIGURE_STACK_CHECKER_ENABLED

#define CONFIGURE_INIT

#include <rtems/confdefs.h>
_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Reply via email to