Enhance shouldBe()/shouldNotBe() to accept anonymous function arguments
authorddkilzer@apple.com <ddkilzer@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Apr 2017 21:29:23 +0000 (21:29 +0000)
committerddkilzer@apple.com <ddkilzer@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Apr 2017 21:29:23 +0000 (21:29 +0000)
<https://webkit.org/b/171362>
<rdar://problem/31867686>

Reviewed by Joseph Pecoraro.

JSTests:

* stress/resources/standalone-pre.js:
(shouldBe):
(shouldNotThrow):
(shouldThrow):
- Update shouldBe() to accept anonymous function arguments.
  (The shouldNotBe() function was never copied over.)
- Also fix shouldThrow()/shouldNotThrow() to accept anonymous
  function arguments (which were missed in r202609 for Bug
  159232).

LayoutTests:

This change makes it possible to pass either the first or second
argument (or both) as anonymous functions into shouldBe() and
shouldNotBe() to make it easy to capture local variables when
writing tests.  This is similar to the change in r202609 for Bug
159232 for shouldThrow() and shouldNotThrow().

Note that shouldBe()/shouldNotBe() from the following files were
NOT updated since they were imported from other projects and did
share the full WebKit history of resources/js-test-pre.js:

    http/tests/webgl/1.0.2/resources/webgl_test_files/resources/js-test-pre.js
    js/mozilla/resources/js-test-pre.js
    webgl/1.0.2/resources/webgl_test_files/resources/js-test-pre.js
    webgl/1.0.3/resources/webgl_test_files/resources/js-test-pre.js

However, these files WERE brought up-to-date with the ability to
pass anonymous functions into shouldBe()/shouldNotBe() for this
bug, and shouldThrow()/shouldNotThrow() which should have
originally been fixed with Bug 159232:

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

* css3/scroll-snap/resources/iframe-content.html: Drive-by fix
to debug message for copy-paste error.  Found by searching
LayoutTests directory for "expects string arguments".

* fast/canvas/webgl/array-unit-tests-expected.txt: Update test
results.
* fast/canvas/webgl/array-unit-tests.html: Fix warning by making
second argument to shouldBe() a string.

* fast/css/script-tests/image-set-parsing.js:
(testImageSetRule): Remove comment by changing second argument
to shouldBe() into an anonymous function.

* http/tests/resources/js-test-pre.js:
(evalAndLog):
(evalAndLogResult):
(shouldBe):
(shouldNotBe):
(shouldEvaluateTo):
- Made a full copy of resources/js-test-pre.js to bring this up
  to speed.  Needs a checker written for it to keep them in sync.
* http/tests/security/xssAuditor/block-does-not-leak-location-expected.txt:
* http/tests/security/xssAuditor/block-does-not-leak-referrer-expected.txt:
- Update line numbers after updating http/tests/resources/js-test-pre.js.

* js/function-declarations-in-switch-statement-expected.txt:
- Update results after fixing warnings.
* js/script-tests/function-declarations-in-switch-statement.js:
- Fix warnings by passing in strings to shouldBe().

* js/script-tests/stack-unwinding.js:
- Update results after fixing warnings.
* js/stack-unwinding-expected.txt:
- Fix warnings by passing in strings to shouldBe().

* resources/js-test-pre.js:
(shouldBe):
(shouldNotBe):
* resources/js-test.js:
(shouldBe):
(shouldNotBe):
- Update shouldBe()/shouldNotBe() to accept anonymous function
  arguments.

* resources/standalone-pre.js:
(shouldBe):
(shouldNotBe):
(shouldNotThrow):
(shouldThrow):
- Update shouldBe()/shouldNotBe() to accept anonymous function
  arguments.
- Also fix shouldThrow()/shouldNotThrow() to accept anonymous
  function arguments (which were missed in r202609 for Bug
  159232).

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

17 files changed:
JSTests/ChangeLog
JSTests/stress/resources/standalone-pre.js
LayoutTests/ChangeLog
LayoutTests/css3/scroll-snap/resources/iframe-content.html
LayoutTests/fast/canvas/webgl/array-unit-tests-expected.txt
LayoutTests/fast/canvas/webgl/array-unit-tests.html
LayoutTests/fast/css/script-tests/image-set-parsing.js
LayoutTests/http/tests/resources/js-test-pre.js
LayoutTests/http/tests/security/xssAuditor/block-does-not-leak-location-expected.txt
LayoutTests/http/tests/security/xssAuditor/block-does-not-leak-referrer-expected.txt
LayoutTests/js/function-declarations-in-switch-statement-expected.txt
LayoutTests/js/script-tests/function-declarations-in-switch-statement.js
LayoutTests/js/script-tests/stack-unwinding.js
LayoutTests/js/stack-unwinding-expected.txt
LayoutTests/resources/js-test-pre.js
LayoutTests/resources/js-test.js
LayoutTests/resources/standalone-pre.js

index 078ed24..abdc2b2 100644 (file)
@@ -1,3 +1,21 @@
+2017-04-27  David Kilzer  <ddkilzer@apple.com>
+
+        Enhance shouldBe()/shouldNotBe() to accept anonymous function arguments
+        <https://webkit.org/b/171362>
+        <rdar://problem/31867686>
+
+        Reviewed by Joseph Pecoraro.
+
+        * stress/resources/standalone-pre.js:
+        (shouldBe):
+        (shouldNotThrow):
+        (shouldThrow):
+        - Update shouldBe() to accept anonymous function arguments.
+          (The shouldNotBe() function was never copied over.)
+        - Also fix shouldThrow()/shouldNotThrow() to accept anonymous
+          function arguments (which were missed in r202609 for Bug
+          159232).
+
 2017-04-27  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         [JSC] Handle PhantomSpread in LoadVarargs as the same to the others
index 2e850f5..61c6527 100644 (file)
@@ -120,24 +120,26 @@ function stringify(v)
         return "" + v;
 }
 
-function shouldBe(_a, _b)
+function shouldBe(_a, _b, quiet)
 {
-  if (typeof _a != "string" || typeof _b != "string")
-    debug("WARN: shouldBe() expects string arguments");
+  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 = eval(_a);
+    _av = (typeof _a == "function" ? _a() : eval(_a));
   } catch (e) {
-     exception = e;
+    exception = e;
   }
-  var _bv = eval(_b);
+  var _bv = (typeof _b == "function" ? _b() : eval(_b));
 
   if (exception)
     testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + exception);
-  else if (isResultCorrect(_av, _bv))
-    testPassed(_a + " is " + _b);
-  else if (typeof(_av) == typeof(_bv))
+  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 + ").");
@@ -233,38 +235,38 @@ function shouldBeUndefined(_a)
     testFailed(_a + " should be undefined. Was " + _av);
 }
 
-function shouldNotThrow(_a) {
+function shouldNotThrow(_a, _message) {
     try {
-        eval(_a);
-        testPassed(_a + " did not throw exception.");
+        typeof _a == "function" ? _a() : eval(_a);
+        testPassed((_message ? _message : _a) + " did not throw exception.");
     } catch (e) {
-        testFailed(_a + " should not throw exception. Threw exception " + e + ".");
+        testFailed((_message ? _message : _a) + " should not throw exception. Threw exception " + e + ".");
     }
 }
 
-function shouldThrow(_a, _e)
+function shouldThrow(_a, _e, _message)
 {
-  var exception;
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-     exception = e;
-  }
-
-  var _ev;
-  if (_e)
-      _ev =  eval(_e);
+    var _exception;
+    var _av;
+    try {
+        _av = typeof _a == "function" ? _a() : eval(_a);
+    } catch (e) {
+        _exception = e;
+    }
 
-  if (exception) {
-    if (typeof _e == "undefined" || exception == _ev)
-      testPassed(_a + " threw exception " + exception + ".");
+    var _ev;
+    if (_e)
+        _ev =  eval(_e);
+
+    if (_exception) {
+        if (typeof _e == "undefined" || _exception == _ev)
+            testPassed((_message ? _message : _a) + " threw exception " + _exception + ".");
+        else
+            testFailed((_message ? _message : _a) + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Threw exception " + _exception + ".");
+    } else if (typeof _av == "undefined")
+        testFailed((_message ? _message : _a) + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was undefined.");
     else
-      testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Threw exception " + exception + ".");
-  } else if (typeof _av == "undefined")
-    testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was undefined.");
-  else
-    testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was " + _av + ".");
+        testFailed((_message ? _message : _a) + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was " + _av + ".");
 }
 
 function isSuccessfullyParsed()
index 4e4e726..63bd0db 100644 (file)
@@ -1,3 +1,89 @@
+2017-04-27  David Kilzer  <ddkilzer@apple.com>
+
+        Enhance shouldBe()/shouldNotBe() to accept anonymous function arguments
+        <https://webkit.org/b/171362>
+        <rdar://problem/31867686>
+
+        Reviewed by Joseph Pecoraro.
+
+        This change makes it possible to pass either the first or second
+        argument (or both) as anonymous functions into shouldBe() and
+        shouldNotBe() to make it easy to capture local variables when
+        writing tests.  This is similar to the change in r202609 for Bug
+        159232 for shouldThrow() and shouldNotThrow().
+
+        Note that shouldBe()/shouldNotBe() from the following files were
+        NOT updated since they were imported from other projects and did
+        share the full WebKit history of resources/js-test-pre.js:
+
+            http/tests/webgl/1.0.2/resources/webgl_test_files/resources/js-test-pre.js
+            js/mozilla/resources/js-test-pre.js
+            webgl/1.0.2/resources/webgl_test_files/resources/js-test-pre.js
+            webgl/1.0.3/resources/webgl_test_files/resources/js-test-pre.js
+
+        However, these files WERE brought up-to-date with the ability to
+        pass anonymous functions into shouldBe()/shouldNotBe() for this
+        bug, and shouldThrow()/shouldNotThrow() which should have
+        originally been fixed with Bug 159232:
+
+            http/tests/resources/js-test-pre.js
+            resources/standalone-pre.js
+
+        * css3/scroll-snap/resources/iframe-content.html: Drive-by fix
+        to debug message for copy-paste error.  Found by searching
+        LayoutTests directory for "expects string arguments".
+
+        * fast/canvas/webgl/array-unit-tests-expected.txt: Update test
+        results.
+        * fast/canvas/webgl/array-unit-tests.html: Fix warning by making
+        second argument to shouldBe() a string.
+
+        * fast/css/script-tests/image-set-parsing.js:
+        (testImageSetRule): Remove comment by changing second argument
+        to shouldBe() into an anonymous function.
+
+        * http/tests/resources/js-test-pre.js:
+        (evalAndLog):
+        (evalAndLogResult):
+        (shouldBe):
+        (shouldNotBe):
+        (shouldEvaluateTo):
+        - Made a full copy of resources/js-test-pre.js to bring this up
+          to speed.  Needs a checker written for it to keep them in sync.
+        * http/tests/security/xssAuditor/block-does-not-leak-location-expected.txt:
+        * http/tests/security/xssAuditor/block-does-not-leak-referrer-expected.txt:
+        - Update line numbers after updating http/tests/resources/js-test-pre.js.
+
+        * js/function-declarations-in-switch-statement-expected.txt:
+        - Update results after fixing warnings.
+        * js/script-tests/function-declarations-in-switch-statement.js:
+        - Fix warnings by passing in strings to shouldBe().
+
+        * js/script-tests/stack-unwinding.js:
+        - Update results after fixing warnings.
+        * js/stack-unwinding-expected.txt:
+        - Fix warnings by passing in strings to shouldBe().
+
+        * resources/js-test-pre.js:
+        (shouldBe):
+        (shouldNotBe):
+        * resources/js-test.js:
+        (shouldBe):
+        (shouldNotBe):
+        - Update shouldBe()/shouldNotBe() to accept anonymous function
+          arguments.
+
+        * resources/standalone-pre.js:
+        (shouldBe):
+        (shouldNotBe):
+        (shouldNotThrow):
+        (shouldThrow):
+        - Update shouldBe()/shouldNotBe() to accept anonymous function
+          arguments.
+        - Also fix shouldThrow()/shouldNotThrow() to accept anonymous
+          function arguments (which were missed in r202609 for Bug
+          159232).
+
 2017-04-27  Chris Dumez  <cdumez@apple.com>
 
         Element.getBoundingClientRect() / getClientRects() should return a DOMRect types
index c2698db..08ac4fb 100644 (file)
@@ -53,7 +53,7 @@
         function shouldMatch(_a, _b, result)
         {
             if (typeof _a !== "string" || typeof _b !== "string")
-                top.debug("WARN: shouldBeEqualToString() expects string arguments");
+                top.debug("WARN: shouldMatch() expects string arguments");
 
             var _av;
             try {
index b41dbb1..3fc41c1 100644 (file)
@@ -5,7 +5,6 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 PASS testSlice
 test inheritance hierarchy of typed array views
 PASS ArrayBufferView should be undefined and is
-WARN: shouldBe() expects string arguments
 PASS new Uint8ClampedArray(1) instanceof Uint8Array is false
 PASS test Float32Array SetAndGetPos10ToNeg10
 PASS test Float32Array ConstructWithArrayOfSignedValues
index f884676..ede7500 100644 (file)
@@ -123,7 +123,7 @@ function testInheritanceHierarchy() {
     testPassed('ArrayBufferView should be undefined and is');
   }
 
-  shouldBe('new Uint8ClampedArray(1) instanceof Uint8Array', false);
+  shouldBe('new Uint8ClampedArray(1) instanceof Uint8Array', 'false');
 }
 
 //
index f720298..c8c1910 100644 (file)
@@ -43,7 +43,7 @@ function testImageSetRule(description, property, rule, expectedLength, expectedT
         }
     }
 
-    shouldBe("imageSetRule.length", "" + expectedLength); // shouldBe expects string arguments
+    shouldBe("imageSetRule.length", function() { return expectedLength; });
 
     if (imageSetRule) {
         for (var i = 0; i < expectedLength; i++) {
index 919e816..62801c5 100644 (file)
@@ -193,7 +193,7 @@ function stringify(v)
 function evalAndLog(_a, _quiet)
 {
   if (typeof _a != "string")
-    debug("WARN: tryAndLog() expects a string argument");
+    debug("WARN: evalAndLog() expects a string argument");
 
   // Log first in case things go horribly wrong or this causes a sync event.
   if (!_quiet)
@@ -208,24 +208,39 @@ function evalAndLog(_a, _quiet)
   return _av;
 }
 
+function evalAndLogResult(_a)
+{
+  if (typeof _a != "string")
+    debug("WARN: evalAndLogResult() expects a string argument");
+
+  var _av;
+  try {
+     _av = eval(_a);
+  } catch (e) {
+    testFailed(_a + " threw exception " + e);
+  }
+
+  debug('<span>' + _a + " is " + escapeHTML(_av) + '</span>');
+}
+
 function shouldBe(_a, _b, quiet)
 {
-  if (typeof _a != "string" || typeof _b != "string")
-    debug("WARN: shouldBe() expects string arguments");
+  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 = eval(_a);
+    _av = (typeof _a == "function" ? _a() : eval(_a));
   } catch (e) {
-     exception = e;
+    exception = e;
   }
-  var _bv = eval(_b);
+  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 " + _b);
+      testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b));
     }
   } else if (typeof(_av) == typeof(_bv))
     testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + ".");
@@ -375,22 +390,22 @@ function shouldBeCloseTo(_to_eval, _target, _tolerance, quiet)
 
 function shouldNotBe(_a, _b, quiet)
 {
-  if (typeof _a != "string" || typeof _b != "string")
-    debug("WARN: shouldNotBe() expects string arguments");
+  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);
+  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 " + _b);
+      testPassed(_a + " is not " + (typeof _b == "function" ? _bv : _b));
     }
   } else
     testFailed(_a + " should not be " + _bv + ".");
@@ -445,7 +460,8 @@ function shouldNotBeEqualToString(a, b)
 }
 function shouldBeEmptyString(_a) { shouldBeEqualToString(_a, ""); }
 
-function shouldEvaluateTo(actual, expected) {
+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.
@@ -617,6 +633,24 @@ function shouldThrow(_a, _e, _message)
         testFailed((_message ? _message : _a) + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was " + _av + ".");
 }
 
+function shouldReject(_a, _message)
+{
+    var _exception;
+    var _av;
+    try {
+        _av = typeof _a == "function" ? _a() : eval(_a);
+    } catch (e) {
+        testFailed((_message ? _message : _a) + " should not throw exception. Threw exception " + e + ".");
+        return Promise.resolve();
+    }
+
+     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 + ".");
+    });
+}
+
 function shouldThrowErrorName(_a, _name)
 {
     var _exception;
index 43391f4..b3269e6 100644 (file)
@@ -1,7 +1,7 @@
 CONSOLE MESSAGE: line 7: The XSS Auditor blocked access to 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?test=/security/xssAuditor/block-does-not-leak-location.html&enable-full-block=1&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53));%3C/script%3E' because the source code of a script was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior.
-CONSOLE MESSAGE: line 218: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
-CONSOLE MESSAGE: line 218: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
-CONSOLE MESSAGE: line 222: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
+CONSOLE MESSAGE: line 233: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
+CONSOLE MESSAGE: line 233: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
+CONSOLE MESSAGE: line 237: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
 PASS xssed.contentDocument is null
 PASS xssed.contentDocument is crossorigin.contentDocument
 PASS xssed.contentWindow.location.href threw exception SecurityError (DOM Exception 18): Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match..
index 58d0cac..f47ed2f 100644 (file)
@@ -1,5 +1,5 @@
 CONSOLE MESSAGE: line 4: The XSS Auditor blocked access to 'http://localhost:8000/security/xssAuditor/resources/echo-intertag.pl?enable-full-block=1&q=%3Cscript%3Ealert(String.fromCharCode(0x58,0x53,0x53))%3C/script%3E' because the source code of a script was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior.
-CONSOLE MESSAGE: line 218: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
+CONSOLE MESSAGE: line 233: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
 PASS frame.contentDocument is null
 PASS successfullyParsed is true
 
index 9b277dc..8f48657 100644 (file)
@@ -1,9 +1,6 @@
-WARN: shouldBe() expects string arguments
-PASS 20 is 20
-WARN: shouldBe() expects string arguments
-PASS 20 is 20
-WARN: shouldBe() expects string arguments
-PASS -1 is -1
+PASS t(1) is 20
+PASS t(2) is 20
+PASS t(3) is -1
 PASS successfullyParsed is true
 
 TEST COMPLETE
index f3c4ba2..06cd90e 100644 (file)
@@ -19,6 +19,6 @@ function t(n) {
     }
 }
 
-shouldBe(t(1), '20');
-shouldBe(t(2), '20');
-shouldBe(t(3), '-1');
+shouldBe('t(1)', '20');
+shouldBe('t(2)', '20');
+shouldBe('t(3)', '-1');
index 9c41641..2ed3614 100644 (file)
@@ -32,7 +32,7 @@ function hostAndException() {
 
 twoHostFunctions();
 myArray = hostCallsUser(myArray);
-shouldBe(myArray, new Array( 5, 6, 7 ) );
+shouldBe('myArray', 'new Array( 5, 6, 7 )');
 
 try {
     hostAndException();
index 17a2124..927c455 100644 (file)
@@ -4,8 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS Two host functions called in a row.
-WARN: shouldBe() expects string arguments
-PASS 5,6,7 is 5,6,7
+PASS myArray is new Array( 5, 6, 7 )
 PASS Exception thrown and caught
 PASS successfullyParsed is true
 
index bda0463..62801c5 100644 (file)
@@ -225,22 +225,22 @@ function evalAndLogResult(_a)
 
 function shouldBe(_a, _b, quiet)
 {
-  if (typeof _a != "string" || typeof _b != "string")
-    debug("WARN: shouldBe() expects string arguments");
+  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 = eval(_a);
+    _av = (typeof _a == "function" ? _a() : eval(_a));
   } catch (e) {
-     exception = e;
+    exception = e;
   }
-  var _bv = eval(_b);
+  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 " + _b);
+      testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b));
     }
   } else if (typeof(_av) == typeof(_bv))
     testFailed(_a + " should be " + stringify(_bv) + ". Was " + stringify(_av) + ".");
@@ -390,22 +390,22 @@ function shouldBeCloseTo(_to_eval, _target, _tolerance, quiet)
 
 function shouldNotBe(_a, _b, quiet)
 {
-  if (typeof _a != "string" || typeof _b != "string")
-    debug("WARN: shouldNotBe() expects string arguments");
+  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);
+  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 " + _b);
+      testPassed(_a + " is not " + (typeof _b == "function" ? _bv : _b));
     }
   } else
     testFailed(_a + " should not be " + _bv + ".");
index c8c6401..066dbb6 100644 (file)
@@ -230,22 +230,22 @@ function evalAndLog(_a, _quiet)
 
 function shouldBe(_a, _b, quiet)
 {
-  if (typeof _a != "string" || typeof _b != "string")
-    debug("WARN: shouldBe() expects string arguments");
+  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 = eval(_a);
+    _av = (typeof _a == "function" ? _a() : eval(_a));
   } catch (e) {
-     _exception = e;
+    _exception = e;
   }
-  var _bv = eval(_b);
+  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 " + _b);
+      testPassed(_a + " is " + (typeof _b == "function" ? _bv : _b));
     }
   } else if (typeof(_av) == typeof(_bv))
     testFailed(_a + " should be " + _bv + ". Was " + stringify(_av) + ".");
@@ -353,22 +353,22 @@ function shouldBeCloseTo(_to_eval, _target, _tolerance, _quiet)
 
 function shouldNotBe(_a, _b, _quiet)
 {
-  if (typeof _a != "string" || typeof _b != "string")
-    debug("WARN: shouldNotBe() expects string arguments");
+  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);
+  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 " + _b);
+      testPassed(_a + " is not " + (typeof _b == "function" ? _bv : _b));
     }
   } else
     testFailed(_a + " should not be " + _bv + ".");
index 2b5859c..1c88151 100644 (file)
@@ -111,24 +111,26 @@ function stringify(v)
         return "" + v;
 }
 
-function shouldBe(_a, _b)
+function shouldBe(_a, _b, quiet)
 {
-  if (typeof _a != "string" || typeof _b != "string")
-    debug("WARN: shouldBe() expects string arguments");
+  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 = eval(_a);
+    _av = (typeof _a == "function" ? _a() : eval(_a));
   } catch (e) {
-     exception = e;
+    exception = e;
   }
-  var _bv = eval(_b);
+  var _bv = (typeof _b == "function" ? _b() : eval(_b));
 
   if (exception)
     testFailed(_a + " should be " + stringify(_bv) + ". Threw exception " + exception);
-  else if (isResultCorrect(_av, _bv))
-    testPassed(_a + " is " + _b);
-  else if (typeof(_av) == typeof(_bv))
+  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 + ").");
@@ -195,22 +197,22 @@ function shouldBeType(_a, _type) {
 
 function shouldNotBe(_a, _b, quiet)
 {
-  if (typeof _a != "string" || typeof _b != "string")
-    debug("WARN: shouldNotBe() expects string arguments");
+  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);
+  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 " + _b);
+      testPassed(_a + " is not " + (typeof _b == "function" ? _bv : _b));
     }
   } else
     testFailed(_a + " should not be " + _bv + ".");
@@ -265,38 +267,38 @@ function shouldBeDefined(_a)
     testFailed(_a + " should be defined. Was " + _av);
 }
 
-function shouldNotThrow(_a) {
+function shouldNotThrow(_a, _message) {
     try {
-        eval(_a);
-        testPassed(_a + " did not throw exception.");
+        typeof _a == "function" ? _a() : eval(_a);
+        testPassed((_message ? _message : _a) + " did not throw exception.");
     } catch (e) {
-        testFailed(_a + " should not throw exception. Threw exception " + e + ".");
+        testFailed((_message ? _message : _a) + " should not throw exception. Threw exception " + e + ".");
     }
 }
 
-function shouldThrow(_a, _e)
+function shouldThrow(_a, _e, _message)
 {
-  var exception;
-  var _av;
-  try {
-     _av = eval(_a);
-  } catch (e) {
-     exception = e;
-  }
-
-  var _ev;
-  if (_e)
-      _ev =  eval(_e);
+    var _exception;
+    var _av;
+    try {
+        _av = typeof _a == "function" ? _a() : eval(_a);
+    } catch (e) {
+        _exception = e;
+    }
 
-  if (exception) {
-    if (typeof _e == "undefined" || exception == _ev)
-      testPassed(_a + " threw exception " + exception + ".");
+    var _ev;
+    if (_e)
+        _ev =  eval(_e);
+
+    if (_exception) {
+        if (typeof _e == "undefined" || _exception == _ev)
+            testPassed((_message ? _message : _a) + " threw exception " + _exception + ".");
+        else
+            testFailed((_message ? _message : _a) + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Threw exception " + _exception + ".");
+    } else if (typeof _av == "undefined")
+        testFailed((_message ? _message : _a) + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was undefined.");
     else
-      testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Threw exception " + exception + ".");
-  } else if (typeof _av == "undefined")
-    testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was undefined.");
-  else
-    testFailed(_a + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was " + _av + ".");
+        testFailed((_message ? _message : _a) + " should throw " + (typeof _e == "undefined" ? "an exception" : _ev) + ". Was " + _av + ".");
 }
 
 function isSuccessfullyParsed()