]> git.lyx.org Git - lyx.git/blobdiff - development/autotests/keytest.py
Adding binary path for Homebrew on MacOS-arm64 (bug 12619).
[lyx.git] / development / autotests / keytest.py
index 7bf240c1371d834a27c012d1f66cb697354dc57b..ce3b2456534a7572748eac54b072ef8752efbb8d 100755 (executable)
@@ -14,6 +14,9 @@ import os
 import re
 import sys
 import time
+import tempfile
+import shutil
+
 #from subprocess import call
 import subprocess
 
@@ -23,6 +26,15 @@ FNULL = open('/dev/null', 'w')
 
 key_delay = ''
 
+# Ignore status == "dead" if this is set. Used at the last commands after "\Cq"
+dead_expected = False
+
+def die(excode, text):
+    if text != "":
+        print(text)
+    sys.stdout.flush()
+    os._exit(excode)
+
 class CommandSource:
 
     def __init__(self):
@@ -61,7 +73,7 @@ class CommandSource:
         if self.count % 200 == 0:
             return 'RaiseLyx'
         elif self.count > self.count_max:
-            os._exit(0)
+            die(0, "")
         else:
             keystr = ''
             for k in range(1, 2):
@@ -140,7 +152,7 @@ class CommandSourceFromFile(CommandSource):
 
     def getCommand(self):
         if self.count >= self.max_count:
-            os._exit(0)
+            die(0, "")
         if self.i >= len(self.lines):
             self.loops = self.loops + 1
             if self.loops >= int(max_loops):
@@ -152,6 +164,76 @@ class CommandSourceFromFile(CommandSource):
         self.i = self.i + 1
         return line
 
+class ControlFile:
+
+    def __init__(self):
+        self.control = re.compile(r'^(C[ONPpRrC])([A-Za-z0-9]*):\s*(.*)$')
+        self.fileformat = re.compile(r'^((\>\>?)[,\s]\s*)?([^\s]+)\s*$')
+        self.cntrfile = dict()
+        # Map keytest marker to pattern-file-marker for searchPatterns.pl
+        self.convertSearchMark = { 'CN': 'Comment: ',
+                                   'CP': 'Simple: ', 'Cp': 'ErrSimple: ',
+                                   'CR': 'Regex: ',  'Cr': 'ErrRegex: '}
+
+    def __open(self, handle, filename):
+        if handle in self.cntrfile:
+            self.cntrfile[handle].close()
+            del self.cntrfile[handle]
+        m = self.fileformat.match(filename)
+        if m:
+            type = m.group(2)
+            filename = m.group(3)
+            if type == '>>':
+                append = True
+            else:
+                append = False
+        else:
+            append = False
+        if append:
+            self.cntrfile[handle] = open(filename, 'a')
+        else:
+            self.cntrfile[handle] = open(filename, 'w')
+
+    def closeall(self):
+        handles = self.cntrfile.keys()
+        for handle in handles:
+            self.__close(handle)
+
+    def __close(self, handle):
+        if handle in self.cntrfile:
+            name = self.cntrfile[handle].name
+            self.cntrfile[handle].close()
+            del self.cntrfile[handle]
+            print("Closed ctrl " + handle + " (" + name + ")")
+
+    # make the method below 'private'
+    def __addline(self, handle, pat):
+        self.cntrfile[handle].writelines(pat + "\n")
+
+    def dispatch(self, c):
+        m = self.control.match(c)
+        if not m:
+            return False
+        command = m.group(1)
+        handle = m.group(2)
+        if handle is None:
+            handle = ""
+        text = m.group(3)
+        if command == "CO":
+            self.__open(handle, text);
+        elif command == "CC":
+            self.__close(handle)
+        else:
+            if handle in self.cntrfile:
+                if command in self.convertSearchMark:
+                    self.__addline(handle, self.convertSearchMark[command] + text)
+                else:
+                    die(1,"Error, Unrecognised Command '" + command + "'")
+            elif handle != "":
+                die(1, "Ctrl-file " + handle + " not in use")
+        return True
+
+
 def get_proc_pid(proc_name):
     pid=os.popen("pidof " + proc_name).read().rstrip()
     return pid
@@ -180,6 +262,8 @@ def lyx_exists():
 # Interruptible os.system()
 def intr_system(cmd, ignore_err = False):
     print("Executing " + cmd)
+    # Assure the output of cmd does not overhaul
+    sys.stdout.flush()
     ret = os.system(cmd)
     if os.WIFSIGNALED(ret):
         raise KeyboardInterrupt
@@ -196,9 +280,10 @@ def printresstatus():
         print("    " + line.rstrip())
     print('End of /proc-lines')
 
-def lyx_status(pid):
+def lyx_status_retry(pid):
     resstatus = []
-    if lyx_pid is None:
+    if pid is None:
+        print('Pid is None')
         return "dead"
     fname = '/proc/' + pid + '/status'
     status = "dead"
@@ -212,6 +297,8 @@ def lyx_status(pid):
                 status = m.group(1)
                 found = True
         f.close()
+        if not found:
+            return "retry"
         return status
     except IOError as e:
         print("I/O error({0}): {1}".format(e.errno, e.strerror))
@@ -219,43 +306,64 @@ def lyx_status(pid):
     except:
         print("Unexpected error:", sys.exc_info()[0])
         return "dead"
+    print('This should not happen')
+    return status
+
+def lyx_status(pid):
+    count = 0
+    while 1:
+        status = lyx_status_retry(pid)
+        if status != "retry":
+            break
+        if count == 0:
+            print('Retrying check for status')
+        count += 1
+        time.sleep(0.01)
+    if count > 1:
+        print('Retried to read status ' + str(count) + ' times')
+    #print('lys_status() returning ' + status)
     return status
 
 # Return true if LyX (identified via lyx_pid) is sleeping
-def lyx_sleeping():
-    return lyx_status(lyx_pid) == "sleeping"
+def lyx_sleeping(LYX_PID):
+    return lyx_status(LYX_PID) == "sleeping"
 
 # Return true if LyX (identified via lyx_pid) is zombie
-def lyx_zombie():
-    return lyx_status(lyx_pid) == "zombie"
+def lyx_zombie(LYX_PID):
+    return lyx_status(LYX_PID) == "zombie"
 
-def lyx_dead():
-    status = lyx_status(lyx_pid)
+def lyx_dead(LYX_PID):
+    status = lyx_status(LYX_PID)
     return (status == "dead") or (status == "zombie")
 
-def wait_until_lyx_sleeping():
+def wait_until_lyx_sleeping(LYX_PID):
     before_secs = time.time()
     while True:
-        status = lyx_status(lyx_pid)
+        status = lyx_status(LYX_PID)
         if status == "sleeping":
-            return
+            return True
         if (status == "dead") or (status == "zombie"):
-            print('Lyx is dead, exiting')
             printresstatus()
-            sys.stdout.flush()
-            os._exit(1)
+            if dead_expected:
+                print('Lyx died while waiting for status == sleeping')
+                return False
+            else:
+                die(1,"Lyx is dead, exiting")
         if time.time() - before_secs > 180:
-            print('Killing due to freeze (KILL_FREEZE)')
-
             # Do profiling, but sysprof has no command line interface?
             # intr_system("killall -KILL lyx")
             printresstatus()
-            sys.stdout.flush()
-            os._exit(1)
+            die(1,"Killing due to freeze (KILL_FREEZE)")
         time.sleep(0.02)
+    # Should be never reached
+    print('Wait for sleeping ends unexpectedly')
+    return False
 
 def sendKeystringLocal(keystr, LYX_PID):
-    wait_until_lyx_sleeping()
+    is_sleeping = wait_until_lyx_sleeping(LYX_PID)
+    if not is_sleeping:
+        print("Not sending \"" + keystr + "\"")
+        return
     if not screenshot_out is None:
         print('Making Screenshot: ' + screenshot_out + ' OF ' + infilename)
         time.sleep(0.2)
@@ -278,85 +386,87 @@ def sendKeystringLocal(keystr, LYX_PID):
     subprocess.call(xvpar, stdout = FNULL, stderr = FNULL)
     sys.stdout.flush()
 
-Axreg = re.compile(r'^(.*)\\Ax([^\\]*)(.*)$')
-returnreg = re.compile(r'(\\\[[A-Z][a-z]+\])(.*)$')
-
-# recursive wrapper around sendKeystringLocal()
-# handling \Ax-entries
-def sendKeystringAx(line, LYX_PID):
-    global key_delay
-    saved_delay = key_delay
-    m = Axreg.match(line)
+def extractmultiple(line, regex):
+    #print("extractmultiple " + line)
+    res = ["", ""]
+    m = regex.match(line)
     if m:
-        prefix = m.group(1)
-        content = m.group(2)
-        rest = m.group(3);
-        if prefix != "":
-            # since (.*) is greedy, check prefix for '\Ax' again
-            sendKeystringAx(prefix, LYX_PID)
-        sendKeystringLocal('\Ax', LYX_PID)
-        time.sleep(0.1)
-        m2 = returnreg.match(rest)
-        if m2:
-            line = m2.group(2)
-            ctrlk = m2.group(1)
-            key_delay = "1"
-            sendKeystringLocal(content + ctrlk, LYX_PID)
-            key_delay = saved_delay
-            time.sleep(controlkey_delay)
-            if line != "":
-                sendKeystringLocal(line, LYX_PID)
+        chr = m.group(1)
+        if m.group(2) == "":
+            res[0] = chr
+            res[1] = ""
         else:
-            if content != "":
-                sendKeystringLocal(content, LYX_PID)
-            if rest != "":
-                sendKeystringLocal(rest, LYX_PID)
+            norm = extractmultiple(m.group(2), regex)
+            res[0] = chr + norm[0]
+            res[1] = norm[1]
     else:
-        if line != "":
-            sendKeystringLocal(line, LYX_PID)
-
-specialkeyreg = re.compile(r'(.+)(\\[AC]([a-zA-Z]|\\\[[A-Z][a-z]+\]).*)$')
-# Split line at start of each meta or controll char
-
-def sendKeystringAC(line, LYX_PID):
-    m = specialkeyreg.match(line)
+        res[0] = ""
+        res[1] = line
+    return res
+
+normal_re = re.compile(r'^([^\\]|\\\\)(.*)$')
+def extractnormal(line):
+    # collect non-special chars from start of line
+    return extractmultiple(line, normal_re)
+
+modifier_re = re.compile(r'^(\\[CAS])(.+)$')
+def extractmodifiers(line):
+    # collect modifiers like '\\A' at start of line
+    return extractmultiple(line, modifier_re)
+
+special_re = re.compile(r'^(\\\[[A-Z][a-z0-9]+\])(.*)$')
+def extractsingle(line):
+    # check for single key following a modifier
+    # either ascii like 'a'
+    # or special like '\[Return]'
+    res = [False, "", ""]
+    m = normal_re.match(line)
     if m:
-        first = m.group(1)
-        second = m.group(2)
-        sendKeystringAC(first, LYX_PID)
-        sendKeystringAC(second, LYX_PID)
+        res[0] = False
+        res[1] = m.group(1)
+        res[2] = m.group(2)
     else:
-        sendKeystringAx(line, LYX_PID)
-
-controlkeyreg = re.compile(r'^(.*\\\[[A-Z][a-z]+\])(.*\\\[[A-Z][a-z]+\])(.*)$')
-# Make sure, only one of \[Return], \[Tab], \[Down], \[Home] etc are in one sent line
-# e.g. split the input line on each keysym
-def sendKeystringRT(line, LYX_PID):
-    m = controlkeyreg.match(line)
-    if m:
-        first = m.group(1)
-        second = m.group(2)
-        third = m.group(3)
-        sendKeystringRT(first, LYX_PID)
-        time.sleep(controlkey_delay)
-        sendKeystringRT(second, LYX_PID)
+        m = special_re.match(line)
+        if m:
+            res[0] = True
+            res[1] = m.group(1)
+            res[2] = m.group(2)
+        else:
+            die(1, "Undecodable key for line \'" + line + "\"")
+    return res
+
+def sendKeystring(line, LYX_PID):
+    if line == "":
+        return
+    normalchars = extractnormal(line)
+    line = normalchars[1]
+    if normalchars[0] != "":
+        sendKeystringLocal(normalchars[0], LYX_PID)
+    if line == "":
+        return
+    modchars = extractmodifiers(line)
+    line = modchars[1]
+    if line == "":
+        die(1, "Missing modified key")
+    modifiedchar = extractsingle(line)
+    line = modifiedchar[2]
+    special = modchars[0] != "" or modifiedchar[0]
+    sendKeystringLocal(modchars[0] + modifiedchar[1], LYX_PID)
+    if special:
+        # give the os time to update the status info (in /proc)
         time.sleep(controlkey_delay)
-        if third != "":
-            sendKeystringRT(third, LYX_PID)
-    else:
-        sendKeystringAC(line, LYX_PID)
+    sendKeystring(line, LYX_PID)
 
 def system_retry(num_retry, cmd):
     i = 0
-    rtn = intr_system(cmd)
+    rtn = intr_system(cmd, True)
     while ( ( i < num_retry ) and ( rtn != 0) ):
         i = i + 1
-        rtn = intr_system(cmd)
+        rtn = intr_system(cmd, True)
         time.sleep(1)
     if ( rtn != 0 ):
         print("Command Failed: "+cmd)
-        print(" EXITING!\n")
-        os._exit(1)
+        die(1," EXITING!")
 
 def RaiseWindow():
     #intr_system("echo x-session-manager PID: $X_PID.")
@@ -366,6 +476,95 @@ def RaiseWindow():
     intr_system("wmctrl -R '"+lyx_window_name+"' ;sleep 0.1")
     system_retry(30, "wmctrl -i -a '"+lyx_window_name+"'")
 
+class Shortcuts:
+
+    def __init__(self):
+        self.shortcut_entry = re.compile(r'^\s*"([^"]+)"\s*\"([^"]+)\"')
+        self.bindings = {}
+        self.unbindings = {}
+        self.bind = re.compile(r'^\s*\\(un)?bind\s+"([^"]+)"')
+        if lyx_userdir_ver is None:
+            self.dir = lyx_userdir
+        else:
+            self.dir = lyx_userdir_ver
+
+    def __UseShortcut(self, c):
+        m = self.shortcut_entry.match(c)
+        if m:
+            sh = m.group(1)
+            fkt = m.group(2)
+            self.bindings[sh] = fkt
+        else:
+            die(1, "cad shortcut spec(" + c + ")")
+
+    def __UnuseShortcut(self, c):
+        m = self.shortcut_entry.match(c)
+        if m:
+            sh = m.group(1)
+            fkt = m.group(2)
+            self.unbindings[sh] = fkt
+        else:
+            die(1, "cad shortcut spec(" + c + ")")
+
+    def __PrepareShortcuts(self):
+        if not self.dir is None:
+            tmp = tempfile.NamedTemporaryFile(suffix='.bind', delete=False)
+            try:
+                old = open(self.dir + '/bind/user.bind', 'r')
+            except IOError as e:
+                old = None
+            if not old is None:
+                lines = old.read().split("\n")
+                old.close()
+                bindfound = False
+                for line in lines:
+                    m = self.bind.match(line)
+                    if m:
+                        bindfound = True
+                        val = m.group(2)
+                        if val in self.bindings:
+                            if self.bindings[val] != "":
+                                tmp.write("\\bind \"" + val + "\" \"" + self.bindings[val] + "\"\n")
+                                self.bindings[val] = ""
+                        elif val in self.unbindings:
+                            if self.unbindings[val] != "":
+                                tmp.write("\\unbind \"" + val + "\" \"" + self.unbindings[val] + "\"\n")
+                                self.unbindings[val] = ""
+                        else:
+                            tmp.write(line + '\n')
+                    elif not bindfound:
+                        tmp.write(line + '\n')
+            else:
+                tmp.writelines(
+                    '## This file is used for keytests only\n\n' +
+                    'Format 4\n\n'
+                )
+            for val in self.bindings:
+                if not self.bindings[val] is None:
+                    if self.bindings[val] != "":
+                        tmp.write("\\bind \"" + val + "\" \"" + self.bindings[val] + "\"\n")
+                        self.bindings[val] = ""
+            for val in self.unbindings:
+                if not self.unbindings[val] is None:
+                    if self.unbindings[val] != "":
+                        tmp.write("\\unbind \"" + val + "\" \"" + self.unbindings[val] + "\"\n")
+                        self.unbindings[val] = ""
+            tmp.close()
+            shutil.move(tmp.name, self.dir + '/bind/user.bind')
+        else:
+            print("User dir not specified")
+
+    def dispatch(self, c):
+        if c[0:12] == 'UseShortcut ':
+            self.__UseShortcut(c[12:])
+        elif c[0:14] == 'UnuseShortcut ':
+            self.__UnuseShortcut(c[14:])
+        elif c == 'PrepareShortcuts':
+            print('Preparing usefull sortcuts for tests')
+            self.__PrepareShortcuts()
+        else:
+            return False
+        return True
 
 lyx_pid = os.environ.get('LYX_PID')
 print('lyx_pid: ' + str(lyx_pid) + '\n')
@@ -376,11 +575,20 @@ lyx_window_name = os.environ.get('LYX_WINDOW_NAME')
 lyx_other_window_name = None
 screenshot_out = os.environ.get('SCREENSHOT_OUT')
 lyx_userdir = os.environ.get('LYX_USERDIR')
+lyx_userdir_ver = os.environ.get('LYX_USERDIR_24x')
+if lyx_userdir is None:
+    lyx_userdir = lyx_userdir_ver
 
 max_loops = os.environ.get('MAX_LOOPS')
 if max_loops is None:
     max_loops = 3
 
+extra_path = os.environ.get('EXTRA_PATH')
+if not extra_path is None:
+  os.environ['PATH'] = extra_path + os.pathsep + os.environ['PATH']
+  print("Added " + extra_path + " to path")
+  print(os.environ['PATH'])
+
 PACKAGE = os.environ.get('PACKAGE')
 if not PACKAGE is None:
   print("PACKAGE = " + PACKAGE + "\n")
@@ -403,9 +611,10 @@ if xvkbd_exe is None:
 
 qt_frontend = os.environ.get('QT_FRONTEND')
 if qt_frontend is None:
-    qt_frontend = 'QT4'
+    qt_frontend = 'QT5'
 if qt_frontend == 'QT5':
-    controlkey_delay = 0.01
+    # Some tests sometimes failed with value 0.01 on Qt5.8
+    controlkey_delay = 0.4
 else:
     controlkey_delay = 0.4
 
@@ -416,7 +625,7 @@ if locale_dir is None:
 def_delay = os.environ.get('XVKBD_DELAY')
 if def_delay is None:
     if qt_frontend == 'QT5':
-        def_delay = '5'
+        def_delay = '1'
     else:
         def_delay = '1'
 
@@ -453,12 +662,13 @@ outfile = open(outfilename, 'w')
 if not lyx_pid is None:
     RaiseWindow()
     # Next command is language dependent
-    #sendKeystringRT("\Afn", lyx_pid)
+    #sendKeystring("\Afn", lyx_pid)
 
 write_commands = True
 failed = False
 lineempty = re.compile(r'^\s*$')
-
+marked = ControlFile()
+shortcuts = Shortcuts()
 while not failed:
     #intr_system('echo -n LOADAVG:; cat /proc/loadavg')
     c = x.getCommand()
@@ -470,6 +680,10 @@ while not failed:
         continue
     outfile.writelines(c + '\n')
     outfile.flush()
+    if marked.dispatch(c):
+        continue
+    elif shortcuts.dispatch(c):
+        continue
     if c[0] == '#':
         print("Ignoring comment line: " + c)
     elif c[0:9] == 'TestBegin':
@@ -480,13 +694,13 @@ while not failed:
             intr_system("killall " + lyx, True)
             time.sleep(0.5)
             intr_system("killall -KILL " + lyx, True)
-        time.sleep(0.2)
+            time.sleep(0.2)
         print("Starting LyX . . .")
         if lyx_userdir is None:
             intr_system(lyx_exe + c[9:] + "&")
         else:
             intr_system(lyx_exe + " -userdir " + lyx_userdir + " " + c[9:] + "&")
-        count = 5
+        count = 10
         old_lyx_pid = "-7"
         old_lyx_window_name = None
         print("Waiting for LyX to show up . . .")
@@ -504,7 +718,7 @@ while not failed:
                     break
             else:
                 count = count - 1
-            time.sleep(1)
+            time.sleep(0.5)
         if count <= 0:
             print('Timeout: could not start ' + lyx_exe, '\n')
             sys.stdout.flush()
@@ -512,8 +726,8 @@ while not failed:
         else:
             print('lyx_pid: ' + lyx_pid)
             print('lyx_win: ' + lyx_window_name)
-            sendKeystringLocal("\C\[Home]", lyx_pid)
-            time.sleep(controlkey_delay)
+            dead_expected = False
+            sendKeystring("\C\[Home]", lyx_pid)
     elif c[0:5] == 'Sleep':
         print("Sleeping for " + c[6:] + " seconds")
         time.sleep(float(c[6:]))
@@ -529,66 +743,75 @@ while not failed:
         RaiseWindow()
     elif c[0:4] == 'KK: ':
         if lyx_exists():
-            sendKeystringRT(c[4:], lyx_pid)
+            sendKeystring(c[4:], lyx_pid)
         else:
             ##intr_system('killall lyx; sleep 2 ; killall -9 lyx')
             if lyx_pid is None:
-              print('No path /proc/xxxx/status, exiting')
+              die(1, 'No path /proc/xxxx/status, exiting')
             else:
-              print('No path /proc/' + lyx_pid + '/status, exiting')
-            os._exit(1)
+              die(1, 'No path /proc/' + lyx_pid + '/status, exiting')
     elif c[0:4] == 'KD: ':
         key_delay = c[4:].rstrip('\n')
         print('Setting DELAY to ' + key_delay)
     elif c == 'Loop':
         RaiseWindow()
-        sendKeystringRT(ResetCommand, lyx_pid)
+        sendKeystring(ResetCommand, lyx_pid)
     elif c[0:6] == 'Assert':
         cmd = c[7:].rstrip()
-        result = intr_system(cmd)
+        result = intr_system(cmd, True)
         failed = failed or (result != 0)
         print("result=" + str(result) + ", failed=" + str(failed))
     elif c[0:15] == 'TestEndWithKill':
+        marked.closeall()
         cmd = c[16:].rstrip()
-        if lyx_dead():
+        if lyx_dead(lyx_pid):
             print("LyX instance not found because of crash or assert !\n")
             failed = True
         else:
             print("    ------------    Forcing kill of lyx instance: " + str(lyx_pid) + "    ------------")
             # This line below is there only to allow lyx to update its log-file
-            sendKeystringLocal("\[Escape]", lyx_pid)
-            while not lyx_dead():
+            sendKeystring("\[Escape]", lyx_pid)
+            dead_expected = True
+            while not lyx_dead(lyx_pid):
                 intr_system("kill -9 " + str(lyx_pid), True);
                 time.sleep(0.5)
             if cmd != "":
                 print("Executing " + cmd)
-                result = intr_system(cmd)
+                result = intr_system(cmd, True)
                 failed = failed or (result != 0)
                 print("result=" + str(result) + ", failed=" + str(failed))
             else:
                 print("failed=" + str(failed))
     elif c[0:7] == 'TestEnd':
-        #lyx_other_window_name = None
-        if lyx_dead():
+         #lyx_other_window_name = None
+        if lyx_dead(lyx_pid):
             print("LyX instance not found because of crash or assert !\n")
+            marked.closeall()
             failed = True
         else:
             print("    ------------    Forcing quit of lyx instance: " + str(lyx_pid) + "    ------------")
-            # \Ax Enter command line is sometimes blocked
-            # \[Escape] works after this
-            sendKeystringAx("\Ax\[Escape]", lyx_pid)
-            time.sleep(controlkey_delay)
+            # \[Escape]+ should work as RESET focus to main window
+            sendKeystring("\[Escape]\[Escape]\[Escape]\[Escape]", lyx_pid)
             # now we should be outside any dialog
             # and so the function lyx-quit should work
-            sendKeystringLocal("\Cq", lyx_pid)
+            sendKeystring("\Cq", lyx_pid)
+            marked.dispatch('CP: action=lyx-quit')
+            marked.dispatch('CC:')
             time.sleep(0.5)
-            if lyx_sleeping():
+            dead_expected = True
+            is_sleeping = wait_until_lyx_sleeping(lyx_pid)
+            if is_sleeping:
+                print('wait_until_lyx_sleeping() indicated "sleeping"')
+                # For a short time lyx-status is 'sleeping', even if it is nearly dead.
+                # Without the wait below, the \[Tab]-char is sent to nirvana
+                # causing a 'beep'
+                time.sleep(0.5)
                 # probably waiting for Save/Discard/Abort, we select 'Discard'
-                sendKeystringRT("\[Tab]\[Return]", lyx_pid)
+                sendKeystring("\[Tab]\[Return]", lyx_pid)
                 lcount = 0
             else:
                 lcount = 1
-            while not lyx_dead():
+            while not lyx_dead(lyx_pid):
                 lcount = lcount + 1
                 if lcount > 20:
                     print("LyX still up, killing process and waiting for it to die...\n")
@@ -597,7 +820,7 @@ while not failed:
         cmd = c[8:].rstrip()
         if cmd != "":
             print("Executing " + cmd)
-            result = intr_system(cmd)
+            result = intr_system(cmd, True)
             failed = failed or (result != 0)
             print("result=" + str(result) + ", failed=" + str(failed))
         else:
@@ -635,7 +858,7 @@ while not failed:
             print('Could not determine PACKAGE name needed for translations\n')
             failed = True
         else:
-          lyx_name = PACKAGE
+            lyx_name = PACKAGE
         intr_system("mkdir -p " + locale_dir + "/" + ccode + "/LC_MESSAGES")
         intr_system("rm -f " + locale_dir + "/" + ccode + "/LC_MESSAGES/" + lyx_name + ".mo")
         if PO_BUILD_DIR is None:
@@ -650,10 +873,8 @@ while not failed:
         print("Unrecognised Command '" + c + "'\n")
         failed = True
 
-print("Test case terminated: ")
+print("Test case terminated: ", end = '')
 if failed:
-    print("FAIL\n")
-    os._exit(1)
+    die(1,"FAIL")
 else:
-    print("Ok\n")
-    os._exit(0)
+    die(0, "Ok")