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.
		
		
		
		
		
			
		
			
				
	
	
		
			344 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			344 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']
 | 
						|
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()
 | 
						|
#Wait for the camera-ui to be up and running so that no more boosters are used
 | 
						|
    wait_for_app('camera-ui')
 | 
						|
 | 
						|
 | 
						|
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
 |