On 24/06/2020 02:48, Chris Johns wrote:
On 19/6/20 11:38 pm, Sebastian Huber wrote:
the qualification toolchain in
https://git.rtems.org/sebh/rtems-qual.git/
needs a bit of documentation. For a start, I propose to add it to the
RTEMS Software Engineering manual.
Does this mean adding references to that repo?
Yes, I already added a how-to section for the glossary of terms:
https://docs.rtems.org/branches/master/eng/req/howto.html
I am not comfortable with the name of the repo and documenting a
personal repo is something we should avoid.
Yes, the name is not great. I think your proposal to name it
rtems-central was a bit better. Another option is rtems-spec.
I see the name rtems-qual.git as the project or outcome name that is
currently undersay and not what it is. If a core developer does not
need to use this repo to maintain RTEMS and that work can be qualified
what role does it perform? If it is simpler and easier for a core
developer to use this repo then this is not about qualification it is
about development of RTEMS that can be qualified.
I would like to understand the intended workflow for this repo. Is
something we should promote as the developer workflow? If so we should
consider embracing this. For example the glossary generation. Editing
by hand the generated output does not make sense to me.
The stuff in this repository is already somewhat useful to maintain
RTEMS. You can generate the glossary of terms for individual documents
from a shared collection of terms. In the RTEMS Classic API Guide the
project-wide glossary is located, other documents only include the terms
they use in their glossary. All the application configuration options
are available as specification items:
https://docs.rtems.org/branches/master/eng/req/items.html#spectypeapplicationconfigurationoptionitemtype
All the sections about application configuration options in the RTEMS
Classic API Guide are generated from them. With a bit of work, we could
also generate pages for the Doxygen documentation. The tool chain
supports context-sensitive substitution. In the specification a
${uid:attribute/path} syntax is used. For example:
* The ${../attr/multiprocessor-resource-sharing:/name} attribute
selects the
MrsP locking protocol in SMP configurations, otherwise it selects the
priority ceiling protocol. For this locking protocol a priority
ceiling
shall be specified in ``${.:/params[3]/name}``. This priority is
used to set
the priority ceiling in all scheduler instances. This can be
changed later
with the ${set-priority:/name} directive using the returned semaphore
identifier.
In the Sphinx output this is transformed to:
* The RTEMS_MULTIPROCESSOR_RESOURCE_SHARING attribute selects the MrsP
locking protocol in SMP configurations, otherwise it selects the
priority
ceiling protocol. For this locking protocol a priority ceiling
shall be
specified in ``priority_ceiling``. This priority is used to set the
priority ceiling in all scheduler instances. This can be changed
later
with the :ref:`rtems_semaphore_set_priority()
<InterfaceRtemsSemaphoreSetPriority>` directive using the returned
semaphore identifier.
In the Doxygen output this is transformed to:
* * The #RTEMS_MULTIPROCESSOR_RESOURCE_SHARING attribute selects the MrsP
* locking protocol in SMP configurations, otherwise it selects the
priority
* ceiling protocol. For this locking protocol a priority ceiling
shall be
* specified in ``priority_ceiling``. This priority is used to set the
* priority ceiling in all scheduler instances. This can be changed
later
* with the rtems_semaphore_set_priority() directive using the returned
* semaphore identifier.
I work currently on a complete specification of the RTEMS Classic API.
The tool chain has also support for test plan and code generation. I
plan to specify the functionality of the RTEMS directives through so
called action requirements:
https://docs.rtems.org/branches/master/eng/req/items.html#spectypeactionrequirementitemtype
This can be used to generate table based test loops to check all states
of pre-conditions and post-conditions (see attached file).
I have a concern about the long term maintenance of a git repo of git
repos. I know of a project that have developed tools to handle
something like this because it is hard to do manually. Maybe we should
find out more about this.
Which long term maintenance issues do you see? Working with Git
submodules can be a bit annoying, however, the rate of change will not
be that high in this project.
/* SPDX-License-Identifier: BSD-2-Clause */
/**
* @file
*
* @ingroup RTEMSTestCaseClassicTaskIdentification
*/
/*
* Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <rtems.h>
#include <t.h>
/**
* @defgroup RTEMSTestCaseClassicTaskIdentification Classic Task Identification
*
* @ingroup RTEMSTestSuiteSpaceProfile
*
* @brief Test Case
*
* @{
*/
typedef enum {
ClassicTaskIdentification_Pre_Name_Invalid,
ClassicTaskIdentification_Pre_Name_Self,
ClassicTaskIdentification_Pre_Name_Valid
} ClassicTaskIdentification_Pre_Name;
typedef enum {
ClassicTaskIdentification_Pre_Node_Local,
ClassicTaskIdentification_Pre_Node_Remote,
ClassicTaskIdentification_Pre_Node_Invalid,
ClassicTaskIdentification_Pre_Node_SearchAll,
ClassicTaskIdentification_Pre_Node_SearchOther,
ClassicTaskIdentification_Pre_Node_SearchLocal
} ClassicTaskIdentification_Pre_Node;
typedef enum {
ClassicTaskIdentification_Pre_Id_NullPtr,
ClassicTaskIdentification_Pre_Id_Valid
} ClassicTaskIdentification_Pre_Id;
typedef enum {
ClassicTaskIdentification_Post_Status_Ok,
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Status_InvName,
ClassicTaskIdentification_Post_Status_InvNode,
ClassicTaskIdentification_Post_Status_InvId
} ClassicTaskIdentification_Post_Status;
typedef enum {
ClassicTaskIdentification_Post_Id_Nop,
ClassicTaskIdentification_Post_Id_NullPtr,
ClassicTaskIdentification_Post_Id_Self,
ClassicTaskIdentification_Post_Id_LocalTask,
ClassicTaskIdentification_Post_Id_RemoteTask
} ClassicTaskIdentification_Post_Id;
/**
* @brief Test context for Classic Task Identification test case.
*/
typedef struct {
/**
* @brief Brief context member description.
*
* Context member description.
*/
rtems_status_code status;
rtems_name name;
uint32_t node;
rtems_id *id;
rtems_id id_value;
rtems_id id_local_task;
rtems_id id_remote_task;
/**
* @brief This member defines the pre-condition states for the next action.
*/
size_t pcs[ 3 ];
/**
* @brief This member indicates if the test action loop is currently
* executed.
*/
bool in_action_loop;
} ClassicTaskIdentification_Context;
static ClassicTaskIdentification_Context
ClassicTaskIdentification_Instance;
static const char * const ClassicTaskIdentification_PreDesc_Name[] = {
"Invalid",
"Self",
"Valid"
};
static const char * const ClassicTaskIdentification_PreDesc_Node[] = {
"Local",
"Remote",
"Invalid",
"SearchAll",
"SearchOther",
"SearchLocal"
};
static const char * const ClassicTaskIdentification_PreDesc_Id[] = {
"NullPtr",
"Valid"
};
static const char * const * const ClassicTaskIdentification_PreDesc[] = {
ClassicTaskIdentification_PreDesc_Name,
ClassicTaskIdentification_PreDesc_Node,
ClassicTaskIdentification_PreDesc_Id
};
/* Test rtems_task_ident() support */
static void ClassicTaskIdentification_Pre_Name_Prepare(
ClassicTaskIdentification_Context *ctx,
ClassicTaskIdentification_Pre_Name state
)
{
/* Prologue */
switch ( state ) {
case ClassicTaskIdentification_Pre_Name_Invalid: {
ctx->name = 1;
break;
}
case ClassicTaskIdentification_Pre_Name_Self: {
ctx->name = RTEMS_SELF;
break;
}
case ClassicTaskIdentification_Pre_Name_Valid: {
ctx->name = rtems_build_name( 'T', 'A', 'S', 'K' );
break;
}
}
/* Epilogue */
}
static void ClassicTaskIdentification_Pre_Node_Prepare(
ClassicTaskIdentification_Context *ctx,
ClassicTaskIdentification_Pre_Node state
)
{
switch ( state ) {
case ClassicTaskIdentification_Pre_Node_Local: {
ctx->node = 1;
break;
}
case ClassicTaskIdentification_Pre_Node_Remote: {
ctx->node = 2;
break;
}
case ClassicTaskIdentification_Pre_Node_Invalid: {
ctx->node = 256;
break;
}
case ClassicTaskIdentification_Pre_Node_SearchAll: {
ctx->node = RTEMS_SEARCH_ALL_NODES;
break;
}
case ClassicTaskIdentification_Pre_Node_SearchOther: {
ctx->node = RTEMS_SEARCH_OTHER_NODES;
break;
}
case ClassicTaskIdentification_Pre_Node_SearchLocal: {
ctx->node = RTEMS_SEARCH_LOCAL_NODE;
break;
}
}
}
static void ClassicTaskIdentification_Pre_Id_Prepare(
ClassicTaskIdentification_Context *ctx,
ClassicTaskIdentification_Pre_Id state
)
{
switch ( state ) {
case ClassicTaskIdentification_Pre_Id_NullPtr: {
ctx->id = NULL;
break;
}
case ClassicTaskIdentification_Pre_Id_Valid: {
ctx->id_value = 0xffffffff;
ctx->id = &ctx->id_value;
break;
}
}
}
static void ClassicTaskIdentification_Post_Status_Check(
ClassicTaskIdentification_Context *ctx,
ClassicTaskIdentification_Post_Status state
)
{
switch ( state ) {
case ClassicTaskIdentification_Post_Status_Ok: {
T_rsc(ctx->status, RTEMS_SUCCESSFUL);
break;
}
case ClassicTaskIdentification_Post_Status_InvAddr: {
T_rsc(ctx->status, RTEMS_INVALID_ADDRESS);
break;
}
case ClassicTaskIdentification_Post_Status_InvName: {
T_rsc(ctx->status, RTEMS_INVALID_NAME);
break;
}
case ClassicTaskIdentification_Post_Status_InvNode: {
T_rsc(ctx->status, RTEMS_INVALID_NODE);
break;
}
case ClassicTaskIdentification_Post_Status_InvId: {
T_rsc(ctx->status, RTEMS_INVALID_ID);
break;
}
}
}
static void ClassicTaskIdentification_Post_Id_Check(
ClassicTaskIdentification_Context *ctx,
ClassicTaskIdentification_Post_Id state
)
{
switch ( state ) {
case ClassicTaskIdentification_Post_Id_Nop: {
T_eq_ptr(ctx->id, &ctx->id_value);
T_eq_u32(ctx->id_value, 0xffffffff);
break;
}
case ClassicTaskIdentification_Post_Id_NullPtr: {
T_null(ctx->id)
break;
}
case ClassicTaskIdentification_Post_Id_Self: {
T_eq_ptr(ctx->id, &ctx->id_value);
T_eq_u32(ctx->id_value, rtems_task_self());
break;
}
case ClassicTaskIdentification_Post_Id_LocalTask: {
T_eq_ptr(ctx->id, &ctx->id_value);
T_eq_u32(ctx->id_value, ctx->id_local_task);
break;
}
case ClassicTaskIdentification_Post_Id_RemoteTask: {
T_eq_ptr(ctx->id, &ctx->id_value);
T_eq_u32(ctx->id_value, ctx->id_remote_task);
break;
}
}
}
/**
* @brief Setup brief description.
*
* Setup description.
*/
static void ClassicTaskIdentification_Setup(
ClassicTaskIdentification_Context *ctx
)
{
static char task_storage[ RTEMS_MINIMUM_STACK_SIZE ];
static const rtems_task_config task_config = {
.name = rtems_build_name( 'T', 'A', 'S', 'K' ),
.initial_priority = 1,
.stack_area = task_storage,
.stack_size = sizeof( task_storage ),
.initial_modes = RTEMS_DEFAULT_MODES,
.attribute_set = RTEMS_DEFAULT_ATTRIBUTES
};
rtems_status_code sc;
sc = rtems_task_build( &task_config, &ctx->id_local_task );
T_assert_rsc_success( sc );
}
static void ClassicTaskIdentification_Setup_Wrap( void *arg )
{
ClassicTaskIdentification_Context *ctx;
ctx = arg;
ctx->in_action_loop = false;
ClassicTaskIdentification_Setup( ctx );
}
static void ClassicTaskIdentification_Scope( void *arg, char *buf, size_t n )
{
ClassicTaskIdentification_Context *ctx;
size_t i;
ctx = arg;
if ( !ctx->in_action_loop ) {
return;
}
for (
i = 0;
i < RTEMS_ARRAY_SIZE( ClassicTaskIdentification_PreDesc );
++i
) {
size_t m;
if ( n > 0 ) {
buf[ 0 ] = '/';
--n;
++buf;
}
m = strlcpy(
buf,
ClassicTaskIdentification_PreDesc[ i ][ ctx->pcs[ i ] ],
n
);
if ( m < n ) {
n -= m;
buf += m;
} else {
n = 0;
}
}
}
static T_fixture ClassicTaskIdentification_Fixture = {
.setup = ClassicTaskIdentification_Setup_Wrap,
.stop = NULL,
.teardown = NULL,
.scope = ClassicTaskIdentification_Scope,
.initial_context = &ClassicTaskIdentification_Instance
};
static const uint8_t ClassicTaskIdentification_TransitionMap[][ 2 ] = {
{
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_InvName,
ClassicTaskIdentification_Post_Id_Nop
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_InvName,
ClassicTaskIdentification_Post_Id_Nop
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_InvName,
ClassicTaskIdentification_Post_Id_Nop
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_InvName,
ClassicTaskIdentification_Post_Id_Nop
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_InvName,
ClassicTaskIdentification_Post_Id_Nop
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_InvName,
ClassicTaskIdentification_Post_Id_Nop
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_Ok,
ClassicTaskIdentification_Post_Id_Self
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_Ok,
ClassicTaskIdentification_Post_Id_Self
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_Ok,
ClassicTaskIdentification_Post_Id_Self
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_Ok,
ClassicTaskIdentification_Post_Id_Self
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_Ok,
ClassicTaskIdentification_Post_Id_Self
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_Ok,
ClassicTaskIdentification_Post_Id_Self
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_Ok,
ClassicTaskIdentification_Post_Id_LocalTask
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
#if defined(RTEMS_MULTIPROCESSING)
ClassicTaskIdentification_Post_Status_Ok,
ClassicTaskIdentification_Post_Id_RemoteTask
#else
ClassicTaskIdentification_Post_Status_InvName,
ClassicTaskIdentification_Post_Id_Nop
#endif
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_InvName,
ClassicTaskIdentification_Post_Id_Nop
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_Ok,
ClassicTaskIdentification_Post_Id_LocalTask
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
#if defined(RTEMS_MULTIPROCESSING)
ClassicTaskIdentification_Post_Status_Ok,
ClassicTaskIdentification_Post_Id_RemoteTask
#else
ClassicTaskIdentification_Post_Status_InvName,
ClassicTaskIdentification_Post_Id_Nop
#endif
}, {
ClassicTaskIdentification_Post_Status_InvAddr,
ClassicTaskIdentification_Post_Id_NullPtr
}, {
ClassicTaskIdentification_Post_Status_Ok,
ClassicTaskIdentification_Post_Id_LocalTask
}
};
/**
* @fn void T_case_body_ClassicTaskIdentification( void )
*
* @brief Test rtems_task_ident() brief description.
*
* Test rtems_task_ident() description.
*/
T_TEST_CASE_FIXTURE(
ClassicTaskIdentification,
&ClassicTaskIdentification_Fixture
)
{
ClassicTaskIdentification_Context *ctx;
size_t index;
ctx = T_fixture_context();
ctx->in_action_loop = true;
index = 0;
for (
ctx->pcs[ 0 ] = ClassicTaskIdentification_Pre_Name_Invalid;
ctx->pcs[ 0 ] != ClassicTaskIdentification_Pre_Name_Valid + 1;
++ctx->pcs[ 0 ]
) {
for (
ctx->pcs[ 1 ] = ClassicTaskIdentification_Pre_Node_Local;
ctx->pcs[ 1 ] != ClassicTaskIdentification_Pre_Node_SearchLocal + 1;
++ctx->pcs[ 1 ]
) {
for (
ctx->pcs[ 2 ] = ClassicTaskIdentification_Pre_Id_NullPtr;
ctx->pcs[ 2 ] != ClassicTaskIdentification_Pre_Id_Valid + 1;
++ctx->pcs[ 2 ]
) {
ClassicTaskIdentification_Pre_Name_Prepare( ctx, ctx->pcs[ 0 ] );
ClassicTaskIdentification_Pre_Node_Prepare( ctx, ctx->pcs[ 1 ] );
ClassicTaskIdentification_Pre_Id_Prepare( ctx, ctx->pcs[ 2 ] );
ctx->status = rtems_task_ident( ctx->name, ctx->node, ctx->id );
ClassicTaskIdentification_Post_Status_Check(
ctx,
ClassicTaskIdentification_TransitionMap[ index ][ 0 ]
);
ClassicTaskIdentification_Post_Id_Check(
ctx,
ClassicTaskIdentification_TransitionMap[ index ][ 1 ]
);
++index;
}
}
}
}
/** @} */
_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel