Bug 1195288 - consider using python webserver for production talos. r=jmaher
authorJulien Pagès <j.parkouss@gmail.com>
Tue, 18 Aug 2015 13:39:09 +0200
changeset 999 335a890ad040
parent 998 e970f49a2dd2
child 1000 3625fcaa75ea
push id688
push userj.parkouss@gmail.com
push dateWed, 19 Aug 2015 19:59:48 +0000
reviewersjmaher
bugs1195288
Bug 1195288 - consider using python webserver for production talos. r=jmaher
talos/config.py
talos/run_tests.py
--- a/talos/config.py
+++ b/talos/config.py
@@ -83,21 +83,20 @@ def parse_args(argv=None):
             help="Filename to store the errors found during the test."
                  " Currently used for xperf only.")
     add_arg('--noShutdown', dest='shutdown', action='store_true',
             help="Record time browser takes to shutdown after testing")
     add_arg('--setPref', action='append', default=[], dest="extraPrefs",
             metavar="PREF=VALUE",
             help="defines an extra user preference")
     add_arg('--webServer', dest='webserver',
-            help="address of the webserver hosting the talos files")
+            help="DEPRECATED")
     add_arg('--develop', action='store_true', default=False,
             help="useful for running tests on a developer machine."
-                 " Creates a local webserver and doesn't upload to the"
-                 " graph servers.")
+                 " Doesn't upload to the graph servers.")
     add_arg('--responsiveness', action='store_true',
             help="turn on responsiveness collection")
     add_arg("--cycles", type=int,
             help="number of browser cycles to run")
     add_arg("--tpmanifest",
             help="manifest file to test")
     add_arg('--tpcycles', type=int,
             help="number of pageloader cycles to run")
@@ -362,19 +361,25 @@ def fix_xperf(config):
                 config['xperf_path'] = xperf_path[1:-1]
                 break
         if not os.path.exists(config['xperf_path']):
             raise ConfigurationError(
                 "xperf.exe cannot be found at the path specified")
 
 
 @validator
-def check_webserver(config):
-    if config['develop'] and not config['webserver']:
-        config['webserver'] = 'localhost:15707'
+def set_webserver(config):
+    # pick a free port
+    import socket
+    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    sock.bind(('', 0))
+    port = sock.getsockname()[1]
+    sock.close()
+
+    config['webserver'] = 'localhost:%d' % port
 
 
 @validator
 def update_prefs(config):
     # if e10s is enabled, set prefs accordingly
     if config['e10s']:
         config['preferences']['browser.tabs.remote.autostart'] = True
     else:
@@ -478,17 +483,17 @@ def get_test(config, global_overrides, c
 
     # fix up url
     url = getattr(test_instance, 'url', None)
     if url:
         test_instance.url = utils.interpolate(convert_url(config, url))
 
     # fix up tpmanifest
     tpmanifest = getattr(test_instance, 'tpmanifest', None)
-    if tpmanifest and config.get('develop'):
+    if tpmanifest:
         test_instance.tpmanifest = \
             build_manifest(config, utils.interpolate(tpmanifest))
 
     # add any counters
     if counters:
         keys = ('linux_counters', 'mac_counters',
                 'win_counters', 'w7_counters', 'xperf_counters')
         for key in keys:
@@ -515,29 +520,28 @@ def tests(config):
         test_class = test_dict[test_name]
         tests.append(get_test(config, global_overrides, counters,
                               test_class()))
     config['tests'] = tests
 
 
 def get_browser_config(config):
     required = ('preferences', 'extensions', 'browser_path', 'browser_wait',
-                'extra_args', 'buildid', 'env', 'init_url')
+                'extra_args', 'buildid', 'env', 'init_url', 'webserver')
     optional = {'bcontroller_config': '${talos}/bcontroller.json',
                 'branch_name': '',
                 'child_process': 'plugin-container',
                 'develop': False,
                 'e10s': False,
                 'process': '',
                 'repository': None,
                 'sourcestamp': None,
                 'symbols_path': None,
                 'test_name_extension': '',
                 'test_timeout': 1200,
-                'webserver': '',
                 'xperf_path': None,
                 'error_filename': None,
                 }
     browser_config = dict(title=config['title'])
     browser_config.update(dict([(i, config[i]) for i in required]))
     browser_config.update(dict([(i, config.get(i, j))
                           for i, j in optional.items()]))
     return browser_config
--- a/talos/run_tests.py
+++ b/talos/run_tests.py
@@ -7,18 +7,18 @@
 import mozversion
 import mozfile
 import logging
 import os
 import sys
 import time
 import traceback
 import urllib
-import urlparse
 import utils
+import mozhttpd
 
 from talos.results import TalosResults
 from talos.ttest import TTest
 from talos.utils import TalosError, TalosCrash, TalosRegression
 from talos.config import get_configs, ConfigurationError
 
 # directory of this file
 here = os.path.dirname(os.path.realpath(__file__))
@@ -72,38 +72,20 @@ def print_logcat():
             data = f.read()
         for l in data.split('\r'):
             # Buildbot will mark the job as failed if it finds 'ERROR'.
             print l.replace('RROR', 'RR_R')
 
 
 def setup_webserver(webserver):
     """use mozhttpd to setup a webserver"""
-
-    scheme = "http://"
-    if (webserver.startswith('http://') or
-        webserver.startswith('chrome://') or
-        webserver.startswith('file:///')):  # noqa
-
-        scheme = ""
-    elif '://' in webserver:
-        print "Unable to parse user defined webserver: '%s'" % (webserver)
-        sys.exit(2)
+    logging.info("starting webserver on %r" % webserver)
 
-    url = urlparse.urlparse('%s%s' % (scheme, webserver))
-    port = url.port
-
-    if port:
-        import mozhttpd
-        return mozhttpd.MozHttpd(host=url.hostname, port=int(port),
-                                 docroot=here)
-    else:
-        print ("WARNING: unable to start web server without custom port"
-               " configured")
-        return None
+    host, port = webserver.split(':')
+    return mozhttpd.MozHttpd(host=host, port=int(port), docroot=here)
 
 
 def run_tests(config, browser_config):
     """Runs the talos tests on the given configuration and generates a report.
     """
     # get the test data
     tests = config['tests']
     tests = useBaseTestDefaults(config.get('basetest', {}), tests)
@@ -124,16 +106,18 @@ def run_tests(config, browser_config):
         if not test.get('url'):
             # build 'url' for tptest
             test['url'] = buildCommandLine(test)
         test['url'] = utils.interpolate(test['url'])
         test['setup'] = utils.interpolate(test['setup'])
         test['cleanup'] = utils.interpolate(test['cleanup'])
 
     # pass --no-remote to firefox launch, if --develop is specified
+    # we do that to allow locally the user to have another running firefox
+    # instance.
     if browser_config['develop']:
         browser_config['extra_args'] = '--no-remote'
 
     # set defaults
     title = config.get('title', '')
     testdate = config.get('testdate', '')
 
     if browser_config['e10s'] and not title.endswith(".e"):
@@ -201,72 +185,60 @@ def run_tests(config, browser_config):
     else:
         # local mode, output to files
         results_urls = dict(
             results_urls=[os.path.abspath('local.out')],
             datazilla_urls=[os.path.abspath('local.json')]
         )
     talos_results.check_output_formats(results_urls)
 
-    # setup a webserver, if --develop is specified
-    httpd = None
-    if browser_config['develop']:
-        httpd = setup_webserver(browser_config['webserver'])
-        if httpd:
-            httpd.start()
+    httpd = setup_webserver(browser_config['webserver'])
+    httpd.start()
 
-    # run the tests
-    timer = utils.Timer()
-    utils.stamped_msg(title, "Started")
-    for test in tests:
-        testname = test['name']
-        utils.stamped_msg("Running test " + testname, "Started")
+    testname = None
+    try:
+        # run the tests
+        timer = utils.Timer()
+        utils.stamped_msg(title, "Started")
+        for test in tests:
+            testname = test['name']
+            utils.stamped_msg("Running test " + testname, "Started")
 
-        mozfile.remove('logcat.log')
+            mozfile.remove('logcat.log')
 
-        try:
             mytest = TTest()
             if mytest:
                 talos_results.add(mytest.runTest(browser_config, test))
             else:
-                utils.stamped_msg("Error found while running %s" % testname,
-                                  "Error")
-        except TalosRegression:
-            utils.stamped_msg("Detected a regression for " + testname,
-                              "Stopped")
-            print_logcat()
-            if httpd:
-                httpd.stop()
-            # by returning 1, we report an orange to buildbot
-            # http://docs.buildbot.net/latest/developer/results.html
-            return 1
-        except (TalosCrash, TalosError):
-            # NOTE: if we get into this condition, talos has an internal
-            # problem and cannot continue
-            #       this will prevent future tests from running
-            utils.stamped_msg("Failed %s" % testname, "Stopped")
-            TalosError_tb = sys.exc_info()
-            traceback.print_exception(*TalosError_tb)
-            print_logcat()
-            if httpd:
-                httpd.stop()
-            # indicate a failure to buildbot, turn the job red
-            return 2
+                utils.stamped_msg("Error found while running %s"
+                                  % testname, "Error")
 
-        utils.stamped_msg("Completed test " + testname, "Stopped")
+            utils.stamped_msg("Completed test " + testname, "Stopped")
+    except TalosRegression:
+        utils.stamped_msg("Detected a regression for %s" % testname,
+                          "Stopped")
+        # by returning 1, we report an orange to buildbot
+        # http://docs.buildbot.net/latest/developer/results.html
+        return 1
+    except (TalosCrash, TalosError):
+        # NOTE: if we get into this condition, talos has an internal
+        # problem and cannot continue
+        #       this will prevent future tests from running
+        utils.stamped_msg("Failed %s" % testname, "Stopped")
+        traceback.print_exception(*sys.exc_info())
+        # indicate a failure to buildbot, turn the job red
+        return 2
+    finally:
+        httpd.stop()
         print_logcat()
 
     elapsed = timer.elapsed()
     print "cycle time: " + elapsed
     utils.stamped_msg(title, "Stopped")
 
-    # stop the webserver if running
-    if httpd:
-        httpd.stop()
-
     # output results
     if results_urls:
         talos_results.output(results_urls)
         if browser_config['develop']:
             print ("Thanks for running Talos locally. Results are in"
                    " %s and %s" % (results_urls['results_urls'],
                                    results_urls['datazilla_urls']))