Add build test runner: b-test.
Test runner can be used to do build testing. The main intention is to
provide a simple and robust way to capture build commands.
For details please check the documentation.
Change-Id: Icab22320a86dcfdb882a36c1c8c2a3380c40d30c
Signed-off-by: Gyorgy Szing <gyorgy.szing@arm.com>
diff --git a/requirements.txt b/requirements.txt
index 1b7d714..b2cebb4 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,4 +5,7 @@
#
# Include packages needed for socument generation
--r docs/requirements.txt
\ No newline at end of file
+-r docs/requirements.txt
+
+# Include packages needed for build test tool
+-r tools/b-test/requirements.txt
diff --git a/tools/b-test/.gitignore b/tools/b-test/.gitignore
new file mode 100644
index 0000000..bde4006
--- /dev/null
+++ b/tools/b-test/.gitignore
@@ -0,0 +1,4 @@
+#Ignore instaniated template.
+run.sh
+# Ignore user specific setting script
+user.env
diff --git a/tools/b-test/Makefile b/tools/b-test/Makefile
new file mode 100644
index 0000000..1a4a321
--- /dev/null
+++ b/tools/b-test/Makefile
@@ -0,0 +1,62 @@
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+.SUFFIXES:
+.SUFFIXES: .j2
+
+# Disable parallel execution for this makefile.
+.NOTPARALLEL:
+
+TEMPLATES:=$(wildcard *.j2)
+OUTPUTS:=$(TEMPLATES:%.j2=%)
+
+all:
+ make config
+ bash run.sh
+
+config: ${OUTPUTS}
+
+list:
+ make config
+ bash run.sh help
+
+# run a command of the generated script
+r-%:
+ make config
+ bash run.sh "$*"
+
+define help_msg
+*************************************************************
+Available targets:
+ all - generate and run test script
+ config - run script generation only
+ clean - remove intermediate files
+ list - run config and list test cases
+ p-<variable> - print value of make variable (for debugging)
+ r-<test> - run a command of the generated script. Allow
+ executing a single test case. Use
+ make r-help
+ to get the list of tests.
+*************************************************************
+endef
+
+export help_msg
+help:
+ @echo "$$help_msg"
+
+# remove intermediate output
+clean:
+ifneq ($(wildcard ./run.sh),)
+ bash run.sh clean
+endif
+ -rm -rf ${OUTPUTS}
+
+# Convert template to shell script
+%.sh : %.sh.j2 test_data.yaml
+ yasha -v test_data.yaml $<
+
+# print variable value (i.e. make p-TEMPLATES)
+p-%:
+ @echo $*=${$*}
diff --git a/tools/b-test/Readme.rst b/tools/b-test/Readme.rst
new file mode 100644
index 0000000..4100e91
--- /dev/null
+++ b/tools/b-test/Readme.rst
@@ -0,0 +1,107 @@
+Build test runner
+=================
+
+This directory captures build test case definitions and a tool to execute the test based on
+the data. The tool combines the power of shell scripting with the power of structured data
+(|yaml|). The bridge between the two technologies is provided by |jinja2| template engine
+and |yasha|.
+
+Dependencies
+------------
+
+|Jinja2| and |yasha| are python tools and python3 is needed to run the tests. Please install
+the following tools into your build environment:
+
+ - python3
+ - pip3
+
+After this please install further pip packages listed in ``requirements.txt`` as:
+
+.. code:: shell
+
+ pip3 install -r requirements.txt
+
+.. note::
+
+ This document lists the dependencies of this tool only. To be able to successfully run the
+ build tests further tools are needed. Please refer to the ``Trusted Services``
+ documentation for details.
+
+Files
+-------
+
+.. uml::
+
+ @startsalt
+ {
+ {T
+ + b-test
+ ++Makefile | generate and run tests
+ ++Readme.rst | this document
+ ++requirements.txt | pip package dependencies
+ ++run.sh.j2 | shell script template
+ ++test_data.schema.json | JSON schema for test case data
+ ++test_data.yaml | test case data
+ ++//user.env// | optional user specific settings
+ }
+ }
+ @endsalt
+
+Design
+------
+
+The project needs a convenient way to define and execute "build tests". This test aims to ensure
+all build configurations are in a good working condition. Testing is done by executing build
+of all supported build configurations. In order to make the testing robust and easy to use a
+"data driven" approach is the best fit. With this test cases are described by pure data and this
+data is processed by some tool which is responsible for test execution.
+
+For command execution the bash shell is a good candidate. It provides portability between OSs, is
+widely adopted and well tested. Unfortunately shells are not good on handling structured data.
+To address this shortcoming templating is utilized or "code generation" is used. The shell script
+to execute the command is generated based on a template file and the test data.
+
+Since python is already a dependency of Trusted Services we selected the |Jinja2| template engine
+to go with, and to decrease maintenance cost, we use it trough |yasha|.
+
+.. uml::
+
+ @startuml
+ [test_data.yaml] --> [yasha]
+ [run.sh.j2] --> [yasha]
+ [//user.env//] -right-> [run.sh]
+ [yasha] --> [run.sh]
+ @enduml
+
+Usage
+-----
+
+There are two "entry points" to the tests. If the intention is to run all tests, issue ``make``.
+
+Makefile
+""""""""
+The makefile is responsible to provide a high level "API". It allows executing the script generation
+process and to run the tests. It ensures all components are fresh before being executed.
+
+Issue ``make help`` to get a list of supported commands.
+
+run.sh
+""""""
+
+``run.sh`` is the test runner. It is responsible to execute the needed builds in a proper way and
+thus validate the build definitions.
+
+Execute ``run.sh help`` to get further details.
+
+
+--------------
+
+*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.*
+
+.. |yasha| replace:: `yasha`_
+.. |jinja2| replace:: `Jinja2`_
+.. |yaml| replace:: `yaml`_
+
+.. _Jinja2: https://palletsprojects.com/p/jinja
+.. _yasha: https://github.com/kblomqvist/yasha
+.. _yaml: https://yaml.org
diff --git a/tools/b-test/requirements.txt b/tools/b-test/requirements.txt
new file mode 100644
index 0000000..1d0415e
--- /dev/null
+++ b/tools/b-test/requirements.txt
@@ -0,0 +1,6 @@
+#
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+yasha==4.4
diff --git a/tools/b-test/run.sh.j2 b/tools/b-test/run.sh.j2
new file mode 100644
index 0000000..32d5e83
--- /dev/null
+++ b/tools/b-test/run.sh.j2
@@ -0,0 +1,174 @@
+#!/bin/bash
+#
+# Copyright (c) 2020, Arm Limited and contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# Exit with error if any command fails
+set -e
+
+# Read in user specific environment settings
+if [ -e user.env ]
+then
+ echo "Reding user specific settings from user.env"
+ source user.env
+fi
+
+# Default to non-verbose mode.
+VERBOSE=${VERBOSE:-0}
+
+# Get root of TS repo.
+TS_ROOT=${TS_ROOT:-$(git rev-parse --show-toplevel)}
+
+# Number of threads to use in parallel
+NUMBER_OF_PROCESSORS=${NUMBER_OF_PROCESSORS:-$(( $(nproc) * 2 )) }
+
+# Convert test name to build directory
+function name-to-bdir() {
+ printf "./build-%s" "$1"
+}
+
+# Wrap cmake to allow verbose vs non-verbose mode
+function _cmake() {
+ log_file=$1
+ shift
+ if [ "$VERBOSE" != "0" ]
+ then
+ cmake "$@" 2>&1 | tee -a "$log_file"
+ return ${PIPESTATUS[0]}
+ else
+ cmake "$@" >>"$log_file" 2>&1
+ fi
+}
+
+{% for config in data %}
+# Run build test "{{config.name}}"
+{{config.name}}() {
+ echo "##################################################################"
+ echo "########################## {{config.name}} started."
+
+ {% if config.os_id is defined %}
+ if [ "$OS_ID" != "{{config.os_id}}" ]
+ then
+ echo "Test case is not supported on this host."
+ echo "########################## $COLOR_YELOW {{config.name}} skipped $COLOR_RESET"
+ echo "##################################################################"
+ return
+ fi
+ {% endif %}
+ b_dir=$(name-to-bdir "{{config.name}}")
+ log_file=$b_dir/build.log
+ rm -rf "$b_dir"
+ mkdir -p "$b_dir"
+
+ _cmake "$log_file" -S {{config.src}} -B "$b_dir" {% for param in config.params %} "{{param}}" {%endfor%} || {
+
+ echo "For details see: $log_file"
+ echo "########################## $COLOR_RED {{config.name}} failed $COLOR_RESET"
+ return
+ }
+
+ if _cmake "$log_file" --build "$b_dir" -j ${NUMBER_OF_PROCESSORS}
+ then
+ if _cmake "$log_file" --install "$b_dir" --prefix ./install
+ then
+ echo "########################## $COLOR_GREEN {{config.name}} passed $COLOR_RESET"
+ else
+ echo "For details see: $log_file"
+ echo "########################## $COLOR_RED {{config.name}} failed $COLOR_RESET"
+ fi
+ else
+ echo "For details see: $log_file"
+ echo "########################## $COLOR_RED {{config.name}} failed $COLOR_RESET"
+ fi
+ echo "##################################################################"
+}
+
+{% endfor %}
+
+# Clean intermediate files
+do_clean() {
+ {% for config in data %}
+ b_dir=$(name-to-bdir "{{config.name}}")
+ if [ -d "$b_dir" ]
+ then
+ echo "Removing $b_dir"
+ rm -rf "$b_dir" || true
+ fi
+ {% endfor %}
+}
+
+# Print usage info
+do_help() {
+ cat <<END_HELP
+Build test runner
+=================
+
+Invocation::
+ ``$0 <command>``
+
+The file "user.env" is sourced from the current directory. Use it to set
+environment specific defaults. For config variables see the start of this script
+and any "$<XXXX>" in the "params" array of any command in test_data.yaml
+Some variables to note
+ - VERBOSE : make the script output more info.
+ VERBOSE=$VERBOSE
+ - TS_ROOT : Root directory of the TS repo.
+ TS_ROOT=$TS_ROOT
+ - NUMBER_OF_PROCESSORS: number of processors in the system. Used for setting the number of
+ parallel processes during build
+ NUMBER_OF_PROCESSORS=$NUMBER_OF_PROCESSORS
+ - SP_DEV_KIT_DIR : location of OP-TEE OS SPDEVKIT export.
+ SP_DEV_KIT_DIR=$SP_DEV_KIT_DIR
+
+Available commands:
+ "" - no command/default -> run all test cases
+ clean - remove build directories
+ help - print this text
+ <test case> - run a single build
+ available test cases:
+ {% for config in data %}
+ {{config.name}}
+ {% endfor %}
+END_HELP
+}
+
+#################### Entry point ###################################
+
+OS_ID=$(uname -o )
+
+if [ -n $(which tput) -a -t ]
+then
+ COLOR_YELOW=$(tput setaf 3)
+ COLOR_RESET=$(tput sgr0)
+ COLOR_RED=$(tput setaf 1)
+ COLOR_GREEN=$(tput setaf 2)
+else
+ COLOR_YELOW=
+ COLOR_RESET=
+ COLOR_RED=
+ COLOR_GREEN=
+fi
+
+case $1 in
+ {% for config in data %}
+ {{config.name}})
+ {{config.name}}
+ ;;
+ {% endfor %}
+ clean)
+ do_clean
+ ;;
+ help)
+ do_help
+ ;;
+ "")
+ {% for config in data %}
+ {{config.name}}
+ {% endfor %}
+ ;;
+ *)
+ do_help
+ ;;
+esac
diff --git a/tools/b-test/test_data.schema.json b/tools/b-test/test_data.schema.json
new file mode 100644
index 0000000..da41e96
--- /dev/null
+++ b/tools/b-test/test_data.schema.json
@@ -0,0 +1,18 @@
+{
+ "$schema" : "http://json-schema.org/schema#",
+ "$id" : "Schema for build test description file",
+ "type": "object",
+ "properties" : {
+ "data" : {
+ "type" : "array",
+ "properties" : {
+ "name" : {"type" : "string"},
+ "src" : {"type" : "string"},
+ "params" : {
+ "type" : "array",
+ "items" : [ {"type" : "string"} ]
+ }
+ }
+ }
+ }
+}
diff --git a/tools/b-test/test_data.yaml b/tools/b-test/test_data.yaml
new file mode 100644
index 0000000..3c8c916
--- /dev/null
+++ b/tools/b-test/test_data.yaml
@@ -0,0 +1,13 @@
+#
+# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+$schema: ./test_data.schema.json,
+data:
+ - name: "libsp-optee-arm"
+ src: "$TS_ROOT/deployments/libsp/opteesp"
+ params:
+ - "-GUnix Makefiles"
+ - "-DSP_DEV_KIT_DIR=$SP_DEV_KIT_DIR"