Skip to content

Instantly share code, notes, and snippets.

@stackedsax
Created May 8, 2012 21:42
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save stackedsax/2639601 to your computer and use it in GitHub Desktop.
Save stackedsax/2639601 to your computer and use it in GitHub Desktop.
Script for starting up multiple android emulators per box
#!/bin/bash
#####
#
# This script creates android emulators on the fly.
#
# Please refer to the README for usage instructions.
#
####
# Set-up ANDROID_SDK_HOME
# this creates all the AVD's and the emulator will look for them in the same location
if [ "x${avd_dir}" != "x" ]; then
export ANDROID_SDK_HOME="${avd_dir}"
else
export ANDROID_SDK_HOME="/var/yandroid_sdk/avd_dir"
fi
# set the directory to find the current webdriver apk
## I downlaod the apk separately and keep it somewhere special
if [ "x${selenium_grid_android_server__apk_dir}" != "x" ]; then
APK_DIR="${apk_dir}"
else
APK_DIR="/usr/lib/selenium_grid_android_server"
fi
# grab some variables
## emulator_count
if [ "x${emulator_count}" != "x" ]; then
EMULATOR_COUNT="${emulator_count}"
else
EMULATOR_COUNT="1"
fi
## android_target
if [ "x${android_target}" != "x" ]; then
ANDROID_TARGET="${android_target}"
else
ANDROID_TARGET="anrdoid-15"
fi
## android_target
if [ "x${android_abi}" != "x" ]; then
ANDROID_ABI="${android_abi}"
else
ANDROID_ABI="x86"
fi
## sdcard_size
if [ "x${sdcard_size}" != "x" ]; then
SDCARD="${sdcard_size}"
else
SDCARD="60M"
fi
## port number to start searching for free ports for the console
if [ "x${console_port_start}" != "x" ]; then
console_port="${console_port_start}"
else
console_port="5554"
fi
## port number to start searching for free ports for the listener
if [ "x${listener_port_start}" != "x" ]; then
listener_port="${listener_port_start}"
else
listener_port="8000"
fi
## port number to start searching for free ports for socat
if [ "x${socat_port_start}" != "x" ]; then
socat_port="${socat_port_start}"
else
socat_port="9000"
fi
## set the hub_host
if [ "x${hub_host}" != "x" ]; then
HUB_HOST="${hub_host}"
else
HUB_HOST="localhost"
fi
## set the hub_port
if [ "x${hub_port}" != "x" ]; then
HUB_PORT="${hub_port}"
else
HUB_PORT="4444"
fi
## set the local ip
LOCAL_IP=`hostname -i`
# Funtions
# Create an array of free port numbers to use for the emulators
# Yes, this looks unnecessarily complex, but CONSOLE_PORT needs to
# be an even integer and can only be within a range of 5554-5584.
function findFreePorts {
k=0
for (( i=0 ; i < $EMULATOR_COUNT; i++ ))
{
while netstat -atwn | grep "^.*{console_port}.*:\*\s*LISTEN\s*$"
do
#Console Port should and can only be an even number
#Android allows only even numbers
console_port=$(( ${console_port} + 2 ))
echo PORT1 ${console_port}
done
ports[k]=${console_port}
k=$(( $k + 1 ))
while netstat -atwn | grep "^.*{listener_port}.*:\*\s*LISTEN\s*$"
do
listener_port=$(( ${listener_port} + 1 ))
echo PORT2 ${listener_port}
done
ports[k]=${listener_port}
k=$(( $k + 1 ))
while netstat -atwn | grep "^.*{socat_port}.*:\*\s*LISTEN\s*$"
do
socat_port=$(( ${socat_port} + 1 ))
echo PORT3 ${socat_port}
done
ports[k]=${socat_port}
k=$(( $k + 1 ))
#Console Port should and can only be an even number
#Android allows only even numbers
console_port=$(( ${console_port} + 2 ))
listener_port=$(( ${listener_port} + 1 ))
socat_port=$(( ${socat_port} + 1 ))
}
}
# create the AVD
function createAVD {
local CONSOLE_PORT=$1
echo no | android -s create avd -n avd_$CONSOLE_PORT -t "$ANDROID_TARGET" -c $SDCARD -f -b $ANDROID_ABI
}
# start the AVD
# This starts the emulator
function startEmulator {
local CONSOLE_PORT=$1
echo "[emulator-$CONSOLE_PORT] Starting emulator with avd avd_$CONSOLE_PORT and console port $CONSOLE_PORT"
emulator -avd avd_$CONSOLE_PORT -port $CONSOLE_PORT -no-boot-anim -noaudio -no-window &
# This waits for emulator to start up
echo "[emulator-$CONSOLE_PORT] Waiting for emulator to boot completely"
wait_for_boot_complete "getprop dev.bootcomplete" 1
wait_for_boot_complete "getprop sys.boot_completed" 1
wait_for_boot_complete "pm path android" package
}
# function to really, really check things are booted up
function wait_for_boot_complete {
local boot_property=$1
local boot_property_test=$2
echo "[emulator-$CONSOLE_PORT] Checking $boot_property..."
local result=`adb -s emulator-$CONSOLE_PORT shell $boot_property 2>/dev/null | grep "$boot_property_test"`
while [ -z $result ]; do
sleep 1
result=`adb -s emulator-$CONSOLE_PORT shell $boot_property 2>/dev/null | grep "$boot_property_test"`
done
echo "[emulator-$CONSOLE_PORT] All boot properties succesful"
}
# Copy the APK in and start webdriver
function installWebdriverAPK {
local CONSOLE_PORT=$1
echo "[emulator-$CONSOLE_PORT] Installing WebDriver apk"
adb -s emulator-$CONSOLE_PORT install $APK_DIR/android-server.apk
}
# Activating Webdriver
function activateWebdriver {
local CONSOLE_PORT=$1
echo "[emulator-$CONSOLE_PORT] Getting out of home screen"
adb -s emulator-$CONSOLE_PORT shell input keyevent 82
adb -s emulator-$CONSOLE_PORT shell input keyevent 4
echo "[emulator-$CONSOLE_PORT] Activating WebDriver app"
adb -s emulator-$CONSOLE_PORT shell am start -a android.intent.action.MAIN -n org.openqa.selenium.android.app/.MainActivity
}
# set up port forwarding
function portForward {
local CONSOLE_PORT=$1
local LISTENER_PORT=$2
echo "[emulator-$CONSOLE_PORT] Setting up port forwarding"
adb -s emulator-$CONSOLE_PORT forward tcp:$LISTENER_PORT tcp:8080
}
# start up socat
function start_socat {
local CONSOLE_PORT=$1
local LISTENER_PORT=$2
local SOCAT_PORT=$3
echo "[emulator-$CONSOLE_PORT] Starting up socat on port $SOCAT_PORT"
socat TCP-LISTEN:$SOCAT_PORT,fork TCP:localhost:$LISTENER_PORT &
}
# register the node on the grid
function register_node {
local CONSOLE_PORT=$1
local SOCAT_PORT=$2
JSON="{'configuration': {'registerCycle': 5000, 'hub': 'http://<HUB_HOST>:<HUB_PORT>/grid/register', 'host': '<LOCAL_IP>', 'proxy': 'org.openqa.grid.selenium.proxy.DefaultRemoteProxy', 'maxSession': 1, 'port': <SOCAT_PORT>, 'hubPort': <HUB_PORT>, 'hubHost': '<HUB_HOST>', 'url': 'http://<LOCAL_IP>:<SOCAT_PORT>', 'remoteHost': 'http://<LOCAL_IP>:<SOCAT_PORT>', 'register': true, 'role': 'node'}, 'class': 'org.openqa.grid.common.RegistrationRequest', 'capabilities': [{'seleniumProtocol': 'WebDriver', 'platform': 'ANDROID', 'browserName': 'android', 'version': null, 'maxInstances': 1}]}"
JSON=${JSON//<HUB_HOST>/$HUB_HOST}
JSON=${JSON//<HUB_PORT>/$HUB_PORT}
JSON=${JSON//<LOCAL_IP>/$LOCAL_IP}
JSON=${JSON//<SOCAT_PORT>/$SOCAT_PORT}
echo "[emulator-$CONSOLE_PORT] json is: ${JSON}"
curl -X POST -d "${JSON}" http://$HUB_HOST:$HUB_PORT/grid/register
}
# create one emulator instance
function createOneEmulatorInstance {
local CONSOLE_PORT=$1
local LISTENER_PORT=$2
local SOCAT_PORT=$3
createAVD $CONSOLE_PORT
startEmulator $CONSOLE_PORT
installWebdriverAPK $CONSOLE_PORT
activateWebdriver $CONSOLE_PORT
portForward $CONSOLE_PORT $LISTENER_PORT
start_socat $CONSOLE_PORT $LISTENER_PORT $SOCAT_PORT
register_node $CONSOLE_PORT $SOCAT_PORT
}
## The main function :)
function main {
# Get an array of free port numbers to use
findFreePorts
# Based on the port number found, create an instance of an emulator up to the EMULATOR_COUNT specified
for (( l=0, i=0 ; l < ${#ports[@]}, i < $EMULATOR_COUNT; i++, l=l+3 ))
{
echo "ports for emulator $((i+1)): console=${ports[$l]}, listener=${ports[$l+1]}, socat=${ports[$l+2]}"
createOneEmulatorInstance ${ports[$l]} ${ports[$l+1]} ${ports[$l+2]} &
}
# Wait until those emulators are registered on the grid
# TODO: make this check an all-in-one comparison, not sequentially checking each IP as it does now.
# However, this won't really block anything more than a millisecond more than reality
for (( l=0, i=0 ; l < ${#ports[@]}, i < $EMULATOR_COUNT; i++, l=l+3 ))
{
echo "[emulator-${ports[$l]}] testing for $LOCAL_IP:${ports[$l+2]} on grid $HUB_HOST:$HUB_PORT ..."
while [[ `curl -s http://$HUB_HOST:$HUB_PORT/grid/console` != *$LOCAL_IP:${ports[$l+2]}* ]]
do
sleep 1
done
echo ""
echo "[emulator-${ports[$l]}] testing for $LOCAL_IP:${ports[$l+2]} on grid $HUB_HOST:$HUB_PORT successful!"
}
echo Emulator startup complete!
}
## Execute the script
main
@isaaclacoba
Copy link

Thanks a lot for publishing this code. It helped me a lot to know how automatically run my tests.

@afjoseph
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment