Bug 1387265 - Expand talos tp6 to macosx; r=jmaher draft
authorRob Wood <rwood@mozilla.com>
Tue, 15 Aug 2017 15:30:23 -0400
changeset 648373 ad7189968b15ea7cd830d18a0e7033df65d8489f
parent 645963 6213fec03a47275d8fcbf79b951547e3993d677f
child 726807 a7b63e02f6276db4fcdb7425afa4f715d67dabec
push id74736
push userrwood@mozilla.com
push dateThu, 17 Aug 2017 17:34:11 +0000
reviewersjmaher
bugs1387265
milestone57.0a1
Bug 1387265 - Expand talos tp6 to macosx; r=jmaher MozReview-Commit-ID: 78LGHEJNGz4
.hgignore
taskcluster/ci/test/test-sets.yml
taskcluster/ci/test/tests.yml
testing/mozharness/mozharness/mozilla/testing/talos.py
testing/talos/talos/mitmproxy/mitmproxy.py
--- a/.hgignore
+++ b/.hgignore
@@ -135,16 +135,19 @@ GPATH
 ^testing/talos/include/
 ^testing/talos/lib/
 ^testing/talos/talos/tests/tp5n.zip
 ^testing/talos/talos/tests/tp5n.tar.gz
 ^testing/talos/talos/tests/tp5n
 ^testing/talos/talos/tests/devtools/damp.manifest.develop
 ^talos-venv
 ^py3venv
+^testing/talos/talos/mitmproxy/mitmdump
+^testing/talos/talos/mitmproxy/mitmproxy
+^testing/talos/talos/mitmproxy/mitmweb
 
 # Ignore files created when running a reftest.
 ^lextab.py$
 
 # tup database
 ^\.tup
 
 # Ignore Visual Studio Code workspace files.
--- a/taskcluster/ci/test/test-sets.yml
+++ b/taskcluster/ci/test/test-sets.yml
@@ -194,16 +194,17 @@ macosx64-tests-talos:
     - talos-g2
     - talos-g4
     - talos-g5
     - talos-other
     - talos-svgr
     - talos-tp5o
     - talos-perf-reftest
     - talos-perf-reftest-singletons
+    - talos-tp6
 
 linux32-tests:
     - cppunit
     - crashtest
     - firefox-ui-functional-local
     - firefox-ui-functional-remote
     - gtest
     - jittest
--- a/taskcluster/ci/test/tests.yml
+++ b/taskcluster/ci/test/tests.yml
@@ -1547,16 +1547,17 @@ talos-tp5o:
 talos-tp6:
     description: "Talos Tp6"
     suite: talos
     try-name: tp6
     treeherder-symbol: tc-T(tp6)
     run-on-projects:
         by-test-platform:
             windows.*: ['mozilla-beta', 'mozilla-central', 'mozilla-inbound', 'autoland', 'try', 'date']
+            macosx.*: ['mozilla-beta', 'mozilla-central', 'mozilla-inbound', 'autoland', 'try', 'date']
             default: []
     max-run-time: 3600
     mozharness:
         script: talos_script.py
         no-read-buildbot-config: true
         config:
             by-test-platform:
                 macosx.*:
--- a/testing/mozharness/mozharness/mozilla/testing/talos.py
+++ b/testing/mozharness/mozharness/mozilla/testing/talos.py
@@ -394,18 +394,26 @@ class Talos(TestingMixin, MercurialScrip
     def setup_mitmproxy(self):
         """Some talos tests require the use of mitmproxy to playback the pages,
         set it up here.
         """
         if not self.query_mitmproxy_recording_set():
             self.info("Skipping: mitmproxy is not required")
             return
 
-        # setup python 3.x virtualenv
-        self.setup_py3_virtualenv()
+        # tp6 is supported in production only on win and macosx
+        os_name = self.platform_name()
+        if 'win' not in os_name and os_name != 'macosx':
+            self.fatal("Aborting: this test is not supported on this platform.")
+
+        # on windows we need to install a pytyon 3 virtual env; on macosx we
+        # use a mitmdump pre-built binary that doesn't need an external python 3
+        if 'win' in os_name:
+            # setup python 3.x virtualenv
+            self.setup_py3_virtualenv()
 
         # install mitmproxy
         self.install_mitmproxy()
 
         # download the recording set; will be overridden by the --no-download
         if '--no-download' not in self.config['talos_extra_options']:
             self.download_mitmproxy_recording_set()
         else:
@@ -421,19 +429,28 @@ class Talos(TestingMixin, MercurialScrip
         self.py3_create_venv()
         requirements = [os.path.join(self.talos_path, 'talos', 'mitmproxy', 'mitmproxy_requirements.txt')]
         self.py3_install_requirement_files(requirements)
         # add py3 executables path to system path
         sys.path.insert(1, self.py3_path_to_executables())
 
     def install_mitmproxy(self):
         """Install the mitmproxy tool into the Python 3.x env"""
-        self.info("Installing mitmproxy")
-        self.py3_install_modules(modules=['mitmproxy'])
-        self.mitmdump = os.path.join(self.py3_path_to_executables(), 'mitmdump')
+        if 'win' in self.platform_name():
+            self.info("Installing mitmproxy")
+            self.py3_install_modules(modules=['mitmproxy'])
+            self.mitmdump = os.path.join(self.py3_path_to_executables(), 'mitmdump')
+        else:
+            # on macosx we use a prebuilt mitmproxy release binary
+            mitmproxy_bin_url = 'https://github.com/mitmproxy/mitmproxy/releases/download/v2.0.2/mitmproxy-2.0.2-osx.tar.gz'
+            mitmproxy_path = os.path.join(self.talos_path, 'talos', 'mitmproxy')
+            self.mitmdump = os.path.join(mitmproxy_path, 'mitmdump')
+            if not os.path.exists(self.mitmdump):
+                self.download_unpack(mitmproxy_bin_url, mitmproxy_path)
+            self.info('The mitmdump macosx binary is found at: %s' % self.mitmdump)
         self.run_command([self.mitmdump, '--version'], env=self.query_env())
 
     def query_mitmproxy_recording_set(self):
         """Mitmproxy requires external playback archives to be downloaded and extracted"""
         if self.mitmproxy_recording_set:
             return self.mitmproxy_recording_set
         if self.query_talos_json_config() and self.suite is not None:
             self.mitmproxy_recording_set = self.talos_json_config['suites'][self.suite].get('mitmproxy_recording_set', False)
--- a/testing/talos/talos/mitmproxy/mitmproxy.py
+++ b/testing/talos/talos/mitmproxy/mitmproxy.py
@@ -1,13 +1,14 @@
 '''This helps loading mitmproxy's cert and change proxy settings for Firefox.'''
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 import os
+import psutil
 import sys
 import subprocess
 import time
 
 import mozinfo
 
 from mozlog import get_proxy_logger
 
@@ -76,16 +77,20 @@ def is_mitmproxy_cert_installed():
     return True
 
 
 def install_mitmproxy_cert(mitmproxy_proc, browser_path, scripts_path):
     """Install the CA certificate generated by mitmproxy, into Firefox"""
     LOG.info("Installing mitmxproxy CA certficate into Firefox")
     # browser_path is exe, we want install dir
     browser_install = os.path.dirname(browser_path)
+    # on macosx we need to remove the last folders 'Content/MacOS'
+    if mozinfo.os == 'mac':
+        browser_install = browser_install[:-14]
+
     LOG.info('Calling configure_mitmproxy with browser folder: %s' % browser_install)
     configure_mitmproxy(browser_install, scripts_path)
     # cannot continue if failed to add CA cert to Firefox, need to check
     if not is_mitmproxy_cert_installed():
         LOG.error('Aborting: failed to install mitmproxy CA cert into Firefox')
         stop_mitmproxy_playback(mitmproxy_proc)
         sys.exit()
 
@@ -99,52 +104,57 @@ def start_mitmproxy_playback(mitmdump_pa
     # recording names can be provided in comma-separated list; build py list including path
     for recording in mitmproxy_recordings_list:
         mitmproxy_recordings.append(os.path.join(mitmproxy_recording_path, recording))
 
     # cmd line to start mitmproxy playback using custom playback script is as follows:
     # <path>/mitmdump -s "<path>mitmdump-alternate-server-replay/alternate-server-replay.py
     #  <path>recording-1.mp <path>recording-2.mp..."
     param = os.path.join(here, 'alternate-server-replay.py')
+    env = os.environ.copy()
 
     # this part is platform-specific
     if mozinfo.os == 'win':
         param2 = '""' + param.replace('\\', '\\\\\\') + ' ' + \
                  ' '.join(mitmproxy_recordings).replace('\\', '\\\\\\') + '""'
-        env = os.environ.copy()
         sys.path.insert(1, mitmdump_path)
         # mitmproxy needs some DLL's that are a part of Firefox itself, so add to path
         env["PATH"] = os.path.dirname(browser_path) + ";" + env["PATH"]
+    elif mozinfo.os == 'mac':
+        param2 = param + ' ' + ' '.join(mitmproxy_recordings)
+        env["PATH"] = os.path.dirname(browser_path)
     else:
         # TODO: support other platforms, Bug 1366355
-        LOG.error('Aborting: talos mitmproxy is currently only supported on Windows')
+        LOG.error('Aborting: talos mitmproxy is currently only supported on Windows and Mac')
         sys.exit()
 
     command = [mitmdump_path, '-k', '-s', param2]
 
     LOG.info("Starting mitmproxy playback using env path: %s" % env["PATH"])
     LOG.info("Starting mitmproxy playback using command: %s" % ' '.join(command))
     # to turn off mitmproxy log output, use these params for Popen:
     # Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
     mitmproxy_proc = subprocess.Popen(command, env=env)
-    time.sleep(5)
+    time.sleep(10)
     data = mitmproxy_proc.poll()
     if data is None:
         LOG.info("Mitmproxy playback successfully started as pid %d" % mitmproxy_proc.pid)
         return mitmproxy_proc
     # cannot continue as we won't be able to playback the pages
     LOG.error('Aborting: mitmproxy playback process failed to start, poll returned: %s' % data)
     sys.exit()
 
 
 def stop_mitmproxy_playback(mitmproxy_proc):
     """Stop the mitproxy server playback"""
     LOG.info("Stopping mitmproxy playback, klling process %d" % mitmproxy_proc.pid)
-    mitmproxy_proc.kill()
-    time.sleep(5)
-    exit_code = mitmproxy_proc.poll()
-    if exit_code:
-        LOG.info("Successfully killed the mitmproxy playback process")
+    if mozinfo.os == 'mac':
+        mitmproxy_proc.terminate()
     else:
+        mitmproxy_proc.kill()
+    time.sleep(10)
+    if mitmproxy_proc.pid in psutil.pids():
         # I *think* we can still continue, as process will be automatically
         # killed anyway when mozharness is done (?) if not, we won't be able
         # to startup mitmxproy next time if it is already running
         LOG.error("Failed to kill the mitmproxy playback process")
+    else:
+        LOG.info("Successfully killed the mitmproxy playback process")