check-webkit-style should keep JavaScript test functions in sync
authorddkilzer@apple.com <ddkilzer@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 May 2017 20:10:12 +0000 (20:10 +0000)
committerddkilzer@apple.com <ddkilzer@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 2 May 2017 20:10:12 +0000 (20:10 +0000)
<https://webkit.org/b/171424>

Reviewed by Joseph Pecoraro.

JSTests:

This change makes shouldBe(), shouldNotBe(), shouldNotThrow()
and shouldThrow() in sync with other copies of these methods.

* stress/resources/standalone-pre.js:
(shouldBe): Fix whitespace.  Prefix 'exception' and 'quiet'
variables with underscore.
(shouldThrow): Fix whitespace.

Tools:

Add a new JSTestChecker for check-webkit-style that keeps these
two files in sync:

    LayoutTests/http/tests/resources/js-test-pre.js
    LayoutTests/resources/js-test-pre.js

And keeps implementations of shouldBe(), shouldNotBe(),
shouldNotThrow(), and shouldThrow() in sync across multiple
files (with the ability to add more functions later):

    JSTests/stress/resources/standalone-pre.js
    LayoutTests/http/tests/resources/js-test-pre.js
    LayoutTests/resources/js-test-pre.js
    LayoutTests/resources/js-test.js
    LayoutTests/resources/standalone-pre.js

* Scripts/webkitpy/style/checker.py: Remove unused import.  Add
import for JSTestChecker.
(_NEVER_SKIPPED_FILES): Add array of file names that are never
skipped regardless of other rules.
(_all_categories): Add JSTestChecker categories.
(CheckerDispatcher.should_skip_without_warning): Use
_NEVER_SKIPPED_FILES.
(CheckerDispatcher._create_checker): Return JSTestChecker for
the files to check.

* Scripts/webkitpy/style/checkers/jstest.py: Add.
(map_functions_to_dict): Parse JavaScript source by splitting on
/^function\s+/ regex.  This is good enough for the sanity checks
to keep function implementations in sync.
(strip_blank_lines_and_comments): Strips blank lines and lines
with comments from the end of a chunk of text representing a
function.
(JSTestChecker): New checker.
(JSTestChecker.__init__):
(JSTestChecker.check):
(JSTestChecker.check_js_test_files): Keeps whole files in sync.
(JSTestChecker.check_js_test_functions): Keeps individual
functions in sync.

* Scripts/webkitpy/style/checkers/jstest_unittest.py: Add test
case.
(JSTestTestCase):
(JSTestTestCase.test_map_functions_to_dict):

LayoutTests:

This change attempts to fix all whitespace issues in these two
files (which are now identical and will be kept in sync by
check-webkit-style):

    LayoutTests/http/tests/resources/js-test-pre.js
    LayoutTests/resources/js-test-pre.js

It also syncs the implementation of shouldBe(), shouldNotBe(),
shouldNotThrow() and shouldThrow() across the following files:

    JSTests/stress/resources/standalone-pre.js
    LayoutTests/http/tests/resources/js-test-pre.js
    LayoutTests/resources/js-test-pre.js
    LayoutTests/resources/js-test.js
    LayoutTests/resources/standalone-pre.js

Only interesting (non-whitespace) changes are listed below.

* http/tests/resources/js-test-pre.js: Copy from resources/js-test-pre.js.
(shouldBe): Prefix 'exception' and 'quiet' variables with
underscore.
(shouldNotBe): Ditto.

* resources/js-test-pre.js:
(shouldBe): Prefix 'exception' and 'quiet' variables with
underscore.
(shouldNotBe): Ditto.

* resources/js-test.js:
(shouldBe): Prefix 'quiet' variable with underscore.  Use
stringify() when printing '_bv' value.

* resources/standalone-pre.js:
(shouldBe): Prefix 'exception' and 'quiet' variables with
underscore.
(shouldNotBe): Ditto.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@216090 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
JSTests/stress/resources/standalone-pre.js
LayoutTests/ChangeLog
LayoutTests/http/tests/resources/js-test-pre.js
LayoutTests/resources/js-test-pre.js
LayoutTests/resources/js-test.js
LayoutTests/resources/standalone-pre.js
Tools/ChangeLog
Tools/Scripts/webkitpy/style/checker.py
Tools/Scripts/webkitpy/style/checkers/jstest.py [new file with mode: 0644]
Tools/Scripts/webkitpy/style/checkers/jstest_unittest.py [new file with mode: 0644]

index 4046027..967ca99 100644 (file)
@@ -1,3 +1,18 @@
+2017-05-02  David Kilzer  <ddkilzer@apple.com>
+
+        check-webkit-style should keep JavaScript test functions in sync
+        <https://webkit.org/b/171424>
+
+        Reviewed by Joseph Pecoraro.
+
+        This change makes shouldBe(), shouldNotBe(), shouldNotThrow()
+        and shouldThrow() in sync with other copies of these methods.
+
+        * stress/resources/standalone-pre.js:
+        (shouldBe): Fix whitespace.  Prefix 'exception' and 'quiet'
+        variables with underscore.
+        (shouldThrow): Fix whitespace.
+
 2017-04-30  Oleksandr Skachkov  <gskachkov@gmail.com>
 
         We initialize functions too early in an eval
index 61c6527..b96b702 100644 (file)
@@ -120,29 +120,29 @@ function stringify(v)
         return "" + v;
 }
 
-function shouldBe(_a, _b, quiet)
+function shouldBe(_a, _b, _quiet)
 {
-  if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
-    debug("WARN: shouldBe() expects function or string arguments");
-  var exception;
-  var _av;
-  try {
-    _av = (typeof _a == "function" ? _a() : eval(_a));
-  } catch (e) {
-    exception = e;
-  }
-  var _bv = (typeof _b == "function" ? _b() : eval(_b));
-
-  if (exception)
-    testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + exception);
-  else if (isResultCorrect(_av, _bv)) {
-    if (!quiet) {
-      testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b));
+    if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
+        debug("WARN: shouldBe() expects function or string arguments");
+    var _exception;
+    var _av;
+    try {
+        _av = (typeof _a == "function" ? _a() : eval(_a));
+    } catch (e) {
+        _exception = e;
     }
-  } else if (typeof(_av) == typeof(_bv))
-    testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + ".");
-  else
-    testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
+    var _bv = (typeof _b == "function" ? _b() : eval(_b));
+
+    if (_exception)
+        testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + _exception);
+    else if (isResultCorrect(_av, _bv)) {
+        if (!_quiet) {
+            testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b));
+        }
+    } else if (typeof(_av) == typeof(_bv))
+        testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + ".");
+    else
+        testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
 }
 
 function dfgShouldBe(theFunction, _a, _b)
@@ -256,7 +256,7 @@ function shouldThrow(_a, _e, _message)
 
     var _ev;
     if (_e)
-        _ev =  eval(_e);
+        _ev = eval(_e);
 
     if (_exception) {
         if (typeof _e == "undefined" || _exception == _ev)
index 4f1c129..7798fa2 100644 (file)
@@ -1,3 +1,47 @@
+2017-05-02  David Kilzer  <ddkilzer@apple.com>
+
+        check-webkit-style should keep JavaScript test functions in sync
+        <https://webkit.org/b/171424>
+
+        Reviewed by Joseph Pecoraro.
+
+        This change attempts to fix all whitespace issues in these two
+        files (which are now identical and will be kept in sync by
+        check-webkit-style):
+
+            LayoutTests/http/tests/resources/js-test-pre.js
+            LayoutTests/resources/js-test-pre.js
+
+        It also syncs the implementation of shouldBe(), shouldNotBe(),
+        shouldNotThrow() and shouldThrow() across the following files:
+
+            JSTests/stress/resources/standalone-pre.js
+            LayoutTests/http/tests/resources/js-test-pre.js
+            LayoutTests/resources/js-test-pre.js
+            LayoutTests/resources/js-test.js
+            LayoutTests/resources/standalone-pre.js
+
+        Only interesting (non-whitespace) changes are listed below.
+
+        * http/tests/resources/js-test-pre.js: Copy from resources/js-test-pre.js.
+        (shouldBe): Prefix 'exception' and 'quiet' variables with
+        underscore.
+        (shouldNotBe): Ditto.
+
+        * resources/js-test-pre.js:
+        (shouldBe): Prefix 'exception' and 'quiet' variables with
+        underscore.
+        (shouldNotBe): Ditto.
+
+        * resources/js-test.js:
+        (shouldBe): Prefix 'quiet' variable with underscore.  Use
+        stringify() when printing '_bv' value.
+
+        * resources/standalone-pre.js:
+        (shouldBe): Prefix 'exception' and 'quiet' variables with
+        underscore.
+        (shouldNotBe): Ditto.
+
 2017-05-02  Joanmarie Diggs  <jdiggs@igalia.com>
 
         AX: Update implementation of aria-orientation
index 62801c5..b488de9 100644 (file)
@@ -192,248 +192,248 @@ function stringify(v)
 
 function evalAndLog(_a, _quiet)
 {
-  if (typeof _a != "string")
-    debug("WARN: evalAndLog() expects a string argument");
+    if (typeof _a != "string")
+        debug("WARN: evalAndLog() expects a string argument");
 
-  // Log first in case things go horribly wrong or this causes a sync event.
-  if (!_quiet)
-    debug(_a);
+    // Log first in case things go horribly wrong or this causes a sync event.
+    if (!_quiet)
+        debug(_a);
 
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-    testFailed(_a + " threw exception " + e);
-  }
-  return _av;
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        testFailed(_a + " threw exception " + e);
+    }
+    return _av;
 }
 
 function evalAndLogResult(_a)
 {
-  if (typeof _a != "string")
-    debug("WARN: evalAndLogResult() expects a string argument");
+    if (typeof _a != "string")
+        debug("WARN: evalAndLogResult() expects a string argument");
 
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-    testFailed(_a + " threw exception " + e);
-  }
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        testFailed(_a + " threw exception " + e);
+    }
 
-  debug('<span>' + _a + " is " + escapeHTML(_av) + '</span>');
+    debug('<span>' + _a + " is " + escapeHTML(_av) + '</span>');
 }
 
-function shouldBe(_a, _b, quiet)
+function shouldBe(_a, _b, _quiet)
 {
-  if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
-    debug("WARN: shouldBe() expects function or string arguments");
-  var exception;
-  var _av;
-  try {
-    _av = (typeof _a == "function" ? _a() : eval(_a));
-  } catch (e) {
-    exception = e;
-  }
-  var _bv = (typeof _b == "function" ? _b() : eval(_b));
-
-  if (exception)
-    testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + exception);
-  else if (isResultCorrect(_av, _bv)) {
-    if (!quiet) {
-      testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b));
+    if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
+        debug("WARN: shouldBe() expects function or string arguments");
+    var _exception;
+    var _av;
+    try {
+        _av = (typeof _a == "function" ? _a() : eval(_a));
+    } catch (e) {
+        _exception = e;
     }
-  } else if (typeof(_av) == typeof(_bv))
-    testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + ".");
-  else
-    testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
+    var _bv = (typeof _b == "function" ? _b() : eval(_b));
+
+    if (_exception)
+        testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + _exception);
+    else if (isResultCorrect(_av, _bv)) {
+        if (!_quiet) {
+            testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b));
+        }
+    } else if (typeof(_av) == typeof(_bv))
+        testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + ".");
+    else
+        testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
 }
 
 function dfgShouldBe(theFunction, _a, _b)
 {
-  if (typeof theFunction != "function" || typeof _a != "string" || typeof _b != "string")
-    debug("WARN: dfgShouldBe() expects a function and two strings");
-  noInline(theFunction);
-  var exception;
-  var values = [];
-
-  // Defend against tests that muck with numeric properties on array.prototype.
-  values.__proto__ = null;
-  values.push = Array.prototype.push;
-  
-  try {
-    while (!dfgCompiled({f:theFunction}))
-      values.push(eval(_a));
-    values.push(eval(_a));
-  } catch (e) {
-    exception = e;
-  }
-
-  var _bv = eval(_b);
-  if (exception)
-    testFailed(_a + " should be " + stringify(_bv) + ". On iteration " + (values.length + 1) + ", threw exception " + exception);
-  else {
-    var allPassed = true;
-    for (var i = 0; i < values.length; ++i) {
-      var _av = values[i];
-      if (isResultCorrect(_av, _bv))
-        continue;
-      if (typeof(_av) == typeof(_bv))
-        testFailed(_a + " should be " + stringify(_bv) + ". On iteration " + (i + 1) + ", was " + stringify(_av) + ".");
-      else
-        testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). On iteration " + (i + 1) + ", was " + _av + " (of type " + typeof _av + ").");
-      allPassed = false;
-    }
-    if (allPassed)
-      testPassed(_a + " is " + _b + " on all iterations including after DFG tier-up.");
-  }
-  
-  return values.length;
+    if (typeof theFunction != "function" || typeof _a != "string" || typeof _b != "string")
+        debug("WARN: dfgShouldBe() expects a function and two strings");
+    noInline(theFunction);
+    var exception;
+    var values = [];
+
+    // Defend against tests that muck with numeric properties on array.prototype.
+    values.__proto__ = null;
+    values.push = Array.prototype.push;
+
+    try {
+        while (!dfgCompiled({f:theFunction}))
+            values.push(eval(_a));
+        values.push(eval(_a));
+    } catch (e) {
+        exception = e;
+    }
+
+    var _bv = eval(_b);
+    if (exception)
+        testFailed(_a + " should be " + stringify(_bv) + ". On iteration " + (values.length + 1) + ", threw exception " + exception);
+    else {
+        var allPassed = true;
+        for (var i = 0; i < values.length; ++i) {
+            var _av = values[i];
+            if (isResultCorrect(_av, _bv))
+                continue;
+            if (typeof(_av) == typeof(_bv))
+                testFailed(_a + " should be " + stringify(_bv) + ". On iteration " + (i + 1) + ", was " + stringify(_av) + ".");
+            else
+                testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). On iteration " + (i + 1) + ", was " + _av + " (of type " + typeof _av + ").");
+            allPassed = false;
+        }
+        if (allPassed)
+            testPassed(_a + " is " + _b + " on all iterations including after DFG tier-up.");
+    }
+
+    return values.length;
 }
 
 // Execute condition every 5 milliseconds until it succeeds.
 function _waitForCondition(condition, completionHandler)
 {
-  if (condition())
-    completionHandler();
-  else
-    setTimeout(_waitForCondition, 5, condition, completionHandler);
+    if (condition())
+        completionHandler();
+    else
+        setTimeout(_waitForCondition, 5, condition, completionHandler);
 }
 
 function shouldBecomeEqual(_a, _b, completionHandler)
 {
-  if (typeof _a != "string" || typeof _b != "string")
-    debug("WARN: shouldBecomeEqual() expects string arguments");
-
-  function condition() {
-    var exception;
-    var _av;
-    try {
-      _av = eval(_a);
-    } catch (e) {
-      exception = e;
-    }
-    var _bv = eval(_b);
-    if (exception)
-      testFailed(_a + " should become " + _bv + ". Threw exception " + exception);
-    if (isResultCorrect(_av, _bv)) {
-      testPassed(_a + " became " + _b);
-      return true;
+    if (typeof _a != "string" || typeof _b != "string")
+        debug("WARN: shouldBecomeEqual() expects string arguments");
+
+    function condition() {
+        var exception;
+        var _av;
+        try {
+            _av = eval(_a);
+        } catch (e) {
+            exception = e;
+        }
+        var _bv = eval(_b);
+        if (exception)
+            testFailed(_a + " should become " + _bv + ". Threw exception " + exception);
+        if (isResultCorrect(_av, _bv)) {
+            testPassed(_a + " became " + _b);
+            return true;
+        }
+        return false;
     }
-    return false;
-  }
-  setTimeout(_waitForCondition, 0, condition, completionHandler);
+    setTimeout(_waitForCondition, 0, condition, completionHandler);
 }
 
 function shouldBecomeEqualToString(value, reference, completionHandler)
 {
-  if (typeof value !== "string" || typeof reference !== "string")
-    debug("WARN: shouldBecomeEqualToString() expects string arguments");
-  var unevaledString = JSON.stringify(reference);
-  shouldBecomeEqual(value, unevaledString, completionHandler);
+    if (typeof value !== "string" || typeof reference !== "string")
+        debug("WARN: shouldBecomeEqualToString() expects string arguments");
+    var unevaledString = JSON.stringify(reference);
+    shouldBecomeEqual(value, unevaledString, completionHandler);
 }
 
 function shouldBeType(_a, _type) {
-  var exception;
-  var _av;
-  try {
-    _av = eval(_a);
-  } catch (e) {
-    exception = e;
-  }
-
-  var _typev = eval(_type);
-  if (_av instanceof _typev) {
-    testPassed(_a + " is an instance of " + _type);
-  } else {
-    testFailed(_a + " is not an instance of " + _type);
-  }
+    var exception;
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        exception = e;
+    }
+
+    var _typev = eval(_type);
+    if (_av instanceof _typev) {
+        testPassed(_a + " is an instance of " + _type);
+    } else {
+        testFailed(_a + " is not an instance of " + _type);
+    }
 }
 
 // Variant of shouldBe()--confirms that result of eval(_to_eval) is within
 // numeric _tolerance of numeric _target.
 function shouldBeCloseTo(_to_eval, _target, _tolerance, quiet)
 {
-  if (typeof _to_eval != "string") {
-    testFailed("shouldBeCloseTo() requires string argument _to_eval. was type " + typeof _to_eval);
-    return;
-  }
-  if (typeof _target != "number") {
-    testFailed("shouldBeCloseTo() requires numeric argument _target. was type " + typeof _target);
-    return;
-  }
-  if (typeof _tolerance != "number") {
-    testFailed("shouldBeCloseTo() requires numeric argument _tolerance. was type " + typeof _tolerance);
-    return;
-  }
-
-  var _result;
-  try {
-     _result = eval(_to_eval);
-  } catch (e) {
-    testFailed(_to_eval + " should be within " + _tolerance + " of "
-               + _target + ". Threw exception " + e);
-    return;
-  }
-
-  if (typeof(_result) != typeof(_target)) {
-    testFailed(_to_eval + " should be of type " + typeof _target
-               + " but was of type " + typeof _result);
-  } else if (Math.abs(_result - _target) <= _tolerance) {
-    if (!quiet) {
-        testPassed(_to_eval + " is within " + _tolerance + " of " + _target);
-    }
-  } else {
-    testFailed(_to_eval + " should be within " + _tolerance + " of " + _target
-               + ". Was " + _result + ".");
-  }
-}
-
-function shouldNotBe(_a, _b, quiet)
-{
-  if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
-    debug("WARN: shouldNotBe() expects function or string arguments");
-  var exception;
-  var _av;
-  try {
-    _av = (typeof _a == "function" ? _a() : eval(_a));
-  } catch (e) {
-    exception = e;
-  }
-  var _bv = (typeof _b == "function" ? _b() : eval(_b));
-
-  if (exception)
-    testFailed(_a + " should not be " + _bv + ". Threw exception " + exception);
-  else if (!isResultCorrect(_av, _bv)) {
-    if (!quiet) {
-      testPassed(_a + " is not " + (typeof _b == "function" ? _bv : _b));
-    }
-  } else
-    testFailed(_a + " should not be " + _bv + ".");
+    if (typeof _to_eval != "string") {
+        testFailed("shouldBeCloseTo() requires string argument _to_eval. was type " + typeof _to_eval);
+        return;
+    }
+    if (typeof _target != "number") {
+        testFailed("shouldBeCloseTo() requires numeric argument _target. was type " + typeof _target);
+        return;
+    }
+    if (typeof _tolerance != "number") {
+        testFailed("shouldBeCloseTo() requires numeric argument _tolerance. was type " + typeof _tolerance);
+        return;
+    }
+
+    var _result;
+    try {
+        _result = eval(_to_eval);
+    } catch (e) {
+        testFailed(_to_eval + " should be within " + _tolerance + " of "
+                   + _target + ". Threw exception " + e);
+        return;
+    }
+
+    if (typeof(_result) != typeof(_target)) {
+        testFailed(_to_eval + " should be of type " + typeof _target
+                   + " but was of type " + typeof _result);
+    } else if (Math.abs(_result - _target) <= _tolerance) {
+        if (!quiet) {
+            testPassed(_to_eval + " is within " + _tolerance + " of " + _target);
+        }
+    } else {
+        testFailed(_to_eval + " should be within " + _tolerance + " of " + _target
+                   + ". Was " + _result + ".");
+    }
 }
 
-function shouldBecomeDifferent(_a, _b, completionHandler)
+function shouldNotBe(_a, _b, _quiet)
 {
-  if (typeof _a != "string" || typeof _b != "string")
-    debug("WARN: shouldBecomeDifferent() expects string arguments");
-
-  function condition() {
-    var exception;
+    if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
+        debug("WARN: shouldNotBe() expects function or string arguments");
+    var _exception;
     var _av;
     try {
-      _av = eval(_a);
+        _av = (typeof _a == "function" ? _a() : eval(_a));
     } catch (e) {
-      exception = e;
+        _exception = e;
     }
-    var _bv = eval(_b);
-    if (exception)
-      testFailed(_a + " should became not equal to " + _bv + ". Threw exception " + exception);
-    if (!isResultCorrect(_av, _bv)) {
-      testPassed(_a + " became different from " + _b);
-      return true;
+    var _bv = (typeof _b == "function" ? _b() : eval(_b));
+
+    if (_exception)
+        testFailed(_a + " should not be " + _bv + ". Threw exception " + _exception);
+    else if (!isResultCorrect(_av, _bv)) {
+        if (!_quiet) {
+            testPassed(_a + " is not " + (typeof _b == "function" ? _bv : _b));
+        }
+    } else
+        testFailed(_a + " should not be " + _bv + ".");
+}
+
+function shouldBecomeDifferent(_a, _b, completionHandler)
+{
+    if (typeof _a != "string" || typeof _b != "string")
+        debug("WARN: shouldBecomeDifferent() expects string arguments");
+
+    function condition() {
+        var exception;
+        var _av;
+        try {
+            _av = eval(_a);
+        } catch (e) {
+            exception = e;
+        }
+        var _bv = eval(_b);
+        if (exception)
+            testFailed(_a + " should became not equal to " + _bv + ". Threw exception " + exception);
+        if (!isResultCorrect(_av, _bv)) {
+            testPassed(_a + " became different from " + _b);
+            return true;
+        }
+        return false;
     }
-    return false;
-  }
-  setTimeout(_waitForCondition, 0, condition, completionHandler);
+    setTimeout(_waitForCondition, 0, condition, completionHandler);
 }
 
 function shouldBeTrue(_a) { shouldBe(_a, "true"); }
@@ -445,129 +445,129 @@ function shouldBeZero(_a) { shouldBe(_a, "0"); }
 
 function shouldBeEqualToString(a, b)
 {
-  if (typeof a !== "string" || typeof b !== "string")
-    debug("WARN: shouldBeEqualToString() expects string arguments");
-  var unevaledString = JSON.stringify(b);
-  shouldBe(a, unevaledString);
+    if (typeof a !== "string" || typeof b !== "string")
+        debug("WARN: shouldBeEqualToString() expects string arguments");
+    var unevaledString = JSON.stringify(b);
+    shouldBe(a, unevaledString);
 }
 
 function shouldNotBeEqualToString(a, b)
 {
-  if (typeof a !== "string" || typeof b !== "string")
-    debug("WARN: shouldBeEqualToString() expects string arguments");
-  var unevaledString = JSON.stringify(b);
-  shouldNotBe(a, unevaledString);
+    if (typeof a !== "string" || typeof b !== "string")
+        debug("WARN: shouldBeEqualToString() expects string arguments");
+    var unevaledString = JSON.stringify(b);
+    shouldNotBe(a, unevaledString);
 }
 function shouldBeEmptyString(_a) { shouldBeEqualToString(_a, ""); }
 
 function shouldEvaluateTo(actual, expected)
 {
-  // A general-purpose comparator.  'actual' should be a string to be
-  // evaluated, as for shouldBe(). 'expected' may be any type and will be
-  // used without being eval'ed.
-  if (expected == null) {
-    // Do this before the object test, since null is of type 'object'.
-    shouldBeNull(actual);
-  } else if (typeof expected == "undefined") {
-    shouldBeUndefined(actual);
-  } else if (typeof expected == "function") {
-    // All this fuss is to avoid the string-arg warning from shouldBe().
-    try {
-      actualValue = eval(actual);
-    } catch (e) {
-      testFailed("Evaluating " + actual + ": Threw exception " + e);
-      return;
-    }
-    shouldBe("'" + actualValue.toString().replace(/\n/g, "") + "'",
-             "'" + expected.toString().replace(/\n/g, "") + "'");
-  } else if (typeof expected == "object") {
-    shouldBeTrue(actual + " == '" + expected + "'");
-  } else if (typeof expected == "string") {
-    shouldBe(actual, expected);
-  } else if (typeof expected == "boolean") {
-    shouldBe("typeof " + actual, "'boolean'");
-    if (expected)
-      shouldBeTrue(actual);
-    else
-      shouldBeFalse(actual);
-  } else if (typeof expected == "number") {
-    shouldBe(actual, stringify(expected));
-  } else {
-    debug(expected + " is unknown type " + typeof expected);
-    shouldBeTrue(actual, "'"  +expected.toString() + "'");
-  }
+    // A general-purpose comparator.  'actual' should be a string to be
+    // evaluated, as for shouldBe(). 'expected' may be any type and will be
+    // used without being eval'ed.
+    if (expected == null) {
+        // Do this before the object test, since null is of type 'object'.
+        shouldBeNull(actual);
+    } else if (typeof expected == "undefined") {
+        shouldBeUndefined(actual);
+    } else if (typeof expected == "function") {
+        // All this fuss is to avoid the string-arg warning from shouldBe().
+        try {
+            actualValue = eval(actual);
+        } catch (e) {
+            testFailed("Evaluating " + actual + ": Threw exception " + e);
+            return;
+        }
+        shouldBe("'" + actualValue.toString().replace(/\n/g, "") + "'",
+                 "'" + expected.toString().replace(/\n/g, "") + "'");
+    } else if (typeof expected == "object") {
+        shouldBeTrue(actual + " == '" + expected + "'");
+    } else if (typeof expected == "string") {
+        shouldBe(actual, expected);
+    } else if (typeof expected == "boolean") {
+        shouldBe("typeof " + actual, "'boolean'");
+        if (expected)
+            shouldBeTrue(actual);
+        else
+            shouldBeFalse(actual);
+    } else if (typeof expected == "number") {
+        shouldBe(actual, stringify(expected));
+    } else {
+        debug(expected + " is unknown type " + typeof expected);
+        shouldBeTrue(actual, "'"  +expected.toString() + "'");
+    }
 }
 
 function shouldBeNonZero(_a)
 {
-  var exception;
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-     exception = e;
-  }
+    var exception;
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        exception = e;
+    }
 
-  if (exception)
-    testFailed(_a + " should be non-zero. Threw exception " + exception);
-  else if (_av != 0)
-    testPassed(_a + " is non-zero.");
-  else
-    testFailed(_a + " should be non-zero. Was " + _av);
+    if (exception)
+        testFailed(_a + " should be non-zero. Threw exception " + exception);
+    else if (_av != 0)
+        testPassed(_a + " is non-zero.");
+    else
+        testFailed(_a + " should be non-zero. Was " + _av);
 }
 
 function shouldBeNonNull(_a)
 {
-  var exception;
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-     exception = e;
-  }
+    var exception;
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        exception = e;
+    }
 
-  if (exception)
-    testFailed(_a + " should be non-null. Threw exception " + exception);
-  else if (_av != null)
-    testPassed(_a + " is non-null.");
-  else
-    testFailed(_a + " should be non-null. Was " + _av);
+    if (exception)
+        testFailed(_a + " should be non-null. Threw exception " + exception);
+    else if (_av != null)
+        testPassed(_a + " is non-null.");
+    else
+        testFailed(_a + " should be non-null. Was " + _av);
 }
 
 function shouldBeUndefined(_a)
 {
-  var exception;
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-     exception = e;
-  }
+    var exception;
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        exception = e;
+    }
 
-  if (exception)
-    testFailed(_a + " should be undefined. Threw exception " + exception);
-  else if (typeof _av == "undefined")
-    testPassed(_a + " is undefined.");
-  else
-    testFailed(_a + " should be undefined. Was " + _av);
+    if (exception)
+        testFailed(_a + " should be undefined. Threw exception " + exception);
+    else if (typeof _av == "undefined")
+        testPassed(_a + " is undefined.");
+    else
+        testFailed(_a + " should be undefined. Was " + _av);
 }
 
 function shouldBeDefined(_a)
 {
-  var exception;
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-     exception = e;
-  }
+    var exception;
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        exception = e;
+    }
 
-  if (exception)
-    testFailed(_a + " should be defined. Threw exception " + exception);
-  else if (_av !== undefined)
-    testPassed(_a + " is defined.");
-  else
-    testFailed(_a + " should be defined. Was " + _av);
+    if (exception)
+        testFailed(_a + " should be defined. Threw exception " + exception);
+    else if (_av !== undefined)
+        testPassed(_a + " is defined.");
+    else
+        testFailed(_a + " should be defined. Was " + _av);
 }
 
 function shouldBeGreaterThanOrEqual(_a, _b) {
@@ -592,11 +592,11 @@ function shouldBeGreaterThanOrEqual(_a, _b) {
 }
 
 function expectTrue(v, msg) {
-  if (v) {
-    testPassed(msg);
-  } else {
-    testFailed(msg);
-  }
+    if (v) {
+        testPassed(msg);
+    } else {
+        testFailed(msg);
+    }
 }
 
 function shouldNotThrow(_a, _message) {
@@ -644,7 +644,7 @@ function shouldReject(_a, _message)
         return Promise.resolve();
     }
 
-     return _av.then(function(result) {
+    return _av.then(function(result) {
         testFailed((_message ? _message : _a) + " should reject promise. Resolved with " + result + ".");
     }, function(error) {
         testPassed((_message ? _message : _a) + " rejected promise  with " + error + ".");
@@ -702,10 +702,10 @@ function gc() {
 function dfgCompiled(argument)
 {
     var numberOfCompiles = "compiles" in argument ? argument.compiles : 1;
-    
+
     if (!("f" in argument))
         throw new Error("dfgCompiled called with invalid argument.");
-    
+
     if (argument.f instanceof Array) {
         for (var i = 0; i < argument.f.length; ++i) {
             if (testRunner.numberOfDFGCompiles(argument.f[i]) < numberOfCompiles)
@@ -715,7 +715,7 @@ function dfgCompiled(argument)
         if (testRunner.numberOfDFGCompiles(argument.f) < numberOfCompiles)
             return false;
     }
-    
+
     return true;
 }
 
@@ -723,16 +723,16 @@ function dfgIncrement(argument)
 {
     if (!self.testRunner)
         return argument.i;
-    
+
     if (argument.i < argument.n)
         return argument.i;
-    
+
     if (didFailSomeTests)
         return argument.i;
-    
+
     if (!dfgCompiled(argument))
         return "start" in argument ? argument.start : 0;
-    
+
     return argument.i;
 }
 
@@ -740,7 +740,7 @@ function noInline(theFunction)
 {
     if (!self.testRunner)
         return;
-    
+
     testRunner.neverInlineFunction(theFunction);
 }
 
@@ -778,8 +778,8 @@ function startWorker(testScriptURL)
     {
         var workerPrefix = "[Worker] ";
         if (event.data.length < 5 || event.data.charAt(4) != ':') {
-          debug(workerPrefix + event.data);
-          return;
+            debug(workerPrefix + event.data);
+            return;
         }
         var code = event.data.substring(0, 4);
         var payload = workerPrefix + event.data.substring(5);
index 62801c5..b488de9 100644 (file)
@@ -192,248 +192,248 @@ function stringify(v)
 
 function evalAndLog(_a, _quiet)
 {
-  if (typeof _a != "string")
-    debug("WARN: evalAndLog() expects a string argument");
+    if (typeof _a != "string")
+        debug("WARN: evalAndLog() expects a string argument");
 
-  // Log first in case things go horribly wrong or this causes a sync event.
-  if (!_quiet)
-    debug(_a);
+    // Log first in case things go horribly wrong or this causes a sync event.
+    if (!_quiet)
+        debug(_a);
 
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-    testFailed(_a + " threw exception " + e);
-  }
-  return _av;
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        testFailed(_a + " threw exception " + e);
+    }
+    return _av;
 }
 
 function evalAndLogResult(_a)
 {
-  if (typeof _a != "string")
-    debug("WARN: evalAndLogResult() expects a string argument");
+    if (typeof _a != "string")
+        debug("WARN: evalAndLogResult() expects a string argument");
 
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-    testFailed(_a + " threw exception " + e);
-  }
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        testFailed(_a + " threw exception " + e);
+    }
 
-  debug('<span>' + _a + " is " + escapeHTML(_av) + '</span>');
+    debug('<span>' + _a + " is " + escapeHTML(_av) + '</span>');
 }
 
-function shouldBe(_a, _b, quiet)
+function shouldBe(_a, _b, _quiet)
 {
-  if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
-    debug("WARN: shouldBe() expects function or string arguments");
-  var exception;
-  var _av;
-  try {
-    _av = (typeof _a == "function" ? _a() : eval(_a));
-  } catch (e) {
-    exception = e;
-  }
-  var _bv = (typeof _b == "function" ? _b() : eval(_b));
-
-  if (exception)
-    testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + exception);
-  else if (isResultCorrect(_av, _bv)) {
-    if (!quiet) {
-      testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b));
+    if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
+        debug("WARN: shouldBe() expects function or string arguments");
+    var _exception;
+    var _av;
+    try {
+        _av = (typeof _a == "function" ? _a() : eval(_a));
+    } catch (e) {
+        _exception = e;
     }
-  } else if (typeof(_av) == typeof(_bv))
-    testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + ".");
-  else
-    testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
+    var _bv = (typeof _b == "function" ? _b() : eval(_b));
+
+    if (_exception)
+        testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + _exception);
+    else if (isResultCorrect(_av, _bv)) {
+        if (!_quiet) {
+            testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b));
+        }
+    } else if (typeof(_av) == typeof(_bv))
+        testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + ".");
+    else
+        testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
 }
 
 function dfgShouldBe(theFunction, _a, _b)
 {
-  if (typeof theFunction != "function" || typeof _a != "string" || typeof _b != "string")
-    debug("WARN: dfgShouldBe() expects a function and two strings");
-  noInline(theFunction);
-  var exception;
-  var values = [];
-
-  // Defend against tests that muck with numeric properties on array.prototype.
-  values.__proto__ = null;
-  values.push = Array.prototype.push;
-  
-  try {
-    while (!dfgCompiled({f:theFunction}))
-      values.push(eval(_a));
-    values.push(eval(_a));
-  } catch (e) {
-    exception = e;
-  }
-
-  var _bv = eval(_b);
-  if (exception)
-    testFailed(_a + " should be " + stringify(_bv) + ". On iteration " + (values.length + 1) + ", threw exception " + exception);
-  else {
-    var allPassed = true;
-    for (var i = 0; i < values.length; ++i) {
-      var _av = values[i];
-      if (isResultCorrect(_av, _bv))
-        continue;
-      if (typeof(_av) == typeof(_bv))
-        testFailed(_a + " should be " + stringify(_bv) + ". On iteration " + (i + 1) + ", was " + stringify(_av) + ".");
-      else
-        testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). On iteration " + (i + 1) + ", was " + _av + " (of type " + typeof _av + ").");
-      allPassed = false;
-    }
-    if (allPassed)
-      testPassed(_a + " is " + _b + " on all iterations including after DFG tier-up.");
-  }
-  
-  return values.length;
+    if (typeof theFunction != "function" || typeof _a != "string" || typeof _b != "string")
+        debug("WARN: dfgShouldBe() expects a function and two strings");
+    noInline(theFunction);
+    var exception;
+    var values = [];
+
+    // Defend against tests that muck with numeric properties on array.prototype.
+    values.__proto__ = null;
+    values.push = Array.prototype.push;
+
+    try {
+        while (!dfgCompiled({f:theFunction}))
+            values.push(eval(_a));
+        values.push(eval(_a));
+    } catch (e) {
+        exception = e;
+    }
+
+    var _bv = eval(_b);
+    if (exception)
+        testFailed(_a + " should be " + stringify(_bv) + ". On iteration " + (values.length + 1) + ", threw exception " + exception);
+    else {
+        var allPassed = true;
+        for (var i = 0; i < values.length; ++i) {
+            var _av = values[i];
+            if (isResultCorrect(_av, _bv))
+                continue;
+            if (typeof(_av) == typeof(_bv))
+                testFailed(_a + " should be " + stringify(_bv) + ". On iteration " + (i + 1) + ", was " + stringify(_av) + ".");
+            else
+                testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). On iteration " + (i + 1) + ", was " + _av + " (of type " + typeof _av + ").");
+            allPassed = false;
+        }
+        if (allPassed)
+            testPassed(_a + " is " + _b + " on all iterations including after DFG tier-up.");
+    }
+
+    return values.length;
 }
 
 // Execute condition every 5 milliseconds until it succeeds.
 function _waitForCondition(condition, completionHandler)
 {
-  if (condition())
-    completionHandler();
-  else
-    setTimeout(_waitForCondition, 5, condition, completionHandler);
+    if (condition())
+        completionHandler();
+    else
+        setTimeout(_waitForCondition, 5, condition, completionHandler);
 }
 
 function shouldBecomeEqual(_a, _b, completionHandler)
 {
-  if (typeof _a != "string" || typeof _b != "string")
-    debug("WARN: shouldBecomeEqual() expects string arguments");
-
-  function condition() {
-    var exception;
-    var _av;
-    try {
-      _av = eval(_a);
-    } catch (e) {
-      exception = e;
-    }
-    var _bv = eval(_b);
-    if (exception)
-      testFailed(_a + " should become " + _bv + ". Threw exception " + exception);
-    if (isResultCorrect(_av, _bv)) {
-      testPassed(_a + " became " + _b);
-      return true;
+    if (typeof _a != "string" || typeof _b != "string")
+        debug("WARN: shouldBecomeEqual() expects string arguments");
+
+    function condition() {
+        var exception;
+        var _av;
+        try {
+            _av = eval(_a);
+        } catch (e) {
+            exception = e;
+        }
+        var _bv = eval(_b);
+        if (exception)
+            testFailed(_a + " should become " + _bv + ". Threw exception " + exception);
+        if (isResultCorrect(_av, _bv)) {
+            testPassed(_a + " became " + _b);
+            return true;
+        }
+        return false;
     }
-    return false;
-  }
-  setTimeout(_waitForCondition, 0, condition, completionHandler);
+    setTimeout(_waitForCondition, 0, condition, completionHandler);
 }
 
 function shouldBecomeEqualToString(value, reference, completionHandler)
 {
-  if (typeof value !== "string" || typeof reference !== "string")
-    debug("WARN: shouldBecomeEqualToString() expects string arguments");
-  var unevaledString = JSON.stringify(reference);
-  shouldBecomeEqual(value, unevaledString, completionHandler);
+    if (typeof value !== "string" || typeof reference !== "string")
+        debug("WARN: shouldBecomeEqualToString() expects string arguments");
+    var unevaledString = JSON.stringify(reference);
+    shouldBecomeEqual(value, unevaledString, completionHandler);
 }
 
 function shouldBeType(_a, _type) {
-  var exception;
-  var _av;
-  try {
-    _av = eval(_a);
-  } catch (e) {
-    exception = e;
-  }
-
-  var _typev = eval(_type);
-  if (_av instanceof _typev) {
-    testPassed(_a + " is an instance of " + _type);
-  } else {
-    testFailed(_a + " is not an instance of " + _type);
-  }
+    var exception;
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        exception = e;
+    }
+
+    var _typev = eval(_type);
+    if (_av instanceof _typev) {
+        testPassed(_a + " is an instance of " + _type);
+    } else {
+        testFailed(_a + " is not an instance of " + _type);
+    }
 }
 
 // Variant of shouldBe()--confirms that result of eval(_to_eval) is within
 // numeric _tolerance of numeric _target.
 function shouldBeCloseTo(_to_eval, _target, _tolerance, quiet)
 {
-  if (typeof _to_eval != "string") {
-    testFailed("shouldBeCloseTo() requires string argument _to_eval. was type " + typeof _to_eval);
-    return;
-  }
-  if (typeof _target != "number") {
-    testFailed("shouldBeCloseTo() requires numeric argument _target. was type " + typeof _target);
-    return;
-  }
-  if (typeof _tolerance != "number") {
-    testFailed("shouldBeCloseTo() requires numeric argument _tolerance. was type " + typeof _tolerance);
-    return;
-  }
-
-  var _result;
-  try {
-     _result = eval(_to_eval);
-  } catch (e) {
-    testFailed(_to_eval + " should be within " + _tolerance + " of "
-               + _target + ". Threw exception " + e);
-    return;
-  }
-
-  if (typeof(_result) != typeof(_target)) {
-    testFailed(_to_eval + " should be of type " + typeof _target
-               + " but was of type " + typeof _result);
-  } else if (Math.abs(_result - _target) <= _tolerance) {
-    if (!quiet) {
-        testPassed(_to_eval + " is within " + _tolerance + " of " + _target);
-    }
-  } else {
-    testFailed(_to_eval + " should be within " + _tolerance + " of " + _target
-               + ". Was " + _result + ".");
-  }
-}
-
-function shouldNotBe(_a, _b, quiet)
-{
-  if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
-    debug("WARN: shouldNotBe() expects function or string arguments");
-  var exception;
-  var _av;
-  try {
-    _av = (typeof _a == "function" ? _a() : eval(_a));
-  } catch (e) {
-    exception = e;
-  }
-  var _bv = (typeof _b == "function" ? _b() : eval(_b));
-
-  if (exception)
-    testFailed(_a + " should not be " + _bv + ". Threw exception " + exception);
-  else if (!isResultCorrect(_av, _bv)) {
-    if (!quiet) {
-      testPassed(_a + " is not " + (typeof _b == "function" ? _bv : _b));
-    }
-  } else
-    testFailed(_a + " should not be " + _bv + ".");
+    if (typeof _to_eval != "string") {
+        testFailed("shouldBeCloseTo() requires string argument _to_eval. was type " + typeof _to_eval);
+        return;
+    }
+    if (typeof _target != "number") {
+        testFailed("shouldBeCloseTo() requires numeric argument _target. was type " + typeof _target);
+        return;
+    }
+    if (typeof _tolerance != "number") {
+        testFailed("shouldBeCloseTo() requires numeric argument _tolerance. was type " + typeof _tolerance);
+        return;
+    }
+
+    var _result;
+    try {
+        _result = eval(_to_eval);
+    } catch (e) {
+        testFailed(_to_eval + " should be within " + _tolerance + " of "
+                   + _target + ". Threw exception " + e);
+        return;
+    }
+
+    if (typeof(_result) != typeof(_target)) {
+        testFailed(_to_eval + " should be of type " + typeof _target
+                   + " but was of type " + typeof _result);
+    } else if (Math.abs(_result - _target) <= _tolerance) {
+        if (!quiet) {
+            testPassed(_to_eval + " is within " + _tolerance + " of " + _target);
+        }
+    } else {
+        testFailed(_to_eval + " should be within " + _tolerance + " of " + _target
+                   + ". Was " + _result + ".");
+    }
 }
 
-function shouldBecomeDifferent(_a, _b, completionHandler)
+function shouldNotBe(_a, _b, _quiet)
 {
-  if (typeof _a != "string" || typeof _b != "string")
-    debug("WARN: shouldBecomeDifferent() expects string arguments");
-
-  function condition() {
-    var exception;
+    if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
+        debug("WARN: shouldNotBe() expects function or string arguments");
+    var _exception;
     var _av;
     try {
-      _av = eval(_a);
+        _av = (typeof _a == "function" ? _a() : eval(_a));
     } catch (e) {
-      exception = e;
+        _exception = e;
     }
-    var _bv = eval(_b);
-    if (exception)
-      testFailed(_a + " should became not equal to " + _bv + ". Threw exception " + exception);
-    if (!isResultCorrect(_av, _bv)) {
-      testPassed(_a + " became different from " + _b);
-      return true;
+    var _bv = (typeof _b == "function" ? _b() : eval(_b));
+
+    if (_exception)
+        testFailed(_a + " should not be " + _bv + ". Threw exception " + _exception);
+    else if (!isResultCorrect(_av, _bv)) {
+        if (!_quiet) {
+            testPassed(_a + " is not " + (typeof _b == "function" ? _bv : _b));
+        }
+    } else
+        testFailed(_a + " should not be " + _bv + ".");
+}
+
+function shouldBecomeDifferent(_a, _b, completionHandler)
+{
+    if (typeof _a != "string" || typeof _b != "string")
+        debug("WARN: shouldBecomeDifferent() expects string arguments");
+
+    function condition() {
+        var exception;
+        var _av;
+        try {
+            _av = eval(_a);
+        } catch (e) {
+            exception = e;
+        }
+        var _bv = eval(_b);
+        if (exception)
+            testFailed(_a + " should became not equal to " + _bv + ". Threw exception " + exception);
+        if (!isResultCorrect(_av, _bv)) {
+            testPassed(_a + " became different from " + _b);
+            return true;
+        }
+        return false;
     }
-    return false;
-  }
-  setTimeout(_waitForCondition, 0, condition, completionHandler);
+    setTimeout(_waitForCondition, 0, condition, completionHandler);
 }
 
 function shouldBeTrue(_a) { shouldBe(_a, "true"); }
@@ -445,129 +445,129 @@ function shouldBeZero(_a) { shouldBe(_a, "0"); }
 
 function shouldBeEqualToString(a, b)
 {
-  if (typeof a !== "string" || typeof b !== "string")
-    debug("WARN: shouldBeEqualToString() expects string arguments");
-  var unevaledString = JSON.stringify(b);
-  shouldBe(a, unevaledString);
+    if (typeof a !== "string" || typeof b !== "string")
+        debug("WARN: shouldBeEqualToString() expects string arguments");
+    var unevaledString = JSON.stringify(b);
+    shouldBe(a, unevaledString);
 }
 
 function shouldNotBeEqualToString(a, b)
 {
-  if (typeof a !== "string" || typeof b !== "string")
-    debug("WARN: shouldBeEqualToString() expects string arguments");
-  var unevaledString = JSON.stringify(b);
-  shouldNotBe(a, unevaledString);
+    if (typeof a !== "string" || typeof b !== "string")
+        debug("WARN: shouldBeEqualToString() expects string arguments");
+    var unevaledString = JSON.stringify(b);
+    shouldNotBe(a, unevaledString);
 }
 function shouldBeEmptyString(_a) { shouldBeEqualToString(_a, ""); }
 
 function shouldEvaluateTo(actual, expected)
 {
-  // A general-purpose comparator.  'actual' should be a string to be
-  // evaluated, as for shouldBe(). 'expected' may be any type and will be
-  // used without being eval'ed.
-  if (expected == null) {
-    // Do this before the object test, since null is of type 'object'.
-    shouldBeNull(actual);
-  } else if (typeof expected == "undefined") {
-    shouldBeUndefined(actual);
-  } else if (typeof expected == "function") {
-    // All this fuss is to avoid the string-arg warning from shouldBe().
-    try {
-      actualValue = eval(actual);
-    } catch (e) {
-      testFailed("Evaluating " + actual + ": Threw exception " + e);
-      return;
-    }
-    shouldBe("'" + actualValue.toString().replace(/\n/g, "") + "'",
-             "'" + expected.toString().replace(/\n/g, "") + "'");
-  } else if (typeof expected == "object") {
-    shouldBeTrue(actual + " == '" + expected + "'");
-  } else if (typeof expected == "string") {
-    shouldBe(actual, expected);
-  } else if (typeof expected == "boolean") {
-    shouldBe("typeof " + actual, "'boolean'");
-    if (expected)
-      shouldBeTrue(actual);
-    else
-      shouldBeFalse(actual);
-  } else if (typeof expected == "number") {
-    shouldBe(actual, stringify(expected));
-  } else {
-    debug(expected + " is unknown type " + typeof expected);
-    shouldBeTrue(actual, "'"  +expected.toString() + "'");
-  }
+    // A general-purpose comparator.  'actual' should be a string to be
+    // evaluated, as for shouldBe(). 'expected' may be any type and will be
+    // used without being eval'ed.
+    if (expected == null) {
+        // Do this before the object test, since null is of type 'object'.
+        shouldBeNull(actual);
+    } else if (typeof expected == "undefined") {
+        shouldBeUndefined(actual);
+    } else if (typeof expected == "function") {
+        // All this fuss is to avoid the string-arg warning from shouldBe().
+        try {
+            actualValue = eval(actual);
+        } catch (e) {
+            testFailed("Evaluating " + actual + ": Threw exception " + e);
+            return;
+        }
+        shouldBe("'" + actualValue.toString().replace(/\n/g, "") + "'",
+                 "'" + expected.toString().replace(/\n/g, "") + "'");
+    } else if (typeof expected == "object") {
+        shouldBeTrue(actual + " == '" + expected + "'");
+    } else if (typeof expected == "string") {
+        shouldBe(actual, expected);
+    } else if (typeof expected == "boolean") {
+        shouldBe("typeof " + actual, "'boolean'");
+        if (expected)
+            shouldBeTrue(actual);
+        else
+            shouldBeFalse(actual);
+    } else if (typeof expected == "number") {
+        shouldBe(actual, stringify(expected));
+    } else {
+        debug(expected + " is unknown type " + typeof expected);
+        shouldBeTrue(actual, "'"  +expected.toString() + "'");
+    }
 }
 
 function shouldBeNonZero(_a)
 {
-  var exception;
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-     exception = e;
-  }
+    var exception;
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        exception = e;
+    }
 
-  if (exception)
-    testFailed(_a + " should be non-zero. Threw exception " + exception);
-  else if (_av != 0)
-    testPassed(_a + " is non-zero.");
-  else
-    testFailed(_a + " should be non-zero. Was " + _av);
+    if (exception)
+        testFailed(_a + " should be non-zero. Threw exception " + exception);
+    else if (_av != 0)
+        testPassed(_a + " is non-zero.");
+    else
+        testFailed(_a + " should be non-zero. Was " + _av);
 }
 
 function shouldBeNonNull(_a)
 {
-  var exception;
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-     exception = e;
-  }
+    var exception;
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        exception = e;
+    }
 
-  if (exception)
-    testFailed(_a + " should be non-null. Threw exception " + exception);
-  else if (_av != null)
-    testPassed(_a + " is non-null.");
-  else
-    testFailed(_a + " should be non-null. Was " + _av);
+    if (exception)
+        testFailed(_a + " should be non-null. Threw exception " + exception);
+    else if (_av != null)
+        testPassed(_a + " is non-null.");
+    else
+        testFailed(_a + " should be non-null. Was " + _av);
 }
 
 function shouldBeUndefined(_a)
 {
-  var exception;
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-     exception = e;
-  }
+    var exception;
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        exception = e;
+    }
 
-  if (exception)
-    testFailed(_a + " should be undefined. Threw exception " + exception);
-  else if (typeof _av == "undefined")
-    testPassed(_a + " is undefined.");
-  else
-    testFailed(_a + " should be undefined. Was " + _av);
+    if (exception)
+        testFailed(_a + " should be undefined. Threw exception " + exception);
+    else if (typeof _av == "undefined")
+        testPassed(_a + " is undefined.");
+    else
+        testFailed(_a + " should be undefined. Was " + _av);
 }
 
 function shouldBeDefined(_a)
 {
-  var exception;
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-     exception = e;
-  }
+    var exception;
+    var _av;
+    try {
+        _av = eval(_a);
+    } catch (e) {
+        exception = e;
+    }
 
-  if (exception)
-    testFailed(_a + " should be defined. Threw exception " + exception);
-  else if (_av !== undefined)
-    testPassed(_a + " is defined.");
-  else
-    testFailed(_a + " should be defined. Was " + _av);
+    if (exception)
+        testFailed(_a + " should be defined. Threw exception " + exception);
+    else if (_av !== undefined)
+        testPassed(_a + " is defined.");
+    else
+        testFailed(_a + " should be defined. Was " + _av);
 }
 
 function shouldBeGreaterThanOrEqual(_a, _b) {
@@ -592,11 +592,11 @@ function shouldBeGreaterThanOrEqual(_a, _b) {
 }
 
 function expectTrue(v, msg) {
-  if (v) {
-    testPassed(msg);
-  } else {
-    testFailed(msg);
-  }
+    if (v) {
+        testPassed(msg);
+    } else {
+        testFailed(msg);
+    }
 }
 
 function shouldNotThrow(_a, _message) {
@@ -644,7 +644,7 @@ function shouldReject(_a, _message)
         return Promise.resolve();
     }
 
-     return _av.then(function(result) {
+    return _av.then(function(result) {
         testFailed((_message ? _message : _a) + " should reject promise. Resolved with " + result + ".");
     }, function(error) {
         testPassed((_message ? _message : _a) + " rejected promise  with " + error + ".");
@@ -702,10 +702,10 @@ function gc() {
 function dfgCompiled(argument)
 {
     var numberOfCompiles = "compiles" in argument ? argument.compiles : 1;
-    
+
     if (!("f" in argument))
         throw new Error("dfgCompiled called with invalid argument.");
-    
+
     if (argument.f instanceof Array) {
         for (var i = 0; i < argument.f.length; ++i) {
             if (testRunner.numberOfDFGCompiles(argument.f[i]) < numberOfCompiles)
@@ -715,7 +715,7 @@ function dfgCompiled(argument)
         if (testRunner.numberOfDFGCompiles(argument.f) < numberOfCompiles)
             return false;
     }
-    
+
     return true;
 }
 
@@ -723,16 +723,16 @@ function dfgIncrement(argument)
 {
     if (!self.testRunner)
         return argument.i;
-    
+
     if (argument.i < argument.n)
         return argument.i;
-    
+
     if (didFailSomeTests)
         return argument.i;
-    
+
     if (!dfgCompiled(argument))
         return "start" in argument ? argument.start : 0;
-    
+
     return argument.i;
 }
 
@@ -740,7 +740,7 @@ function noInline(theFunction)
 {
     if (!self.testRunner)
         return;
-    
+
     testRunner.neverInlineFunction(theFunction);
 }
 
@@ -778,8 +778,8 @@ function startWorker(testScriptURL)
     {
         var workerPrefix = "[Worker] ";
         if (event.data.length < 5 || event.data.charAt(4) != ':') {
-          debug(workerPrefix + event.data);
-          return;
+            debug(workerPrefix + event.data);
+            return;
         }
         var code = event.data.substring(0, 4);
         var payload = workerPrefix + event.data.substring(5);
index 066dbb6..1df1b8b 100644 (file)
@@ -228,29 +228,29 @@ function evalAndLog(_a, _quiet)
   return _av;
 }
 
-function shouldBe(_a, _b, quiet)
+function shouldBe(_a, _b, _quiet)
 {
-  if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
-    debug("WARN: shouldBe() expects function or string arguments");
-  var _exception;
-  var _av;
-  try {
-    _av = (typeof _a == "function" ? _a() : eval(_a));
-  } catch (e) {
-    _exception = e;
-  }
-  var _bv = (typeof _b == "function" ? _b() : eval(_b));
-
-  if (_exception)
-    testFailed(_a + " should be " + _bv + ". Threw exception " + _exception);
-  else if (isResultCorrect(_av, _bv)) {
-    if (!quiet) {
-      testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b));
+    if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
+        debug("WARN: shouldBe() expects function or string arguments");
+    var _exception;
+    var _av;
+    try {
+        _av = (typeof _a == "function" ? _a() : eval(_a));
+    } catch (e) {
+        _exception = e;
     }
-  } else if (typeof(_av) == typeof(_bv))
-    testFailed(_a + " should be " + _bv + ". Was " + stringify(_av) + ".");
-  else
-    testFailed(_a + " should be " + _bv + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
+    var _bv = (typeof _b == "function" ? _b() : eval(_b));
+
+    if (_exception)
+        testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + _exception);
+    else if (isResultCorrect(_av, _bv)) {
+        if (!_quiet) {
+            testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b));
+        }
+    } else if (typeof(_av) == typeof(_bv))
+        testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + ".");
+    else
+        testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
 }
 
 // Execute condition every 5 milliseconds until it succeeds.
@@ -353,25 +353,25 @@ function shouldBeCloseTo(_to_eval, _target, _tolerance, _quiet)
 
 function shouldNotBe(_a, _b, _quiet)
 {
-  if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
-    debug("WARN: shouldNotBe() expects function or string arguments");
-  var _exception;
-  var _av;
-  try {
-    _av = (typeof _a == "function" ? _a() : eval(_a));
-  } catch (e) {
-    _exception = e;
-  }
-  var _bv = (typeof _b == "function" ? _b() : eval(_b));
-
-  if (_exception)
-    testFailed(_a + " should not be " + _bv + ". Threw exception " + _exception);
-  else if (!isResultCorrect(_av, _bv)) {
-    if (!_quiet) {
-      testPassed(_a + " is not " + (typeof _b == "function" ? _bv : _b));
+    if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
+        debug("WARN: shouldNotBe() expects function or string arguments");
+    var _exception;
+    var _av;
+    try {
+        _av = (typeof _a == "function" ? _a() : eval(_a));
+    } catch (e) {
+        _exception = e;
     }
-  } else
-    testFailed(_a + " should not be " + _bv + ".");
+    var _bv = (typeof _b == "function" ? _b() : eval(_b));
+
+    if (_exception)
+        testFailed(_a + " should not be " + _bv + ". Threw exception " + _exception);
+    else if (!isResultCorrect(_av, _bv)) {
+        if (!_quiet) {
+            testPassed(_a + " is not " + (typeof _b == "function" ? _bv : _b));
+        }
+    } else
+        testFailed(_a + " should not be " + _bv + ".");
 }
 
 function shouldBecomeDifferent(_a, _b, completionHandler)
@@ -564,7 +564,7 @@ function expectTrue(v, msg) {
 
 function shouldNotThrow(_a, _message) {
     try {
-        typeof _a == "function" ?  _a() : eval(_a);
+        typeof _a == "function" ? _a() : eval(_a);
         testPassed((_message ? _message : _a) + " did not throw exception.");
     } catch (e) {
         testFailed((_message ? _message : _a) + " should not throw exception. Threw exception " + e + ".");
index 1c88151..dac5495 100644 (file)
@@ -111,29 +111,29 @@ function stringify(v)
         return "" + v;
 }
 
-function shouldBe(_a, _b, quiet)
+function shouldBe(_a, _b, _quiet)
 {
-  if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
-    debug("WARN: shouldBe() expects function or string arguments");
-  var exception;
-  var _av;
-  try {
-    _av = (typeof _a == "function" ? _a() : eval(_a));
-  } catch (e) {
-    exception = e;
-  }
-  var _bv = (typeof _b == "function" ? _b() : eval(_b));
-
-  if (exception)
-    testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + exception);
-  else if (isResultCorrect(_av, _bv)) {
-    if (!quiet) {
-      testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b));
+    if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
+        debug("WARN: shouldBe() expects function or string arguments");
+    var _exception;
+    var _av;
+    try {
+        _av = (typeof _a == "function" ? _a() : eval(_a));
+    } catch (e) {
+        _exception = e;
     }
-  } else if (typeof(_av) == typeof(_bv))
-    testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + ".");
-  else
-    testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
+    var _bv = (typeof _b == "function" ? _b() : eval(_b));
+
+    if (_exception)
+        testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + _exception);
+    else if (isResultCorrect(_av, _bv)) {
+        if (!_quiet) {
+            testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b));
+        }
+    } else if (typeof(_av) == typeof(_bv))
+        testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + ".");
+    else
+        testFailed(_a + " should be " + stringify(_bv) + " (of type " + typeof _bv + "). Was " + _av + " (of type " + typeof _av + ").");
 }
 
 function dfgShouldBe(theFunction, _a, _b)
@@ -195,27 +195,27 @@ function shouldBeType(_a, _type) {
   }
 }
 
-function shouldNotBe(_a, _b, quiet)
+function shouldNotBe(_a, _b, _quiet)
 {
-  if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
-    debug("WARN: shouldNotBe() expects function or string arguments");
-  var exception;
-  var _av;
-  try {
-    _av = (typeof _a == "function" ? _a() : eval(_a));
-  } catch (e) {
-    exception = e;
-  }
-  var _bv = (typeof _b == "function" ? _b() : eval(_b));
-
-  if (exception)
-    testFailed(_a + " should not be " + _bv + ". Threw exception " + exception);
-  else if (!isResultCorrect(_av, _bv)) {
-    if (!quiet) {
-      testPassed(_a + " is not " + (typeof _b == "function" ? _bv : _b));
+    if ((typeof _a != "function" && typeof _a != "string") || (typeof _b != "function" && typeof _b != "string"))
+        debug("WARN: shouldNotBe() expects function or string arguments");
+    var _exception;
+    var _av;
+    try {
+        _av = (typeof _a == "function" ? _a() : eval(_a));
+    } catch (e) {
+        _exception = e;
     }
-  } else
-    testFailed(_a + " should not be " + _bv + ".");
+    var _bv = (typeof _b == "function" ? _b() : eval(_b));
+
+    if (_exception)
+        testFailed(_a + " should not be " + _bv + ". Threw exception " + _exception);
+    else if (!isResultCorrect(_av, _bv)) {
+        if (!_quiet) {
+            testPassed(_a + " is not " + (typeof _b == "function" ? _bv : _b));
+        }
+    } else
+        testFailed(_a + " should not be " + _bv + ".");
 }
 
 function shouldBeTrue(_a) { shouldBe(_a, "true"); }
@@ -288,7 +288,7 @@ function shouldThrow(_a, _e, _message)
 
     var _ev;
     if (_e)
-        _ev =  eval(_e);
+        _ev = eval(_e);
 
     if (_exception) {
         if (typeof _e == "undefined" || _exception == _ev)
index f7f0b7a..be0ce2c 100644 (file)
@@ -1,3 +1,55 @@
+2017-05-02  David Kilzer  <ddkilzer@apple.com>
+
+        check-webkit-style should keep JavaScript test functions in sync
+        <https://webkit.org/b/171424>
+
+        Reviewed by Joseph Pecoraro.
+
+        Add a new JSTestChecker for check-webkit-style that keeps these
+        two files in sync:
+
+            LayoutTests/http/tests/resources/js-test-pre.js
+            LayoutTests/resources/js-test-pre.js
+
+        And keeps implementations of shouldBe(), shouldNotBe(),
+        shouldNotThrow(), and shouldThrow() in sync across multiple
+        files (with the ability to add more functions later):
+
+            JSTests/stress/resources/standalone-pre.js
+            LayoutTests/http/tests/resources/js-test-pre.js
+            LayoutTests/resources/js-test-pre.js
+            LayoutTests/resources/js-test.js
+            LayoutTests/resources/standalone-pre.js
+
+        * Scripts/webkitpy/style/checker.py: Remove unused import.  Add
+        import for JSTestChecker.
+        (_NEVER_SKIPPED_FILES): Add array of file names that are never
+        skipped regardless of other rules.
+        (_all_categories): Add JSTestChecker categories.
+        (CheckerDispatcher.should_skip_without_warning): Use
+        _NEVER_SKIPPED_FILES.
+        (CheckerDispatcher._create_checker): Return JSTestChecker for
+        the files to check.
+
+        * Scripts/webkitpy/style/checkers/jstest.py: Add.
+        (map_functions_to_dict): Parse JavaScript source by splitting on
+        /^function\s+/ regex.  This is good enough for the sanity checks
+        to keep function implementations in sync.
+        (strip_blank_lines_and_comments): Strips blank lines and lines
+        with comments from the end of a chunk of text representing a
+        function.
+        (JSTestChecker): New checker.
+        (JSTestChecker.__init__):
+        (JSTestChecker.check):
+        (JSTestChecker.check_js_test_files): Keeps whole files in sync.
+        (JSTestChecker.check_js_test_functions): Keeps individual
+        functions in sync.
+
+        * Scripts/webkitpy/style/checkers/jstest_unittest.py: Add test
+        case.
+        (JSTestTestCase):
+        (JSTestTestCase.test_map_functions_to_dict):
+
 2017-05-02  Joanmarie Diggs  <jdiggs@igalia.com>
 
         AX: Update implementation of aria-orientation
index b6a38a9..75e9d11 100644 (file)
@@ -34,7 +34,6 @@
 import logging
 import os.path
 import re
-import sys
 
 from checkers.common import categories as CommonCategories
 from checkers.common import CarriageReturnChecker
@@ -48,6 +47,7 @@ from checkers.jsonchecker import JSONChecker
 from checkers.jsonchecker import JSONContributorsChecker
 from checkers.jsonchecker import JSONFeaturesChecker
 from checkers.jsonchecker import JSONCSSPropertiesChecker
+from checkers.jstest import JSTestChecker
 from checkers.messagesin import MessagesInChecker
 from checkers.png import PNGChecker
 from checkers.python import PythonChecker
@@ -299,6 +299,16 @@ _PNG_FILE_EXTENSION = 'png'
 
 _CMAKE_FILE_EXTENSION = 'cmake'
 
+# Files that are never skipped by name.
+#
+# Do not skip these files, even when they appear in
+# _SKIPPED_FILES_WITH_WARNING or _SKIPPED_FILES_WITHOUT_WARNING.
+_NEVER_SKIPPED_FILES = [
+    'js-test-pre.js',
+    'standalone-pre.js',
+    'TestExpectations',
+]
+
 # Files to skip that are less obvious.
 #
 # Some files should be skipped when checking style. For example,
@@ -354,6 +364,7 @@ def _all_categories():
     categories = CommonCategories.union(CppChecker.categories)
     categories = categories.union(JSChecker.categories)
     categories = categories.union(JSONChecker.categories)
+    categories = categories.union(JSTestChecker.categories)
     categories = categories.union(TestExpectationsChecker.categories)
     categories = categories.union(ChangeLogChecker.categories)
     categories = categories.union(PNGChecker.categories)
@@ -550,7 +561,7 @@ class CheckerDispatcher(object):
         basename = os.path.basename(file_path)
         if basename.startswith('ChangeLog'):
             return False
-        elif basename == 'TestExpectations':
+        elif basename in _NEVER_SKIPPED_FILES:
             return False
         for skipped_file in _SKIPPED_FILES_WITHOUT_WARNING:
             if self._should_skip_file_path(file_path, skipped_file):
@@ -613,9 +624,12 @@ class CheckerDispatcher(object):
             checker = CppChecker(file_path, file_extension,
                                  handle_style_error, min_confidence)
         elif file_type == FileType.JS:
+            basename = os.path.basename(file_path)
             # Do not attempt to check non-Inspector or 3rd-party JavaScript files as JS.
             if os.path.join('WebInspectorUI', 'UserInterface') in file_path and (not 'External' in file_path):
                 checker = JSChecker(file_path, handle_style_error)
+            elif basename == 'js-test-pre.js' or basename == 'standalone-pre.js':
+                checker = JSTestChecker(file_path, handle_style_error)
             else:
                 checker = TextChecker(file_path, handle_style_error)
         elif file_type == FileType.JSON:
diff --git a/Tools/Scripts/webkitpy/style/checkers/jstest.py b/Tools/Scripts/webkitpy/style/checkers/jstest.py
new file mode 100644 (file)
index 0000000..457088a
--- /dev/null
@@ -0,0 +1,138 @@
+# Copyright (C) 2017 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Supports ensuring equality of js-test-pre.js and related files."""
+
+import re
+
+from webkitpy.common.system.systemhost import SystemHost
+
+ALL_JS_TEST_FILES = [
+    'JSTests/stress/resources/standalone-pre.js',
+    'LayoutTests/http/tests/resources/js-test-pre.js',
+    'LayoutTests/resources/js-test-pre.js',
+    'LayoutTests/resources/js-test.js',
+    'LayoutTests/resources/standalone-pre.js',
+]
+
+KEEP_JS_TEST_FILES_IN_SYNC = [
+    'LayoutTests/http/tests/resources/js-test-pre.js',
+    'LayoutTests/resources/js-test-pre.js',
+]
+
+KEEP_JS_TEST_FUNCTIONS_IN_SYNC = [
+    'shouldBe',
+    'shouldNotBe',
+    'shouldNotThrow',
+    'shouldThrow',
+]
+
+
+def map_functions_to_dict(content):
+    """Splits multi-line string containing JavaScript source into a dictionary.
+
+    The dictionary uses the function name as a key, and the function source (less the "function " keyword) as the value.
+
+    Args:
+      content: A multi-line string containing JavaScript source to be split into individual function definitions.
+    """
+    functions = re.split('^function\s+', content, flags=re.MULTILINE)
+    function_name_regex = re.compile('^(?P<name>\w+)\s*\(', flags=re.MULTILINE)
+    result = {}
+    for f in functions:
+        match = function_name_regex.match(f)
+        if match:
+            result[match.group('name')] = strip_trailing_blank_lines_and_comments(f)
+    return result
+
+
+def strip_trailing_blank_lines_and_comments(function):
+    """Removes blank lines and lines containing only comments from the end of a multi-line string.
+
+    Args:
+        function: A multi-line string representing the source for one JavaScript function, less the "function" keyword.
+    """
+    lines = function.splitlines(True)
+    blank_line_regex = re.compile('^\s*$')
+    comment_line_regex = re.compile('^\s*//.*$')
+    while blank_line_regex.search(lines[-1]) or comment_line_regex.search(lines[-1]):
+        del lines[-1]
+    return ''.join(lines)
+
+
+class JSTestChecker(object):
+    categories = {'jstest/function_equality', 'jstest/resource_equality'}
+
+    def __init__(self, file_path, handle_style_error):
+        self._file_path = file_path
+        self._handle_style_error = handle_style_error
+        self._handle_style_error.turn_off_line_filtering()
+        self._host = SystemHost()
+        self._fs = self._host.filesystem
+
+    def check(self, lines):
+        """Run all the checks."""
+        if self._file_path not in ALL_JS_TEST_FILES:
+            return
+
+        if self._file_path in KEEP_JS_TEST_FILES_IN_SYNC:
+            self.check_js_test_files()
+
+        if self._file_path in ALL_JS_TEST_FILES:
+            self.check_js_test_functions()
+
+    def check_js_test_files(self):
+        """Test that files in KEEP_JS_TEST_FILES_IN_SYNC are identical."""
+        with self._fs.open_binary_file_for_reading(self._file_path) as file_handle:
+            baseline_content = file_handle.read()
+
+        other_files = KEEP_JS_TEST_FILES_IN_SYNC
+        other_files.remove(self._file_path)
+
+        for path in other_files:
+            with self._fs.open_binary_file_for_reading(path) as file_handle:
+                test_content = file_handle.read()
+                if baseline_content != test_content:
+                    error_message = "Changes should be kept in sync with {0}.".format(path)
+                    self._handle_style_error(0, 'jstest/resource_equality', 5, error_message)
+
+    def check_js_test_functions(self):
+        """Test that functions in KEEP_JS_TEST_FUNCTIONS_IN_SYNC are identical."""
+        with self._fs.open_binary_file_for_reading(self._file_path) as file_handle:
+            baseline_content = file_handle.read()
+        baseline_function_map = map_functions_to_dict(baseline_content)
+
+        other_files = ALL_JS_TEST_FILES
+        other_files.remove(self._file_path)
+
+        for path in other_files:
+            with self._fs.open_binary_file_for_reading(path) as file_handle:
+                test_content = file_handle.read()
+            test_function_map = map_functions_to_dict(test_content)
+
+            for function_name in KEEP_JS_TEST_FUNCTIONS_IN_SYNC:
+                if function_name in baseline_function_map.keys() and function_name in test_function_map.keys():
+                    if baseline_function_map[function_name] != test_function_map[function_name]:
+                        error_message = "Changes to function {0}() should be kept in sync with {1}.".format(
+                            function_name, path)
+                        self._handle_style_error(0, 'jstest/function_equality', 5, error_message)
diff --git a/Tools/Scripts/webkitpy/style/checkers/jstest_unittest.py b/Tools/Scripts/webkitpy/style/checkers/jstest_unittest.py
new file mode 100644 (file)
index 0000000..1947667
--- /dev/null
@@ -0,0 +1,66 @@
+# Copyright (C) 2017 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unit test for jstest.py."""
+
+import unittest
+
+from jstest import map_functions_to_dict
+
+
+class JSTestTestCase(unittest.TestCase):
+    """TestCase for jstest.py"""
+
+    def test_map_functions_to_dict(self):
+        """Tests map_functions_to_dict().
+
+        This also implicitly tests strip_trailing_blank_lines_and_comments().
+        """
+        file1 = """
+function shouldBe() {}
+
+// Same as !shouldBe(), but output makes more sense.
+function shouldNotBe() {}
+
+function shouldNotThrow() {
+    return;
+}
+
+// See also shouldNotThrow().
+function shouldThrow() {
+}
+
+"""
+        result1 = map_functions_to_dict(file1)
+
+        file2 = """function shouldBe() {}
+function shouldNotBe() {}
+function shouldThrow() {
+}
+function shouldNotThrow() {
+    return;
+}
+"""
+        result2 = map_functions_to_dict(file2)
+
+        self.assertDictEqual(result1, result2)