Bug 1301776 - Added telemetry-tests command with initial telemetry test with ping server draft
authorJohn Dorlus <jdorlus@mozilla.com>
Fri, 27 Jan 2017 18:00:30 -0500
changeset 496178 a9366c2ab831a3bb170a916b7b84c2d616edc86e
parent 466816 d92fd6b6d6bfc5b566222ae2957e55772d60151a
child 548567 41fddf595c3493d48bfc2650a0d587784c8a2097
push id48547
push userbmo:jdorlus@mozilla.com
push dateThu, 09 Mar 2017 22:18:18 +0000
bugs1301776
milestone54.0a1
Bug 1301776 - Added telemetry-tests command with initial telemetry test with ping server Amended commit with changes. MozReview-Commit-ID: RvhRtrF7QD
toolkit/components/telemetry/tests/marionette_tests/__init__.py
toolkit/components/telemetry/tests/marionette_tests/requirements.txt
toolkit/components/telemetry/tests/marionette_tests/runtests.py
toolkit/components/telemetry/tests/marionette_tests/setup.py
toolkit/components/telemetry/tests/marionette_tests/telemetry_harness/__init__.py
toolkit/components/telemetry/tests/marionette_tests/telemetry_harness/testcase.py
toolkit/components/telemetry/tests/marionette_tests/telemetry_tests/__init__.py
toolkit/components/telemetry/tests/marionette_tests/telemetry_tests/test_telemetry_ping.py
new file mode 100755
--- /dev/null
+++ b/toolkit/components/telemetry/tests/marionette_tests/__init__.py
@@ -0,0 +1,3 @@
+# 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/.
new file mode 100755
--- /dev/null
+++ b/toolkit/components/telemetry/tests/marionette_tests/requirements.txt
@@ -0,0 +1,4 @@
+firefox-puppeteer
+marionette-driver
+requests==2.11.1
+simplejson
new file mode 100755
--- /dev/null
+++ b/toolkit/components/telemetry/tests/marionette_tests/runtests.py
@@ -0,0 +1,14 @@
+# 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/.
+
+from marionette_harness.runtests import cli as mn_cli
+from telemetry_harness.testcase import TelemetryTestCase
+
+
+def cli():
+    mn_cli(testcase_class=TelemetryTestCase)
+
+if __name__ == '__main__':
+    cli()
+
new file mode 100755
--- /dev/null
+++ b/toolkit/components/telemetry/tests/marionette_tests/setup.py
@@ -0,0 +1,43 @@
+# 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
+
+from setuptools import setup, find_packages
+
+PACKAGE_VERSION = '0.1'
+
+THIS_DIR = os.path.dirname(os.path.realpath(__name__))
+
+
+def read(*parts):
+    with open(os.path.join(THIS_DIR, *parts)) as f:
+        return f.read()
+
+setup(name='telemetry-tests',
+      version=PACKAGE_VERSION,
+      description=('A collection of Mozilla Firefox Telemetry tests run '
+                   'with Marionette'),
+      classifiers=[
+          'Environment :: Console',
+          'Intended Audience :: Developers',
+          'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
+          'Natural Language :: English',
+          'Operating System :: OS Independent',
+          'Programming Language :: Python',
+          'Topic :: Software Development :: Libraries :: Python Modules',
+      ],
+      keywords='mozilla',
+      author='Firefox Test Engineering Team',
+      author_email='firefox-test-engineering@mozilla.org',
+      url='https://hg.mozilla.org/mozilla-central/toolkit/telemetry/tests',
+      license='MPL 2.0',
+      packages=find_packages(),
+      zip_safe=False,
+      install_requires=read('requirements.txt').splitlines(),
+      include_package_data=True,
+      entry_points="""
+        [console_scripts]
+        telemetry-tests = runtests:cli
+    """)
new file mode 100755
--- /dev/null
+++ b/toolkit/components/telemetry/tests/marionette_tests/telemetry_harness/__init__.py
@@ -0,0 +1,3 @@
+# 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/.
new file mode 100755
--- /dev/null
+++ b/toolkit/components/telemetry/tests/marionette_tests/telemetry_harness/testcase.py
@@ -0,0 +1,129 @@
+# 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 gzip
+import os
+import re
+import shutil
+import time
+import urllib
+import pdb
+
+import simplejson as json
+from firefox_puppeteer import PuppeteerMixin
+from marionette_driver.errors import MarionetteException
+from marionette_harness import MarionetteTestCase
+from marionette_harness.runner import httpd
+from marionette_driver.by import By
+from marionette_driver.addons import Addons
+
+
+here = os.path.abspath(os.path.dirname(__file__))
+doc_root = os.path.join(os.path.dirname(here), "www")
+temp_dir = os.path.join(os.path.dirname(here), "temp")
+
+
+class TelemetryTestCase(PuppeteerMixin, MarionetteTestCase):
+
+    _addons_install_button_locator = (By.ID, 'react-view')
+
+    ping_list = []
+
+    def setUp(self, *args, **kwargs):
+        super(TelemetryTestCase, self).setUp()
+
+        # Start and configure server
+        self.httpd = httpd.FixtureServer(doc_root)
+        self.httpd.start()
+        ping_route = [("POST", re.compile('/pings.*'), self.pings)]
+        self.httpd.routes.extend(ping_route)
+
+        self.ping_url = '{}pings'.format(self.httpd.get_url('/'))
+
+        telemetry_prefs = {
+            'toolkit.telemetry.send.overrideOfficialCheck': True,
+            'toolkit.telemetry.server': self.ping_url,
+            'toolkit.telemetry.initDelay': '1',
+            'datareporting.healthreport.uploadEnabled': True,
+            'datareporting.policy.dataSubmissionEnabled': False,
+            'datareporting.policy.dataSubmissionPolicyBypassNotification': True,
+            'toolkit.telemetry.log.level': 0,
+            'toolkit.telemetry.log.dump': True
+        }
+
+        # Firefox will be forced to restart with the prefs enforced.
+        self.marionette.enforce_gecko_prefs(telemetry_prefs)
+        if not os.path.exists(temp_dir):
+            os.makedirs(temp_dir)
+
+    def tearDown(self, *args, **kwargs):
+        super(TelemetryTestCase, self).tearDown()
+        self.httpd.stop()
+        # if os.path.exists(temp_dir):
+        #     shutil.rmtree(temp_dir, True)
+        self.marionette.close()
+
+    def trigger_ping(self):
+        current_num_pings = len(TelemetryTestCase.ping_list)
+        time_for_ping = 0
+        try:
+            self._install_addon()
+            # self.marionette.restart(clean=False, in_app= False)
+            while not len(self.ping_list) > current_num_pings:
+                self.logger.info("{} seconds elasped waiting for ping...".format(time_for_ping))
+                time.sleep(1)
+                if time_for_ping > 59:
+                    self.fail("60 second ping timeout exceeded")
+                time_for_ping += 1
+            self.logger.debug('ping received')
+            return TelemetryTestCase.ping_list.pop()
+        except Exception as e:
+            self.fail('Error generating ping: {}'.format(e.message))
+
+    def _install_addon(self):
+        try:
+            file_url = "http://testpilot.firefox.com/static/addon/addon.xpi"
+            addon_path = os.path.join(temp_dir, 'addon.xpi')
+            self.logger.info(addon_path)
+            urllib.urlretrieve(file_url, addon_path)
+            addons = Addons(self.marionette)
+            addons.install(addon_path, False)
+        except MarionetteException as e:
+            self.fail('{} - Error installing addon: {} - '.format(e.cause, e.message))
+
+    def pings(self, request, response):
+        json_data = json.loads(TelemetryTestCase.unpack(request))
+        self.ping_list.append(json_data)
+        return 200
+
+    @property
+    def client_id(self):
+        return self.marionette.execute_script('Cu.import("resource://gre/modules/ClientID.jsm");'
+                                              'return ClientID.getCachedClientID();')
+
+    @property
+    def ping_id(self):
+        pass
+
+    @property
+    def build_id(self):
+        pass
+
+    @property
+    def search_count(self):
+        pass
+
+    @staticmethod
+    def unpack(incoming):
+        post_data = incoming.body
+        if "Content-Encoding" in incoming.headers and incoming.headers["Content-Encoding"] == "gzip":
+            gz_data = post_data
+            with open('temp.gz', 'wb') as gz_file:
+                gz_file.write(gz_data)
+            with gzip.open('temp.gz', 'rb') as unzipped_file:
+                plain_data = unzipped_file.read()
+            os.remove('temp.gz')
+        else:
+            plain_data = post_data
+        return plain_data
new file mode 100755
--- /dev/null
+++ b/toolkit/components/telemetry/tests/marionette_tests/telemetry_tests/__init__.py
@@ -0,0 +1,3 @@
+# 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/.
new file mode 100755
--- /dev/null
+++ b/toolkit/components/telemetry/tests/marionette_tests/telemetry_tests/test_telemetry_ping.py
@@ -0,0 +1,23 @@
+# 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/.
+
+from telemetry_harness.testcase import TelemetryTestCase
+
+
+class TestPingServer(TelemetryTestCase):
+
+    def test_wait_for_ping(self):
+        with self.marionette.using_context(self.marionette.CONTEXT_CONTENT):
+            self.marionette.navigate('http://www.mozilla.com')
+        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
+            self.browser.tabbar.open_tab()
+            assert len(self.browser.tabbar.tabs) == 2
+            self.browser.tabbar.close_tab()
+            assert len(self.browser.tabbar.tabs) == 1
+        ping = self.trigger_ping()
+        with self.marionette.using_context(self.marionette.CONTEXT_CONTENT):
+            self.marionette.navigate('http://testpilot.mozilla.com')
+        assert ping['type'] == 'main'
+
+