THRIFT-2976: add browserify support and tests
Client: nodejs
Patch: Andrew de Andrade
diff --git a/lib/nodejs/test/test_driver.js b/lib/nodejs/test/test_driver.js
index 9f2b894..f79baa6 100644
--- a/lib/nodejs/test/test_driver.js
+++ b/lib/nodejs/test/test_driver.js
@@ -26,177 +26,195 @@
  // supports an optional callback function which is called with
  // a status message when the test is complete.
 
-var assert = require('assert');
+var test = require('tape');
+//var assert = require('assert');
 var ttypes = require('./gen-nodejs/ThriftTest_types');
 var Int64 = require('node-int64');
 var testCases = require('./test-cases');
 
 exports.ThriftTestDriver = function(client, callback) {
 
-  function makeAsserter(assertionFn) {
-    return function(c) {
-      var fnName = c[0];
-      var expected = c[1];
-      client[fnName](expected, function(err, actual) {
-        assert(!err);
-        assertionFn(actual, expected);
-      })
-    };
-  }
+  test('NodeJS Style Callback Client Tests', function(assert) {
 
-  testCases.simple.forEach(makeAsserter(assert.equal));
-  testCases.deep.forEach(makeAsserter(assert.deepEqual));
+    var checkRecursively = makeRecursiveCheck(assert);
 
-  client.testStruct(testCases.out, function(err, response) {
-    assert(!err);
-    checkRecursively(testCases.out, response);
-  });
+    function makeAsserter(assertionFn) {
+      return function(c) {
+        var fnName = c[0];
+        var expected = c[1];
+        client[fnName](expected, function(err, actual) {
+          assert.error(err, fnName + ': no callback error');
+          assertionFn(actual, expected, fnName);
+        })
+      };
+    }
 
-  client.testNest(testCases.out2, function(err, response) {
-    assert(!err);
-    checkRecursively(testCases.out2, response);
-  });
+    testCases.simple.forEach(makeAsserter(assert.equal));
+    testCases.simpleLoose.forEach(makeAsserter(function(a, e, m){
+      assert.ok(a == e, m);
+    }));
+    testCases.deep.forEach(makeAsserter(assert.deepEqual));
 
-  client.testInsanity(testCases.crazy, function(err, response) {
-    assert(!err);
-    checkRecursively(testCases.insanity, response);
-  });
-
-  client.testException('TException', function(err, response) {
-    assert(!err);
-    assert(!response);
-  });
-
-  client.testException('Xception', function(err, response) {
-    assert(!response);
-    assert.equal(err.errorCode, 1001);
-    assert.equal('Xception', err.message);
-  });
-
-  client.testException('no Exception', function(err, response) {
-    assert(!err);
-    assert.equal(undefined, response); //void
-  });
-
-  client.testOneway(0, function(err, response) {
-    assert(false); //should not answer
-  });
-
-  checkOffByOne(function(done) {
-    client.testI32(-1, function(err, response) {
-      assert(!err);
-      assert.equal(-1, response);
-      done();
+    client.testStruct(testCases.out, function(err, response) {
+      assert.error(err, 'testStruct: no callback error');
+      checkRecursively(testCases.out, response, 'testStruct');
     });
-  }, callback);
 
+    client.testNest(testCases.out2, function(err, response) {
+      assert.error(err, 'testNest: no callback error');
+      checkRecursively(testCases.out2, response, 'testNest');
+    });
+
+    client.testInsanity(testCases.crazy, function(err, response) {
+      assert.error(err, 'testInsanity: no callback error');
+      checkRecursively(testCases.insanity, response, 'testInsanity');
+    });
+
+    client.testException('TException', function(err, response) {
+      assert.error(err, 'testException: no callback error');
+      assert.ok(!response, 'testException: no response');
+    });
+
+    client.testException('Xception', function(err, response) {
+      assert.ok(!response, 'testException: no response');
+      assert.equal(err.errorCode, 1001, 'testException: correct error code');
+      assert.equal('Xception', err.message, 'testException: correct error message');
+    });
+
+    client.testException('no Exception', function(err, response) {
+      assert.error(err, 'testException: no callback error');
+      assert.ok(!response, 'testException: no response');
+    });
+
+    client.testOneway(0, function(err, response) {
+      assert.fail('testOneway should not answer');
+    });
+
+    checkOffByOne(function(done) {
+      client.testI32(-1, function(err, response) {
+        assert.error(err, 'checkOffByOne: no callback error');
+        assert.equal(-1, response);
+        assert.end();
+        done();
+      });
+    }, callback);
+
+  });
 };
 
 exports.ThriftTestDriverPromise = function(client, callback) {
 
-  function makeAsserter(assertionFn) {
-    return function(c) {
-      var fnName = c[0];
-      var expected = c[1];
-      client[fnName](expected)
-        .then(function(actual) {
-          assert.equal(actual, expected);
-        })
-        .fail(failTest);
-    };
-  }
+  test('Q Promise Client Tests', function(assert) {
 
-  testCases.simple.forEach(makeAsserter(assert.equal));
-  testCases.deep.forEach(makeAsserter(assert.deepEqual));
+    var checkRecursively = makeRecursiveCheck(assert);
 
-  client.testStruct(testCases.out)
-    .then(function(response) {
-      checkRecursivelyP(testCases.out, response);
-    })
-    .fail(failTest);
+    function fail(msg) {
+      return function() {
+        assert.fail(msg);
+      }
+    }
 
-  client.testNest(testCases.out2)
-    .then(function(response) {
-      checkRecursivelyP(testCases.out2, response);
-    })
-    .fail(failTest);
+    function makeAsserter(assertionFn) {
+      return function(c) {
+        var fnName = c[0];
+        var expected = c[1];
+        client[fnName](expected)
+          .then(function(actual) {
+            assertionFn(actual, expected, fnName);
+          })
+          .fail(fail('fnName'));
+      };
+    }
 
-  client.testInsanity(testCases.crazy)
-    .then(function(response) {
-      checkRecursivelyP(testCases.insanity, response);
-    })
-    .fail(failTest);
+    testCases.simple.forEach(makeAsserter(assert.equal));
+    testCases.simpleLoose.forEach(makeAsserter(function(a, e, m){
+      assert.ok(a == e, m);
+    }));
+    testCases.deep.forEach(makeAsserter(assert.deepEqual));
 
-  client.testException('TException')
-    .then(failTest);
-
-  client.testException('Xception')
-    .then(function(response) {
-      assert.equal(err.errorCode, 1001);
-      assert.equal('Xception', err.message);
-    })
-    .fail(failTest);
-
-  client.testException('no Exception')
-    .then(function(response) {
-      assert.equal(undefined, response); //void
-    })
-    .fail(failTest);
-
-  client.testOneway(0, failTest); //should not answer
-
-  checkOffByOne(function(done) {
-    client.testI32(-1)
+    client.testStruct(testCases.out)
       .then(function(response) {
-          assert.equal(-1, response);
-          done();
+        checkRecursively(testCases.out, response, 'testStruct');
       })
-      .fail(function() {
-        assert(false);
-      });
-  }, callback);
+      .fail(fail('testStruct'));
 
+    client.testNest(testCases.out2)
+      .then(function(response) {
+        checkRecursively(testCases.out2, response, 'testNest');
+      })
+      .fail(fail('testNest'));
+
+    client.testInsanity(testCases.crazy)
+      .then(function(response) {
+        checkRecursively(testCases.insanity, response, 'testInsanity');
+      })
+      .fail(fail('testInsanity'));
+
+    client.testException('TException')
+      .then(function(response) {
+        assert.ok(!response, 'testException: TException');
+      })
+      .fail(fail('testException: TException'));
+
+    client.testException('Xception')
+      .then(function(response) {
+        assert.ok(!response);
+      })
+      .fail(function(err) {
+        assert.equal(err.errorCode, 1001);
+        assert.equal('Xception', err.message);
+      });
+
+    client.testException('no Exception')
+      .then(function(response) {
+        assert.equal(undefined, response); //void
+      })
+      .fail(fail('testException'));
+
+    client.testOneway(0, fail('testOneway: should not answer'));
+
+    checkOffByOne(function(done) {
+      client.testI32(-1)
+        .then(function(response) {
+            assert.equal(-1, response);
+            assert.end();
+            done();
+        })
+        .fail(fail('checkOffByOne'));
+    }, callback);
+  });
 };
 
 
 // Helper Functions
 // =========================================================
 
-function failTest() {
-  assert(false);
-}
+function makeRecursiveCheck(assert) {
 
-// This is the version of checkRecursively that was in the vanilla callback
-// version of test_driver.
-function checkRecursively(map1, map2) {
-  if (typeof map1 !== 'function' && typeof map2 !== 'function') {
-    if (!map1 || typeof map1 !== 'object') {
-      //Handle int64 types (which use node-int64 in Node.js JavaScript)
-      if ((typeof map1 === "number") && (typeof map2 === "object") &&
-          (map2.buffer) && (map2.buffer instanceof Buffer) && (map2.buffer.length === 8)) {
-        var n = new Int64(map2.buffer);
-        assert.equal(map1, n.toNumber());
-      } else {
-        assert.equal(map1, map2);
-      }
-    } else {
-      for (var key in map1) {
-        checkRecursively(map1[key], map2[key]);
-      }
-    }
-  }
-}
+  return function (map1, map2, msg) {
+    var equal = true;
 
-// This is the version of checkRecursively that was in the promise version of
-// test_driver.
-// deepEqual doesn't work with fields using node-int64
-function checkRecursivelyP(map1, map2) {
-  if (typeof map1 !== 'function' && typeof map2 !== 'function') {
-    if (!map1 || typeof map1 !== 'object') {
-        assert.equal(map1, map2);
-    } else {
-      for (var key in map1) {
-        checkRecursivelyP(map1[key], map2[key]);
+    var equal = checkRecursively(map1, map2);
+
+    assert.ok(equal, msg);
+
+    // deepEqual doesn't work with fields using node-int64
+    function checkRecursively(map1, map2) {
+      if (typeof map1 !== 'function' && typeof map2 !== 'function') {
+        if (!map1 || typeof map1 !== 'object') {
+          //Handle int64 types (which use node-int64 in Node.js JavaScript)
+          if ((typeof map1 === "number") && (typeof map2 === "object") &&
+              (map2.buffer) && (map2.buffer instanceof Buffer) && (map2.buffer.length === 8)) {
+            var n = new Int64(map2.buffer);
+            return map1 === n.toNumber();
+          } else {
+            return map1 == map2;
+          }
+        } else {
+          return Object.keys(map1).every(function(key) {
+            return checkRecursively(map1[key], map2[key]);
+          });
+        }
       }
     }
   }