From 9845b69012ac9d4ac69779387a94422ca1020a36 Mon Sep 17 00:00:00 2001
From: Lloyd Hilaiel <lloyd@hilaiel.com>
Date: Fri, 4 Nov 2011 00:43:53 -0600
Subject: [PATCH] fix race condition between token request and waiting for
 token, was causing test hangs.  closes #530

---
 tests/cert-emails-test.js               | 13 ++++---------
 tests/email-throttling-test.js          |  6 ++----
 tests/forgotten-email-test.js           |  9 +++------
 tests/lib/start-stop.js                 | 19 ++++++++++++++++++-
 tests/list-emails-wsapi-test.js         |  3 +--
 tests/password-bcrypt-update-test.js    |  3 +--
 tests/registration-status-wsapi-test.js |  6 ++----
 7 files changed, 31 insertions(+), 28 deletions(-)

diff --git a/tests/cert-emails-test.js b/tests/cert-emails-test.js
index b8e353fe3..59d0521f1 100755
--- a/tests/cert-emails-test.js
+++ b/tests/cert-emails-test.js
@@ -50,18 +50,13 @@ jwt = require('jwcrypto/jwt');
 
 var suite = vows.describe('cert-emails');
 
+var token = undefined;
+
 // disable vows (often flakey?) async error behavior
 suite.options.error = false;
 
 start_stop.addStartupBatches(suite);
 
-// ever time a new token is sent out, let's update the global
-// var 'token'
-var token = undefined;
-start_stop.browserid.on('token', function(secret) {
-  token = secret;
-});
-
 // INFO: some of these tests are repeat of sync-emails... to set
 // things up properly for key certification
 
@@ -83,11 +78,11 @@ suite.addBatch({
 suite.addBatch({
   "a token": {
     topic: function() {
-      if (token) return token;
-      else start_stop.browserid.once('token', this.callback);
+      start_stop.waitForToken(this.callback);
     },
     "is obtained": function (t) {
       assert.strictEqual(typeof t, 'string');
+      token = t;
     }
   }
 });
diff --git a/tests/email-throttling-test.js b/tests/email-throttling-test.js
index 52e86a126..bc3a18059 100755
--- a/tests/email-throttling-test.js
+++ b/tests/email-throttling-test.js
@@ -67,8 +67,7 @@ suite.addBatch({
 suite.addBatch({
   "a token": {
     topic: function() {
-      if (token) return token;
-      else start_stop.browserid.once('token', this.callback);
+      start_stop.waitForToken(this.callback);
     },
     "is obtained": function (t) {
       assert.strictEqual(typeof t, 'string');
@@ -118,8 +117,7 @@ suite.addBatch({
 suite.addBatch({
   "a token": {
     topic: function() {
-      if (token) return token;
-      else start_stop.browserid.once('token', this.callback);
+      start_stop.waitForToken(this.callback);
     },
     "is obtained": function (t) {
       assert.strictEqual(typeof t, 'string');
diff --git a/tests/forgotten-email-test.js b/tests/forgotten-email-test.js
index 87774f4a8..25ee67630 100755
--- a/tests/forgotten-email-test.js
+++ b/tests/forgotten-email-test.js
@@ -68,8 +68,7 @@ suite.addBatch({
 suite.addBatch({
   "a token": {
     topic: function() {
-      if (token) return token;
-      else start_stop.browserid.once('token', this.callback);
+      start_stop.waitForToken(this.callback);
     },
     "is obtained": function (t) {
       assert.strictEqual(typeof t, 'string');
@@ -118,8 +117,7 @@ suite.addBatch({
 suite.addBatch({
   "a token": {
     topic: function() {
-      if (token) return token;
-      else start_stop.browserid.once('token', this.callback);
+      start_stop.waitForToken(this.callback);
     },
     "is obtained": function (t) {
       assert.strictEqual(typeof t, 'string');
@@ -182,8 +180,7 @@ suite.addBatch({
 suite.addBatch({
   "a token": {
     topic: function() {
-      if (token) return token;
-      else start_stop.browserid.once('token', this.callback);
+      start_stop.waitForToken(this.callback);
     },
     "is obtained": function (t) {
       assert.strictEqual(typeof t, 'string');
diff --git a/tests/lib/start-stop.js b/tests/lib/start-stop.js
index a54da6659..1f2893910 100644
--- a/tests/lib/start-stop.js
+++ b/tests/lib/start-stop.js
@@ -49,6 +49,19 @@ process.on('exit', function () {
   if (proc) { proc.kill(); }
 });
 
+var nextTokenFunction = undefined;
+var tokenStack = [];
+
+exports.waitForToken = function(cb) {
+  if (tokenStack.length) {
+    cb(tokenStack.shift());
+  }
+  else {
+    if (nextTokenFunction) throw "can't wait for a verification token when someone else is!";
+    nextTokenFunction = cb;
+  }
+};
+
 exports.browserid = new events.EventEmitter;
 
 function setupProc(proc) {
@@ -62,7 +75,11 @@ function setupProc(proc) {
       exports.browserid.emit('ready');
       sentReady = true;
     } else if (m = tokenRegex.exec(x)) {
-      exports.browserid.emit('token', m[1]);
+      tokenStack.push(m[1]);
+      if (nextTokenFunction) {
+        nextTokenFunction(tokenStack.shift());
+        nextTokenFunction = undefined;
+      }
     }
   });
   proc.stderr.on('data', function(x) {
diff --git a/tests/list-emails-wsapi-test.js b/tests/list-emails-wsapi-test.js
index 1cc604231..ac9581ba6 100755
--- a/tests/list-emails-wsapi-test.js
+++ b/tests/list-emails-wsapi-test.js
@@ -70,8 +70,7 @@ suite.addBatch({
 suite.addBatch({
   "a token": {
     topic: function() {
-      if (token) return token;
-      else start_stop.browserid.once('token', this.callback);
+      start_stop.waitForToken(this.callback);
     },
     "is obtained": function (t) {
       assert.strictEqual(typeof t, 'string');
diff --git a/tests/password-bcrypt-update-test.js b/tests/password-bcrypt-update-test.js
index ad0483652..15f684112 100755
--- a/tests/password-bcrypt-update-test.js
+++ b/tests/password-bcrypt-update-test.js
@@ -89,8 +89,7 @@ suite.addBatch({
 suite.addBatch({
   "a token": {
     topic: function() {
-      if (token) return token;
-      else start_stop.browserid.once('token', this.callback);
+      start_stop.waitForToken(this.callback);
     },
     "is obtained": function (t) {
       assert.strictEqual(typeof t, 'string');
diff --git a/tests/registration-status-wsapi-test.js b/tests/registration-status-wsapi-test.js
index e0d40aa77..171974e91 100755
--- a/tests/registration-status-wsapi-test.js
+++ b/tests/registration-status-wsapi-test.js
@@ -90,8 +90,7 @@ suite.addBatch({
 suite.addBatch({
   "a token": {
     topic: function() {
-      if (token) return token;
-      else start_stop.browserid.once('token', this.callback);
+      start_stop.waitForToken(this.callback);
     },
     "is obtained": function (t) {
       assert.strictEqual(typeof t, 'string');
@@ -210,8 +209,7 @@ suite.addBatch({
 suite.addBatch({
   "a token": {
     topic: function() {
-      if (token) return token;
-      else start_stop.browserid.once('token', this.callback);
+      start_stop.waitForToken(this.callback);
     },
     "is obtained": function (t) {
       assert.strictEqual(typeof t, 'string');
-- 
GitLab