1#!/bin/bash 2# 3# Copyright (c) 2011-2014, Intel Corporation 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without modification, 7# are permitted provided that the following conditions are met: 8# 9# 1. Redistributions of source code must retain the above copyright notice, this 10# list of conditions and the following disclaimer. 11# 12# 2. Redistributions in binary form must reproduce the above copyright notice, 13# this list of conditions and the following disclaimer in the documentation and/or 14# other materials provided with the distribution. 15# 16# 3. Neither the name of the copyright holder nor the names of its contributors 17# may be used to endorse or promote products derived from this software without 18# specific prior written permission. 19# 20# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 24# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31set -ueo pipefail 32 33# In order to dispatch log properly 4 output streams are available: 34# - 1 info 35# - 2 error 36# - 3 (reserved) 37# - 4 standard 38# - 5 warning 39 40# Leave standard output unmodified 41exec 4>&1 42# If the nonverbose long option is provided, do not output info log lines prefixed on stderr. 43if test "$1" == --nonverbose 44then 45 shift 46 exec 1>/dev/null 47else 48 exec 1> >(sed "s/^/($$) Info: /" >&2) 49fi 50# Prefix all warning and error log lines and redirect them to stderr 51exec 5> >(sed "s/^/($$) Warning: /" >&2) 52exec 2> >(sed "s/^/($$) Error: /" >&2) 53 54# Get script arguments 55validationEnabled="false" 56if [ "$1" = "--validate" ]; then 57 validationEnabled="true" 58 shift 59fi 60PFWconfigurationFilePath="$1"; shift 61CriterionFilePath="$1"; shift 62xmlDomainFilePath="$1"; shift 63 64# Set constant variables 65testPlatform="test-platform_host" 66remoteProcess="remote-process_host" 67 68hostConfig="hostConfig.py" 69PFWScriptGenerator="PFWScriptGenerator.py" 70portAllocator="portAllocator.py" 71 72TPHost=127.0.0.1 73PFWHost=127.0.0.1 74TPCreated=false 75 76HostRoot="$ANDROID_HOST_OUT" 77TargetRoot="$ANDROID_PRODUCT_OUT/system" 78 79# Global variables 80TPSocket=5003 81PFWSocket=5000 82PFWStartTimeout=60 83 84tmpDir=$(mktemp -d) 85tmpFile=$(mktemp --tmpdir="$tmpDir") 86 87# [Workaround] 88# The build system does not preserve execution right in external prebuild 89for file in "$testPlatform" "$remoteProcess" "$hostConfig" "$PFWScriptGenerator" "$portAllocator" 90do 91 chmod +x "${HostRoot}/bin/${file}" 92done 93 94# Set environment paths 95export LD_LIBRARY_PATH="$HostRoot/lib:${LD_LIBRARY_PATH:-}" 96 97# Setup clean trap, it will be called automatically on exit 98clean_up () { 99 status=$? 100 set +e # An error should not abort clean up 101 102 # Exit the test-platform only if it was created by this process 103 if $TPCreated 104 then 105 echo "Exiting test-platform listening on port $TPSocket" 106 $remoteProcess $TPHost $TPSocket exit 107 fi 108 109 echo "Cleaning $tmpFile ..." 110 rm "$tmpFile" || true 111 112 if [ "$validationEnabled" = "true" ]; then 113 echo "Cleaning $tmpDir/Schemas ..." 114 rm -r "$tmpDir/Schemas" || true 115 rmdir "$tmpDir" || true 116 fi 117 118 echo "Cleaning status: $status ..." 119 return $status 120} 121 122trap clean_up SIGHUP SIGINT SIGTERM EXIT 123 124# Create a symlink link to rename a library. 125# Eg: /lib/ contains the lib mylib_host.so but it must be found under the name 126# mylib.so. linkLibrary mylib_host.so mylib.so will create a symlink in mylib_host.so's folder 127# called mylib.so, pointing to mylib_host.so 128linkLibrary () { 129 local src="$1" 130 local dest="$2" 131 local path=$(find $HostRoot/lib -name "$src") 132 133 # Check that both names are different, otherwise there is an error 134 if ! test "$(basename "$path")" != "$dest" 135 then 136 echo "Cannot link $dest to $src !" 137 return 1 138 fi 139 140 # Check that destination file does not already exist 141 if ! test -f "$(dirname "$path")/$dest" 142 then 143 # Create the symlink. Do not force if it has been created after the previous 144 # test, in this case simply ignore the error 145 ln -s "$src" "$(dirname "$path")/$dest" || true 146 fi 147 return 0 148} 149 150# The retry function will execute the provided command nbRety times util success. 151# It also sleep sleepTime second between each retry. 152retry() { 153 local command=$1 154 local nbRetry=$2 155 local sleepTime=$3 156 local retry=0 157 while ! $command 2>/dev/null >&2 158 do 159 (($retry < $nbRetry)) || return 1 160 retry=$(($retry + 1)) 161 sleep $sleepTime 162 done 163 return 0; 164} 165 166# Configure the PFW main config file for simulation 167formatConfigFile () { 168 "$hostConfig" $PFWSocket "$(readlink -f "$(dirname "$1")")" <"$1" 169} 170 171# The initTestPlatform starts a testPlatform instance with the config file given in argument. 172# It will also set the PFWSocket global variable to the PFW remote processor listening socket. 173initTestPlatform () { 174 # Format the PFW config file 175 formatConfigFile "$1" >"$tmpFile" 176 177 # Start test platform 178 echo "Starting test-platform on port $TPSocket ..." 179 $testPlatform -d "$tmpFile" $TPSocket 2>&5 180 181 res=$? 182 if test $res -ne 0 183 then 184 echo "Unable to launch the simulation platform (using socket $TPSocket)" >&5 185 return 4 186 fi 187 188 echo "Test platform successfuly loaded!" 189 return 0 190} 191 192# Execute a command for each input line, stopping in case of error 193forEachLine () { 194 xargs -I@ sh -c "echo \> $1;$1 || exit 255" 195} 196 197# Configure test platform (mainly criterion) and start the PFW 198launchTestPlatform () { 199 local TPSendCommand="$remoteProcess $TPHost $TPSocket" 200 sed -e 's/InclusiveCriterion/createInclusiveSelectionCriterionFromStateList/' \ 201 -e 's/ExclusiveCriterion/createExclusiveSelectionCriterionFromStateList/' \ 202 -e 's/[[:space:]]:[[:space:]]/ /g' "$CriterionFilePath" | 203 forEachLine "$TPSendCommand @" 204 205 $TPSendCommand setFailureOnMissingSubsystem false 206 $TPSendCommand setFailureOnFailedSettingsLoad false 207 $TPSendCommand setValidateSchemasOnStart $validationEnabled 208 209 echo "Asking test-platform (port $TPSocket) to start a new PFW instance (listening on port $PFWSocket) ..." 210 $TPSendCommand start 211 res=$? 212 if test $res -ne 0 213 then 214 echo "Unable to launch the parameter framework (using port $PFWSocket)" >&5 215 return 5 216 fi 217 218 echo "Parameter framework successfully started!" 219 return 0 220} 221 222startPFW () { 223 # Init the test-platform 224 initTestPlatform "$PFWconfigurationFilePath" || return 1 225 TPCreated=true 226 227 # Ask the test-platform to start the PFW 228 if ! launchTestPlatform "$CriterionFilePath" 229 then 230 # If PFW didn't start, exit the current test-platform, and return failure in 231 # order to choose new socket ports 232 echo "Exiting test-platform listening on port $TPSocket" 233 $remoteProcess $TPHost $TPSocket exit 234 TPCreated=false 235 return 1 236 fi 237} 238 239# Get a new pair of available ports for TP and PFW sockets 240changeSocketsPorts() { 241 TPSocket=$($portAllocator) || return 1 242 PFWSocket=$($portAllocator) || return 1 243} 244 245# Start the pfw using different socket if it fails 246safeStartPFW () { 247 local retry=0 248 local nbRetry=1000 # Workaround to avoid build failure, it very very rarely fail this many time 249 250 # Choose a new pair of socket ports 251 changeSocketsPorts 252 echo "Trying to start test-platform and PFW, with socket $TPSocket and $PFWSocket" 253 254 while ! startPFW 255 do 256 (($retry < $nbRetry)) || return 1 257 retry=$(($retry + 1)) 258 259 # Choose a new pair of socket ports 260 changeSocketsPorts || continue 261 262 echo "Unable to start PFW, try again with socket $TPSocket and $PFWSocket" 263 done 264} 265 266deleteEscapedNewLines () { 267 sed -r ':a;/\\$/{N;s/\\\n//;ba}' 268} 269 270copySchemaFiles() { 271 cp -r "$HostRoot"/etc/parameter-framework/Schemas "$tmpDir/Schemas" 272} 273 274# Copy the schema files needed for validation 275if [ "$validationEnabled" = "true" ]; then 276 copySchemaFiles 277fi 278 279# The PFW looks for a libremote-processor.so library, not a libremote-processor_host.so 280linkLibrary libremote-processor_host.so libremote-processor.so 281 282# Start test platform and the PFW 283# Start the pfw using different socket if it fails 284safeStartPFW 285 286PFWSendCommand="$remoteProcess $PFWHost $PFWSocket" 287 288$PFWSendCommand setTuningMode on 289 290# Send the xml domain tunning file 291if test -s "$xmlDomainFilePath" 292then 293 echo "Import the xml domain tunning file: $(readlink -e $xmlDomainFilePath)" 294 $PFWSendCommand importDomainsWithSettingsXML "$(readlink -e $xmlDomainFilePath)" 295fi 296 297# Send the extended domain description routing files converted to pfw commands 298m4 "$@" | 299 "$PFWScriptGenerator" --output-kind pfw | 300 deleteEscapedNewLines | 301 forEachLine "$PFWSendCommand @" | sed '/^Done$/d' 302 303# Export the global xml domains description 304$PFWSendCommand getDomainsWithSettingsXML | 305 # Delete trailing carriage return and format absolute paths 306 sed -r -e 's/\r$//' \ 307 -e 's@(xsi:noNamespaceSchemaLocation=")'"$tmpDir"'/?@\1@' >&4 308 309