Running iOS UIAutomation as a post-action build script is return as a posix spawn error - ios

I'm entirely new to using bash and Xcode build scripts and so my code is probably a jungle full of errors.
The idea here is to trigger the script below which will scrape the directory that it is saved in for any .js automation scripts. It will then send these scripts to instruments to be run one at a time. I found some nifty code that created time stamped files and so I used that to create a more meaningful storage system.
#!/bin/bash
# This script should run all (currently only one) tests, independently from
# where it is called from (terminal, or Xcode Run Script).
# REQUIREMENTS: This script has to be located in the same folder as all the
# UIAutomation tests. Additionally, a *.tracetemplate file has to be present
# in the same folder. This can be created with Instruments (Save as template...)
# The following variables have to be configured:
#EXECUTABLE="Plans.app"
# Find the test folder (this script has to be located in the same folder).
ROOT="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Prepare all the required args for instruments.
TEMPLATE=`find $ROOT -name '*.tracetemplate'`
#EXECUTABLE=`find ~/Library/Application\ Support/iPhone\ Simulator | grep "${EXECUTABLE}$"`
echo "$BUILT_PRODUCTS_DIR"
echo "$PRODUCT_NAME"
EXECUTABLE="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/"
SCRIPTS=`find $ROOT -name '*.js'`
# Prepare traces folder
TRACES="${ROOT}/Traces/`date +%Y-%m-%d_%H-%M-%S`"
mkdir -p "$TRACES"
printf "\n" >> "$ROOT/results.log"
echo `date +%Y-%m-%d_%H-%M-%S` >> "$ROOT/results.log"
# Get the name of the user we should use to run Instruments.
# Currently this is done, by getting the owner of the folder containing this script.
USERNAME=`ls -l "${ROOT}/.." | grep \`basename "$ROOT"\` | awk '{print $3}'`
# Bring simulator window to front. Depending on the localization, the name is different.
osascript -e 'try
tell application "iPhone Simulator" to activate
on error
tell application "iOS Simulator" to activate
end try'
# Prepare an Apple Script that promts for the password.
PASS_SCRIPT="tell application \"System Events\"
activate
display dialog \"Password for user $USER:\" default answer \"\" with hidden answer
text returned of the result
end tell"
# Run all the tests.
for SCRIPT in $SCRIPTS; do
echo -e "\nRunning test script $SCRIPT"
TESTC="sudo -u ${USER} xcrun instruments -l -c -t ${TEMPLATE} ${EXECUTABLE} -e UIARESULTSPATH ${TRACES}/${TRACENAME} -e UIASCRIPT ${SCRIPT} >> ${ROOT}/results.log"
#echo "$COMMAND"
echo "Executing command $TESTC" >> "$ROOT/results.log"
echo "here $TESTC" >> "$ROOT/results.log"
OUTPUT=$(TESTC)
echo $OUTPUT >> "$ROOT/results.log"
echo "Finished logging" >> "$ROOT/results.log"
SCRIPTNAME=`basename "$SCRIPT"`
TRACENAME=`echo "$SCRIPTNAME" | sed 's_\.js$_.trace_g'`
for i in $(ls -A1t $PWD | grep -m 1 '.trace')
do
TRACEFILE="$PWD/$i"
done
if [ -e $TRACEFILE ]; then
mv "$TRACEFILE" "${TRACES}/${TRACENAME}"
fi
if [ `grep " Fail: " results.log | wc -l` -gt 0 ]; then
echo "Test ${SCRIPTNAME} failed. See trace for details."
open "${TRACES}/${TRACENAME}"
exit 1
break
fi
done
rm results.log
A good portion of this was taken from another Stack Overflow answer but because of the repository setup that I'm working with I needed to keep the paths abstract and separate from the root folder of the script. Everything seems to work (although probably not incredibly efficiently) except for the actual xcrun command to launch instruments.
TESTC="sudo -u ${USER} xcrun instruments -l -c -t ${TEMPLATE} ${EXECUTABLE} -e UIARESULTSPATH ${TRACES}/${TRACENAME} -e UIASCRIPT ${SCRIPT} >> ${ROOT}/results.log"
echo "Executing command $TESTC" >> "$ROOT/results.log"
OUTPUT=$(TESTC)
This is turned into the following by whatever black magic Bash runs on:
sudo -u Braains xcrun instruments -l -c -t
/Users/Braains/Documents/Automation/AppName/TestCases/UIAutomationTemplate.tracetemplate
/Users/Braains/Library/Developer/Xcode/DerivedData/AppName-
ekqevowxyipndychtscxwgqkaxdk/Build/Products/Debug-iphoneos/AppName.app/ -e UIARESULTSPATH
/Users/Braains/Documents/Automation/AppName/TestCases/Traces/2014-07-17_16-31-49/ -e
UIASCRIPT /Users/Braains/Documents/Automation/AppName/TestCases/Test-Case_1js
(^ Has inserted line breaks for clarity of the question ^)
The resulting error that I am seeing is:
posix spawn failure; aborting launch (binary ==
/Users/Braains/Library/Developer/Xcode/DerivedData/AppName-
ekqevowxyipndychtscxwgqkaxdk/Build/Products/Debug-iphoneos/AppName.app/AppName).
I have looked all over for a solution to this but I can't find anything because Appium has a similar issue. Unfortunately I don't understand the systems well enough to know how to translate the fixes to Appium to my own code but I imagine it's a similar issue.
I do know that the posix spawn failure is related to threading, but I don't know enough about xcrun to say what's causing the threading issue.
Related info:
- I'm building for the simulator but it'd be great to work on real devices too
- I'm using xCode 5.1.1 and iOS Simulator 7.1
- This script is meant to be run as a build post action script in xCode
- I did get it briefly working once before I broke it and couldn't get it back to the working state. So I think that means all of my permissions are set correctly.
UPDATE: So I've gotten to the root of this problem although I have not found a fix yet. First of all I have no idea what xcrun is for and so I dropped it. Then after playing around I found that my Xcode environment variables are returning the wrong path, probably because of some project setting somewhere. If you copy the Bash command from above but replace Debug-iphoneos with Debug-iphonesimulator the script can be run from the command line and will work as expected.

So for anyone who happens across this the only solution I could find was to hardcode the script for the simulator.
I changed EXECUTABLE="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/" to be EXECUTABLE="${SYMROOT}/Debug-iphonesimulator/${EXECUTABLE_PATH}". This is obviously not a great solution but it works for now.

Related

Trigger specific job on push to specific directory

We have 12 different projects inside the same repository and have a different job to run for each of these.
I want to know how I can trigger a job only when a change has happened in a specific folder, since running all 12 on every push takes too long to finish.
Well I have hacked a solution that works for us.
First, add an Execute Shell Build Step:
#!/bin/bash
export DIRS="api objects"
DIFF=`git diff --name-only develop`
echo "export RUN_TEST=0" > "$WORKSPACE/RUN_TEST"
for DIR in $DIRS; do
for LINE in $DIFF; do
# Is this file inside an interesting directory?
echo $LINE | grep -e "^$DIR/"
# Checking if it is inside
if [ $? -eq 0 ]; then
echo "export RUN_TEST=1" > "$WORKSPACE/RUN_TEST"
fi
done
done
Here:
api and objects are the 2 directories I want to trigger this Job
develop is the main branch we use, so I want to know how my directories compare to that branch in particular
I create a file $WORKSPACE/RUN_TEST to set a variable if I should or not run it
Then in the time-consuming build steps add:
#!/bin/sh
. "$WORKSPACE/RUN_TEST"
if [ $RUN_TEST -eq 1 ]; then
# Time consuming code here
fi
That way the job is triggered but runs as fast as if it wasn't triggered.
Now I modified it to:
#!/bin/bash
export DIRS="api objects"
DIFF=`git diff --name-only origin/develop`
RUN_TEST=111
for DIR in $DIRS; do
for LINE in $DIFF; do
# Is this file inside an interesting directory?
echo $LINE | grep -e "^$DIR/"
# Checking if it is inside
if [ $? -eq 0 ]; then
RUN_TEST=0
fi
done
done
echo "RUN_TEST=$RUN_TEST"
echo "return $RUN_TEST" > "$WORKSPACE/RUN_TEST"
exit $RUN_TEST
And set Exit code to set build unstable to 111 on all build steps. Then, in all following build steps I did:
#!/bin/bash
# Exit on any error
set -euo pipefail
. "$WORKSPACE/RUN_TEST"
# Rest of build step

ROS how to find all executables of a package?

I want to ask how to find all the executable names of a package in ROS (Robot Operating System)? For example, find spawn_model in gazebo_ros package. When I inspect the package in my system, it just shows some .xml, .cmake files, without any executables. But I can run it, such as: rosrun gazebo_ros spawn_model.
Thank you!
An easy way to do this is to type: "rosrun name_of_package " and then press tab two times, it should show you all the executables built.
After looking in the bash autocompletion script for rosrun, it looks like the command catkin_find is used to find the location of the executables for a package, and the executables are filtered with a find command.
If you want to create a script to give you a list of the executables follow the instructions below:
Save the following script in a file called rospack-list-executables:
#!/bin/bash
if [[ $# -lt 1 ]]; then
echo "usage: $(basename $0) <pkg_name>"
echo ""
echo " To get a list of all package names use the command"
echo " 'rospack list-names'"
exit
fi
pkgname=${1}
pkgdir="$(catkin_find --first-only --without-underlays --libexec ${pkgname})"
if [[ -n "${pkgdir}" ]]; then
find -L "${pkgdir}" -executable -type f ! -regex ".*/[.].*" ! -regex ".*${pkgdir}\/build\/.*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)/\1/g" | sort
else
echo "Cannot find executables for package '${pkgname}'." >&2
exit 1
fi
Then make the rospack-list-executables script executable (chmod +x rospack-list-executables) and place it in a directory that can be found in your $PATH environment variable.
Run the script:
$ rospack-list-executables gazebo_ros
debug
gazebo
gdbrun
gzclient
gzserver
libcommon.sh
perf
spawn_model
You should get the same result that you get when you type the rosrun <pkgname> command and press Tab:
$ rosrun gazebo_ros
debug gazebo gdbrun gzclient gzserver libcommon.sh perf spawn_model
You can check the executables for all packages with the following bash code:
rospack list-names | while read pkgname; do
echo "Executables for package '${pkgname}':";
rospack-list-executables $pkgname; echo "";
done
To enable package autocompletion for your newly created command, type the following:
complete -F _roscomplete rospack-list-executables
If you do not want to have to type the complete command every time you login, you can append it to your .bashrc file:
echo "complete -F _roscomplete rospack-list-executables" >> ~/.bashrc
Now when you type the command rospack-list-executables and press the Tab key, you should get a list of all the available packages to choose from.
catkin_find --first-only --without-underlays --libexec <your package name>)
should give you the folder where the executables are

Unable to run command line for iOS UI Automation

I used the template from this website: http://blog.manbolo.com/2012/04/08/ios-automated-tests-with-uiautomation and created my own command line to run the automation test on terminal.
Here are some useful information about my script:
I'm using xCode 6.4.
I ran this automation script in Xcode instrument and it works fine.
Here is my command line:
instruments -w 927b666816e2d4377b208a872b42a1d3xxxxxxxx -t /Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/PlugIns/AutomationInstrument.xrplugin/Contents/Resources/Automation.tracetemplate ConsumeriOS -e UIASCRIPT/Users/wendywang/Documents/TIO/ConsumeriOS/ConsumeriOS/ConsumeriOSTests/automationScript/LogIn.js
But I received this error:
2015-10-05 14:16:34.122 instruments[23330:551118] WebKit Threading Violation - initial use of WebKit from a secondary thread. Instruments Usage Error : Failed to resolve target for Instrument 'Automation' instruments, version 6.4 (57082) usage: instruments [-t template] [-D document] [-l timeLimit] [-i #] [-w device] [[-p pid] | [application [-e variable value] [argument ...]]] tio-spare:~ wendywang$ ConsumeriOS -e UIASCRIPT /Users/wendywang/Documents/xxx/ConsumeriOS/ConsumeriOS/ConsumeriOSTests/automationScript/LogIn.js -bash: ConsumeriOS: command not found
I double checked that
The UDID is correct
The automation trace template is in the correct path
The LogIn.js file is in the correct path
One thing I am not sure:
The ConsumeriOS is the name of the code. But inside the code, it can actually produce a few apps. I am testing the app called Consumer. So I am not sure if I should write ConsumeriOS as the name of the app, or Consumer instead.
Does anyone know why it is generating this error? Thanks!
Huhu,
try this:
Give the
complete path to the app with the .app extension,
Put the DeviceID and the script into "",
try it with the device name, if it doesn't
work.
Here a sample that works for me.
instruments -w "DeviceID" -t PATHTOTEMPLATE/Automation.tracetemplate PATHTOAPP/ConsumeriOS.app -e UIASCRIPT "PATHTOSCRIPT/UITest.js"
Let me know!
The relevant message is this one:
tio-spare:~ wendywang$ ConsumeriOS -e UIASCRIPT /Users/wendywang/Documents/xxx/ConsumeriOS/ConsumeriOS/ConsumeriOSTests/automationScript/LogIn.js -bash: ConsumeriOS: command not found
It appears that you may have copy-pasted this command:
instruments -w 927b666816e2d4377b208a872b42a1d3xxxxxxxx -t /Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/PlugIns/AutomationInstrument.xrplugin/Contents/Resources/Automation.tracetemplate ConsumeriOS -e UIASCRIPT/Users/wendywang/Documents/TIO/ConsumeriOS/ConsumeriOS/ConsumeriOSTests/automationScript/LogIn.js
But incorrectly -- in two separate pieces, part 1:
instruments -w 927b666816e2d4377b208a872b42a1d3xxxxxxxx -t /Applications/Xcode.app/Contents/Applications/Instruments.app/Contents/PlugIns/AutomationInstrument.xrplugin/Contents/Resources/Automation.tracetemplate
And part 2 (separated by a newline):
ConsumeriOS -e UIASCRIPT/Users/wendywang/Documents/TIO/ConsumeriOS/ConsumeriOS/ConsumeriOSTests/automationScript/LogIn.js
Separately, it looks like you wrote the name of your app (ConsumeriOS) instead of the full path to your app (/path/to/ConsumeriOS.app).

How to symbolicate crash logs using the .xcarchive file?

I am having issues extracting the dsym file from .xcarchive to symbolicate crash logs. I understand that .xcarchive contains both the .app files and .dsym files. Normally you should be able to right click on the xcarchive file and selecct "Show Package Contents" (link). However "Show Package Contents" does not show up for me.
I also attempted to symbolicate the crash logs manually by using symbolicatecrash and giving it the xcarchive file (link). However it would still return crash logs that were not symbolicated.
Would anyone know what could be going on here? Any help is appreciated, Thank you!
I have prepared a script which takes two parameters,
MyApp.crash
MyApp.xcarchive
And gracefully output the MyApp_symbolicated.crash
Scripts:
#!/bin/bash
if [ "$#" -ne 2 ]; then
echo "Argument missing [symbolicate #logLocation #xcarchiveLocation]"
exit 0
fi
if test -e "$1"; then
echo "$1 exists"
else
echo "$1 does not exist!"
exit 1
fi
if test -e "$2"; then
echo "$2 exists"
else
echo "$2 does not exist!"
exit 1
fi
parentdir=`pwd`
export DEVELOPER_DIR=`xcode-select -p`
PATH=$PATH:$DEVELOPER_DIR
echo $PATH
cd $DEVELOPER_DIR
cd ../SharedFrameworks/
commanddir=`pwd`
command=$commanddir/`find . -name symbolicatecrash`
cd $parentdir
crashlog="$1"
archive="$2"
outputdir=`dirname "$crashlog"`
nfile=$(echo $1 | rev | cut -f 2- -d '.' | rev)
outputfile="$nfile"_symbolicated.crash
echo $nfile
desymfile="$archive"/dSYMs/*.dSYM
$command -v "$crashlog" "$desymfile" > "$outputfile"
How to use:
create a file symbolicate in /usr/local/bin/
Put the above code in symbolicate file
set execute permission with chmod 777 symbolicate
Run from wherever in your location with proper params
output will be generated in same directory of crash file.
Plug an iOS Device into the Machine that contains the archive in the designated archives folder.
Open the devices window in Xcode.
Open device logs.
Drag an drop your crash report into the list of logs of the device. Wait until it gets resymbolicated.

Unpredictable result with echo command when used in a for loop

I am trying to write a small shell script to find out the signed and unsigned jars in particular directory. While the script works fine until 4-5 jars, it starts showing unpredictable results if my directory has more jars ( currntly about 25 jars). I am not sure but a possible reason for this might be related to buffering of STDIN/STDOUT. I tried to find a resolution for this in related posts but could not get a clear answer.
Here goes my script: ( it takes JAVA_HOME as an argument ):
#! /bin/bash
JV_HOME=$1
for i in `ls *.jar`
do
echo "scanning $i ..."
FILE=$i
$JV_HOME/bin/jarsigner -verify -verbose -certs $FILE | grep "jar verified" ;
if [ $? -eq 0 ]; then
echo "\n$FILE is code-signed\n"
else
echo "\n$FILE is unsigned/unverified..\n"
fi
done
For some of the jars, it says the jar to be unsigned, when they are actually signed when checked individually with the following command:
$JAVA_HOME/bin/jarsigner -verify -verbose -certs
What could possibly be wrong with the above script?
Thanks in advance,
Pabi

Resources