mirror of https://github.com/cutefishos/appmotor
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
342 lines
10 KiB
Python
342 lines
10 KiB
Python
import os, os.path, glob
|
|
import subprocess
|
|
import commands
|
|
import time
|
|
import sys
|
|
import re
|
|
from subprocess import Popen
|
|
from os.path import basename
|
|
|
|
DEV_NULL = file("/dev/null","w")
|
|
DAEMONS_TO_BE_STOPPED = ['xsession/applifed', 'xsession/conndlgs']
|
|
LAUNCHER_BINARY='/usr/bin/applauncherd'
|
|
DEV_NULL = file("/dev/null","w")
|
|
LAUNCHABLE_APPS = ['/usr/bin/fala_ft_hello','/usr/bin/fala_ft_hello1', '/usr/bin/fala_ft_hello2']
|
|
LAUNCHABLE_APPS_QML = ['/usr/bin/fala_qml_helloworld','/usr/bin/fala_qml_helloworld1', '/usr/bin/fala_qml_helloworld2']
|
|
PREFERED_APP = '/usr/bin/fala_ft_hello'
|
|
PREFERED_APP_QML = '/usr/bin/fala_qml_helloworld'
|
|
GET_COORDINATE_SCRIPT = '/usr/share/applauncherd-testscripts/get-coordinates.rb'
|
|
PIXELCHANHED_BINARY = '/usr/bin/fala_pixelchanged'
|
|
|
|
# Function to stop desired daemons. This is also done in setup function
|
|
# if stop_daemons is not called before.
|
|
def stop_daemons():
|
|
for daemon in DAEMONS_TO_BE_STOPPED:
|
|
os.system('initctl stop %s'%(daemon))
|
|
wait_for_single_applauncherd()
|
|
get_booster_pid()
|
|
|
|
# Function to start desired daemons. This is also done in teardown function
|
|
# if start_daemons is not called before.
|
|
def start_daemons():
|
|
for daemon in DAEMONS_TO_BE_STOPPED:
|
|
os.system('initctl start %s'%(daemon))
|
|
wait_for_single_applauncherd()
|
|
get_booster_pid()
|
|
|
|
def daemons_running():
|
|
st, op = commands.getstatusoutput('pgrep %s'%DAEMONS_TO_BE_STOPPED[0].split("/")[1])
|
|
return not(st)
|
|
|
|
def debug(*msg):
|
|
"""
|
|
Debug function
|
|
"""
|
|
sys.stderr.write('[DEBUG %s] %s\n' % (time.ctime(), \
|
|
' '.join([str(s) for s in msg]),))
|
|
|
|
def error(*msg):
|
|
"""
|
|
exit when error, give proper log
|
|
"""
|
|
sys.stderr.write('ERROR %s\n' % (' '.join([str(s) for s in msg]),))
|
|
sys.exit(1)
|
|
|
|
def remove_applauncherd_runtime_files():
|
|
"""
|
|
Removes files that applauncherd leaves behind after it has been stopped
|
|
"""
|
|
debug("Removing files that applauncherd leaves behind after it has been stopped")
|
|
files = glob.glob('/tmp/boost*')
|
|
|
|
for f in files:
|
|
debug("removing %s" % f)
|
|
|
|
try:
|
|
os.remove(f)
|
|
except:
|
|
pass
|
|
|
|
def start_applauncherd():
|
|
debug("Starting applauncherd")
|
|
handle = Popen(['initctl', 'start', 'xsession/applauncherd'],
|
|
stdout = DEV_NULL, stderr = DEV_NULL,
|
|
shell = False)
|
|
get_booster_pid()
|
|
return handle.wait() == 0
|
|
|
|
def stop_applauncherd():
|
|
debug("Stoping applauncherd")
|
|
handle = Popen(['initctl', 'stop', 'xsession/applauncherd'],
|
|
stdout = DEV_NULL, stderr = DEV_NULL,
|
|
shell = False)
|
|
|
|
time.sleep(1)
|
|
|
|
remove_applauncherd_runtime_files()
|
|
|
|
return handle.wait()
|
|
|
|
def restart_applauncherd():
|
|
debug("Restart applauncherd")
|
|
stop_applauncherd()
|
|
start_applauncherd()
|
|
|
|
def run_app_as_user_with_invoker(appname, booster = 'm', arg = "", out = DEV_NULL, err = DEV_NULL):
|
|
"""
|
|
Runs the specified app as a user.
|
|
"""
|
|
inv_cmd = "/usr/bin/invoker --type=%s %s %s" %(booster,arg, appname)
|
|
debug("run %s as user" %inv_cmd)
|
|
cmd = ['su', '-', 'user', '-c']
|
|
if type(appname) == list:
|
|
cmd += inv_cmd
|
|
elif type(appname) == str:
|
|
cmd.append(inv_cmd)
|
|
else:
|
|
raise TypeError("List or string expected")
|
|
p = subprocess.Popen(cmd, shell = False,
|
|
stdout = out, stderr = err)
|
|
return p
|
|
|
|
def run_cmd_as_user(cmnd, out = DEV_NULL, err = DEV_NULL):
|
|
"""
|
|
Runs the specified command as a user.
|
|
"""
|
|
debug("run %s as user" %cmnd)
|
|
cmd = ['su', '-', 'user', '-c']
|
|
if type(cmnd) == list:
|
|
cmd += cmnd
|
|
elif type(cmnd) == str:
|
|
cmd.append(cmnd)
|
|
else:
|
|
raise TypeError("List or string expected")
|
|
p = subprocess.Popen(cmd, shell = False,
|
|
stdout = out, stderr = err)
|
|
return p
|
|
|
|
def get_pid(appname):
|
|
temp = basename(appname)[:14]
|
|
st, op = commands.getstatusoutput("pgrep %s" % temp)
|
|
debug("The Pid of %s is %s" %(appname, op))
|
|
if st == 0:
|
|
return op
|
|
else:
|
|
return None
|
|
|
|
def get_newest_pid(app):
|
|
p = subprocess.Popen(['pgrep', '-n', app], shell = False,
|
|
stdout = subprocess.PIPE, stderr = DEV_NULL)
|
|
|
|
op = p.communicate()[0]
|
|
|
|
debug("The New Pid of %s is %s" %(app, op.strip()))
|
|
if p.wait() == 0:
|
|
return op.strip()
|
|
|
|
return None
|
|
|
|
def wait_for_app(app = None, timeout = 40, sleep = 1):
|
|
"""
|
|
Waits for an application to start. Checks periodically if
|
|
the app is running for a maximum wait set in timeout.
|
|
|
|
Returns the pid of the application if it was running before
|
|
the timeout finished, otherwise None is returned.
|
|
"""
|
|
|
|
pid = None
|
|
start = time.time()
|
|
|
|
while pid == None and time.time() < start + timeout:
|
|
pid = get_newest_pid(app)
|
|
|
|
if pid != None:
|
|
break
|
|
|
|
debug("waiting %s secs for %s" % (sleep, app))
|
|
|
|
time.sleep(sleep)
|
|
|
|
return pid
|
|
|
|
def wait_for_single_applauncherd(timeout = 20, sleep = 1):
|
|
pid = get_pid('applauncherd')
|
|
count = len(pid.split("\n"))
|
|
start = time.time()
|
|
|
|
while count > 1 and time.time() < start + timeout:
|
|
|
|
debug("waiting %s secs for single applauncherd" %sleep)
|
|
time.sleep(sleep)
|
|
|
|
pid = get_pid('applauncherd')
|
|
count = len(pid.split("\n"))
|
|
if count == 1:
|
|
break
|
|
return pid
|
|
|
|
def get_booster_pid():
|
|
wait_for_app('booster-q')
|
|
wait_for_app('booster-e')
|
|
wait_for_app('booster-d')
|
|
wait_for_app('booster-m')
|
|
|
|
def kill_process(appname=None, apppid=None, signum=15):
|
|
# obtained by running 'kill -l'
|
|
signal = {1: "HUP", 2: "INT", 3: "QUIT", 4: "ILL", 5: "TRAP", 6: "ABRT", 7: "BUS",
|
|
8: "FPE", 9: "KILL", 10: "USR1", 11: "SEGV", 12: "USR2", 13: "PIPE",
|
|
14: "ALRM", 15: "TERM", 16: "STKFLT", 17: "CHLD", 18: "CONT", 19: "STOP",
|
|
20: "TSTP", 21: "TTIN", 22: "TTOU", 23: "URG", 24: "XCPU", 25: "XFSZ",
|
|
26: "VTALRM", 27: "PROF", 28: "WINCH", 29: "POLL", 30: "PWR", 31: "SYS"}
|
|
if signal.has_key(signum):
|
|
signame = "SIG%s" % signal[signum]
|
|
else:
|
|
# should never reach this
|
|
signame = "signal %s" % signum
|
|
|
|
if apppid and appname:
|
|
return None
|
|
else:
|
|
if apppid:
|
|
debug("Now sending %s to the app with pid %s" % (signame, apppid))
|
|
st, op = commands.getstatusoutput("kill -%s %s" % (str(signum), str(apppid)))
|
|
if appname:
|
|
debug("Now sending %s to %s" % (signame, appname))
|
|
temp = basename(appname)[:14]
|
|
st, op = commands.getstatusoutput("pkill -%s %s" % (str(signum), temp))
|
|
|
|
def process_state(processid):
|
|
st, op = commands.getstatusoutput('cat /proc/%s/stat' %processid)
|
|
debug("The Process State of %s is %s" %(processid, op))
|
|
if st == 0:
|
|
return op
|
|
else:
|
|
debug(op)
|
|
return None
|
|
|
|
def get_creds(path = None, pid = None):
|
|
"""
|
|
Tries to retrieve credentials for a running application
|
|
using either the pid or path. Credentials are returned
|
|
as a string list.
|
|
"""
|
|
|
|
if path != None:
|
|
pid = get_pid(path)
|
|
|
|
if pid == None:
|
|
print 'invalid PID'
|
|
return None
|
|
|
|
handle = Popen(['/usr/bin/creds-get', '-p', str(pid)],
|
|
stdout = subprocess.PIPE)
|
|
|
|
op = handle.communicate()[0].strip()
|
|
handle.wait()
|
|
|
|
if handle.returncode != 0:
|
|
print 'error retrieving credentials'
|
|
return None
|
|
|
|
#self.assert_(handle.returncode == 0, "There was no such PID!")
|
|
debug("creds-get gave >>>>>\n%s\n<<<<<" % op)
|
|
|
|
creds = op.split("\n")[1:]
|
|
|
|
return creds
|
|
|
|
def launch_and_get_creds(path):
|
|
"""
|
|
Tries to launch an application and if successful, returns the
|
|
credentials the application has as a list.
|
|
"""
|
|
|
|
# try launch the specified application
|
|
handle = run_app_as_user_with_invoker(path,arg = '--no-wait')
|
|
|
|
# sleep for a moment to allow applauncherd to start the process
|
|
time.sleep(3)
|
|
|
|
# with luck, the process should have correct name by now
|
|
pid = get_pid(path)
|
|
|
|
debug("%s has PID %s" % (basename(path), pid,))
|
|
|
|
if pid == None:
|
|
print "couldn't launch %s" % basename(path)
|
|
return None
|
|
|
|
creds = get_creds(pid = pid)
|
|
|
|
kill_process(path)
|
|
|
|
return creds
|
|
|
|
def get_file_descriptor(booster, type, app_name):
|
|
"""
|
|
To test that file descriptors are closed before calling application main
|
|
"""
|
|
#get fd of booster before launching application
|
|
debug("get fd of booster before launching application")
|
|
pid = commands.getoutput("pgrep '%s$'" %booster)
|
|
fd_info = commands.getoutput('ls -l /proc/%s/fd/' % str(pid))
|
|
fd_info = fd_info.split('\n')
|
|
init = {}
|
|
final = {}
|
|
|
|
for fd in fd_info:
|
|
if "->" in fd:
|
|
init[fd.split(" -> ")[0].split(' ')[-1]] = fd.split(" -> ")[-1]
|
|
debug("\nThe initial file descriptors are : %s\n" %init)
|
|
|
|
#launch application using booster
|
|
debug("launch %s using booster" % app_name)
|
|
st = os.system('invoker --type=%s --no-wait /usr/bin/%s' % (type, app_name))
|
|
time.sleep(4)
|
|
|
|
#get fd of booster after launching the application
|
|
debug("get fd of booster after launching the application")
|
|
if st == 0:
|
|
fd_info = commands.getoutput('ls -l /proc/%s/fd/' % str(pid))
|
|
fd_info = fd_info.split('\n')
|
|
for fd in fd_info:
|
|
if "->" in fd:
|
|
final[fd.split(" -> ")[0].split(' ')[-1]] = fd.split(" -> ")[-1]
|
|
debug("\nThe final file descriptors are : %s\n" %final)
|
|
pid = commands.getoutput('pgrep %s' % app_name)
|
|
|
|
mykeys = init.keys()
|
|
count = 0
|
|
|
|
for key in mykeys:
|
|
try:
|
|
if init[key] != final[key]:
|
|
count = count + 1
|
|
except KeyError:
|
|
print "some key in init is not in final"
|
|
time.sleep(4)
|
|
debug("The number of changed file descriptors %d" %count)
|
|
kill_process(apppid=pid)
|
|
return count
|
|
|
|
def get_groups_for_user():
|
|
# get supplementary groups user belongs to (doesn't return
|
|
# the gid group)
|
|
p = run_cmd_as_user('id -Gn', out = subprocess.PIPE)
|
|
groups = p.communicate()[0].split()
|
|
debug("The groups for users is :%s" %groups)
|
|
p.wait()
|
|
|
|
return groups
|