test: add additional async listener tests
authorJacob Groundwater <groundwater@gmail.com>
Tue, 15 Oct 2013 20:50:00 +0000 (13:50 -0700)
committerTrevor Norris <trev.norris@gmail.com>
Fri, 1 Nov 2013 00:10:23 +0000 (17:10 -0700)
test/simple/test-asynclistener-error-multiple-handled.js [new file with mode: 0644]
test/simple/test-asynclistener-error-multiple-mix.js [new file with mode: 0644]
test/simple/test-asynclistener-error-multiple-unhandled.js [new file with mode: 0644]
test/simple/test-asynclistener-error-throw-in-after.js [new file with mode: 0644]
test/simple/test-asynclistener-error-throw-in-before-multiple.js [new file with mode: 0644]
test/simple/test-asynclistener-error-throw-in-before.js [new file with mode: 0644]
test/simple/test-asynclistener-error-throw-in-error.js [new file with mode: 0644]
test/simple/test-asynclistener-remove-after.js
test/simple/test-asynclistener-remove-before.js [new file with mode: 0644]
test/simple/test-asynclistener-remove-inflight-error.js [new file with mode: 0644]
test/simple/test-asynclistener-remove-inflight.js [new file with mode: 0644]

diff --git a/test/simple/test-asynclistener-error-multiple-handled.js b/test/simple/test-asynclistener-error-multiple-handled.js
new file mode 100644 (file)
index 0000000..5a8dfbd
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+
+var active = null;
+var cntr = 0;
+
+function onAsync0() {
+  return 0;
+}
+
+function onAsync1() {
+  return 1;
+}
+
+var results = [];
+var asyncNoHandleError = {
+  error: function(stor) {
+    results.push(stor);
+    return true;
+  }
+};
+
+var listeners = [
+  process.addAsyncListener(onAsync0, asyncNoHandleError),
+  process.addAsyncListener(onAsync1, asyncNoHandleError)
+];
+
+process.nextTick(function() {
+  throw new Error();
+});
+
+process.removeAsyncListener(listeners[0]);
+process.removeAsyncListener(listeners[1]);
+
+process.on('exit', function(code) {
+  // If the exit code isn't ok then return early to throw the stack that
+  // caused the bad return code.
+  if (code !== 0)
+    return;
+
+  // Handling of errors should propagate to all listeners.
+  assert.equal(results[0], 0);
+  assert.equal(results[1], 1);
+  assert.equal(results.length, 2);
+
+  console.log('ok');
+});
diff --git a/test/simple/test-asynclistener-error-multiple-mix.js b/test/simple/test-asynclistener-error-multiple-mix.js
new file mode 100644 (file)
index 0000000..544900d
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+
+function onAsync() {}
+
+var results = [];
+var asyncNoHandleError = {
+  error: function(stor) {
+    results.push(1);
+  }
+};
+
+var asyncHandleError = {
+  error: function(stor) {
+    results.push(0);
+    return true;
+  }
+};
+
+var listeners = [
+  process.addAsyncListener(onAsync, asyncHandleError),
+  process.addAsyncListener(onAsync, asyncNoHandleError)
+];
+
+// Even if an error handler returns true, both should fire.
+process.nextTick(function() {
+  throw new Error();
+});
+
+process.removeAsyncListener(listeners[0]);
+process.removeAsyncListener(listeners[1]);
+
+process.on('exit', function(code) {
+  // If the exit code isn't ok then return early to throw the stack that
+  // caused the bad return code.
+  if (code !== 0)
+    return;
+
+  // Mixed handling of errors should propagate to all listeners.
+  assert.equal(results[0], 0);
+  assert.equal(results[1], 1);
+  assert.equal(results.length, 2);
+
+  console.log('ok');
+});
diff --git a/test/simple/test-asynclistener-error-multiple-unhandled.js b/test/simple/test-asynclistener-error-multiple-unhandled.js
new file mode 100644 (file)
index 0000000..7f3540b
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+
+function onAsync0() {
+  return 0;
+}
+
+function onAsync1() {
+  return 1;
+}
+
+var results = [];
+var asyncNoHandleError = {
+  error: function(stor) {
+    results.push(stor);
+  }
+};
+
+var listeners = [
+  process.addAsyncListener(onAsync0, asyncNoHandleError),
+  process.addAsyncListener(onAsync1, asyncNoHandleError)
+];
+
+var uncaughtFired = false;
+process.on('uncaughtException', function() {
+  uncaughtFired = true;
+
+  // Unhandled errors should propagate to all listeners.
+  assert.equal(results[0], 0);
+  assert.equal(results[1], 1);
+  assert.equal(results.length, 2);
+});
+
+process.nextTick(function() {
+  throw new Error();
+});
+
+process.on('exit', function(code) {
+  // If the exit code isn't ok then return early to throw the stack that
+  // caused the bad return code.
+  if (code !== 0)
+    return;
+
+  // Need to remove the async listeners or tests will always pass
+  for (var i = 0; i < listeners.length; i++)
+    process.removeAsyncListener(listeners[i]);
+
+  assert.ok(uncaughtFired);
+  console.log('ok');
+});
diff --git a/test/simple/test-asynclistener-error-throw-in-after.js b/test/simple/test-asynclistener-error-throw-in-after.js
new file mode 100644 (file)
index 0000000..77f8965
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+
+var once = 0;
+function onAsync0() { }
+
+var results = [];
+var handlers = {
+  after: function() {
+    throw 1;
+  },
+  error: function(stor, err) {
+    // Error handler must be called exactly *once*.
+    once++;
+    assert.equal(err, 1);
+    return true;
+  }
+}
+
+var key = process.addAsyncListener(onAsync0, handlers);
+
+var uncaughtFired = false;
+process.on('uncaughtException', function(err) {
+  uncaughtFired = true;
+
+  assert.equal(once, 1);
+});
+
+process.nextTick(function() { });
+
+process.removeAsyncListener(key);
+
+process.on('exit', function(code) {
+  // If the exit code isn't ok then return early to throw the stack that
+  // caused the bad return code.
+  if (code !== 0)
+    return;
+
+  assert.ok(uncaughtFired);
+  console.log('ok');
+});
diff --git a/test/simple/test-asynclistener-error-throw-in-before-multiple.js b/test/simple/test-asynclistener-error-throw-in-before-multiple.js
new file mode 100644 (file)
index 0000000..38da4e3
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+
+var once = 0;
+function onAsync0() { }
+function onAsync1() { }
+
+var results = [];
+var handlers = {
+  before: function() {
+    throw 1;
+  },
+  error: function(stor, err) {
+    // Must catch error thrown in before callback.
+    assert.equal(err, 1);
+    once++;
+    return true;
+  }
+}
+
+var handlers1 = {
+  before: function() {
+    throw 2;
+  },
+  error: function(stor, err) {
+    // Must catch *other* handlers throw by error callback.
+    assert.equal(err, 1);
+    once++;
+    return true;
+  }
+}
+
+var listeners = [
+  process.addAsyncListener(onAsync0, handlers),
+  process.addAsyncListener(onAsync1, handlers1)
+];
+
+var uncaughtFired = false;
+process.on('uncaughtException', function(err) {
+  uncaughtFired = true;
+
+  // Both error handlers must fire.
+  assert.equal(once, 2);
+});
+
+process.nextTick(function() { });
+
+for (var i = 0; i < listeners.length; i++)
+  process.removeAsyncListener(listeners[i]);
+
+process.on('exit', function(code) {
+  // If the exit code isn't ok then return early to throw the stack that
+  // caused the bad return code.
+  if (code !== 0)
+    return;
+  // Make sure uncaughtException actually fired.
+  assert.ok(uncaughtFired);
+  console.log('ok');
+});
+
diff --git a/test/simple/test-asynclistener-error-throw-in-before.js b/test/simple/test-asynclistener-error-throw-in-before.js
new file mode 100644 (file)
index 0000000..b8d0348
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+
+var once = 0;
+function onAsync0() {}
+
+var results = [];
+var handlers = {
+  before: function() {
+    throw 1;
+  },
+  error: function(stor, err) {
+    // Error handler must be called exactly *once*.
+    once++;
+    assert.equal(err, 1);
+    return true;
+  }
+}
+
+var key = process.addAsyncListener(onAsync0, handlers);
+
+var uncaughtFired = false;
+process.on('uncaughtException', function(err) {
+  uncaughtFired = true;
+
+  // Process should propagate error regardless of handlers return value.
+  assert.equal(once, 1);
+});
+
+process.nextTick(function() { });
+
+process.removeAsyncListener(key);
+
+process.on('exit', function(code) {
+  // If the exit code isn't ok then return early to throw the stack that
+  // caused the bad return code.
+  if (code !== 0)
+    return;
+
+  // Make sure that the uncaughtException actually fired.
+  assert.ok(uncaughtFired);
+  console.log('ok');
+});
diff --git a/test/simple/test-asynclistener-error-throw-in-error.js b/test/simple/test-asynclistener-error-throw-in-error.js
new file mode 100644 (file)
index 0000000..271dd03
--- /dev/null
@@ -0,0 +1,86 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+var spawn = require('child_process').spawn;
+
+var checkStr = 'WRITTEN ON EXIT\n';
+
+if (process.argv[2] === 'child')
+  runChild();
+else
+  runParent();
+
+
+function runChild() {
+  var cntr = 0;
+
+  var key = process.addAsyncListener(function() { }, {
+    error: function onError() {
+      cntr++;
+      throw new Error('onError');
+    }
+  });
+
+  process.on('unhandledException', function() {
+    // Throwing in 'error' should bypass unhandledException.
+    process.exit(2);
+  });
+
+  process.on('exit', function() {
+    // Make sure that we can still write out to stderr even when the
+    // process dies.
+    process._rawDebug(checkStr);
+  });
+
+  process.nextTick(function() {
+    throw new Error('nextTick');
+  });
+}
+
+
+function runParent() {
+  var childDidExit = false;
+  var childStr = '';
+  var child = spawn(process.execPath, [__filename, 'child']);
+  child.stderr.on('data', function(chunk) {
+    process._rawDebug('received data from child');
+    childStr += chunk.toString();
+  });
+
+  child.on('exit', function(code) {
+    process._rawDebug('child process exiting');
+    childDidExit = true;
+    // This is thrown when Node throws from _fatalException.
+    assert.equal(code, 7);
+  });
+
+  process.on('exit', function() {
+    process._rawDebug('child ondata message:',
+                childStr.substr(0, childStr.indexOf('\n')));
+
+    assert.ok(childDidExit);
+    assert.notEqual(childStr.indexOf(checkStr), -1);
+    console.log('ok');
+  });
+}
+
index 1a1cca2..41d7c96 100644 (file)
 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 // USE OR OTHER DEALINGS IN THE SOFTWARE.
 
-
 var common = require('../common');
 var assert = require('assert');
 var net = require('net');
 
 
 // TODO(trevnorris): Test has the flaw that it's not checking if the async
-// flag has been removed on the class instance.
+// flag has been removed on the class instance. Though currently there's
+// no way to do that.
 var listener = process.addAsyncListener(function() { });
 
 
diff --git a/test/simple/test-asynclistener-remove-before.js b/test/simple/test-asynclistener-remove-before.js
new file mode 100644 (file)
index 0000000..5154e67
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+var set = 0;
+
+function onAsync0() { }
+
+var asyncNoHandleError = {
+  before: function() {
+    set++;
+  },
+  after: function() {
+    set++;
+  }
+}
+
+var key = process.addAsyncListener(onAsync0, asyncNoHandleError);
+
+process.removeAsyncListener(key);
+
+process.nextTick(function() { });
+
+process.on('exit', function(code) {
+  // If the exit code isn't ok then return early to throw the stack that
+  // caused the bad return code.
+  if (code !== 0)
+    return;
+
+  // The async handler should never be called.
+  assert.equal(set, 0);
+  console.log('ok');
+});
+
+
diff --git a/test/simple/test-asynclistener-remove-inflight-error.js b/test/simple/test-asynclistener-remove-inflight-error.js
new file mode 100644 (file)
index 0000000..40135b0
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+
+function onAsync0() { }
+
+var set = 0;
+var asyncNoHandleError = {
+  error: function() {
+    set++;
+  }
+}
+
+var key = process.addAsyncListener(onAsync0, asyncNoHandleError);
+
+process.nextTick(function() {
+  throw 1;
+});
+
+process.removeAsyncListener(key);
+
+var uncaughtFired = false;
+process.on('uncaughtException', function() {
+  uncaughtFired = true;
+
+  // Throwing should call the error handler once, then propagate to
+  // uncaughtException
+  assert.equal(set, 1);
+});
+
+process.on('exit', function(code) {
+  // If the exit code isn't ok then return early to throw the stack that
+  // caused the bad return code.
+  if (code !== 0)
+    return;
+
+  assert.ok(uncaughtFired);
+  console.log('ok');
+});
diff --git a/test/simple/test-asynclistener-remove-inflight.js b/test/simple/test-asynclistener-remove-inflight.js
new file mode 100644 (file)
index 0000000..1346609
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+
+function onAsync0() { }
+
+var set = 0;
+var asyncNoHandleError = {
+  before: function() {
+    set++;
+  },
+  after: function() {
+    set++;
+  }
+}
+
+var key = process.addAsyncListener(onAsync0, asyncNoHandleError);
+
+process.nextTick(function() { });
+
+process.removeAsyncListener(key);
+
+process.on('exit', function(code) {
+  // If the exit code isn't ok then return early to throw the stack that
+  // caused the bad return code.
+  if (code !== 0)
+    return;
+
+  // Calling removeAsyncListener *after* a callback is scheduled
+  // should not affect the handler from responding to the callback.
+  assert.equal(set, 2);
+  console.log('ok');
+});
+