Bug 500142 Create mozmill and mozmill-one make targets for build automation to use - add the initial targets. r=asuth,gozer
authorMark Banner <bugzilla@standard8.plus.com>
Fri, 24 Jul 2009 08:40:10 +0100
changeset 3125 63a765629dc88fab2c4d8de839b6d5cb7ffb0eec
parent 3124 79a02c573e2cb8a0bcef5e1239cbe99468390a3e
child 3126 5f48e2b67685124bc8120b30d3e054fd806d44d1
push idunknown
push userunknown
push dateunknown
reviewersasuth, gozer
bugs500142
Bug 500142 Create mozmill and mozmill-one make targets for build automation to use - add the initial targets. r=asuth,gozer
mail/Makefile.in
mail/build.mk
mail/makefiles.sh
mail/test/mozmill/Makefile.in
mail/test/mozmill/mozmilltests.list
mail/test/mozmill/runtest.py
mail/test/mozmill/runtestlist.py
--- a/mail/Makefile.in
+++ b/mail/Makefile.in
@@ -47,16 +47,20 @@ DIRS		= base locales components extensio
 
 ifeq ($(OS_ARCH),WINNT)
 ifdef MOZ_INSTALLER
 # though some lasts are more last than others
 DIRS += installer/windows
 endif
 endif
 
+ifdef ENABLE_TESTS
+DIRS += test/mozmill
+endif
+
 include $(topsrcdir)/config/rules.mk
 
 ifeq ($(OS_ARCH),WINNT)
 ifdef MOZ_INSTALLER
 
 # For Windows build the uninstaller during the application build since the
 # uninstaller is included with the application for mar file generation.
 libs::
--- a/mail/build.mk
+++ b/mail/build.mk
@@ -93,8 +93,39 @@ package-compare:
 install::
 	@$(MAKE) -C mail/installer install
 
 source-package::
 	@$(MAKE) -C mail/installer source-package
 
 upload::
 	@$(MAKE) -C mail/installer upload
+
+# Instructions below this line are for mail/ specific tests.
+
+MOZMILLDIR=$(DEPTH)/mozilla/_tests/mozmill
+
+PROGRAM = $(DIST)
+
+ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
+# Mac options
+APP_NAME = $(MOZ_APP_DISPLAYNAME)
+ifdef MOZ_DEBUG
+APP_NAME := $(APP_NAME)Debug
+endif
+PROGRAM = ../../../$(DIST)/$(APP_NAME).app/Contents/MacOS/
+PROGRAM := $(PROGRAM)thunderbird-bin$(BIN_SUFFIX)
+else
+# Non-mac options
+PROGRAM = ../../../$(DIST)/bin/
+PROGRAM := $(PROGRAM)thunderbird$(BIN_SUFFIX)
+endif
+
+ifdef ENABLE_TESTS
+mozmill::
+	cd $(MOZMILLDIR) && MACOSX_DEPLOYMENT_TARGET= $(PYTHON) \
+	runtestlist.py --list=mozmilltests.list --binary=$(PROGRAM) \
+	--dir=$(topsrcdir)/mail/test/mozmill
+
+mozmill-one::
+	cd $(MOZMILLDIR) && MACOSX_DEPLOYMENT_TARGET= $(PYTHON) runtest.py \
+	--test=$(topsrcdir)/mail/test/mozmill/$(SOLO_TEST) --binary=$(PROGRAM)
+endif
--- a/mail/makefiles.sh
+++ b/mail/makefiles.sh
@@ -56,16 +56,17 @@ mail/extensions/Makefile
 mail/extensions/mailviews/Makefile
 mail/extensions/smime/Makefile
 mail/installer/Makefile
 mail/installer/windows/Makefile
 mail/themes/Makefile
 mail/themes/pinstripe/Makefile
 mail/themes/qute/Makefile
 mail/themes/gnomestripe/Makefile
+mail/test/mozmill/Makefile
 "
 
 if test -n "$MOZ_BRANDING_DIRECTORY"; then
   add_makefiles "
     $MOZ_BRANDING_DIRECTORY/Makefile
     $MOZ_BRANDING_DIRECTORY/locales/Makefile
   "
 fi
new file mode 100644
--- /dev/null
+++ b/mail/test/mozmill/Makefile.in
@@ -0,0 +1,73 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = mozmill
+
+include $(topsrcdir)/config/rules.mk
+
+# We're installing to _tests/mozmill
+TARGET_DEPTH = ../..
+include $(MOZILLA_DIR)/build/automation-build.mk
+
+_DEST_DIR = $(MOZDEPTH)/_tests/mozmill
+
+_HARNESS_FILES = \
+	$(srcdir)/runtest.py \
+	$(srcdir)/runtestlist.py \
+	$(srcdir)/mozmilltests.list \
+	automation.py \
+	$(NULL)
+
+GARBAGE += automation.py
+
+$(_DEST_DIR):
+	echo $(_HARNESS_FILES)
+	$(NSINSTALL) -D $@
+
+$(_HARNESS_FILES): $(_DEST_DIR)
+
+# Copy the mozmill bits to $(_DEST_DIR)
+libs:: $(_HARNESS_FILES)
+	echo $(_HARNESS_FILES)
+	$(INSTALL) $(_HARNESS_FILES) $(_DEST_DIR)
new file mode 100644
--- /dev/null
+++ b/mail/test/mozmill/mozmilltests.list
@@ -0,0 +1,4 @@
+bloat
+folder-display
+junk-commands
+search-window
--- a/mail/test/mozmill/runtest.py
+++ b/mail/test/mozmill/runtest.py
@@ -46,16 +46,19 @@ Runs the Bloat test harness
 import sys
 import os
 import shutil
 import mozrunner
 import jsbridge
 import mozmill
 import socket
 import copy
+SCRIPT_DIRECTORY = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
+sys.path.append(SCRIPT_DIRECTORY)
+import automation
 from time import sleep
 
 # We need this because rmtree-ing read-only files fails on Windows
 def rmtree_onerror(func, path, exc_info):
     """
     Error handler for ``shutil.rmtree``.
 
     If the error is due to an access error (read only file)
@@ -128,91 +131,33 @@ class ThunderTestProfile(mozrunner.Thund
         'mail.smtpservers' :  "smtp1",
         'mail.startup.enabledMailCheckOnce' :  True,
         'mailnews.start_page_override.mstone' :  "ignore",
         }
 
     def __init__(self, default_profile=None, profile=None, create_new=True,
                  plugins=[], preferences={}):
         self.init_env()
-        self.init_paths()
+        self.profile_dir = os.path.join(SCRIPT_DIRECTORY, 'mozmillprofile')
+
         mozrunner.Profile.__init__(self, default_profile, profile, create_new, plugins, preferences)
 
 
-    def init_paths(self):
-        global automation
-        self.src_dir = self.find_src_dir()
-        self.obj_dir = self.find_obj_dir()
-
-        self.automation_dir = os.path.join(self.obj_dir, 'mozilla', 'build')
-        sys.path.append(self.automation_dir)
-        import automation
-
-        self.profile_dir = os.path.join(self.obj_dir, 'mozilla',
-                                        '_tests', 'leakprofile')
-        # XXX tidy up
-        if automation.IS_MAC:
-            if automation.IS_DEBUG_BUILD:
-              appName = 'ShredderDebug.app'
-            else:
-              appName = 'Shredder.app'
-            self.bin_dir = os.path.join(self.obj_dir, 'mozilla', 'dist', appName, 'Contents', 'MacOS')
-            appname = 'thunderbird-bin'
-        else:
-            self.bin_dir = os.path.join(self.obj_dir, 'mozilla', 'dist', 'bin')
-            appname = 'thunderbird'
-            if automation.IS_WIN32:
-                appname += '.exe'
-
-        self.app_path = os.path.join(self.bin_dir, appname)
-
-        self.base_test_dir = os.getcwd()
-
-
-    def find_src_dir(self):
-        curdir = os.getcwd()
-        while not os.path.isdir(os.path.join(curdir, '.hg')):
-            curdir, olddir = os.path.split(curdir)
-            if curdir == '':
-                raise Exception("unable to figure out src_dir")
-        return os.path.expanduser(os.path.expandvars(curdir))
-
-    def find_obj_dir(self):
-        if 'MOZCONFIG' in os.environ:
-            mozconfig_path = os.environ['MOZCONFIG']
-        else:
-            mozconfig_path = os.path.join(self.src_dir, '.mozconfig.mk')
-
-        guess_path = os.path.join(self.src_dir, 'mozilla/build/autoconf/config.guess')
-        config_guess = os.popen("sh " + guess_path).read()
-        config_guess = config_guess.strip()
-        f = open(mozconfig_path, 'rt')
-        for line in f:
-            if 'MOZ_OBJDIR' in line:
-                varpath = line.split('=')[1].strip()
-                varpath = varpath.replace('@TOPSRCDIR@', self.src_dir)
-                varpath = varpath.replace('$(TOPSRCDIR)', self.src_dir)
-                varpath = varpath.replace('@CONFIG_GUESS@',config_guess)
-                return os.path.expanduser(os.path.expandvars(varpath))
-        f.close()
-
-        raise Exception("unable to figure out obj_dir")
-
     def init_env(self):
         self.base_env = dict(os.environ)
         # note, we do NOT want to set NO_EM_RESTART or jsbridge wouldn't work
         # avoid dialogs on windows
         self.base_env['XPCOM_DEBUG_BREAK'] = 'stack'
         # do not reuse an existing instance
         self.base_env['MOZ_NO_REMOTE'] = '1'
 
     def _run(self, *args, **extraenv):
         env = self.base_env.copy()
         env.update(extraenv)
-        allArgs = [self.app_path]
+        allArgs = [BINARY]
         allArgs.extend(args)
         proc = automation.Process(allArgs, env=env)
         status = proc.wait()
 
     def create_new_profile(self, default_profile):
         # create a clean directory
         if os.path.exists(self.profile_dir):
             shutil.rmtree(self.profile_dir, onerror=rmtree_onerror)
@@ -243,17 +188,16 @@ class ThunderTestRunner(mozrunner.Thunde
 
 class ThunderTestCLI(mozmill.CLI):
 
     profile_class = ThunderTestProfile
     runner_class = ThunderTestRunner
     parser_options = copy.copy(mozmill.CLI.parser_options)
     parser_options[('-m', '--bloat-tests')] = {"default":None, "dest":"created_profile", "help":"Log file name."}
 
-
     def parse_and_get_runner(self):
         """Parses the command line arguments and returns a runner instance."""
         (options, args) = self.parser.parse_args()
         self.options = options
         self.args = args
         if self.options.plugins is None:
             plugins = []
         else:
@@ -272,16 +216,23 @@ class ThunderTestCLI(mozmill.CLI):
                 shutil.copytree(profilename, workingprofile, False)
                 crea_new = False
                 def_profile = False
             else:
                 def_profile = options.default_profile
                 workingprofile = options.profile
                 crea_new = options.create_new
 
+        # We use a global as there appears to be no easy way of getting the
+        # binary details into the profile without re-implementing what mozmill
+        # gives us.
+        global BINARY
+        BINARY = self.options.binary
+        print BINARY
+
         profile = self.get_profile(def_profile, 
                                    workingprofile, crea_new,
                                    plugins=plugins)
         runner = self.get_runner(binary=self.options.binary, 
                                  profile=profile)
         
         return runner
 
@@ -329,17 +280,20 @@ def prettyPrintException(e):
             else:
                 print '           ', prettifyFilename(path), line
 
 
 import pprint
 def prettyPrintResults():
     for result in TEST_RESULTS:
         #pprint.pprint(result)
-        print 'TEST', result['name'], len(result['fails']) and "FAILED" or "PASSED"
+        if len(result['fails']) == 0:
+            print 'TEST-PASS | ', result['name']
+        else:
+            print 'TEST-UNEXPECTED-FAIL | ', result['name']
         for failure in result['fails']:
             if 'exception' in failure:
                 prettyPrintException(failure['exception'])
 
 import atexit
 atexit.register(prettyPrintResults)
 
 if __name__ == '__main__':
new file mode 100644
--- /dev/null
+++ b/mail/test/mozmill/runtestlist.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mail Bloat Test.
+#
+# The Initial Developer of the Original Code is
+# Mozilla Messaging.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Mark Banner <bugzilla@standard8.plus.com>
+#   Andrew Sutherland <bugzilla@asutherland.org>
+#   Ludovic Hirlimann <ludovic@hirlimann.net>
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+import optparse
+import sys
+import os
+import shutil
+import subprocess
+import logging
+
+SCRIPT_DIRECTORY = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
+
+class RunTestListOptions(optparse.OptionParser):
+    """Parsed run test list command line options."""
+    def __init__(self, **kwargs):
+        optparse.OptionParser.__init__(self, **kwargs)
+        defaults = {}
+
+        self.add_option("--binary",
+                        action = "store", type = "string", dest = "binary",
+                        help = "Binary to be run")
+        defaults["binary"] = ""
+
+        self.add_option("--list",
+                        action = "store", type = "string", dest = "list",
+                        help = "List of tests to be run")
+        defaults["list"] = ""
+
+        self.add_option("--dir",
+                        action = "store", type = "string", dest = "dir",
+                        help = "Directory of the tests, leave blank for current directory")
+        defaults["dir"] = ""
+
+        self.set_defaults(**defaults);
+
+        usage = """\
+Usage instructions for runtestlist.py
+All arguments must be specified.
+"""
+        self.set_usage(usage)
+
+log = logging.getLogger()
+handler = logging.StreamHandler(sys.stdout)
+log.setLevel(logging.INFO)
+log.addHandler(handler)
+
+parser = RunTestListOptions()
+options, args = parser.parse_args()
+
+if options.binary == "" or options.list == "":
+    parser.print_help()
+    sys.exit(1)
+
+totalTestErrors = 0
+totalTestPasses = 0
+totalDirectories = 0
+
+f = open(options.list, 'rt')
+for directory in f:
+    log.info("INFO | (runtestlist.py) | Running directory: %s",
+             directory.rstrip())
+    if options.dir != "":
+        testDirectory = os.path.join(options.dir, directory.rstrip())
+    else:
+        testDirectory = directory.rstrip()
+    args = ["python", "runtest.py", "-t", testDirectory, "--binary",
+                   options.binary]
+    print args
+    outputPipe = subprocess.PIPE
+
+    proc = subprocess.Popen(args, cwd=SCRIPT_DIRECTORY, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
+
+    testErrors = 0
+    testPasses = 0
+
+    line = proc.stdout.readline()
+    while line != "":
+        log.info(line.rstrip())
+        if line.find("TEST-UNEXPECTED-") != -1:
+            testErrors += 1
+        if line.find("TEST-PASS") != -1:
+            testPasses += 1
+        line = proc.stdout.readline()
+
+    result = proc.wait()
+
+    if result != 0:
+        log.info("TEST-UNEXPECTED-FAIL | (runtestlist.py) | Exited with code %d during directory run", result)
+        totalTestErrors += 1
+    else:
+        totalTestPasses += 1
+
+    log.info("INFO | (runtestlist.py) | %s: %d passed, %d failed",
+             directory.rstrip(), testPasses, testErrors)
+    totalTestErrors += testErrors
+    totalTestPasses += testPasses
+    totalDirectories += 1
+
+
+log.info("INFO | (runtestlist.py) | Directories Run: %d, Passed: %d, Failed: %d",
+         totalDirectories, totalTestPasses, totalTestErrors)
+
+if totalTestErrors:
+    sys.exit(1)