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

Reply via email to