[Pkg-mozext-commits] [requestpolicy] 57/80: Marionette: detect Console and Logging errors

David Prévot taffit at moszumanska.debian.org
Sun Jul 5 15:02:30 UTC 2015


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository requestpolicy.

commit 1837bca02fa13b129503a9a849be648ffd095acd
Author: Martin Kimmerle <dev at 256k.de>
Date:   Mon Jun 22 03:24:37 2015 +0200

    Marionette: detect Console and Logging errors
    
    The new `RequestPolicyTestCase` class will check for Logging
    errors and Console errors after each test in its `tearDown`
    method. It will be the base class for all test cases.
    
    Error detection is done in the `ErrorDetection` classes,
    whose functions are again checked by the tests in the
    "test_error_detection.py" file. The DevHelper's ConsoleObserver
    has been extended so that the error count can be reset.
    
    In the "addons" library's `RequestPolicy` class, the enable,
    disable etc. functions directly check for logging/console
    errors. In this manner, a failed shutdown/startup can be
    detected immediately.
---
 src/content/lib/logger.jsm                         | 80 ++++++++++++++++++++++
 .../dev-helper/content/console-observer.jsm        |  6 +-
 .../marionette/rp_puppeteer/api/error_detection.py | 70 +++++++++++++++++++
 tests/marionette/rp_puppeteer/tests/manifest.ini   |  1 +
 tests/marionette/rp_puppeteer/tests/test_addons.py |  8 +--
 .../rp_puppeteer/tests/test_error_detection.py     | 45 ++++++++++++
 tests/marionette/rp_puppeteer/tests/test_prefs.py  |  6 +-
 tests/marionette/rp_puppeteer/ui/addons.py         | 42 ++++++++++--
 tests/marionette/rp_ui_harness/__init__.py         |  4 ++
 tests/marionette/rp_ui_harness/testcases.py        | 49 +++++++++++++
 tests/marionette/tests/test_restartlessness.py     |  6 +-
 tests/marionette/tests/test_setup_page.py          |  4 +-
 12 files changed, 302 insertions(+), 19 deletions(-)

diff --git a/src/content/lib/logger.jsm b/src/content/lib/logger.jsm
index fb2bd18..c6bebcf 100644
--- a/src/content/lib/logger.jsm
+++ b/src/content/lib/logger.jsm
@@ -199,3 +199,83 @@ let Logger = (function() {
 
   return self;
 }());
+
+// #ifdef UNIT_TESTING
+
+/**
+ * Triggers errors for a RequestPolicy unit test.
+ * It's used to test Error Detection from the unit tests.
+ */
+var UnitTestObserver = (function (self) {
+
+  var loggingErrorTopic = "requestpolicy-trigger-logging-error";
+  var consoleErrorTopic = "requestpolicy-trigger-console-error";
+
+  self.startup = function () {
+    Services.obs.addObserver(self, loggingErrorTopic, false);
+    Services.obs.addObserver(self, consoleErrorTopic, false);
+  };
+
+  self.shutdown = function () {
+    Services.obs.removeObserver(self, loggingErrorTopic);
+    Services.obs.removeObserver(self, consoleErrorTopic);
+  };
+
+  /**
+   * Split a string like
+   *   "foo:bar:baz"
+   * to two strings:
+   *   ["foo", "bar:baz"]
+   * Only the first colon counts.
+   */
+  function splitColon(aString) {
+    var index = aString.indexOf(":");
+    if (index === -1) {
+      return [aString, ""]
+    }
+    var part1 = aString.substr(0, index);
+    var part2 = aString.substr(index + 1);
+    return [part1, part2];
+  }
+
+  self.observe = function (aSubject, aTopic, aData) {
+    switch (aTopic) {
+      case loggingErrorTopic:
+        let [logLevel, logMessage] = splitColon(aData);
+
+        if (logLevel === "warning") {
+          Logger.warning(Logger.TYPE_ERROR, logMessage);
+        } else if (logLevel === "severe") {
+          Logger.severe(Logger.TYPE_INTERNAL, logMessage);
+        }
+        break;
+
+      case consoleErrorTopic:
+        if (aData === "ReferenceError") {
+          runAsync(produceReferenceError);
+        }
+        break;
+
+      default:
+        break;
+    }
+  };
+
+  function produceReferenceError() {
+    var localVar = nonexistantVariable;
+  }
+
+  function runAsync(aFunction) {
+    var runnable = {run: aFunction};
+    Services.tm.currentThread.dispatch(runnable,
+        Ci.nsIEventTarget.DISPATCH_NORMAL);
+  }
+
+  return self;
+})({});
+
+ProcessEnvironment.addStartupFunction(Environment.LEVELS.BACKEND,
+                                      UnitTestObserver.startup);
+ProcessEnvironment.addShutdownFunction(Environment.LEVELS.BACKEND,
+                                       UnitTestObserver.shutdown);
+// #endif
diff --git a/tests/helper-addons/dev-helper/content/console-observer.jsm b/tests/helper-addons/dev-helper/content/console-observer.jsm
index 4ad7d8b..3ddfb7b 100644
--- a/tests/helper-addons/dev-helper/content/console-observer.jsm
+++ b/tests/helper-addons/dev-helper/content/console-observer.jsm
@@ -56,8 +56,12 @@ var ConsoleObserver = (function (self) {
     return numErrors;
   };
 
-  self.startup = function () {
+  self.reset = function () {
     numErrors = 0;
+  };
+
+  self.startup = function () {
+    self.reset();
     Services.console.registerListener(self);
   };
 
diff --git a/tests/marionette/rp_puppeteer/api/error_detection.py b/tests/marionette/rp_puppeteer/api/error_detection.py
new file mode 100644
index 0000000..1c8f68c
--- /dev/null
+++ b/tests/marionette/rp_puppeteer/api/error_detection.py
@@ -0,0 +1,70 @@
+# 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 firefox_puppeteer.base import BaseLib
+from firefox_puppeteer.api.prefs import Preferences
+
+ERROR_COUNT_PREF = "extensions.requestpolicy.unitTesting.errorCount"
+
+
+class ErrorDetection(BaseLib):
+    def _notify_observers(self, topic, data):
+        with self.marionette.using_context("chrome"):
+            self.marionette.execute_script(
+                """
+                Components.utils.import("resource://gre/modules/Services.jsm");
+                Services.obs.notifyObservers(null, "{}", "{}");
+                """.format(topic, data))
+
+    def get_error_count(self):
+        raise NotImplementedError
+
+    def reset_error_count(self):
+        raise NotImplementedError
+
+    def trigger_error(self):
+        raise NotImplementedError
+
+
+class LoggingErrorDetection(ErrorDetection):
+    def __init__(self, marionette_getter):
+        BaseLib.__init__(self, marionette_getter)
+
+        self.prefs = Preferences(marionette_getter)
+
+    def get_error_count(self):
+        return self.prefs.get_pref(ERROR_COUNT_PREF)
+
+    def reset_error_count(self):
+        self.prefs.set_pref(ERROR_COUNT_PREF, 0)
+
+    def trigger_error(self, error_type, msg="[Marionette unit test]"):
+        self._notify_observers("requestpolicy-trigger-logging-error",
+                               "{}:{}".format(error_type, msg))
+
+
+class ConsoleErrorDetection(ErrorDetection):
+    def get_error_count(self):
+        with self.marionette.using_context("chrome"):
+            return self.marionette.execute_script(
+                """
+                let scope = {};
+                Components.utils.import("chrome://rpc-dev-helper/" +
+                    "content/console-observer.jsm", scope);
+                return scope.ConsoleObserver.getNumErrors();
+                """)
+
+    def reset_error_count(self):
+        with self.marionette.using_context("chrome"):
+            return self.marionette.execute_script(
+                """
+                let scope = {};
+                Components.utils.import("chrome://rpc-dev-helper/content/" +
+                    "console-observer.jsm", scope);
+                scope.ConsoleObserver.reset();
+                """)
+
+    def trigger_error(self, error_type):
+        self._notify_observers("requestpolicy-trigger-console-error",
+                               error_type)
diff --git a/tests/marionette/rp_puppeteer/tests/manifest.ini b/tests/marionette/rp_puppeteer/tests/manifest.ini
index c0e5d78..ed6a809 100644
--- a/tests/marionette/rp_puppeteer/tests/manifest.ini
+++ b/tests/marionette/rp_puppeteer/tests/manifest.ini
@@ -1,2 +1,3 @@
 [test_addons.py]
+[test_error_detection.py]
 [test_prefs.py]
diff --git a/tests/marionette/rp_puppeteer/tests/test_addons.py b/tests/marionette/rp_puppeteer/tests/test_addons.py
index 673bd3f..e28fba3 100644
--- a/tests/marionette/rp_puppeteer/tests/test_addons.py
+++ b/tests/marionette/rp_puppeteer/tests/test_addons.py
@@ -2,7 +2,7 @@
 # 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 firefox_ui_harness import FirefoxTestCase
+from rp_ui_harness import RequestPolicyTestCase
 
 from rp_puppeteer.ui.addons import Addons, AboutAddonsTab
 
@@ -11,7 +11,7 @@ ADDON_ID = "dummy-ext at requestpolicy.org"
 INSTALL_URL = "http://localhost/link.html?.dist/dummy-ext.xpi"
 
 
-class AddonsTestCase(FirefoxTestCase):
+class AddonsTestCase(RequestPolicyTestCase):
     def selected_tab_is_about_addons(self):
         location = self.browser.tabbar.selected_tab.location
         return location == "about:addons"
@@ -122,7 +122,7 @@ class TestAddons(AddonsTestCase):
 
 class TestAboutAddons(AddonsTestCase):
     def setUp(self):
-        FirefoxTestCase.setUp(self)
+        RequestPolicyTestCase.setUp(self)
 
         Addons(lambda: self.marionette).install_addon(INSTALL_URL)
 
@@ -136,7 +136,7 @@ class TestAboutAddons(AddonsTestCase):
                 self.about_addons.remove_addon(self.addon)
             self.about_addons.close_tab()
         finally:
-            FirefoxTestCase.tearDown(self)
+            RequestPolicyTestCase.tearDown(self)
 
     @property
     def addon(self):
diff --git a/tests/marionette/rp_puppeteer/tests/test_error_detection.py b/tests/marionette/rp_puppeteer/tests/test_error_detection.py
new file mode 100644
index 0000000..2259bb2
--- /dev/null
+++ b/tests/marionette/rp_puppeteer/tests/test_error_detection.py
@@ -0,0 +1,45 @@
+# 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 rp_ui_harness import RequestPolicyTestCase
+from rp_puppeteer.api.error_detection import (LoggingErrorDetection,
+                                              ConsoleErrorDetection)
+
+
+class TestErrorDetection(RequestPolicyTestCase):
+    def test_logging_error_detection(self):
+        error_detect = LoggingErrorDetection(lambda: self.marionette)
+
+        previous_value = error_detect.get_error_count()
+
+        self.assertIsNotNone(previous_value,
+                             msg="The pref for the error count exists.")
+
+        error_detect.trigger_error(
+            "warning", msg="[Marionette] test_logging_error_detection")
+        self.assertEqual(error_detect.get_error_count(), previous_value + 1,
+                         msg="The error has been detected.")
+
+        error_detect.trigger_error(
+            "severe", msg="[Marionette] test_logging_error_detection")
+        self.assertEqual(error_detect.get_error_count(), previous_value + 2,
+                         msg="The severe log message has been detected.")
+
+        error_detect.reset_error_count()
+        self.assertEqual(error_detect.get_error_count(), 0,
+                         msg="The Logging error count has been reset.")
+
+    def test_console_error_detection(self):
+        error_detect = ConsoleErrorDetection(lambda: self.marionette)
+
+        self.assertEqual(error_detect.get_error_count(), 0,
+                         msg="The Console error count is zero.")
+
+        error_detect.trigger_error("ReferenceError")
+        self.assertEqual(error_detect.get_error_count(), 1,
+                         msg="The Console error count has increased.")
+
+        error_detect.reset_error_count()
+        self.assertEqual(error_detect.get_error_count(), 0,
+                         msg="The Console error count has been reset.")
diff --git a/tests/marionette/rp_puppeteer/tests/test_prefs.py b/tests/marionette/rp_puppeteer/tests/test_prefs.py
index e128474..58ae98d 100644
--- a/tests/marionette/rp_puppeteer/tests/test_prefs.py
+++ b/tests/marionette/rp_puppeteer/tests/test_prefs.py
@@ -2,15 +2,15 @@
 # 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 firefox_ui_harness import FirefoxTestCase
+from rp_ui_harness import RequestPolicyTestCase
 
 from rp_puppeteer.api.prefs import using_pref
 
 
-class TestPrefs(FirefoxTestCase):
+class TestPrefs(RequestPolicyTestCase):
 
     def setUp(self):
-        FirefoxTestCase.setUp(self)
+        RequestPolicyTestCase.setUp(self)
 
         self.new_pref = 'marionette.unittest.using_pref'
 
diff --git a/tests/marionette/rp_puppeteer/ui/addons.py b/tests/marionette/rp_puppeteer/ui/addons.py
index 67845f7..830acce 100644
--- a/tests/marionette/rp_puppeteer/ui/addons.py
+++ b/tests/marionette/rp_puppeteer/ui/addons.py
@@ -6,6 +6,8 @@ from marionette_driver.errors import NoSuchElementException
 from marionette_driver.wait import Wait
 from firefox_puppeteer.base import BaseLib
 from firefox_puppeteer.ui.windows import Windows
+from rp_puppeteer.api.error_detection import (LoggingErrorDetection,
+                                              ConsoleErrorDetection)
 from contextlib import contextmanager
 
 
@@ -68,22 +70,50 @@ class RequestPolicy(BaseLib):
 
         self.addons = Addons(marionette_getter)
 
+        self.logging_error_detect = LoggingErrorDetection(marionette_getter)
+        self.console_error_detect = ConsoleErrorDetection(marionette_getter)
+
+    @contextmanager
+    def _ensure_no_errors(self):
+        logging_errors_before = self.logging_error_detect.get_error_count()
+        console_errors_before = self.console_error_detect.get_error_count()
+        yield
+        logging_error_count = (self.logging_error_detect.get_error_count() -
+                               logging_errors_before)
+        console_error_count = (self.console_error_detect.get_error_count() -
+                               console_errors_before)
+        if logging_error_count > 0 and console_error_count > 0:
+            raise Exception("There have been {} Logging errors and "
+                            "{} Console errors!".format(logging_error_count,
+                                                        console_error_count))
+        elif logging_error_count > 0:
+            raise Exception("There have been {} Logging "
+                            "errors!".format(logging_error_count))
+        elif console_error_count > 0:
+            raise Exception("There have been {} Console "
+                            "errors!".format(console_error_count))
+
     @contextmanager
     def install_in_two_steps(self):
-        with self.addons.install_addon_in_two_steps(self.install_url):
-            yield
+        with self._ensure_no_errors():
+            with self.addons.install_addon_in_two_steps(self.install_url):
+                yield
 
     def install(self):
-        self.addons.install_addon(self.install_url)
+        with self._ensure_no_errors():
+            self.addons.install_addon(self.install_url)
 
     def remove(self):
-        self.addons.remove_addon_by_id(self.addon_id)
+        with self._ensure_no_errors():
+            self.addons.remove_addon_by_id(self.addon_id)
 
     def enable(self):
-        self.addons.enable_addon_by_id(self.addon_id)
+        with self._ensure_no_errors():
+            self.addons.enable_addon_by_id(self.addon_id)
 
     def disable(self):
-        self.addons.disable_addon_by_id(self.addon_id)
+        with self._ensure_no_errors():
+            self.addons.disable_addon_by_id(self.addon_id)
 
     def is_installed(self):
         return self.addons.is_addon_installed(self.addon_id)
diff --git a/tests/marionette/rp_ui_harness/__init__.py b/tests/marionette/rp_ui_harness/__init__.py
index 8b13789..c1f6d17 100644
--- a/tests/marionette/rp_ui_harness/__init__.py
+++ b/tests/marionette/rp_ui_harness/__init__.py
@@ -1 +1,5 @@
+# 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 testcases import RequestPolicyTestCase
diff --git a/tests/marionette/rp_ui_harness/testcases.py b/tests/marionette/rp_ui_harness/testcases.py
new file mode 100644
index 0000000..9bd4d1d
--- /dev/null
+++ b/tests/marionette/rp_ui_harness/testcases.py
@@ -0,0 +1,49 @@
+# 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 firefox_ui_harness import FirefoxTestCase
+
+from rp_puppeteer.api.error_detection import (LoggingErrorDetection,
+                                              ConsoleErrorDetection)
+
+
+class RequestPolicyTestCase(FirefoxTestCase):
+    """Base testcase class for RequestPolicy Marionette tests.
+    """
+
+    def __init__(self, *args, **kwargs):
+        FirefoxTestCase.__init__(self, *args, **kwargs)
+
+
+    def _check_error_counts(self):
+        self.assertEqual(self.logging_error_detect.get_error_count(), 0,
+                         msg="The Logging error count is zero.")
+        self.assertEqual(self.console_error_detect.get_error_count(), 0,
+                         msg="The Console error count is zero.")
+
+    def _reset_error_counts(self):
+        self.logging_error_detect.reset_error_count()
+        self.console_error_detect.reset_error_count()
+
+    def _check_and_reset_error_counts(self):
+        try:
+            self._check_error_counts()
+        finally:
+            self._reset_error_counts()
+
+
+    def setUp(self, *args, **kwargs):
+        FirefoxTestCase.setUp(self, *args, **kwargs)
+
+        marionette_getter = lambda: self.marionette
+        self.logging_error_detect = LoggingErrorDetection(marionette_getter)
+        self.console_error_detect = ConsoleErrorDetection(marionette_getter)
+
+        self._check_and_reset_error_counts()
+
+    def tearDown(self, *args, **kwargs):
+        try:
+            self._check_and_reset_error_counts()
+        finally:
+            FirefoxTestCase.tearDown(self, *args, **kwargs)
diff --git a/tests/marionette/tests/test_restartlessness.py b/tests/marionette/tests/test_restartlessness.py
index a634397..c77d36e 100644
--- a/tests/marionette/tests/test_restartlessness.py
+++ b/tests/marionette/tests/test_restartlessness.py
@@ -2,7 +2,7 @@
 # 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 firefox_ui_harness import FirefoxTestCase
+from rp_ui_harness import RequestPolicyTestCase
 from rp_puppeteer.ui.addons import RequestPolicy
 
 PREF_WELCOME_WIN_SHOWN = "extensions.requestpolicy.welcomeWindowShown"
@@ -10,13 +10,13 @@ RP_ID = "rpcontinued at non-amo.requestpolicy.org"
 INSTALL_URL = "http://localhost/link.html?.dist/requestpolicy-unit-testing.xpi"
 
 
-class TestRequestPolicyRestartlessness(FirefoxTestCase):
+class TestRequestPolicyRestartlessness(RequestPolicyTestCase):
     """These tests ensure that RequestPolicy can be uninstalled/installed and
     disabled/enabled restartless.
     """
 
     def setUp(self):
-        FirefoxTestCase.setUp(self)
+        RequestPolicyTestCase.setUp(self)
         self.rp = RequestPolicy(lambda: self.marionette)
 
     def test_disable_enable(self):
diff --git a/tests/marionette/tests/test_setup_page.py b/tests/marionette/tests/test_setup_page.py
index 80292fa..b7480fd 100644
--- a/tests/marionette/tests/test_setup_page.py
+++ b/tests/marionette/tests/test_setup_page.py
@@ -2,7 +2,7 @@
 # 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 firefox_ui_harness import FirefoxTestCase
+from rp_ui_harness import RequestPolicyTestCase
 from marionette_driver.wait import Wait
 from rp_puppeteer.ui.addons import RequestPolicy
 
@@ -10,7 +10,7 @@ from rp_puppeteer.ui.addons import RequestPolicy
 PREF_WELCOME_WIN_SHOWN = "extensions.requestpolicy.welcomeWindowShown"
 
 
-class TestSetupPageShowingUp(FirefoxTestCase):
+class TestSetupPageShowingUp(RequestPolicyTestCase):
     def _get_setup_tab(self):
         # TODO: Search in all windows for setup tabs.
         #       Assert there isn't more than one setup tab.

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/requestpolicy.git



More information about the Pkg-mozext-commits mailing list