1[windows,qtip,tip,qbase] a7932594cea9 2009-03-26 15:21 -0400 joel
authorClint Talbert <ctalbert@mozilla.com>
Thu, 26 Mar 2009 12:26:40 -0700
changeset 1 527dc910d556e3649553f3fb0f3beb094bf1eb89
parent 0 a0103806b64dc7ab99e4ffe6cb6ff1389d8d91b9
child 2 ba8ae7730e36a1961756aea20991bbd49c492cce
push id2
push userctalbert@mozilla.com
push dateFri, 27 Mar 2009 01:05:28 +0000
bugs1
1[windows,qtip,tip,qbase] a7932594cea9 2009-03-26 15:21 -0400 joel [mq]: windows
TODO
chromedriver.py
maemkit-chunked.py
maemkit-windows.cfg
maemkit.cfg
maemkit.py
mochidriver.py
refdriver.py
xpcdriver.py
--- a/TODO
+++ b/TODO
@@ -1,4 +1,3 @@
-0) fix maemkit.py file commands (move, copy, etc...)
-1) test xpcshell on fennec
-2) test maemkit on windows
-3) test maemkit on Mac OS
+1) test maemkit on Mac OS
+2) add support for browser-chrome
+3) add support for mmochitest-a11y
--- a/chromedriver.py
+++ b/chromedriver.py
@@ -1,16 +1,17 @@
 import os, re, maemkit
 
 class ChromeDriver(maemkit.MaemKit):
   options = {}
   mochitestCommand = []
   directories = []
 
   def __init__(self, mkit):
+    self.dirtype = mkit.dirtype
     self.addOptions(mkit.config_options["chrome"])
 
   def addOptions(self, input):
     for option in input: self.options[option] = input[option]
     #TODO: figure out if we are doing a splitdirs here (might be required for wince or symbian)
     #TODO: figure out if we are going to support a test-path for chrome
     self.options["backupdir"] = os.path.normpath(os.path.join(self.options["testroot"], self.options["backupdir"]))
 
@@ -49,15 +50,16 @@ class ChromeDriver(maemkit.MaemKit):
     #TODO: this block is the same as MochiDriver except for the --chrome flag
     #TODO: figure out a method for utilizing all the other config/cli options available
     cmd = os.path.normpath(os.path.join(self.options["testroot"], "runtests.py"))
     self.mochitestCommand = ["python " + cmd + " --autorun --close-when-done --chrome"]
     for option in ["utility-path","appname","xre-path","certificate-path"]:
       self.mochitestCommand.append("--" + option + "=" + os.path.normpath(self.options[option]))
     mCommand = " ".join(self.mochitestCommand)
 
-    print "\n".join(self.directories)
-
     for directory in self.directories:
       targetdir = os.path.normpath(os.path.join(self.options["testroot"], "chrome"))
       self.rmdir(targetdir)
       self.copytree(os.path.normpath(os.path.join(self.options["backupdir"], str(directory))), targetdir)
-      self.addCommand(mCommand + " --log-file=" + os.path.normpath(os.path.join(logdir, self.getLogFileName(directory))))
+      self.addCommand(mCommand + " --log-file=" + os.path.normpath(os.path.join(self.options["logdir"], self.getLogFileName(directory))))
+
+  def parseLogs(self):
+    self.stitchLogs()
--- a/maemkit-chunked.py
+++ b/maemkit-chunked.py
@@ -7,19 +7,17 @@ def runTest(kit):
   if (kit.testtype == "reftest"): testdriver = refdriver.Reftest(kit)
   if (kit.testtype == "crashtest"): testdriver = refdriver.Crashtest(kit)
   if (kit.testtype == "xpcshell"): testdriver = xpcdriver.XpcDriver(kit)
 
   if (testdriver != ""):
     testdriver.getTests()
     testdriver.prepTests()
     testdriver.runTests()
-
+    testdriver.parseLogs()
 
 def main():
   mk = maemkit.MaemKit()
-  mk.getConfig()
-  mk.getCli()
   runTest(mk)
 
 if __name__ == "__main__":
   main()
 
new file mode 100644
--- /dev/null
+++ b/maemkit-windows.cfg
@@ -0,0 +1,48 @@
+[general]
+xre-path = c:/release/fennec/xulrunner
+appname = c:/release/fennec/fennec.exe
+total-clients = 1
+client-number = 1
+logdir = logs
+ostype = windows
+debug = 1
+
+[mochitest]
+autorun = True
+close-when-done = True
+test-path =  
+utility-path = c:/release/bin
+certificate-path = c:/release/certs
+split-directories = "toolkit/content/tests/widgets","content/canvas/test","content/html/content/test","layout/style/test","content/base/test","dom/tests/mochitest/dom-level1-core","dom/tests/mochitest/dom-level2-core"
+split-percentage = 20
+testroot = c:/release/mochitest
+log-file = log_mochitests.txt
+
+[chrome]
+autorun = True
+close-when-done = True
+utility-path = c:/release/bin
+certificate-path = c:/release/certs
+backupdir = chrome.bak
+testroot = c:/release/mochitest
+log-file = log_chrome.txt
+
+[reftest]
+split-directories = "layout/reftests/bugs/reftest.list","modules/libpr0n/test/reftest/reftest.list"
+split-percentage = 100
+testroot = c:/release/reftest/tests
+utility-path = c:/release/reftest
+manifest = c:/release/reftest/tests/layout/reftests/reftest.list
+log-file = log_reftest.txt
+
+[crashtest]
+testroot = c:/release/reftest/tests
+utility-path = c:/release/reftest
+manifest = c:/release/reftest/tests/testing/crashtest/crashtests.list
+log-file = log_crashtest.txt
+
+[xpcshell]
+testroot = c:/release/xpcshell/tests
+utility-path = c:/release/xpcshell
+manifest = c:/release/xpcshell/tests/all-test-dirs.list
+log-file = log_xpcshell.txt
--- a/maemkit.cfg
+++ b/maemkit.cfg
@@ -1,14 +1,16 @@
 [general]
 xre-path = /media/mmc1/release/fennec/xulrunner
 appname = /media/mmc1/release/fennec/fennec
 total-clients = 1
 client-number = 1
 logdir = logs
+ostype = linux
+debug = 1
 
 [mochitest]
 autorun = True
 close-when-done = True
 test-path =  
 utility-path = /media/mmc1/release/bin
 certificate-path = /media/mmc1/release/certs
 split-directories = "toolkit/content/tests/widgets","content/canvas/test","content/html/content/test","layout/style/test","content/base/test","dom/tests/mochitest/dom-level1-core","dom/tests/mochitest/dom-level2-core"
@@ -18,24 +20,29 @@ log-file = log_mochitests.txt
 
 [chrome]
 autorun = True
 close-when-done = True
 utility-path = /media/mmc1/release/bin
 certificate-path = /media/mmc1/release/certs
 backupdir = chrome.bak
 testroot = /media/mmc1/release/mochitest
+log-file = log_chrome.txt
 
 [reftest]
 split-directories = "layout/reftests/bugs/reftest.list","modules/libpr0n/test/reftest/reftest.list"
 split-percentage = 100
 testroot = /media/mmc1/release/reftest/tests
 utility-path = /media/mmc1/release/reftest
+manifest = /media/mmc1/release/reftest/tests/layout/reftests/reftest.list
+log-file = log_reftest.txt
 
 [crashtest]
 testroot = /media/mmc1/release/reftest/tests
 utility-path = /media/mmc1/release/reftest
-
+manifest = /media/mmc1/release/reftest/tests/testing/crashtest/crashtests.list
+log-file = log_crashtest.txt
 
 [xpcshell]
-testroot = /media/mmc1/release/_tests
+testroot = /media/mmc1/release/xpcshell/tests
 utility-path = /media/mmc1/release/xpcshell
 manifest = /media/mmc1/release/xpcshell/tests/all-test-dirs.list
+log-file = log_xpcshell.txt
--- a/maemkit.py
+++ b/maemkit.py
@@ -3,26 +3,33 @@ import ConfigParser, optparse
 import datetime, time, subprocess, commands
 
 class MaemKit(object):
   config_options = {}
   default_options = {}
   testtype = "mochitest"
   testdriver = ""
   config_file = "maemkit.cfg"
-
-  #TODO: figure out this in a smarter way.  Really only used for split and sub based on regex
   dirtype = "/"
+  debug = 0
 
   testtypes = ["mochitest","chrome","reftest","crashtest","xpcshell"]
 
   def __init__(self):
     self.defaultOptions()
+    self.getConfig()
+    self.getCli()
+    ostype = self.config_options[self.testtype]["ostype"]
+    if (ostype == "linux"): self.dirtype = "/"
+    if (ostype == "macos"): self.dirtype = "/"
+    if (ostype == "windows"): self.dirtype = "\\\\"
 
   def defaultOptions(self):
+    self.default_options["debug"] = 0
+    self.default_options["ostype"] = "linux"
     self.default_options["close-when-done"] = False
     self.default_options["utility-path"] = "."
     self.default_options["xre-path"] = "."
     self.default_options["certificate-path"] = "certs"
     self.default_options["log-file"] = ""
     self.default_options["autorun"] = False
     self.default_options["console-level"] = ""
     self.default_options["file-level"] = "INFO"
@@ -105,17 +112,17 @@ class MaemKit(object):
     myenv["TOPSRCDIR"] = testroot
     myenv["MOZILLA_FIVE_HOME"] = xrepath
     myenv["LD_LIBRARY_PATH"] = xrepath
 
     parts = []
     for cmd in newcmd.split(" "):
       if (cmd.strip() != ""):
         parts.append(cmd.strip())
-    print " ".join(parts)
+    if (self.debug >= 1): print " ".join(parts)
     sub_proc = subprocess.Popen(parts, bufsize=-1, env=myenv, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
     starttime = datetime.datetime.now()
 
     retVal = ""
     std_out = ""
     std_err = ""
 
     while (datetime.datetime.now() - starttime < datetime.timedelta(minutes=timeout)):
@@ -129,28 +136,66 @@ class MaemKit(object):
         break
       time.sleep(1)                                       
     retVal = std_out + "\n" + std_err
 
     if (datetime.datetime.now() - starttime >= datetime.timedelta(minutes=timeout)):
       retVal = "*** TIMEOUT ***"
     return retVal
 
+  #parse log files, tally results
+  #TODO: test on all types of logs
+  def stitchLogs(self):
+    p = 0
+    f = 0
+    t = 0
+    myre = re.compile('.*TEST\-([A-Z]+).*')
+
+    masterLog = open(os.path.normpath(self.options["log-file"]), "a")
+
+    for root, dirs, files in os.walk(os.path.normpath(self.options["logdir"])):
+      for logFile in files:
+
+        #parse each line, looking for TEST-PASS (pass), TEST-UNEXPECTED-FAIL (fail), TEST-KNOWN-FAIL (todo)
+        fLog = open(os.path.normpath(os.path.join(self.options["logdir"], logFile)), "r")
+        for line in fLog:
+          res = None
+          res = myre.match(line)
+          if (res):
+            if (res.group(1) == "PASS"): p = p + 1
+            if (res.group(1) == "UNEXPECTED"): f = f + 1
+            if (res.group(1) == "KNOWN"): t = t + 1
+            masterLog.write(line)
+
+    masterLog.write("\n\n-------------------------\n")
+    masterLog.write("INFO PASSED: " + str(p) + "\n")
+    masterLog.write("INFO FAILED: " + str(f) + "\n")
+    masterLog.write("INFO TODO: " + str(t) + "\n")
+    masterLog.close()
+
 
   def cleanup(self):
-    #TODO: figure out a method for killing process other than killall.  maybe tskill?  and what about appname instead of fennec
-    self.addCommand("killall fennec")
-    self.addCommand("killall ssltunnel")
-    self.addCommand("killall xpcshell")
+    #TODO: figure out a method for killing process on wince (custom program)
+    #TODO: what if we are using firefox instead of fennec?
+    terminate = "killall"
+    if (self.dirtype == '\\\\'): terminate = "tskill"
+
+    try:
+      self.addCommand(terminate + " fennec")
+      self.addCommand(terminate + " ssltunnel")
+      self.addCommand(terminate + " xpcshell")
+    except:
+      if (self.debug >= 1): print "error in cleanup() command"
+      pass
 
   def getLogFileName(self, aDir):
     # returns the name of a log file from a directory
     logPrefix = "log_"
     logExtension = ".txt"
-    p = re.compile(self.dirtype)
+    p = re.compile("[\/\\\\:]+")
     logMiddle = p.sub('_', aDir)
     logFileName = logPrefix + logMiddle + logExtension
     return logFileName
 
 
   #split a list of tests up to be run as parallel.
   #requires: total-clients and client-number in order to
   #calculate number of list items to return
@@ -173,63 +218,61 @@ class MaemKit(object):
     # return self if we have just 1 client
     return dirlist
 
   def copytree(self, src, dst):
     dest = os.path.normpath(dst)
     source = os.path.normpath(src)
 
     try:
-      print "calling copytree on file: " + source
       if (os.path.isdir(source)):
         shutil.copytree(source, dest)
       else:
         fname = os.path.basename(source)
-        print "copying file from: " + source + "; to: " + os.path.join(dest,fname)
         self.mkdir(dest)
         self.copyfile(source, os.path.join(dest, fname))
     except:
-      print "exception in copytree: " + os.path.normpath(src) + " " + os.path.normpath(dst)
+      if (self.debug > 1): print "exception in copytree: " + os.path.normpath(src) + " " + os.path.normpath(dst)
       pass
 
   def copyfile(self, src, dst):
     dest = os.path.normpath(dst)
     file = os.path.basename(os.path.normpath(src))
     root = os.path.dirname(os.path.normpath(src))
     if (file == "*"): file = ".*"
     p = re.compile(file)
 
     try:
       files = [file for file in os.listdir(root) if p.match(file)]
       for file in files:
         if (os.path.isdir(os.path.join(root,file)) == False):
           shutil.copy(os.path.join(root, file), dest) 
     except:
-      print "exception in copy: " + os.path.normpath(file) + " " + os.path.normpath(dst)
+      if (self.debug > 1): print "exception in copy: " + os.path.normpath(file) + " " + os.path.normpath(dst)
       pass
 
   def move(self, src, dst):
     try:
       dest = os.path.normpath(dst)
       file = os.path.basename(os.path.normpath(src))
       root = os.path.dirname(os.path.normpath(src))
       if (file == "*"): file = ".*"
       p = re.compile(file)
       files = [file for file in os.listdir(root) if p.match(file)]
       for file in files:
         shutil.move(os.path.join(root, file), dest) 
     except:
-      print "exception in move: " + os.path.join(root, file) + " " + dest
+      if (self.debug > 1): print "exception in move: " + os.path.join(root, file) + " " + dest
       pass
 
   def mkdir(self, src):
     try:
       os.makedirs(os.path.normpath(src))
     except:
-      print "exception in mkdir: " + os.path.normpath(src)
+      if (self.debug > 1): print "exception in mkdir: " + os.path.normpath(src)
       pass
 
   def rmdir(self, src):
     try:
       shutil.rmtree(os.path.normpath(src))
     except:
-      print "exception in rmdir: " + os.path.normpath(src)
+      if (self.debug > 1): print "exception in rmdir: " + os.path.normpath(src)
       pass
--- a/mochidriver.py
+++ b/mochidriver.py
@@ -1,55 +1,26 @@
 import os,re,maemkit
 
 class MochiKit(maemkit.MaemKit):
   options = {}
   mochitestCommand = []
 
   def __init__(self, mkit):
+    self.dirtype = mkit.dirtype
     self.addOptions(mkit.config_options["mochitest"])
 
   def addOptions(self, input):
     for option in input:
       if (option == "split-directories"):
         self.options[option] = []
         for part in input[option].split(','): self.options[option].append(os.path.normpath(part.strip('\"')))
       else:
         self.options[option] = input[option]
 
-  #parse log files, tally results
-  def stitchLogs(self):
-    p = 0
-    f = 0
-    t = 0
-    myre = re.compile('.*TEST\-([A-Z]+).*')
-
-    masterLog = open(os.path.normpath(self.options["log-file"]), "a")
-
-    for root, dirs, files in os.walk(os.path.normpath(self.options["logdir"])):
-      for logFile in files:
-
-        #parse each line, looking for TEST-PASS (pass), TEST-UNEXPECTED-FAIL (fail), TEST-KNOWN-FAIL (todo)
-        fLog = open(os.path.normpath(os.path.join(self.options["logdir"], logFile)), "r")
-        for line in fLog:
-          masterLog.write(line)
-          res = None
-          res = myre.match(line)
-          if (res):
-            if (res.group(1) == "PASS"): p = p + 1
-            if (res.group(1) == "UNEXPECTED"): f = f + 1
-            if (res.group(1) == "KNOWN"): t = t + 1
-
-    masterLog.write("\n\n-------------------------\n")
-    masterLog.write("INFO PASSED: " + str(p) + "\n")
-    masterLog.write("INFO FAILED: " + str(f) + "\n")
-    masterLog.write("INFO TODO: " + str(t) + "\n")
-    masterLog.close()
-
-
   #originally written by harthur
   def getDirectories(self, aDir):
     testFilePattern = 'test_.*'
     testsDirPattern = ".*?" + self.dirtype + "tests" + self.dirtype + "(.*)"
 
     #returns the smallest possible directories containing tests (leaves of tests tree)
     dir = []
     relDirectories = []
@@ -100,22 +71,26 @@ class MochiKit(maemkit.MaemKit):
     if (stitch == True):
       myre = re.compile("^([0-9]+)$")
       for dir in dirlist:
         res = myre.match(dir)
         if (res):
           try:
             self.move(os.path.normpath(os.path.join(os.path.join(base_dir, res.group(1)), "*")), base_dir)
             self.rmdir(os.path.normpath(os.path.join(base_dir, res.group(1))))
-          except: print "couldn't find directory: " + res.group(1) + " in " + aDir
+          except: 
+            if (self.debug >= 1): print "couldn't find directory: " + res.group(1) + " in " + aDir
+            pass
 
       try:
         self.move(os.path.normpath(os.path.join(os.path.join(base_dir, "tests"), "*")), base_dir)
         self.rmdir(os.path.normpath(os.path.join(base_dir, "tests")))
-      except: print "no directory tests in: " + aDir
+      except:
+        if (self.debug >= 1): print "no directory tests in: " + aDir
+        pass
     return
 
   def splitDirectory(self, aDir):
 
     num_files = 0
     for root,dirs,files in os.walk(os.path.normpath(os.path.join(os.path.join(self.options["testroot"], "tests"), aDir))):
       num_files = len(files)
       break
@@ -189,10 +164,15 @@ class MochiKit(maemkit.MaemKit):
 
     #TODO: figure out a method for utilizing all the other config/cli options available
     self.mochitestCommand = ["python " + os.path.normpath(os.path.join(self.options["testroot"], "runtests.py")) + " --autorun --close-when-done"]
     for option in ["utility-path","appname","xre-path","certificate-path"]:
       self.mochitestCommand.append("--" + option + "=" + os.path.normpath(self.options[option]))
     mCommand = " ".join(self.mochitestCommand)
 
     for directory in self.directories:
-      self.addCommand(mCommand + " --test-path=" + directory + " --log-file=" + os.path.join(self.options["logdir"],  self.getLogFileName(directory)))
+      mydir = directory.replace('\\', '/')
+      logfile = os.path.join(self.options["logdir"],  self.getLogFileName(directory))
+      self.addCommand(mCommand + " --test-path=" + mydir + " --log-file=" + logfile)
       self.cleanup() #just for safety measures
+
+  def parseLogs(self):
+    self.stitchLogs()
--- a/refdriver.py
+++ b/refdriver.py
@@ -5,16 +5,19 @@ class RefDriver(maemkit.MaemKit):
   directories = []
 
   def addDir(self,targetDir):
     try:
       if (self.directories.index(targetDir) >= 0):
         return
     except ValueError: self.directories.append(targetDir)
 
+  def parseLogs(self):
+    self.stitchLogs()
+
   def parseManifest(self, manifest):
     p = re.compile("^include ([a-zA-Z0-9\\\/\-\.]+)")
 
     rootdir = os.path.dirname(manifest)
 
     #backup manifest, use backup incase we are running again
     self.move(manifest + ".bak", manifest + "")
     self.move(manifest, manifest + ".bak")
@@ -49,19 +52,16 @@ class RefDriver(maemkit.MaemKit):
       if (option == "split-directories"):
         self.options[option] = []
         for part in input[option].split(','): self.options[option].append(os.path.normpath(part.strip('\"')))
       else:
         self.options[option] = input[option]
 
   #split directories, do parallel
   def prepTests(self):
-    logdir = os.path.normpath(str(RefDriver.options["logdir"]))
-    self.rmdir(logdir)
-    self.mkdir(logdir)
 
     for dir in self.directories:
       test = dir.split(os.path.normpath(RefDriver.options["testroot"]))
       test = test[1].lstrip(self.dirtype)
       try:
         if (self.options["split-directories"].index(test) >= 0): self.splitManifest(dir)
       except ValueError: continue
 
@@ -82,51 +82,61 @@ class RefDriver(maemkit.MaemKit):
     while (counter < len(lines)):
       fHandle = open(dir + str(iter), "w")
       for line in lines[counter:counter+max]: fHandle.write(line)
       fHandle.close()
       self.addDir(dir + str(iter))
       iter += 1
       counter += max
 
+  def runTests(self):
+    self.mkLogDir(self.options["logdir"])
+
+    for dir in RefDriver.directories:
+      logfile = os.path.join(self.options["logdir"],  self.getLogFileName(dir))
+      logHandle = open(logfile, "w")
+      utilname = os.path.normpath(os.path.join(self.options["utility-path"], "runreftest.py"))
+      output = RefDriver.addCommand(self, "python " + utilname + " --appname=" + os.path.normpath(RefDriver.options["appname"]) + " " + dir, True)
+      logHandle.write(output)
+      logHandle.close()
+      RefDriver.cleanup(self)
+
 class Reftest(RefDriver):
 
   def __init__(self, mkit):
+    self.dirtype = mkit.dirtype
     self.addOptions(mkit.config_options["reftest"])
 
   def addOptions(self, options):
     RefDriver.addOptions(self, options)
 
   def getTests(self):
     RefDriver.findDirs(self, os.path.normpath(self.options["manifest"]))
 
   def prepTests(self):
     RefDriver.prepTests(self)
 
   def runTests(self):
-    self.mkLogDir(self.options["logdir"])
+    RefDriver.runTests(self)
 
-    for dir in RefDriver.directories:
-      utilname = os.path.normpath(os.path.join(self.options["utility-path"], "runreftest.py"))
-      print RefDriver.addCommand(self, "python " + utilname + " --appname=" + os.path.normpath(RefDriver.options["appname"]) + " " + dir, True)
-      RefDriver.cleanup(self)
+  def parseLogs(self):
+    RefDriver.parseLogs(self)
 
 class Crashtest(RefDriver):
 
   def __init__(self, mkit):
+    self.dirtype = mkit.dirtype
     self.addOptions(mkit.config_options["crashtest"])
 
   def addOptions(self, options):
     RefDriver.addOptions(self, options)
 
   def getTests(self):
     RefDriver.findDirs(self, os.path.normpath(self.options["manifest"]))
 
   def prepTests(self):
     RefDriver.prepTests(self)
 
   def runTests(self):
-    self.mkLogDir(self.options["logdir"])
+    RefDriver.runTests(self)
 
-    for dir in RefDriver.directories:
-      utilname = os.path.normpath(os.path.join(self.options["utility-path"], "runreftest.py"))
-      print RefDriver.addCommand(self, "python " + utilname + " --appname=" + RefDriver.options["appname"] + " " + dir, True)
-      RefDriver.cleanup(self)
+  def parseLogs(self):
+    RefDriver.parseLogs(self)
--- a/xpcdriver.py
+++ b/xpcdriver.py
@@ -1,16 +1,17 @@
 import os, re, maemkit
 
 class XpcDriver(maemkit.MaemKit):
   options = {}
   mochitestCommand = []
   directories = []
 
   def __init__(self, mkit):
+    self.dirtype = mkit.dirtype
     self.addOptions(mkit.config_options["xpcshell"])
 
   def addOptions(self, input):
     for option in input: self.options[option] = input[option]
 
 
   def readManifest(self, manifest):
     manifestdir = os.path.dirname(manifest)
@@ -41,12 +42,18 @@ class XpcDriver(maemkit.MaemKit):
 
     buffered = True
     utilname = os.path.normpath(os.path.join(self.options["utility-path"], "runxpcshelltests.py"))
     command = "python " + utilname
     command += " --xre-path=" + os.path.normpath(self.options["xre-path"]) + " " 
     command += " --manifest=" + os.path.normpath(self.options["manifest"]) + ".maemkit " 
     command += os.path.normpath(os.path.join(self.options["xre-path"], "xpcshell")) + " "
     command += " --keep-going"
+
+    logfile = os.path.join(self.options["logdir"],  self.getLogFileName(self.options["manifest"]))
+    logHandle = open(logfile, "w")
     testResults = self.addCommand(command, buffered)
-    self.cleanup()                                                  
-    print testResults
+    logHandle.write(testResults)
+    logHandle.close()
+    self.cleanup() 
 
+  def parseLogs(self):
+    self.stitchLogs()