#!/bin/bash
#
# Copyright (c) 2011-2014, Intel Corporation
# All rights reserved.
#
# 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.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# 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 HOLDER 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.
set -ueo pipefail
# In order to dispatch log properly 4 output streams are available:
# - 1 info
# - 2 error
# - 3 (reserved)
# - 4 standard
# - 5 warning
# Leave standard output unmodified
exec 4>&1
# If the nonverbose long option is provided, do not output info log lines prefixed on stderr.
if test "$1" == --nonverbose
then
shift
exec 1>/dev/null
else
exec 1> >(sed "s/^/($$) Info: /" >&2)
fi
# Prefix all warning and error log lines and redirect them to stderr
exec 5> >(sed "s/^/($$) Warning: /" >&2)
exec 2> >(sed "s/^/($$) Error: /" >&2)
# Get script arguments
validationEnabled="false"
if [ "$1" = "--validate" ]; then
validationEnabled="true"
shift
fi
PFWconfigurationFilePath="$1"; shift
CriterionFilePath="$1"; shift
xmlDomainFilePath="$1"; shift
# Set constant variables
testPlatform="test-platform_host"
remoteProcess="remote-process_host"
hostConfig="hostConfig.py"
PFWScriptGenerator="PFWScriptGenerator.py"
portAllocator="portAllocator.py"
TPHost=127.0.0.1
PFWHost=127.0.0.1
TPCreated=false
HostRoot="$ANDROID_HOST_OUT"
TargetRoot="$ANDROID_PRODUCT_OUT/system"
# Global variables
TPSocket=5003
PFWSocket=5000
PFWStartTimeout=60
tmpDir=$(mktemp -d)
tmpFile=$(mktemp --tmpdir="$tmpDir")
# [Workaround]
# The build system does not preserve execution right in external prebuild
for file in "$testPlatform" "$remoteProcess" "$hostConfig" "$PFWScriptGenerator" "$portAllocator"
do
chmod +x "${HostRoot}/bin/${file}"
done
# Set environment paths
export LD_LIBRARY_PATH="$HostRoot/lib:${LD_LIBRARY_PATH:-}"
# Setup clean trap, it will be called automatically on exit
clean_up () {
status=$?
set +e # An error should not abort clean up
# Exit the test-platform only if it was created by this process
if $TPCreated
then
echo "Exiting test-platform listening on port $TPSocket"
$remoteProcess $TPHost $TPSocket exit
fi
echo "Cleaning $tmpFile ..."
rm "$tmpFile" || true
if [ "$validationEnabled" = "true" ]; then
echo "Cleaning $tmpDir/Schemas ..."
rm -r "$tmpDir/Schemas" || true
rmdir "$tmpDir" || true
fi
echo "Cleaning status: $status ..."
return $status
}
trap clean_up SIGHUP SIGINT SIGTERM EXIT
# Create a symlink link to rename a library.
# Eg: /lib/ contains the lib mylib_host.so but it must be found under the name
# mylib.so. linkLibrary mylib_host.so mylib.so will create a symlink in mylib_host.so's folder
# called mylib.so, pointing to mylib_host.so
linkLibrary () {
local src="$1"
local dest="$2"
local path=$(find $HostRoot/lib -name "$src")
# Check that both names are different, otherwise there is an error
if ! test "$(basename "$path")" != "$dest"
then
echo "Cannot link $dest to $src !"
return 1
fi
# Check that destination file does not already exist
if ! test -f "$(dirname "$path")/$dest"
then
# Create the symlink. Do not force if it has been created after the previous
# test, in this case simply ignore the error
ln -s "$src" "$(dirname "$path")/$dest" || true
fi
return 0
}
# The retry function will execute the provided command nbRety times util success.
# It also sleep sleepTime second between each retry.
retry() {
local command=$1
local nbRetry=$2
local sleepTime=$3
local retry=0
while ! $command 2>/dev/null >&2
do
(($retry < $nbRetry)) || return 1
retry=$(($retry + 1))
sleep $sleepTime
done
return 0;
}
# Configure the PFW main config file for simulation
formatConfigFile () {
"$hostConfig" $PFWSocket "$(readlink -f "$(dirname "$1")")" <"$1"
}
# The initTestPlatform starts a testPlatform instance with the config file given in argument.
# It will also set the PFWSocket global variable to the PFW remote processor listening socket.
initTestPlatform () {
# Format the PFW config file
formatConfigFile "$1" >"$tmpFile"
# Start test platform
echo "Starting test-platform on port $TPSocket ..."
$testPlatform -d "$tmpFile" $TPSocket 2>&5
res=$?
if test $res -ne 0
then
echo "Unable to launch the simulation platform (using socket $TPSocket)" >&5
return 4
fi
echo "Test platform successfuly loaded!"
return 0
}
# Execute a command for each input line, stopping in case of error
forEachLine () {
xargs -I@ sh -c "echo \> $1;$1 || exit 255"
}
# Configure test platform (mainly criterion) and start the PFW
launchTestPlatform () {
local TPSendCommand="$remoteProcess $TPHost $TPSocket"
sed -e 's/InclusiveCriterion/createInclusiveSelectionCriterionFromStateList/' \
-e 's/ExclusiveCriterion/createExclusiveSelectionCriterionFromStateList/' \
-e 's/[[:space:]]:[[:space:]]/ /g' "$CriterionFilePath" |
forEachLine "$TPSendCommand @"
$TPSendCommand setFailureOnMissingSubsystem false
$TPSendCommand setFailureOnFailedSettingsLoad false
$TPSendCommand setValidateSchemasOnStart $validationEnabled
echo "Asking test-platform (port $TPSocket) to start a new PFW instance (listening on port $PFWSocket) ..."
$TPSendCommand start
res=$?
if test $res -ne 0
then
echo "Unable to launch the parameter framework (using port $PFWSocket)" >&5
return 5
fi
echo "Parameter framework successfully started!"
return 0
}
startPFW () {
# Init the test-platform
initTestPlatform "$PFWconfigurationFilePath" || return 1
TPCreated=true
# Ask the test-platform to start the PFW
if ! launchTestPlatform "$CriterionFilePath"
then
# If PFW didn't start, exit the current test-platform, and return failure in
# order to choose new socket ports
echo "Exiting test-platform listening on port $TPSocket"
$remoteProcess $TPHost $TPSocket exit
TPCreated=false
return 1
fi
}
# Get a new pair of available ports for TP and PFW sockets
changeSocketsPorts() {
TPSocket=$($portAllocator) || return 1
PFWSocket=$($portAllocator) || return 1
}
# Start the pfw using different socket if it fails
safeStartPFW () {
local retry=0
local nbRetry=1000 # Workaround to avoid build failure, it very very rarely fail this many time
# Choose a new pair of socket ports
changeSocketsPorts
echo "Trying to start test-platform and PFW, with socket $TPSocket and $PFWSocket"
while ! startPFW
do
(($retry < $nbRetry)) || return 1
retry=$(($retry + 1))
# Choose a new pair of socket ports
changeSocketsPorts || continue
echo "Unable to start PFW, try again with socket $TPSocket and $PFWSocket"
done
}
deleteEscapedNewLines () {
sed -r ':a;/\\$/{N;s/\\\n//;ba}'
}
copySchemaFiles() {
cp -r "$HostRoot"/etc/parameter-framework/Schemas "$tmpDir/Schemas"
}
# Copy the schema files needed for validation
if [ "$validationEnabled" = "true" ]; then
copySchemaFiles
fi
# The PFW looks for a libremote-processor.so library, not a libremote-processor_host.so
linkLibrary libremote-processor_host.so libremote-processor.so
# Start test platform and the PFW
# Start the pfw using different socket if it fails
safeStartPFW
PFWSendCommand="$remoteProcess $PFWHost $PFWSocket"
$PFWSendCommand setTuningMode on
# Send the xml domain tunning file
if test -s "$xmlDomainFilePath"
then
echo "Import the xml domain tunning file: $(readlink -e $xmlDomainFilePath)"
$PFWSendCommand importDomainsWithSettingsXML "$(readlink -e $xmlDomainFilePath)"
fi
# Send the extended domain description routing files converted to pfw commands
m4 "$@" |
"$PFWScriptGenerator" --output-kind pfw |
deleteEscapedNewLines |
forEachLine "$PFWSendCommand @" | sed '/^Done$/d'
# Export the global xml domains description
$PFWSendCommand getDomainsWithSettingsXML |
# Delete trailing carriage return and format absolute paths
sed -r -e 's/\r$//' \
-e 's@(xsi:noNamespaceSchemaLocation=")'"$tmpDir"'/?@\1@' >&4